Ardunio Tick-Tock DS1307 RTC Shield Basics

This arrived in the mail from China a few days ago and, for the small money, has been a lot of fun.

Clock Shield RTC module DS1307 module Multifunction Expansion Board with 4 Digit Display Light Sensor and Thermistor For Arduino

This board is a lot of fun for a few bucks. It has a low grade Real Time Clock that runs on a little coin battery, a low grade light sensor and a low grade thermistor. In this context "low grade", means that the components are mostly for fun and educational purposes, but they are not accurate enough to use for most practical applications. This is especially true for the DS1307 RTC, which runs a bit fast, gaining second(s) every hours, and minutes by the day. In addition, the thermistor (the MF52E103F) is not very accurate, even when I calibrate is using the Steinhart-Hart Equation for calibrating thermistors (more on that in a later post) so, at least so far, I cannot get accurate temperature measures, even after re-rewriting the thermistor code (off by about 2 degrees Celsius, give or take). The light sensor is also a bit dodgy, but it works OK.

I have modified the Arduino libs which were provided as examples, calibrated the thermistors using some matrix methods for solving the Steinhart-Hart Equation (more on this later), and fixed a lot of errors (it was backwards before, getting brighter in the dark and less bright in strong light) in the sample code to control the display brightness, etc.

However, overall, this shield is fun to play with a a nice value for under $5. I'm happy to modify the sample lib code for this price!

Today, in this post I will share a quick Arduino sketch I used to set the RTC (lazy to reply on syncing with unix time on my computer) manually.

///////////////////////////////////////////
// DS1307 RTC date and time              //
//                                       //
// This sample program is for the user   //
// to manually set the date and time     //
// of an RTC  using the I2C bus.         //
//                                       //
// Original sketch by:                   //
// eGizmo Mechatronix Central            //
// Taft, Manila, Philippines             //
// April 15, 2013                        //
//                                       //
// Modified by Neo  (www.unix.com)       //
// January 2020                          //
///////////////////////////////////////////

#include <Wire.h>        // required for IC2 data bus comms
const int DS1307 = 0x68; // Address of the DS1307 RTC from the data sheet
const char *days[] =
    {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
const char *months[] =
    {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};

// declare and initializes values:
byte second = 0;
byte minute = 0;
byte hour = 0;
byte weekday = 0;
byte monthday = 0;
byte month = 0;
byte year = 0;
boolean flag1 = false;
void setup()
{
    Wire.begin();
    Serial.begin(9600);
    if (flag1 == false)
    {
        Serial.println("Please change to newline ending the settings on the lower right of the Serial Monitor");
        delay(2000);  // This delay helps when the MCU reada the current date and time.
        flag1 = true; // user message control, not critical
    }

    Serial.print("The current date and time is: ");
    printTime();
}

// Main loop
void loop()
{
    Serial.print("The current date and time is now: ");
    printTime();
    delay(1000);
    Serial.println("Would you like to set the date and time? (press 'y' to set)");

    while (!Serial.available())
        delay(10);
    if (Serial.read() == 'y')
    {
        Serial.read();
        setTime();
    }
}
byte decToBcd(byte val)
{
    return ((val / 10 * 16) + (val % 10));
}
byte bcdToDec(byte val)
{
    return ((val / 16 * 10) + (val % 16));
}

// This is the main dialog to set the date and time (manually)
// Currently, no error checking...
void setTime()
{
    Serial.print("Enter the current year, 00-99. - ");
    year = readByte();
    Serial.println(year);
    Serial.print("Enter the current month, 1-12. - ");
    month = readByte();
    Serial.println(months[month - 1]);
    Serial.print("Enter the current day of the month, 1-31. - ");
    monthday = readByte();
    Serial.println(monthday);
    Serial.println("Please enter the current day of the week, 1-7.");
    Serial.print("| 1 Sun | 2 Mon | 3 Tues | 4 Weds | 5 Thu | 6 Fri | 7 Sat | - ");
    weekday = readByte();
    Serial.println(days[weekday - 1]);
    Serial.print("Enter the current hour in 24hr format, 0-23. - ");
    hour = readByte();
    Serial.println(hour);
    Serial.print("Enter the current minute, 0-59. - ");
    minute = readByte();
    Serial.println(minute);
    Serial.print("Enter the current second, 0-59. - ");
    second = readByte();
    Serial.println(second);
    //second = 0;
    Serial.println("The date and time has been updated.");
    // The following codes transmits the data to the RTC
    Wire.beginTransmission(DS1307);
    Wire.write(byte(0));
    Wire.write(decToBcd(second));
    Wire.write(decToBcd(minute));
    Wire.write(decToBcd(hour));
    Wire.write(decToBcd(weekday));
    Wire.write(decToBcd(monthday));
    Wire.write(decToBcd(month));
    Wire.write(decToBcd(year));
    Wire.write(byte(0));
    Wire.endTransmission();
    Serial.print("The current date and time is now: ");
    printTime();
    // Ends transmission of data
}

byte readByte()
{
    while (!Serial.available())
        delay(10);
    byte reading = 0;
    byte incomingByte = Serial.read();
    while (incomingByte != '\n')
    {
        if (incomingByte >= '0' && incomingByte <= '9')
            reading = reading * 10 + (incomingByte - '0');
        else
            ;
        incomingByte = Serial.read();
    }
    Serial.flush();
    return reading;
}

void printTime()
{
    char buffer[3];
    char buffer2[3];
    const char *AMPM = 0;
    readTime();
    Serial.print(days[weekday - 1]);
    Serial.print(" ");
    Serial.print(months[month - 1]);
    Serial.print(" ");
    Serial.print(monthday);
    Serial.print(", 20");
    Serial.print(year);
    Serial.print(" ");
    if (hour > 12)
    {
        hour -= 12;
        AMPM = " PM";
    }
    else
        AMPM = " AM";
    Serial.print(hour);
    Serial.print(":");
    sprintf(buffer, "%02d", minute);
    Serial.print(buffer);
    Serial.print(":");
    sprintf(buffer2, "%02d", second);
    Serial.print(buffer2);
    Serial.println(AMPM);
}

void readTime()
{
    Wire.beginTransmission(DS1307);
    Wire.write(byte(0));
    Wire.endTransmission();
    Wire.requestFrom(DS1307, 7);
    second = bcdToDec(Wire.read());
    minute = bcdToDec(Wire.read());
    hour = bcdToDec(Wire.read());
    weekday = bcdToDec(Wire.read());
    monthday = bcdToDec(Wire.read());
    month = bcdToDec(Wire.read());
    year = bcdToDec(Wire.read());
}

I think in a future post, I will explain in detail how to calibrate the thermistor, including what data to record, how to convert the calibration data so it is be used in an online "matrix solver" for Steinhart-Hart. Plus, I have a fun story how I "froze" the X1 crystal oscillator in the freezer and overheated (and temporarily killed) the board using a hairdryer for "hot" calibration data, but I did manage to get some good data, both frozen and fried :slight_smile: .

Also my new Rigol DS1054Z 4-channel oscilloscope arrived from China yesterday, in perfect working order, fully loaded with "all options" as a gift; so the "tick-tock shield" has taken a back seat to the DS1054Z, which I have to say is just an amazing o-scope for the money. It's easy to see why this has been the top selling scope for many years running. I'm still getting to know this scope and have only start testing.....

More on this later.

Most of you don't know this, but when I was working as a network engineer in the DC area in the US, I also had a side business buying and selling surplus electronic test equipment, mostly HP and WaveTek. That was a long time ago. Back then I had an HP Cesium Atomic Clock in my living room, which I eventually sold. Actually, I used to have test equipment stacked up to the ceiling, so it's really fun to see the great gear on the market in 2020, light, good, quality and very affordable.

This is my last update / post on this Arduino Tick Tock shield for now. I was going to post the details on how to calibrate the thermistor; including taking various measurements, recording the resistance at various temperatures, setting up the Steinhart-Hart Equation and solving it with matrix math, but I'm going to put that off for now.

Basically, this shield is a nice learning tool, with the real-time clock, thermistor, light sensor, display, buttons and LEDs to play with; but the RTC, the light sensor and the thermistor are of such low quality, that it's not really useful for anything more than "a toy shield" for learning and playing around.

The Ardunio Tick-Tock DS1307 RTC Shield was "fun" but not sure I recommend it to anyone, even for under $5 USD.

But on-the-other-hand, I did get my $5 worth playing with it so, as always, YMMV.