/*
Thermometer and Clock
LCD part based on previous examples by Tomek and Dojodave
*/
#include <Wire.h>
////////////////////////////////////////////////////////////
/*
Temperature module commands and registers over I2C
*/
int TMP_RD = 0x91;
int TMP_WR = 0x90; //Assume ADR0 is tied to VCC
int TEMP_REG = 0x00;
int TEMP_ADDR = 0b1001000;
int ReadTemperature()
{
int val_h = 0;
int val_l = 0;
Wire.requestFrom(TEMP_ADDR, 2);
val_h = Wire.receive();
val_l = Wire.receive();
// convert temp reading into degrees C
int tempint = ((val_h << 8) | val_l) >> 4; // combine and shift
float tempflt = float( tempint ) * .0625; // calculate actual temperature per chip doc
return int(tempflt);
}
////////////////////////////////////////////////////////////
/*
Clock functions
*/
// adjust button digital pins
int HOURS = 9;
int MINS = 8;
// our base milliseconds count and corresponding time
unsigned long ulBaseMillis = 0;
int iBaseH = 0;
int iBaseM = 0;
int iBaseS = 0;
unsigned long ulLastMillis = 0;
int iLastH = 0;
int iLastM = 0;
int iLastS = 0;
unsigned long ulmSperS = 1000;
unsigned long ulmSperM = (ulmSperS * 60);
unsigned long ulmSperH = (ulmSperM * 60);
void PrintDigits(int iVal)
{
// utility function for digital clock display: prints colon and leading 0
if (iVal < 10)
{
LcdDataWrite('0');
}
LcdNumberWrite(iVal);
}
boolean ClockAdjust()
{
boolean bRet = false;
if (digitalRead(HOURS) == LOW) // read the input switch
{
iBaseH++;
if (iBaseH > 23)
{
iBaseH = 0;
}
bRet = true;
}
if (digitalRead(MINS) == LOW) // read the input switch
{
iBaseM++;
if (iBaseM > 59)
{
iBaseM = 0;
}
bRet = true;
}
return bRet; // did we adjust
}
// calc time difference from start and carry on
// we always recalc from scratch to avoid creep
void ClockDisplay()
{
unsigned long ulNow = millis();
unsigned long ulDiff = ulNow - ulBaseMillis;
if (ulNow < ulLastMillis) // deal with wrap
{
ulDiff = (4294967295 - ulLastMillis) + ulNow;
ulBaseMillis = ulLastMillis;
iBaseH = iLastH;
iBaseM = iLastM;
iBaseS = iLastS;
ulNow = ulBaseMillis + ulDiff; // time since last time we knew
}
// calc hms since base
int iHours = ulDiff / ulmSperH;
int iMins = (ulDiff - (iHours * ulmSperH)) / ulmSperM;
int iSecs = (ulDiff - (iHours * ulmSperH) - (iMins * ulmSperM)) / ulmSperS;
int iH = iBaseH + iHours;
int iM = iBaseM + iMins;
int iS = iBaseS + iSecs;
if (iS > 59)
{
iM += iS/60;
iS = iS % 60;
}
if (iM > 59)
{
iH += iM/60;
iM = iM % 60;
}
if (iH > 23)
{
iH = iH % 24;
}
// remember so we can cope with a wrap
ulLastMillis = ulNow;
iLastH = iH;
iLastM = iM;
iLastS = iS;
// move to pos
LcdPosition(1,0);
PrintDigits(iH);
LcdDataWrite(':');
PrintDigits(iM);
LcdDataWrite(':');
PrintDigits(iS);
}
////////////////////////////////////////////////////////////
/*
LCD functions
*/
// pins to be used on Arduino for LCD display
int DOUT = 11;
int STR = 12;
int CLK = 10;
// the Qx in the order they are connected on the chip
int RS = 0x40;
int RW = 0x20;
int EnableSet = 0x10;
int EnableClr = 0xEF;
int DMASK = 0x0F;
// shift byte and strobe to display
void sendByteOut(int value)
{
digitalWrite(STR,LOW); // set the strobe LOW
shiftOut(DOUT, CLK, LSBFIRST, value);
digitalWrite(STR, HIGH);
delayMicroseconds(100);
digitalWrite(STR,LOW);
}
void LcdClockByte(int output)
{
output &= EnableClr; // set Enable LOW
sendByteOut(output);
delayMicroseconds(2);
output |= EnableSet; // Set Enable HIGH
sendByteOut(output);
delayMicroseconds(2);
output &= EnableClr; // set Enable LOW
sendByteOut(output);
delayMicroseconds(100);
}
void LcdWrite(int value, boolean bData)
{
int iData = bData ? RS : 0;
int output = value >> 4; //send the upper 4 databits (from 8)
output |= iData;
LcdClockByte(output);
output = value & 0x0F; // send lower 4 bytes
output |= iData;
LcdClockByte(output);
}
void LcdCommandWrite(int value)
{
LcdWrite(value,false);
}
void LcdDataWrite(int value)
{
LcdWrite(value,true);
}
void LcdInit()
{
delay(100);
// initialize LCD after a short pause
// 4 pin initialization - needed twice
LcdCommandWrite(0x28); // function set: 4 pin initialization, 2 lines, 5x8 characters
delay(10);
LcdCommandWrite(0x28); // function set: 4 pin initialization, 2 lines, 5x8 characters
delay(10);
LcdCommandWrite(0x0C); // display on: on with no cursor
delay(10);
LcdCommandWrite(0x01); // clear display
delay(10);
LcdCommandWrite(0x06); // entry mode set: increment automatically, no display shift
delay(10);
LcdCommandWrite(0x80); // display control: address top left
delay(10);
}
// checks out how many digits there are in a number, keep dividing by 10 until there's nothing left
int countDigits(int nr)
{
int iNum = 0;
while (nr > 0)
{
iNum++;
nr = nr/10;
}
return iNum;
}
// this function help us to write numbers with more than one digit
// up to 20
void LcdNumberWrite(int nr)
{
int iDigits; // how many digits
int iIndex;
int cNum[20]; // build number in here
if (nr == 0)
{
LcdDataWrite('0'); // zero is a special case
}
else
{ // if negative write a minus sign
if (nr < 0)
{
LcdDataWrite('-');
}
nr = abs(nr); // make positive
iDigits = countDigits(nr); // count number of digits
iIndex = iDigits-1; // start at the end
while (nr > 0) // store each digit working up the powers of 10
{
cNum[iIndex] = '0' + (nr % 10);
nr = nr/10;
iIndex--;
}
// now write all the digits out
for(iIndex = 0; iIndex < iDigits; iIndex++)
{
LcdDataWrite(cNum[iIndex]);
}
}
}
// write a string from an array
void LcdWriteString(int* msg, int len)
{
for (int count = 0; count < len; count++)
{
LcdDataWrite(msg[count]);
}
}
// position the cursor
void LcdPosition(int iRow, int iCol)
{
int iPos = ((iRow * 0x40) + iCol) | 0x80;
LcdCommandWrite(iPos);
}
void setup (void)
{
int msg[] = {'T','i','m','e',' ',' ',' ',' ',' ',' ',' ',' ','T','e','m','p'};
Serial.begin(9600); // for debug
pinMode(CLK,OUTPUT); // LCD control lines
pinMode(DOUT,OUTPUT);
pinMode(STR,OUTPUT);
pinMode(HOURS,INPUT); // hours adjust switch
digitalWrite(HOURS, HIGH); // turn on pullup resistor
pinMode(MINS,INPUT); // mins adjust switch
digitalWrite(MINS, HIGH); // turn on pullup resistor
LcdInit(); // set up the LCD
delay(20);
LcdCommandWrite(0x01); // clear screen
delay(20);
LcdCommandWrite(0x02); // set cursor position to zero
delay(20);
LcdWriteString(msg,16); // show our titles
// begin wire library and set address to temp register
Wire.begin();
Wire.beginTransmission(TEMP_ADDR);
Wire.send(TEMP_REG);
Wire.endTransmission();
}
void loop (void)
{
int temp;
ClockDisplay(); // Show the time
ClockAdjust(); // Make any time adjustments
temp = ReadTemperature(); // read the temperature
LcdPosition(1,11); // position on second row character 8
if (temp >= 0) // if its positive
{
LcdDataWrite(' '); // insert a space as no minus sign
}
LcdNumberWrite(temp); // write the temp value
LcdDataWrite(0xDF); // degree symbol
LcdDataWrite('C'); // centigrade
delay(200); // laze about a bit
}
/*
Thermometer and Clock
LCD part based on previous examples by Tomek and Dojodave
*/
#include <Wire.h>
////////////////////////////////////////////////////////////
/*
Temperature module commands and registers over I2C
*/
int TMP_RD = 0x91;
int TMP_WR = 0x90; //Assume ADR0 is tied to VCC
int TEMP_REG = 0x00;
int TEMP_ADDR = 0b1001000;
int ReadTemperature()
{
int val_h = 0;
int val_l = 0;
Wire.requestFrom(TEMP_ADDR, 2);
val_h = Wire.receive();
val_l = Wire.receive();
// convert temp reading into degrees C
int tempint = ((val_h << 8) | val_l) >> 4; // combine and shift
float tempflt = float( tempint ) * .0625; // calculate actual temperature per chip doc
return int(tempflt);
}
////////////////////////////////////////////////////////////
/*
Clock functions
*/
// adjust button digital pins
int HOURS = 9;
int MINS = 8;
// our base milliseconds count and corresponding time
unsigned long ulBaseMillis = 0;
int iBaseH = 0;
int iBaseM = 0;
int iBaseS = 0;
unsigned long ulLastMillis = 0;
int iLastH = 0;
int iLastM = 0;
int iLastS = 0;
unsigned long ulmSperS = 1000;
unsigned long ulmSperM = (ulmSperS * 60);
unsigned long ulmSperH = (ulmSperM * 60);
void PrintDigits(int iVal)
{
// utility function for digital clock display: prints colon and leading 0
if (iVal < 10)
{
LcdDataWrite('0');
}
LcdNumberWrite(iVal);
}
boolean ClockAdjust()
{
boolean bRet = false;
if (digitalRead(HOURS) == LOW) // read the input switch
{
iBaseH++;
if (iBaseH > 23)
{
iBaseH = 0;
}
bRet = true;
}
if (digitalRead(MINS) == LOW) // read the input switch
{
iBaseM++;
if (iBaseM > 59)
{
iBaseM = 0;
}
bRet = true;
}
return bRet; // did we adjust
}
// calc time difference from start and carry on
// we always recalc from scratch to avoid creep
void ClockDisplay()
{
unsigned long ulNow = millis();
unsigned long ulDiff = ulNow - ulBaseMillis;
if (ulNow < ulLastMillis) // deal with wrap
{
ulDiff = (4294967295 - ulLastMillis) + ulNow;
ulBaseMillis = ulLastMillis;
iBaseH = iLastH;
iBaseM = iLastM;
iBaseS = iLastS;
ulNow = ulBaseMillis + ulDiff; // time since last time we knew
}
// calc hms since base
int iHours = ulDiff / ulmSperH;
int iMins = (ulDiff - (iHours * ulmSperH)) / ulmSperM;
int iSecs = (ulDiff - (iHours * ulmSperH) - (iMins * ulmSperM)) / ulmSperS;
int iH = iBaseH + iHours;
int iM = iBaseM + iMins;
int iS = iBaseS + iSecs;
if (iS > 59)
{
iM += iS/60;
iS = iS % 60;
}
if (iM > 59)
{
iH += iM/60;
iM = iM % 60;
}
if (iH > 23)
{
iH = iH % 24;
}
// remember so we can cope with a wrap
ulLastMillis = ulNow;
iLastH = iH;
iLastM = iM;
iLastS = iS;
// move to pos
LcdPosition(1,0);
PrintDigits(iH);
LcdDataWrite(':');
PrintDigits(iM);
LcdDataWrite(':');
PrintDigits(iS);
}
////////////////////////////////////////////////////////////
/*
LCD functions
*/
// pins to be used on Arduino for LCD display
int DOUT = 11;
int STR = 12;
int CLK = 10;
// the Qx in the order they are connected on the chip
int RS = 0x40;
int RW = 0x20;
int EnableSet = 0x10;
int EnableClr = 0xEF;
int DMASK = 0x0F;
// shift byte and strobe to display
void sendByteOut(int value)
{
digitalWrite(STR,LOW); // set the strobe LOW
shiftOut(DOUT, CLK, LSBFIRST, value);
digitalWrite(STR, HIGH);
delayMicroseconds(100);
digitalWrite(STR,LOW);
}
void LcdClockByte(int output)
{
output &= EnableClr; // set Enable LOW
sendByteOut(output);
delayMicroseconds(2);
output |= EnableSet; // Set Enable HIGH
sendByteOut(output);
delayMicroseconds(2);
output &= EnableClr; // set Enable LOW
sendByteOut(output);
delayMicroseconds(100);
}
void LcdWrite(int value, boolean bData)
{
int iData = bData ? RS : 0;
int output = value >> 4; //send the upper 4 databits (from 8)
output |= iData;
LcdClockByte(output);
output = value & 0x0F; // send lower 4 bytes
output |= iData;
LcdClockByte(output);
}
void LcdCommandWrite(int value)
{
LcdWrite(value,false);
}
void LcdDataWrite(int value)
{
LcdWrite(value,true);
}
void LcdInit()
{
delay(100);
// initialize LCD after a short pause
// 4 pin initialization - needed twice
LcdCommandWrite(0x28); // function set: 4 pin initialization, 2 lines, 5x8 characters
delay(10);
LcdCommandWrite(0x28); // function set: 4 pin initialization, 2 lines, 5x8 characters
delay(10);
LcdCommandWrite(0x0C); // display on: on with no cursor
delay(10);
LcdCommandWrite(0x01); // clear display
delay(10);
LcdCommandWrite(0x06); // entry mode set: increment automatically, no display shift
delay(10);
LcdCommandWrite(0x80); // display control: address top left
delay(10);
}
// checks out how many digits there are in a number, keep dividing by 10 until there's nothing left
int countDigits(int nr)
{
int iNum = 0;
while (nr > 0)
{
iNum++;
nr = nr/10;
}
return iNum;
}
// this function help us to write numbers with more than one digit
// up to 20
void LcdNumberWrite(int nr)
{
int iDigits; // how many digits
int iIndex;
int cNum[20]; // build number in here
if (nr == 0)
{
LcdDataWrite('0'); // zero is a special case
}
else
{ // if negative write a minus sign
if (nr < 0)
{
LcdDataWrite('-');
}
nr = abs(nr); // make positive
iDigits = countDigits(nr); // count number of digits
iIndex = iDigits-1; // start at the end
while (nr > 0) // store each digit working up the powers of 10
{
cNum[iIndex] = '0' + (nr % 10);
nr = nr/10;
iIndex--;
}
// now write all the digits out
for(iIndex = 0; iIndex < iDigits; iIndex++)
{
LcdDataWrite(cNum[iIndex]);
}
}
}
// write a string from an array
void LcdWriteString(int* msg, int len)
{
for (int count = 0; count < len; count++)
{
LcdDataWrite(msg[count]);
}
}
// position the cursor
void LcdPosition(int iRow, int iCol)
{
int iPos = ((iRow * 0x40) + iCol) | 0x80;
LcdCommandWrite(iPos);
}
void setup (void)
{
int msg[] = {'T','i','m','e',' ',' ',' ',' ',' ',' ',' ',' ','T','e','m','p'};
Serial.begin(9600); // for debug
pinMode(CLK,OUTPUT); // LCD control lines
pinMode(DOUT,OUTPUT);
pinMode(STR,OUTPUT);
pinMode(HOURS,INPUT); // hours adjust switch
digitalWrite(HOURS, HIGH); // turn on pullup resistor
pinMode(MINS,INPUT); // mins adjust switch
digitalWrite(MINS, HIGH); // turn on pullup resistor
LcdInit(); // set up the LCD
delay(20);
LcdCommandWrite(0x01); // clear screen
delay(20);
LcdCommandWrite(0x02); // set cursor position to zero
delay(20);
LcdWriteString(msg,16); // show our titles
// begin wire library and set address to temp register
Wire.begin();
Wire.beginTransmission(TEMP_ADDR);
Wire.send(TEMP_REG);
Wire.endTransmission();
}
void loop (void)
{
int temp;
ClockDisplay(); // Show the time
ClockAdjust(); // Make any time adjustments
temp = ReadTemperature(); // read the temperature
LcdPosition(1,11); // position on second row character 8
if (temp >= 0) // if its positive
{
LcdDataWrite(' '); // insert a space as no minus sign
}
LcdNumberWrite(temp); // write the temp value
LcdDataWrite(0xDF); // degree symbol
LcdDataWrite('C'); // centigrade
delay(200); // laze about a bit
}
Excellent article my friend. This is exactly what I’ve been looking for for quite a time now. You have my gratitude man.
ЎHola!
ЎGracias por el artнculo. Cada vez que quieres leer.
Ilias