# Getting Started with Arduino! – Chapter Seven

This is part of a series titled “Getting Started with Arduino!” – A tutorial on the Arduino microcontrollers. The first chapter is here, the complete index is here.

Welcome back fellow arduidans!

This week is going to focus around the concept of real time, and how we can work with time to our advantage. (Perhaps working with time to our disadvantage is an oxymoron…) Once we have the ability to use time in our sketches, a whole new world of ideas and projects become possible. From a simple alarm clock, to complex timing automation systems, it can all be done with our Arduino and some brainpower. There is no time to waste, so let’s go!

First of all, there are a few mathematical and variable-type concepts to grasp in order to be able to understand the sketch requirements. It is a bit dry, but I will try and minimise it.

The first of these is binary-coded decimal.

Can you recall from chapter four how binary numbers worked? If not, have a look then come back. Binary coded decimal (or BCD) numbers are similar, but different… each digit is stored in a nibble of data. Remember when working with the 74HC595 shift registers, we sent bytes of data – a nibble is half of a byte. For example:

Below is a short clip of BCD in action – counting from 0 to 9 using LEDs:

However, remember each digit is one nibble, so to express larger numbers, you need more bits. For example, 12 would be 0001 0010; 256 is 0010 0101 0110, etc. Note that two BCD digits make up a byte. For example, the number 56 in BCD is 0101 0110,  which is 2 x 4 bits = 1 byte.

Next, we will need to work with variables that are bytes. Like any other variable, they can be declared easily, for example:

byte seconds = B11111;

B11111 is 31 in base 10, (that is, 2^4+2^3+2^2+2^1+2^0     or    16+8+4+2+1)

However, you can equate an integer into a byte variable. Here is a small sketch demonstrating this. And the result:

If you printed off the results of the sketch in example 7.1, it would make a good cheat sheet for the Binary Quiz program in Chapter Five.

Anyhow, moving forward we now take a look at hexadecimal numbers. ‘Hex’ numbers are base-16, in that 16 digits/characters are used to represent numbers. Can you detect a pattern with the base-x numbers? Binary numbers are base-2, as they use 0 and 1; decimal numbers are base-10, as they use 0 to 9 – and hexadecimal numbers use 0 to 9 then A to F. Run the following sketch to see how they compare with binary and decimal.

Below is a screenshot of the result: the left column is binary, the centre decimal, and the right hexadecimal:

Unfortunately the IC we use for timing uses BCD, so we need to be able to convert to and from BCD to make sense of the timing data. So now we have an understanding of BCD, binary, base-10 decimal, bytes, hexadecimal and nibbles. What a mouthful that was!

Coffee break.

Before we head back to timing, let’s look at a new function: switch… case. Say you needed to examine a variable, and make a decision based on the value of that variable, but there were more than two possible options. You could always use multiple if…then…else if functions, but that can be hard on the eyes. That is where switch… case comes in. It is quite self-explanatory, look at this example:

```switch (zz) {
case 10:
//do something when variable zz equals 10
break;
case 20:
//do something when variable zz equals 20
break;
case 30:
// do something when variable equals 30
break;
default:
// if nothing else matches, do the default
// default is optional
}```

OK, we’re back. It would seem that this chapter is all numbers and what not, but we are scaffolding our learning to be able to work with an integrated circuit that deals with the time for us. There is one last thing to look at then we can get on with timing things. And that thing is…

The I2C bus.

(There are two ways one could explain this, the simple way, and the detailed way. As this is “Getting Started with Arduino”, I will use the simple method. If you would like more detailed technical information, please read this document: NXP I2C Bus.pdf, or read the detailed website by NXP here)

The I2C bus (also known as “two wire interface”) is the name of a type of interface between devices (integrated circuits) that allows them to communicate, control and share data with each other. (It was invented by Philips in the late 1970s. [Philips spun off their semiconductor division into NXP]).  This interchange of data occurs serially, using only  two wires (ergo two wire interface), one called SDA (serial data) and the other SCL (serial clock).

I2C bus – image from NXP documentation

A device can be a master, or a slave. In our situation, the Arduino is the master, and our time chip is the slave. Each chip on the bus has their own unique “address”, just like your home address, but in binary or in hexadecimal. You use the address in your sketch before communicating with the desired device on the I2C bus. There are many different types of devices that work with the I2C bus, from lighting controllers, analogue<> digital converters, LED drivers, the list is quite large. But the chip of interest to us, is the Maxim DS1307 Serial I2C real-time clock. Let’s have a look:

This amazing little chip, with only a few external components, can keep track of the time in 12-and 24-hour formats, day of week, calendar day, month and year, leap years, and the number of days in a month. Interestingly, it can also generate a square wave at 1Hz, 4kHz, 8kHz, or 32 kHz. For further technical information, here is the DS1307 data sheet.pdf. Note – the DS1307 does not work below 0 degrees Celsius/32 degrees Fahrenheit, if you need to go below freezing, use a DS1307N.

Using the DS1307 with our Arduino board is quite simple, either you can purchase a board with the chip and external circuitry ready to use, or make the circuit yourself. If you are going to do it yourself, here is the circuit diagram for you to follow:

The 3V battery is for backup purposes, a good example to use would be a CR2032 coin cell – however any 3V, long-life source should be fine. If you purchase a DS1307 board, check the battery voltage before using it…. my board kept forgetting the time, until I realised it shipped with a flat battery. The backup battery will not allow the chip to communicate when Vcc has dropped, it only allows the chip to keep time so it is accurate when the supply voltage is restored. Fair enough. The crystal is 32.768 kHz, and easily available. The capacitor is just a standard 0.1uF ceramic.

Now to the software, or working with the DS1307 in our sketches. To enable the I2C bus on Arduino there is the wire library which contains the functions required to communicate with devices connected to our I2C bus. The Arduino pins to use are analogue 4 (data) and analogue 5 (clock). If you are using a Mega, they are 20 (data) and 21 (clock). There are only three things that we need to accomplish: initially setting the time data to the chip; reading the time data back from the chip; and enabling that 1Hz square-wave function (very useful – if you were making an LED clock, you could have a nice blinking LED).

First of all, we need to know the I2C address for our DS1307. It is 0x68 in hexadecimal. Addresses are unique to the device type, not each individual device of the same type.

Next, the DS1307 accepts or returns the timing data in a specific order…

• seconds (always set seconds to zero, otherwise the oscillator in the DS1307 will stay off)
• minutes
• hours
• day of week (You can set this number to any value between 1 and 7, e.g. 1 is Sunday, then 2 is Monday…)
• day of month
• month
• year
• control register (optional – used to control the square-wave function frequency and logic level)

… but it only accepts and returns this data in BCD. So – we’re going to need some functions to convert decimal numbers to BCD and vice-versa (unless you want to make a BCD clock …)

However, once again in the interests of trying to keep this simple, I will present you with a boilerplate sketch, with which you can copy and paste the code into your own creations. Please examine this file. Note that this sketch also activates the 1Hz square wave, available on pin 7. Below is a quick video of this square wave on my little oscilloscope:

This week we will look at only using 24-hour time; in the near future we will examine how to use 12-hour (AM/PM) time with the DS1307. Here is a screen capture of the serial output box:

Now that you have the ability to send this time data to the serial output box, you can send it to other devices. For example, let’s make a simple LCD clock. It is very easy to modify our example 7.3 sketch, the only thing to take into account is the available space on the LCD module. To save time I am using the Electronic Brick kit to assemble this example. Below is a short clip of our LCD clock operating:

and here is the sketch. After seeing that clock fire up and work correctly, I felt really great – I hope you did too.

Now let’s head back in time, to when digital clocks were all the rage…

Exercise 7.1

Using our Arduino, DS1307 clock chip, and the exact hardware from exercise 6.2 (except for the variable resistor, no need for that) – make a nice simple digital clock. It will only need to show the hours and minutes, unless you wish to add more display hardware. Have fun!

Here is my result, in video form:

and the sketch. Just an interesting note – after you upload your sketch to set the time; comment out the line to set the time, then upload the sketch a second time. Otherwise every time your clock loses power and reboots, it will start from the time defined in the sketch!

As mentioned earlier, the DS1307 has a square-wave output that we can use for various applications. This can be used from pin 7. To control the SQW is very easy – we just set the pointer to the SQW register then a value for the frequency. This is explained in the following sketch:

```/*
DS1307 Square-wave machine
Used to demonstrate the four different square-wave outputs from Maxim DS1307
John Boxall - tronixstuff.com
*/

#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68 // each I2C object has a unique bus address, the DS1307 is 0x68

void setup()
{
Wire.begin();
}

void sqw1() // set to 1Hz
{
Wire.write(0x07); // move pointer to SQW address
Wire.write(0x10); // sends 0x10 (hex) 00010000 (binary)
Wire.endTransmission();
}

void sqw2() // set to 4.096 kHz
{
Wire.write(0x07); // move pointer to SQW address
Wire.write(0x11); // sends 0x11 (hex) 00010001 (binary)
Wire.endTransmission();
}

void sqw3() // set to 8.192 kHz
{
Wire.write(0x07); // move pointer to SQW address
Wire.write(0x12); // sends 0x12 (hex) 00010010 (binary)
Wire.endTransmission();
}

void sqw4() // set to 32.768 kHz (the crystal frequency)
{
Wire.write(0x07); // move pointer to SQW address
Wire.write(0x13); // sends 0x13 (hex) 00010011 (binary)
Wire.endTransmission();
}

void sqwOff()
// turns the SQW off
{
Wire.write(0x07); // move pointer to SQW address
Wire.write(0x00); // turns the SQW pin off
Wire.endTransmission();
}

void loop()
{
sqw1();
delay(5000);
sqw2();
delay(5000);
sqw3();
delay(5000);
sqw4();
delay(5000);
sqwOff();
delay(5000);
}```

And here it is in action – we have connected a very old frequency counter to pin 7 of the DS1307:

And there we have it – another useful chapter. Now to move on to Chapter Eight.

Have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

## 35 thoughts on “Getting Started with Arduino! – Chapter Seven”

1. James Chambers

Something went wrong with your hexadecimal example. F equals 15, A equals 10 etc.

1. John Boxall

Hello James
Thank you very much for pointing this out to me. I have updated the sketch and replaced the screen shot. I really appreciate you taking the time to point this out.
Cheers
John

2. Conner Thomas

I have the same arduino kit that the video of the LCD show….do you have any idea of the pinout of the LCD? I haven’t been able to figure it out….I use the LCD4bit library, modified to match the pins hooked out to the arduino.

Thanks,
Conner

1. John Boxall

Hello Miroslav
That is an error I have made, thank you for pointing it out to me – will fix it now. If you are making the project yourself, please change the liquidcrystal statement to suit your own hardware. For more information please see chapter two.
cheers
john

3. Mr Guy

I’m a new in Arduino word. I have a compilation errors when i try to compile example 7.4: t1 is not declared, invalid types……
Somebody can help me?

4. Kalin79

Hi

I made DS1307 clock, as it is on the diagram.
And everything works ok, but after about 2 hours, the clock stops.
I thought that something is wrong with the crystal. But after the change, everything is just a clock works, and after 2 hours stops.

5. ed

Somehow this circuit got the better of me. The clock does not seem to work: The time will not update and strangely enough, the pull up resistors mess with the serial output: Connect both and I have no serial output, connect 1 and I get serial output but all on 1 line, connect none and I get a nicely formatted output.

It is not a complicated circuit. Checked and rechecked. The battery is present and gives 3.5 V.
What can I possibly have done wrong?

6. ed

Hmm, I might have found the source of my problems. Seems that instead of a 32.768 Crystal, my supplier gave me a 3.2768 Crystal. Before I try anything else, maybe I better try that one first. Dont know if it causes my problems, but I got to start somewhere 🙂

7. ed

Fortunately I had a 32.768 on an old motherboard. Put that in. Works like a charm. Thanks for the great tutorial

8. ed

Apparently I still have a problem: When I power off and later power on again, the chip will have remembered the last time that the power was on, but did not update the time since. I have a 3V battery inserted and I measure 3 volts over pin 3 and 4 of the DS1307.

Am I overlooking something?

9. ed

Like usual, I find the solution myself, even thugh this time I do not understand the solution:
Rather than to only comment out the “setDateDS” function, commenting out the entire “second=….year=xx;” section. That did it for me.

Sorry to have bothered you again :-). As I’ll be going through yr entire set of (really great) tutorials, I hope I won’t bother you too much 🙂

Happy Newyear

10. ed

Just a small remark on the RTC sketch. (excercise 7p1.pde).
It contains a line: “Wire.send(0x10); // sends 0x10 (hex) 00010000 (binary) to control register – turns on square wave”

Judging from the value sent, it should indeed turn on the SQW, however, in my setup it did not. Only when I added lines from the SQW sketch above:
Wire.send(0x07); // move pointer to SQW address
Wire.send(0x10); // sends 0x10 (hex) 00010000 (binary)
Wire.endTransmission();
it immediately worked, eventhough the same value 0x10 is used. (added them in void setup)
Could it be that in the original line somehow the wrong address is specified?

Anyway, it works. Maybe others are helped by this

1. John Boxall

In the sketch we don’t need to specify the address as it just follows the previous data sent to the DS1307.
However yes you’re method is correct if not sending all the time/date/sqw data at once, as we have demonstrated in the final sketch of the article.
cheers
john

11. anas_ali

hi guys
sketch is not working . there is an error while compiling

:sketch_jan07j.cpp: In function ‘void setDateDs1307(byte, byte, byte, byte, byte, byte, byte)’:
sketch_jan07j:52: error: ‘class TwoWire’ has no member named ‘send’

As of Arduino 1.0, the Wire.send() function was renamed to Wire.write() for consistency with other libraries.

any one kindly help

12. zweeriused

🙂 This simple RTC is giving me more problems than I expected. It suddenly won’t keep time anymore.
Battery: check!
When I upload the Sketch with the proper time it seems to do fine, but when I do not immediately start the serial monitor, but wait say, 2 minutes, it starts at the time that was set in the program, so the RTC did not update itself.

In fact, if I then again start the monitor, it just starts at the time set in the program again. If I upload the sketch again with also commenting out the entire “second=….year=xx;” section, as I have done above, the time and date are just zero.
A Led on SQW just flashes every second as it is supposed to do, so the DS1307 does something. It just doesn’t do what it needs to do.

It has worked perfectly before
I do admitt that once by accident I connected ground to the SDA pin instead of to the ground (old eyes, small pins), but I am not sure if my problems immediately started thererafter, It still seemed to work then, but I did not really check it then

Any pointers, other than to buy a ned DS1307 (quite cheap so no big disaster)?

1. ed

It worked before, so that seems the best solution. I guess I partly killed it. It is still updating time and generating the SQW pulse but it is not keeping time. Thanks

13. ed

Yep, a new chip was the answer. Should have gotten some new glasses as well, so I won’t wire it up wrong anymore. OK, on to the next tutorial and tnx for yr support 🙂

14. EschatologicalEngineer

Greetings, Thank you for this tutorial. I purchased the ds1337 originally, because i liked its name (1337, leet ) but decided to work w/ the 1307 first since there is more documentation for it used as a slave to the arduino.

I am utilizing the RTClib example ds1307.pde . The serial monitor explains that the “RTC is NOT running” followed by an unchanging date/time reading.

When I got frustrated fidgeting with my fickle oscilloscope, trying to read the SQUARE wave output, I decided to hook it up to the logic analyzer.

I even just created a flicr account so I can share the screen shot to anyone interested who may have similar issues or may be able to help.

Here is a wide view:

and a closer:

if required, I will take a new sample with different parameters/settings. if so, please advice.

I will continue to work on the problem and if I solve it, I will share but if anyone has a clue or advice, please don’t be afraid to go ahead and chime in.

Thank you & best wishes,
-EschatologicalEngineer-

1. EschatologicalEngineer

I think I posted two diff. links to the same screen shot. hopefully got this straightened out and the second screen shot is here:

Its just a lil closer view so you can closer read the No ack! descriptive text. I absolutely love this hardware/analyzer software..

15. jason

What is the purpose of the .1uf capacitor? Other diagrams do not use this.. and it doesn’t show a capacitor being used in the DS1307 datasheet

16. Mefaso

Hi, I’m really digging your tutorial so far, but sadly I can not obtain the Maxim DS1307, if i use an arduino module with a I2C DS1307 will the address be the same?