Thermometer and Clock

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

3 thoughts on “Thermometer and Clock

Leave a Reply

Your email address will not be published. Required fields are marked *