⏲ How to connect the real time (RTC) clock to Arduino

In this article we will connect two modules with real-time timers (or real-time clock, RTC) - DS3231 and DS1307 - to the Arduino. Both modules work on the I2C interface and are powered by a 2032 format battery.
ds1307_arduino

In this article we will connect two modules with real-time timers (or real-time clock, RTC) – DS3231 and DS1307 – to the Arduino. Both modules work on the I2C interface and are powered by a 2032 format battery.
We will need:

  • Arduino UNO or another compatible card;
  • ZS-042 module with DS3231 real-time clock;
  • DS1307 real time clock module;
  • connecting wires (I recommend this set);
  • breadboard;

Connection to Arduino of the ZS-042 module with a real-time clock DS3231
The ZS-042 module with a real-time clock (RTC) has the following characteristics:

  • Calendar up to 2100 with counts of seconds, minutes, hours, date of the month, month, day of the week and year (taking into account leap years);
  • 12 or 24-hour format;
  • 2 alarm clocks;
  • supply voltage: 3.3 or 5 V;
  • Accuracy: ± 0.432 sec per day;
  • internal quartz oscillator with a frequency of 32768 Hz;
  • supported protocol: I2C with speed from 100 to 400 kHz;
  • dimensions: 38 × 22 × 15 mm;
  • operating temperature range –40 … + 85 ° C.

The module contains: DS3231 real-time timer chip (1 in the figure), AT24C32 memory chip of 32 kbps (2 in the figure), space for three jumpers A0, A1 and A2 (3 in the figure), with which you can change the memory addressing of the chip memory; space for a 2032 battery (4 in the figure).

The purpose of the module outputs is:

Name Description
32K generator output 32 kHz;
SQW square wave output; the frequency is set using the control register 0x0E and can be 1, 1024, 4096 or 8192 Hz;
SCL I2C interface clock bus;
SDA I2C interface data bus;
VCC power supply – 3.3 or 5 volts;
GND ground.

 

On the opposite side of the module, the SCL, SDA, power and ground pins are duplicated. The output from 32K is constantly present signal from the built-in crystal oscillator:

Now you need to connect the module to the Arduino. We already know that the SDA line needs to be connected to the A4 Arduino UNO and Nano pin, and the SCL line to the A5 pin. For a power supply, take the 5V output of the Arduino board, connect the module’s ground to the ground of the Arduino.

Consider the read and write diagrams for the DS3231 real-time timer:

As you can see, everything is standard for the I2C interface. It remains only to find out which registers are responsible for what, and we will be ready to begin data exchange with the DS3231 timer. And here is the register map:

The first thing you need to set the date and time. And then you only need to read the value of time and calendar. Advanced features – set alarms, etc. – all this is done in a similar way, so we will not dwell on this. So, to set the date and time, we are interested in registers 0x00 … 0x06. To record the values ​​in them, you need to send a write command, specify the starting address (0x00), and then – 7 bytes, formed for the desired date and time. For example, to record the date of January 02, 2019, Wednesday, and time 19:00 30 min, sec, you need to send the slave device with I2C address 0x68 array: 00 00 30 19 03 02 01 19. The sketch that implements it will be as follows:

#include 

void setup() {
  Wire.begin();
  Wire.beginTransmission(0x68);
  byte arr[] = {0x00, 0x00, 0x30, 0x19, 0x03, 0x02, 0x01, 0x19};
  Wire.write(arr, 8); 
  Wire.endTransmission(); 
}

void loop() {
}

Here is the diagram for writing this array to the memory of the DS3231 real-time timer:

The timer will remember the set date and time. If a battery is connected, the data will be stored in the device’s memory until it is reset or until the battery is completely discharged, because this is the purpose of such devices. Let’s now with a period of 1 second read the time value and output to the monitor of the serial port. To do this, we write this sketch:

#include 
const byte DS3231 = 0x68; 

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

void loop() {
  Wire.beginTransmission(DS3231);
  Wire.write(byte(0x00)); 
  Wire.endTransmission(); 

  byte t[7]; 
  int i = 0;
  Wire.beginTransmission(DS3231); 
  Wire.requestFrom(DS3231, 7); 
  while(Wire.available()) { 
    t[i] = Wire.read();  
    i++; 
  }
  Wire.endTransmission(); 
  
  printDateTime(t); 
  delay(1000); 
}

void printDateTime(byte *arr) {
  if (arr[4]<10) Serial.print("0"); 
  Serial.print(arr[4], HEX);
  Serial.print(".");
  if (arr[5]<10) Serial.print("0"); 
  Serial.print(arr[5], HEX); 
  Serial.print(".20");
  Serial.print(arr[6], HEX); 
  Serial.print(" ");
  if (arr[2]<10) Serial.print("0"); 
  Serial.print(arr[2], HEX); 
  Serial.print(":");
  if (arr[1]<10) Serial.print("0"); 
  Serial.print(arr[1], HEX);
  Serial.print(":");
  if (arr[0]<10) Serial.print("0"); 
  Serial.println(arr[0], HEX);  
}

This is how the result of this sketch looks like in the serial port monitor:

And here is the timing diagram generated by the work of this sketch:

Finally, let’s complicate our program a bit and read the temperature value as well:

#include 
const byte DS3231 = 0x68; 

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

void loop() {
  Wire.beginTransmission(DS3231); 
  Wire.write(byte(0x00)); 
  Wire.endTransmission(); 

  byte dateTime[7]; 
  int i = 0; 
  Wire.beginTransmission(DS3231);
  Wire.requestFrom(DS3231, 7);
  while(Wire.available()) 
  {
    dateTime[i] = Wire.read(); 
    i+=1; 
  }
  Wire.endTransmission(); 

  printDateTime(dateTime); 
 
  Wire.beginTransmission(DS3231); 
  Wire.write(byte(0x11)); 
  Wire.endTransmission(); 

  i = 0; 
  byte temp[2]; 
  Wire.beginTransmission(DS3231); 
  Wire.requestFrom(DS3231, 2);
  while(Wire.available()) 
  {
    temp[i] = Wire.read();
    i+=1;
  }
  Wire.endTransmission();

  printTemp(temp); 
    
  delay(1000); 
}

void printDateTime(byte *dateTime) {
  if (dateTime[4]<10) Serial.print("0"); 
  Serial.print(dateTime[4], HEX);
  Serial.print(".");
  if (dateTime[5]<10) Serial.print("0"); 
  Serial.print(dateTime[5], HEX); 
  Serial.print(".20");
  Serial.print(dateTime[6], HEX); 
  Serial.print(" ");
  if (dateTime[2]<10) Serial.print("0"); 
  Serial.print(dateTime[2], HEX); 
  Serial.print(":");
  if (dateTime[1]<10) Serial.print("0"); 
  Serial.print(dateTime[1], HEX); 
  Serial.print(":");
  if (dateTime[0]<10) Serial.print("0"); 
  Serial.print(dateTime[0], HEX); 
}

void printTemp(byte *temp) {
  Serial.print("t"); 
  float temperature = getTemp(temp);
  Serial.print(temperature);
  Serial.println("oC"); 
}

float getTemp(byte *temp){
  float temperature = temp[0]; 
  temperature += (temp[1]*0.25/100); 
  return temperature;
}

Here is the output of our program now:

Of course, the Internet is full of libraries for Arduino, which simplifies the work with the DS3231 real-time clock and the ZS-042 module in particular. They do all the routine work, and you will not need to deal with the registered card and carry out manipulations with the permutation of the bytes received to get a readable time value. At the end of the article is a link to download the archive, which contains several libraries for working with real-time clock DS3231 and DS1307.

Connection to the Arduino module with a real-time clock DS1307

The DS1307 timer, in contrast to the DS3231, is simpler in functionality: it has fewer registers, does not have a built-in temperature sensor and a built-in clock generator. It also does not have an alarm function. I2C bus operates only at a frequency of 100 kHz. The DS1307 real-time clock module might look like this:

Here, number 1 is the chip of the DS1307 timer itself, number 2 is the AT24C32 memory chip with a volume of 32 kbps, 3 is a crystal oscillator with a frequency of 32.768 kHz, 4 is the holder for a 2032 type battery.

There are two groups of contacts on the module: P1 and P2. The P2 group has standard pins for the I2C bus, plus an additional DS pin to which an external DS18B20 temperature sensor can be connected. Group P1 has more contacts:

Pin Description
SQ 30 kHz square wave output;
DS connection of an external temperature sensor DS18B20;
SCL I2C interface clock bus;
SDA I2C interface data bus;
VCC module power supply – 3.3 or 5 volts;
GND ground;
BAT power input from an external battery with a voltage in the range of 2.0 … 3.5 V.

 Connecting this module to the Arduino is carried out in exactly the same way as previously discussed: VCC module – 5V Arduino, GND – GND, SDA – A4, SCL – A5.

Now it’s time to get acquainted with the device of the DS1307 watch registers. Map registers shown in the figure:

 

 If you take a closer look, we will see that the registers 0x00 … 0x06 coincide exactly with the similar registers of the considered DS3231 timer, and the register 0x07 is responsible for the frequency of the generated rectangular signal. In addition, the I2C DS1307 address is also the same as the DS3231 module address. Therefore, it is logical to assume that the time setting sketch will work here. This is easy to verify if you load the sketch into the Arduino with the DS1307 module connected. Do not forget to update the installation array in accordance with the time that you will put on the clock. The example is analyzed in the previous section.

The time output sketch will also work with this module. After setting the time, load the sketch and check it. Everything is working!

 

 

Share on facebook
Facebook
Share on google
Google+
Share on twitter
Twitter
Share on linkedin
LinkedIn
Share on pinterest
Pinterest