How to get DS1307 hour in AM/PM Format easily?

by obbi13 on Fri Dec 31, 2010 12:40 pm

Hello and Happy new year beforehand!

After getting my DS1307 working beautifully I put together a nice sketch (at least for me) to print out the temperature (from a 1-Wire DS18B20) and the date time (from Lady Ada DSRTC1307 breakout board) by toggling a switch to a serial enabled (by SparkFun serial backpack) 16x2 LCD. Everything works perfect right now, but I would like to change the time format to AM/PM instead of the 24Hrs format. I have looked at the RTClib.h and haven't found a method or functions for this. Maybe I'm not looking at the right place or something but I'm sure there should be a method or library where that should be already implemented. I have used methods/functions from many others around. Also feel free to use it as your heart desires.

Anyway, here's my code (sorry for the coding mess, it's been almost 10 years since I programmed again and it's a wip:
Code: Select all
/*                         
  Sketch to print the temperature from a DS18B20 on a 16x2 serial enabled
  LCD (SparkFun v2.5) attached to a SparkFun LCD serial backpack.  Also prints the
  date and time from an AdaFruit RTC 1307 breakout board.
*/
#include <Wire.h>              // for easy I2C communications with the RTC
#include <OneWire.h>           // OneWire communication library
#include <DallasTemperature.h> // TEmp Sensor DS18B20 library
#include <math.h>              // library for math manipulations (might not be needed)
#include <SparkSoftLCD.h>  // library to manipulate the LCD
#include "RTClib.h"            //Real Time Clock library (by LadyAda)

#define RTC5vPin 17 // pin 17 (analog pin 3) will be used to provide +5v to the RTC
#define RTCgndPin 16 // pin 16 (analog pin 2) will be used to provide GND to the RTC

RTC_DS1307 RTC;

#define LCDtxPin 2           // Using Digital Pin 2 as the Soft Serial Tx output
#define LCD_WIDTH 16         // LCD width definition
#define TempSensor_PIN 14    // Analog Pin 0, digital 14
#define buttonPin 12         // Digital pin 12 for push button
#define LED_PIN 13           // Digital Pin 13 led

float temp;                  // temperature variable
int decimals = 1;            // Decimal precision on the temperature
int gate = 0;                // counter to preserve state on push button switch

OneWire oneWire(TempSensor_PIN);  // instantiate a OneWire object
DallasTemperature sensors(&oneWire); // instantiate a sensor (DS18B20) object(s)

long interval = 500;            // interval in ms to get temperature and print it on LCD

SparkSoftLCD LCD = SparkSoftLCD(LCDtxPin, LCD_WIDTH); // create an LCD object with soft serial on pin 2.

void setup() {
 
  pinMode(LED_PIN, OUTPUT);       //sets pin for output
  pinMode(RTC5vPin, OUTPUT);      //sets Pin for output
  digitalWrite(RTC5vPin, HIGH);   // turn pin on (5v) to power RTC
  pinMode(RTCgndPin, OUTPUT);     //sets Pin for output
  digitalWrite(RTCgndPin, LOW);   // turn pin off to (GND) to power RTC
  pinMode(buttonPin, INPUT);      //Sets pin for input
  Wire.begin();                   // Initialize I2C protocol for clock communications
  pinMode(LCDtxPin, OUTPUT);      // Set defined Pin as an Output Pin for transmission
  LCD.begin(9600);                // Set baud rate speed to the LCD backpack on the defined Pin
  LCD.clear();
  RTC.begin();
  sensors.begin();
  if (! RTC.isrunning()) {
    LCD.print("RTC is NOT running!");
//  following line sets the RTC to the date & time this sketch was compiled
    RTC.adjust(DateTime(__DATE__, __TIME__));
  } // end if for RTC adjust
}
void loop(){
  if(digitalRead(buttonPin)  == LOW){
     gate++;
  }
  if(gate == 0){
    digitalWrite(LED_PIN, LOW);
    printTemp();
 //   delay(interval);
  }
  if(gate == 1){
    digitalWrite(LED_PIN, HIGH);
    printClock();
    gate = 0;
    delay(500);
  }
}

/***********************************************************************/
/**********************  BEGIN RTC FUNCTIONS  **************************/
/***********************************************************************/

void printClock(){
    DateTime now = RTC.now();
    LCD.clear();
    LCD.print("Date: ");
    LCD.print(now.month(), DEC);
    LCD.print('/');
    LCD.print(now.day(), DEC);
    LCD.print('/');
    LCD.print(now.year(), DEC);
    LCD.print("Time: ");
    LCD.print(now.hour(), DEC);
    LCD.print(':');
    LCD.print(now.minute(), DEC);
    LCD.print(':');
    LCD.print(now.second(), DEC);

}
/***********************************************************************/
/**********************  END RTC FUNCTIONS  **************************/
/***********************************************************************/


/***********************************************************************/
/*******************  BEGIN TEMPERATURE FUNCTIONS  *********************/
/***********************************************************************/
void printTemp(){
  float temp;
  sensors.requestTemperatures(); // Send the command to get temperatures
  LCD.cursorTo(1,1);
  LCD.print("Real Time Temp: ");
  LCD.cursorTo(2,1);
  temp = sensors.getTempCByIndex(0);
  printDouble(temp,decimals); LCD.print((char)223); LCD.print("C ,");    // display in Celsius
  temp = sensors.getTempFByIndex(0);
  printDouble(temp,decimals); LCD.print((char)223); LCD.print("F  "); // display in Fahrenheit
}

void printDouble(double val, byte precision) {
  // prints val with number of decimal places determine by precision
  // precision is a number from 0 to 6 indicating the desired decimal places
  // example: printDouble(3.1415, 2); // prints 3.14 (two decimal places)
  LCD.print (int(val));  //prints the int part
  if( precision > 0) {
    LCD.print("."); // print the decimal point
    unsigned long frac, mult = 1;
    byte padding = precision -1;
    while(precision--) mult *=10;
    if(val >= 0) frac = (val - int(val)) * mult; else frac = (int(val) - val) * mult;
    unsigned long frac1 = frac;
    while(frac1 /= 10) padding--;
    while(padding--) LCD.print("0");
    LCD.print(frac,DEC) ;
  }
}
/***********************************************************************/
/**********************  END TEMPERATURE FUNCTIONS  ********************/
/***********************************************************************/

User avatar
obbi13
 
Posts: 10
Joined: Wed Dec 08, 2010 9:58 pm
Location: Carolina, PR

Re: How to get DS1307 hour in AM/PM Format easily?

by oPossum on Fri Dec 31, 2010 5:43 pm

The easy way is to just convert the 24 hour format to 12 hour format when printing.

Code: Select all
 // Put hour in a variable that will not change
const uint8_t h = now.hour();

// If hour > 12 then subtract 12, else if hour == 0 use 12, else unchanged
LCD.print((h > 12) ? h - 12 : ((h == 0) ? 12 : h), DEC);

LCD.print(':');
LCD.print(now.minute(), DEC);
LCD.print(':');
LCD.print(now.second(), DEC);

// AM if hour < 12, else PM
LCD.print((h < 12) ? " AM" : " PM");
I am the Possum, and I approve of this message. Sent from MacBook Wheel Sorry for my bad German.
User avatar
oPossum
 
Posts: 635
Joined: Thu Oct 25, 2007 11:42 pm
Location: Michigan, USA

Re: How to get DS1307 hour in AM/PM Format easily?

by obbi13 on Sun Jan 02, 2011 6:05 pm

oPossum, thanks for the help, it worked nicely, although I had to modify the following line:

Code: Select all
LCD.print((h < 12) ? " AM" : " PM");


because I was getting an overloading error on the LCD.print() function not being able to test numeric values and print chars at the same time. Plus I took the time to pad the time elements with zeros if less than 10. Here's the final code I ended up with on the time function:
Code: Select all
void printClock(){
    DateTime now = RTC.now();
    LCD.clear();
    LCD.cursorTo(1,1);              // Functions to move the cursor to first line fisrt position
    LCD.print("Date ");
    if(now.month() < 10){           // Zero padding if value less than 10 ie."09" instead of "9"
      LCD.print("0");
      LCD.print(now.month(), DEC);
    }
    LCD.print('/');
    if(now.day() < 10){            // Zero padding if value less than 10 ie."09" instead of "9"
      LCD.print("0");
      LCD.print(now.day(), DEC);
    }
    LCD.print('/');
    LCD.print(now.year(), DEC);
/*************  Now comes the time section  **************/
    const uint8_t h = now.hour();
    const uint8_t hr_12 = h%12;
    LCD.cursorTo(2,1);              // Functions to move the cursor to second line fisrt position
    LCD.print("Time ");
    if(hr_12 < 10){                // Zero padding if value less than 10 ie."09" instead of "9"
      LCD.print(" ");
      LCD.print((h > 12) ? h - 12 : ((h == 0) ? 12 : h), DEC); // Conversion to AM/PM 
    }
    else{
      LCD.print((h > 12) ? h - 12 : ((h == 0) ? 12 : h), DEC); // Conversion to AM/PM
    }
    LCD.print(':');
    if(now.minute() < 10){         // Zero padding if value less than 10 ie."09" instead of "9"
      LCD.print("0");
      LCD.print(now.minute(), DEC);
    }
    else{
       LCD.print(now.minute(), DEC);
    }
    LCD.print(':');
    if(now.second() < 10){        // Zero padding if value less than 10 ie."09" instead of "9"
      LCD.print("0");
      LCD.print(now.second(), DEC);
    }
    else{
       LCD.print(now.second(), DEC);
    }
    if(h < 12){                  // Adding the AM/PM sufffix
      LCD.print(" AM");
    }
    else{
      LCD.print(" PM");
    }
}
User avatar
obbi13
 
Posts: 10
Joined: Wed Dec 08, 2010 9:58 pm
Location: Carolina, PR

Re: How to get DS1307 hour in AM/PM Format easily?

by csracruisers on Mon Feb 18, 2013 10:04 pm

How is the best way to add the day of the week to this code.

I have seen several uses of switch(dayOfWeek) but don't seem to be able to produce anything.

Thanks
csracruisers
 
Posts: 30
Joined: Mon Feb 18, 2013 10:03 pm

Re: How to get DS1307 hour in AM/PM Format easily?

by adafruit_support_rick on Tue Feb 19, 2013 9:20 am

Easiest thing is to download the Arduino Time Library. Check out the TimeSerialDateStrings example.
User avatar
adafruit_support_rick
 
Posts: 8510
Joined: Tue Mar 15, 2011 10:42 am
Location: Buffalo, NY

Re: How to get DS1307 hour in AM/PM Format easily?

by odometer on Tue Feb 19, 2013 2:20 pm

I don't think you need to download another library. Here's why:

It seems already have RTClib. RTClib has a dayOfWeek method. I suggest using something like this:

Code: Select all
switch (now.dayOfWeek()) {
  case 0: LCD.print("Sun"); break;
  case 1: LCD.print("Mon"); break;
  case 2: LCD.print("Tue"); break;
  case 3: LCD.print("Wed"); break;
  case 4: LCD.print("Thu"); break;
  case 5: LCD.print("Fri"); break;
  case 6: LCD.print("Sat"); break;
}


This goes in your printClock function.

(Ladyada, you might want to mention the dayOfWeek method in the docs.)
odometer
 
Posts: 98
Joined: Sun Aug 21, 2011 10:01 pm

Re: How to get DS1307 hour in AM/PM Format easily?

by adafruit_support_rick on Tue Feb 19, 2013 5:50 pm

@odometer - actually, the proper way to do that is with an array of characters (which is what the Time library does, btw). I was originally considering posting that, but I decided that the Time library offers a whole lot more than just this one thing, so the OP might be better off with it in the long run.

Code: Select all
char* dayStr[] = { "Sunday",  "Monday",  "Tuesday",  "Wednesday",  "Thursday",  "Friday",  "Saturday" };

 . . . .

Serial.print(dayStr[now.dayOfWeek()]);

 . . . .
User avatar
adafruit_support_rick
 
Posts: 8510
Joined: Tue Mar 15, 2011 10:42 am
Location: Buffalo, NY

Re: How to get DS1307 hour in AM/PM Format easily?

by csracruisers on Wed Feb 20, 2013 3:21 pm

driverblock wrote:Easiest thing is to download the Arduino Time Library. Check out the TimeSerialDateStrings example.


Thank you for the info. After looking at the link, I was able to get what I needed.
csracruisers
 
Posts: 30
Joined: Mon Feb 18, 2013 10:03 pm