/*
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