Clock & Temp on 16x2 Display

Our range of tiny modules are designed to make it easy for you to quickly add functionality to your projects. [Module List]
Post Reply
Chris
Posts: 17
Joined: Sat Aug 30, 2014 5:37 am
Location: Adelaide, South Australia

Clock & Temp on 16x2 Display

Post by Chris » Thu Jun 23, 2016 7:43 am

Hi guys. I've got a code somewhat working to display the time on the top line and the day/date and the temp on the second.
2 things, something's not correct as the temp is flashing every second or so, which in turn somehow effects the seconds on the time on the top row, that change every 2 or 3 seconds, but keeps up time. Also, is there any way to make the temp printout just the degrees with no decimal places

Im using a Arduino Mega with the Freetronics Display Shiels mounted on it. I have a DS18B20 and an RTC on a Breadboard with Jumpers
Here's my code

Code: Select all

// Libraries
#include <Wire.h>
#define DS3232_I2C_ADDRESS 0x68
#include <OneWire.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd( 8, 9, 4, 5, 6, 7 );
#include <DallasTemperature.h> //will find addresses of sensors automatically
const char degree = 223;   //This will give us the degree symbol after the temp 

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return( (val/16*10) + (val%16) );
}
// Data wire from DS18B20 to Arduino Digital PIn 31
#define ONE_WIRE_BUS 31

// Setup oneWire instance to communicate with devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

int n = 1;

void setup()
{
  
  Wire.begin();
  lcd.begin(16, 2);
  // set the initial time here:
  // DS3232 seconds, minutes, hours, day, date, month, year
  //setDS3232time(0, 32, 17, 3, 21, 6, 16);
}
void setDS3232time(byte second, byte minute, byte hour, byte dayOfWeek, byte
dayOfMonth, byte month, byte year)
{
  // sets time and date data to DS3232
  Wire.beginTransmission(DS3232_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3232time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
  Wire.beginTransmission(DS3232_I2C_ADDRESS);
  Wire.write(0); // set DS3232 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3232_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3232 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void displayTime()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  // retrieve data from DS3232
  readDS3232time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
  &year);
  // send the data to the LCD shield
  lcd.clear();
  lcd.setCursor(4,0);
  lcd.print(hour, DEC);
  lcd.print(":");
  if (minute<10)
  {
    lcd.print("0");
  }
  lcd.print(minute, DEC);
  lcd.print(":");
  if (second<10)
  {
    lcd.print("0");
  }
  lcd.print(second, DEC);
  lcd.setCursor(0,1);
    switch(dayOfWeek)
    {
  case 1:
    lcd.print("Sun");
    break;
  case 2:
    lcd.print("Mon");
    break;
  case 3:
    lcd.print("Tue");
    break;
  case 4:
    lcd.print("Wed");
    break;
  case 5:
    lcd.print("Thu");
    break;
  case 6:
    lcd.print("Fri");
    break;
  case 7:
    lcd.print("Sat");
    break;
 }
  lcd.print(" ");
  lcd.print(dayOfMonth, DEC);
  lcd.print("/");
  lcd.print(month, DEC);
  lcd.print("/");
  lcd.print(year, DEC);
  
   sensors.begin();
  }
 void readtemp(void) 
{
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  sensors.requestTemperatures(); // Get temps
   lcd.setCursor ( 12, 1 ); //Print Room temp on bottom line
    lcd.print(sensors.getTempCByIndex(0)); //Use this if you want C
  //lcd.print(sensors.getTempCByIndex(0)* 9/5 * .54); //convert to F
 
}
void loop()
{
  displayTime(); // display the real-time clock time on the LCD,
  delay(1000); // every second 
readtemp();
  delay (1000);//reads temp every .5 second
}

Thanks
Chris

angusgr
Freetronics Staff
Freetronics Staff
Posts: 853
Joined: Tue Apr 09, 2013 11:19 pm
Location: Melbourne, Australia
Contact:

Re: Clock & Temp on 16x2 Display

Post by angusgr » Fri Jun 24, 2016 4:03 am

Hi Chris,

Sorry to hear it's not quite working yet. At the moment the code updates the time, then waits one second, then updates the temperature, then waits one second before updating the time again. You can try updating both at the same time.

Change this part:

Code: Select all

void loop()
{
  displayTime(); // display the real-time clock time on the LCD,
  delay(1000); // every second 
readtemp();
  delay (1000);//reads temp every .5 second
}
To something like this:

Code: Select all

void loop()
{
  displayTime();
  readtemp();
  delay (1000);
}
Chris wrote:Also, is there any way to make the temp printout just the degrees with no decimal places
You can, by making the temperature into an "int" (integer whole number) instead of a "float" (floating point number.) Try changing this line:

Code: Select all

    lcd.print(sensors.getTempCByIndex(0)); //Use this if you want C
To this:

Code: Select all

    lcd.print( (int) sensors.getTempCByIndex(0)); //Use this if you want C
Regards,

Angus

Chris
Posts: 17
Joined: Sat Aug 30, 2014 5:37 am
Location: Adelaide, South Australia

Re: Clock & Temp on 16x2 Display

Post by Chris » Fri Jun 24, 2016 9:24 am

Thanks for the reply Angus. Unfortunately the time is still updating every 2 seconds and the temp is flashing every 1 or so. But the temp whole number worked ok.

Chris

angusgr
Freetronics Staff
Freetronics Staff
Posts: 853
Joined: Tue Apr 09, 2013 11:19 pm
Location: Melbourne, Australia
Contact:

Re: Clock & Temp on 16x2 Display

Post by angusgr » Mon Jun 27, 2016 12:28 am

You can try removing the "lcd.clear()" line (which will erase the entire display each time it redraws), although you might find you need to print some extra spaces ' ' so it doesn't leave "cruft" at the end of the line when it draws the new time over the old time.

At the same time, you could also try reducing the 'delay' in the main loop to less than the current one second (1000ms), because all of the other updating probably takes some time as well. Maybe try 250 or 500, or even try removing it entirely.

AllanGH
Posts: 2
Joined: Mon Sep 25, 2017 3:42 pm

Re: Clock & Temp on 16x2 Display

Post by AllanGH » Mon Sep 25, 2017 4:15 pm

I realize that this is an old thread, and I really don't have much experience with Arduino programming, however, I did spend some time patching together various example code blocks to do what the OP was attempting to achieve with the 16x02 LCD display.

In my situation, the display used is a 40x02 display, addressed via an I2C bus which passes through a DS3231 RTC module. Temp is derived from a Maxim Integrated DS18B20 sensor that I had laying about--only for the higher precision of the temp readout.

With patching-together several bits of example code to get this to do what I wanted it to do, and fiddling with it to solve problems that I encountered, there is--admittedly--a lot of dross in the code below (It's downright ugly right now!) that can be adjusted and / or cleaned-up; however, the essential problems that I see discussed in this thread have been solved. I only provide this in an attempt to aid anyone who might be wandering the same path as the OP.

My apologies for the condition of the contribution, but I really am more of a hardware guy, getting back into programming as a means to an end, the last experience with which I had back in the mid-1980's. I'll get around to actually cleaning it up later.

Code: Select all

#include <LiquidCrystal_I2C.h>
#include <TimeLib.h>
#include <Wire.h>
#include <DS1307RTC.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define DS3231_I2C_ADDR   0x68
#define ONE_WIRE_BUS   2

LiquidCrystal_I2C lcd(0x27, 40, 2);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

char    weekDay[9];

float   tempC,
        tempF;

int     Wkday;

byte bcdToDec(byte val)  {
  return( (val/16*10) + (val%16) );
}



void setup()  {
  lcd.begin(40,2);
  lcd.backlight();
  sensors.begin();
  setSyncProvider(RTC.get);
  checkTimeSetStatus();
}



void checkTimeSetStatus()  {
  if (timeStatus()!= timeSet)  {
     lcd.clear();
     lcd.setCursor ( 0, 0 );
     lcd.print("Unable to sync with the RTC.");
     delay(4000);
     lcd.clear();
     delay(1000);
  } else {
     lcd.clear();
     lcd.setCursor ( 0, 0 );
     lcd.print("RTC has set the system time.");
     delay(1000);
     lcd.clear();
  }
}



void ClockDisplay()  {
  lcd.setCursor ( 0, 0 );
  lcd.print("   ");
  lcd.print(year());
  printMoDy(month());
  printMoDy(day()); 
  lcd.print("    ");
  printHour(hour());
  printDigits(minute());
  printDigits(second());
  lcd.print(" ");
  printDoW();
}



void printHour(int digits)  {
  if(digits < 10)
    lcd.print('0');
  lcd.print(digits);
}



void printDigits(int digits)  {
  lcd.print(":");
  if(digits < 10)
    lcd.print('0');
  lcd.print(digits);
}



void printMoDy(int digits)  {
  lcd.print(".");
  if(digits < 10)
    lcd.print('0');
  lcd.print(digits);
}



void printDoW()  {
  Wkday = (weekday());
  switch (Wkday) {
    case 1:
      strcpy(weekDay, " SUNDAY  ");
      break;
    case 2:
      strcpy(weekDay, " MONDAY  ");
      break;
    case 3:
      strcpy(weekDay, " TUESDAY ");
      break;
    case 4:
      strcpy(weekDay, "WEDNESDAY");
      break;
    case 5:
      strcpy(weekDay, "THURSDAY ");
      break;
    case 6:
      strcpy(weekDay, " FRIDAY  ");
      break;
    case 7:
      strcpy(weekDay, "SATURDAY ");
      break;
  }
  lcd.print("   ");
  lcd.print(weekDay);
}



void TempDisplay()  {
  sensors.requestTemperatures();
  tempC = (sensors.getTempCByIndex(0));
  tempF = ((tempC * 1.8) + 32.0);
  lcd.setCursor ( 0, 1 );
  lcd.print("           T = ");
  lcd.print(tempC);
  lcd.print("C  ");
  lcd.print(tempF);
  lcd.print("F  ");
}



void loop()  {
  if (timeStatus() == timeSet) {
    ClockDisplay();
    TempDisplay();
  } else {
    lcd.clear();
    delay(1000);
    lcd.setCursor ( 0, 0 );
    lcd.print("The Time has not been set.");
    lcd.setCursor ( 0, 1 );
    lcd.print("                   Please set the Time.");
    delay(1000);
    lcd.clear();
  }
}
All-in-all, this will be either a helpful first post, here, for me, or a terrible mistake. LOL

Best Regards




######## EDITED ########

Should you wish to only print-out the integer portion of the temp, simply declare an integer variable, local to the "TempDisplay" function, and assign the float temp value to the integer variable and substitute the integer temp variable in the output statement. The decimal fraction of the float will be dropped in the assignment to the integer.

Post Reply

Who is online

Users browsing this forum: Google [Bot] and 2 guests