Connecting the ds1302 real time clock to Arduino. Clock on Arduino without using an RTC module

Real time clock - a module that stores current date and does not reset it when the power is turned off thanks to the built-in battery. You may have heard about a watch based on the DS1307 chip. This chip has extremely low clock accuracy. A delay of one hour per day is too much. I recommend using a module based on a high-precision DS3231 chip, which is equipped with a thermometer to adjust the clock rate depending on the temperature. The clock accuracy of this chip is at a good level wristwatch and is 2ppm at temperature environment 0°-40°. At the same time, the module is compatible with all libraries written for the module based on the DS1307 chip. The article talks about connecting the module to Arduino and interacting with them using the Time library. You can buy such a module from a seller I have verified.

Real time clock connection

The clock is connected using the I2C protocol with just two wires. It is necessary to additionally tighten the terminals to which the clock is connected to the power rail using 2 KΩ resistors. The clock outputs look like this:

The 32K and SQW pins can be ignored. Their purpose is not discussed in this article. SCL and SDA are the I2C interface pins. They need to be connected to the controller. VCC and GND are +5V and ground respectively.

SCL and SDA on different boards located on different pins:

Uno, Nano A4 (SDA), A5 (SCL)
Mega2560 20 (SDA), 21 (SCL)
Leonardo 2 (SDA), 3 (SCL)

The SDA pin of the clock is connected to the SDA pin of the controller. SDL clock, respectively, to SDL controller. After connecting the wires, you should get the following picture:

The most convenient way to work with the real-time clock module is using the library. The most convenient one in this regard is called: Time ( English time).
The library is a “wrapper” for another popular library for working with the clock module: DS1307RTC. Despite the fact that the library was developed for the DS1307 chip, it works perfectly with the DS3231, since the communication protocols are compatible.

Download both libraries.

After downloading, place the contents of the archives in the libraries folder, which is located in the environment folder Arduino development. Run Arduino environment IDE and open standard example libraries: Examples->Time->TimeRTC
Or just copy this code:

#include #include #include void setup() ( Serial.begin(9600); while (!Serial) ; // wait until Arduino Serial Monitor opens setSyncProvider(RTC.get); // the function to get the time from the RTC if(timeStatus()! = timeSet) Serial.println("Unable to sync with the RTC"); else Serial.println("RTC has set the system time"); void loop() ( if (timeStatus() == timeSet) ( digitalClockDisplay( ); ) else ( Serial.println("The time has not been set. Please run the Time"); Serial.println("TimeRTCSet example, or DS1307RTC SetTime example."); Serial.println(); delay(4000) ; ) delay(1000); ) void digitalClockDisplay())( // digital clock display of the time Serial.print(hour()); printDigits(minute()); printDigits(second()); Serial.print(" " ); Serial.print(day()); Serial.print(month()); ; ) void printDigits(int digits)( // utility function for digital clock display: prints preceding colon and leading 0 Serial.print(":"); if(digits< 10) Serial.print("0"); Serial.print(digits); }

#include

#include

#include

void setup() (

Serial. begin(9600);

while (! Serial ) ; // wait until Arduino Serial Monitor opens

setSyncProvider(RTC.get); // the function to get the time from the RTC

if (timeStatus() != timeSet)

Serial. println("Unable to sync with the RTC");

else

Serial. println("RTC has set the system time");

void loop()

if (timeStatus() == timeSet) (

digitalClockDisplay();

) else (

Serial. println( "The time has not been set. Please run the Time") ;

Serial. println( "TimeRTCSet example, or DS1307RTC SetTime example.") ;

Serial. println();

delay(4000);

delay(1000);

void digitalClockDisplay() (

// digital clock display of the time

Serial. print(hour());

printDigits(minute());

printDigits(second());

Serial. print (" " ) ;

Serial. print(day());

Serial. print (" " ) ;

Serial. print(month());

Serial. print (" " ) ;

Serial. print(year());

Serial. println();

void printDigits(int digits) (

// utility function for digital clock display: prints preceding colon and leading 0

Serial. print(":");

if (digits< 10 )

Serial. print("0");

Serial. print(digits);

After loading the sketch into the board, launch the port monitor (Tools->port monitor). You will see messages from the library. The displayed time will be incorrect, or the library will complain that the clock is not configured. To set the clock, load an example from the DS1307RTC “SetTime” library into the board (Examples->DS1307RTC->SetTime). Load this example into your board. After downloading, the watch will be set to sketch compilation time. Delay between compilation and fully loaded will be quite a bit, which will be enough for a finely tuned watch. But if you disconnect and reconnect the board's power, even after several hours, the clock time will still be reset to the time of compilation and will be incorrect. Therefore, use this example only for setup, after setup, turn off the clock or upload another sketch to the board.

I needed to make something bigger somehow. Wall Clock with automatic brightness.

This watch is perfect for large premises, for example, an office hall or a large apartment.

Making such a large wall clock is not very difficult using these instructions.


To estimate the size of the watch, you can assume that one segment of the watch will be the size of A4 paper, which will make it easy to use photo frames of the appropriate size.

Step 1. Components of a large wall clock.

Wires, solder, soldering iron, LED strip Arduino Nano DC-DC converter LM2596
4 meters of LED strip WS2811 light sensor real time clock DS3231
microswitches

What I used for this project:

Step 8. Program the clock.

After some fiddling around, I managed to get a watch that completely satisfied my needs. I'm sure you can do better than me.

The code is well commented and it will not be difficult for you to understand it; the debugging messages are also very well commented.

If you need to change the wall clock color used, you need to change the variable on line 22 ( int ledColor = 0x0000FF; // Color used (in hex)). You can find a list of colors and their hex codes on the page: https://github.com/FastLED/FastLED/wiki/Pixel-refe…

If you have problems downloading, use the mirror: http://bit.ly/1Qjtgg0

My final sketch can be downloaded.

Step 9. Make numbers using polystyrene.

Cutter base Working body of the cutter General form cutter
Result of the cutter

Cut each segment into the template printed at the beginning.
Polystyrene can be cut with a sharp knife, which is quite difficult, or with a simple device made from nichrome wire or guitar string and several pieces of OSB board.

You can see how I did it in the images above.

In order to power the cutter I used a 12v power supply.

As a result of cutting, you should get four segments for big clock, one of which is shown in the photo.

Step 10. Glue the numbers and cover everything with a diffuser. The final large wall clock.

Glow during the day Glow at night

After cutting out all four numbers and points of the wall clock, glue them all onto the cardboard along with LED strips(I used double sided tape to make the process easier)

To dispel the hard led light I used two sheets of paper on top of the polystyrene numbers. For convenience and aesthetics, I used A2 size paper folded in half.

After completing all these steps, I placed the resulting large wall clock assembly into a matching large photo frame.

This watch turned out to be very impressive and eye-catching. I think that such a large wall clock will perfectly decorate many rooms.

In contact with

One of the first projects that beginners build using an Arduino board is simple clock, counting down time. Basically, such clocks are based on an RTC (Real Time Clock) module connected to Arduino. On the market today electronic components available different models RTCs that vary in accuracy and price. Common models include DS1302, DS1307, DS3231.



But you can make a clock on Arduino without using an RTC, especially if you can’t get such modules. Of course, the accuracy is in this case will be small, so the project should rather be considered as a training project.


The operating principle of such watches is quite simple. Every time you turn on this Arduino clock, you will need to set it to the current time, just like any analog clock. It is certainly better not to use such watches in your Everyday life if they are active for a long time without rebooting and further configuration, since desynchronization with current time during long-term operation can be significant.


This watch can be assembled using a regular breadboard, since it doesn't require many components. Our main link here will be the fee Arduino Uno. To display the time, you can take a 16x2 LCD display. To change the time settings, you need to connect two buttons (for hours and minutes). The buttons are connected to Aduino via 10KΩ resistors. To change the brightness of the display you will need a 10 kOhm potentiometer. Connection diagram of all these components to Arduino board Uno is shown below.



Now you need to program the Arduino. A simple code (sketch) that allows you to display the time on the LCD screen is given below.


#include LiquidCrystal lcd(12,11,5,4,3,2); int h=12; int m; int s; int flag; int TIME; const int hs=8; const int ms=9; int state1; int state2; void setup() ( lcd.begin(16,2); ) void loop() ( lcd.setCursor(0,0); s=s+1; lcd.print("TIME:"); lcd.print(h ); lcd.print(":"); lcd.print(":");<12)lcd.print("AM"); if(flag==12)lcd.print("PM"); if(flag>12)lcd.print("PM"); if(flag==24)flag=0; delay(1000); lcd.clear(); if(s==60)( s=0; m=m+1; ) if(m==60) ( m=0; h=h+1; flag=flag+1; ) if(h==13 ) ( h=1; ) lcd.setCursor(0,1); lcd.print("HAVE A NICE DAY"); //-------Time // setting-------// state1=digitalRead(hs); if(state1==1) ( h=h+1; flag=flag+1; if(flag<12)lcd.print("AM"); if(flag==12)lcd.print("PM"); if(flag>12)lcd.print("PM");

if(flag==24)flag=0; if(h==13)h=1; ) state2=digitalRead(ms); if(state2==1)( s=0; m=m+1; ) )   Thank you for your interest in
information project website.   If you want interesting and
useful materials

came out more often and there was less advertising,    You can support our project by donating any amount for its development. This article discusses an example of creating a real time clock. The indicator will display the exact time, and the colon on it will blink once per second.

Exact time

will be automatically installed during firmware compilation.

Description of components

    Real time clock

    We use the real-time clock module from Seeed Studio. They are based on the DS1307 chip from Maxim Integrated. Of the strapping elements, it requires three resistors, a clock quartz and a battery, which are already available on this module. The module has the following properties:

Counting time (seconds, minutes, hours), date (year, month, day), day of week Two-wire I²C interface The essence of a real-time clock is that if there is a battery, it can run even if the main device is de-energized. We constantly encounter such clocks in laptops or

digital cameras

. If you remove the battery from these devices and put them back after a while, the time will not reset. This is thanks to the real time clock, Real Time Clock (RTC).

All necessary libraries can be downloaded from the official website.

    Indicator

    We use a four-digit indicator from Seeed Studio. The main thing in the indicator is the TM1637 chip, which is a driver for individual 7-segment bits. This module uses 4 bits. The module has the following properties:

We use this module to display time: hours and minutes. The convenience of the module is that it is connected via only two wires and does not require software implementation dynamic display, since everything is already implemented inside the module.

Dynamic indication is a process in which the indicators in our module light up sequentially. But we don’t see flickering, since the human eye has great inertia. This method allows you to very well save the number of connections between the indicators and the controller:

    Static display: 4 digits × 7 segments = 28 connections.

    Dynamic indication: 7 segments + 4 common anodes or cathodes = 11 connections.

    Chip TM1637: 2 connections.

The benefit is obvious.

Connection

The real time clock module must be connected to the SCL/SDA pins related to the I²C bus. It is also necessary to connect the power (Vcc) and ground (GND) lines.

The SDA/SCL lines have their own separate pins on the Arduino, but internally they are somehow connected to the pins general purpose. If we look at the Arduino Uno, the SDA line corresponds to pin A4, and the SCL line corresponds to A5.

The module comes with a cable with female contacts, which are more convenient to connect to Troyka Shield. However, separate SDA and SCL pins are not displayed on it, so we connected directly through pins A5 and A4.

In terms of connecting the indicator, everything is much simpler. The CLK and DIO pins can be connected to any digital pins. In this case, the 12th and 11th pins are used, respectively.

Writing firmware

The setup function should initialize the real-time clock and indicator, and record the compilation time in internal memory real time clock. The entire action, or rather, reading the time from the RTC and displaying it on the indicator, will be performed in the loop function.

The code for this looks like this:

rtc.ino #include #include //Classes TM1637 and DS1307 are declared in them clock ; void setup() ( clock .begin () ; clock clock .setTime () ; ) void loop() ( int8_t timeDisp[ 4 ] ;//Request the time from the clock ] = clock .minute % 10 ; display.point (clock .second % 2 ? POINT_ON : POINT_OFF) ;

)

getInt function explained

First, you need to understand where the time comes from in the compileTime array. It appears in this line:

unsigned char compileTime = __TIME__;

The compiler replaces __TIME__ with a string containing the compilation time in the form __TIME__ = "hh:mm:ss" , where hh is hours, mm is minutes, ss is seconds.

Let's return to the code that needs to be explained:

char getInt(const char * string, int startIndex) ( return int (string[ startIndex] - "0" ) * 10 + int (string[ startIndex+ 1 ] ) - "0" ; )

In the string array passed as a parameter to the getInt function, we get the character at index startIndex and the one following it to end up with a two-digit integer. However, initially this is not a number, but a pair characters. To get a number from a symbol, we need to subtract the zero symbol (“0”) from this symbol: after all, in ASCII table all digit symbols come one after another, starting with the zero symbol. Therefore, the code int(string) - "0"), literally, does the following: “Take the character number startIndex , subtract the zero character from it and convert it to an integer type.”

Problems

Yes, this code is working, and the clock will run. However, if you turn off the power and turn it on a few minutes later, then after turning it on, the time will again become the same as it was during compilation.

This happens because after turning on the power, the code found in the setup function is executed again. And he writes the old time value to the real time clock.

To avoid this, we need to modify the code a little more. Each time in the setup function, a “hash” of the compilation time will be calculated - the number of seconds that have passed from 00:00:00 to the compilation time will be calculated. And this hash will be compared with the hash in the EEPROM. Let us remind you that EEPROM is a memory that is not reset when the power is turned off.

If the values ​​of the calculated and previously saved hash coincide, this means that there is no need to rewrite the time in the clock module: this has already been done. But if this check does not pass, then the time is overwritten in the RTC.

To write/read a number of the unsigned int type to/from EEPROM, two additional functions EEPROMWriteInt and EEPROMReadInt . They are added because the EEPROM.read and EEPROM.write functions can only read and write char data.

rtc-eeprom.ino #include #include #include "TM1637.h" #include "DS1307.h" //Array containing compile time char compileTime = __TIME__; //Numbers of Arduino pins to which the indicator is connected#define DISPLAY_CLK_PIN 12 #define DISPLAY_DIO_PIN 13 //To work with the clock chip and indicator we use libraries TM1637 display(DISPLAY_CLK_PIN, DISPLAY_DIO_PIN) ; DS1307 clock ; void setup() ( //Enable and configure the indicator display.set(); display.init();//Start the real time clock clock.begin(); //Get a number from a string, knowing the number of the first character byte hour = getInt(compileTime, 0 ) ; byte minute = getInt(compileTime, 3 ) ; byte second = getInt(compileTime, 6 ) ; //Improvised time hash//Contains the number of seconds since the beginning of the day unsigned int hash = hour * 60 * 60 + minute * 60 + second;//Check if the new hash does not match the hash in the EEPROM if (EEPROMReadInt(0 ) != hash) ( //Save the new hash EEPROMWriteInt(0 , hash) ; //Prepare hours, minutes, seconds for recording in RTC clock .fillByHMS (hour, minute, second) ; void setup() ( clock .begin () ; clock clock .setTime () ; ) void loop() ( int8_t timeDisp[ 4 ] ;//Write this data to the internal memory of the watch. //From this moment they begin to count the time we need clock.setTime(); ) ) void loop() ( //Values ​​to display on each of the 4 digits int8_t timeDisp[ 4 ] ; ] = clock .minute % 10 ;//... and then display it on the screen display.display(timeDisp);//we don't have separate digits for seconds, so<< 8 ) | lowByte; }

//we will turn the colon on and off every second

display.point (clock .second % 2 ? POINT_ON : POINT_OFF) ;

It all started with the fact that by chance I turned out to be the owner of a BTHQ 22005VSS text LCD screen (2 lines of 20 characters each) and a DS1302 electronic clock board. To tell the truth, I am taking my first steps in Arduino Engineering, so the affordable price and the possibility of fast delivery played a decisive role in purchasing these parts. After all, there is often no time to wait for the “device” to arrive from the Middle Kingdom, having traveled almost “half the world,” and you simply don’t want to.

Why watches? At a time when there are a lot of different watches on sale around, the price of the simplest ones is comparable to a juice box. But the thing is that it is often necessary not only to know the exact time (and date, which is also sometimes necessary), but also to operate with this time. For example, keep logs of temperature changes (humidity, pressure, light, etc.) indicating the exact time when these changes occurred. This is where ARDUINO, equipped with a clock, will provide a wonderful service. And besides, it’s nice when the device also shows the time. After all, even when working on a personal computer, we occasionally glance at the lower right corner, what if it’s already time for lunch, or the end of the working day has come, or maybe it’s already dawn?

The heart of this project was ARDUINO UNO, which is quite easy to purchase - this, of course, if you want to buy something of high quality and quickly. You can, of course, find it cheaper, but again you have to wait, and I didn’t want to wait. The Arduinka cheerfully blinked its LED, did everything that was required of it, giving simple messages through the serial port, and in general made me happy. But let's get back to the clock. The problems began, as always, unexpectedly. It was not possible to find sensible articles and everything else either on the screen or during the “meeting” hours. On other screens - there is, on other watches - as much as you like, but on what is in your hands - almost nothing. But when there is nothing, “almost” is also a lot.

Let's start with the screen. The BTHQ 22005VSS turned out to be a banal 20x2 LCD screen (i.e. it has 2 lines of 20 characters each); instead, it is quite possible to use, for example, a screen - although it has “only” 16 characters in each line, but for most projects this is more, than enough. This screen has a 16-pin connector, although not a single-row, but a double-row (2x8), if you hold the device with the screen facing away from you and the connector on the right, then the first pin will be lower left, the second lower right, the third above the first, the fourth above the second, etc. .d. The top left (15) will be the anode, the top right (16) will be the cathode. If you have knowledge of English and curiosity, you can read the technical description. If there is very little of the first, and curiosity is much weaker than the desire to experiment, this is how I connected it:

Screen Contact Arduino contact Note
1 GND This is "minus" or "ground".
2 +5V
3 GND If you need bright signs.
4 4
5 GND If only to “write”.
6 5
7 -- Didn't use
8 -- Didn't use
9 -- Didn't use
10 -- Didn't use
11 10
12 11
13 12
14 13
A(15) +5V I connected through a 500 Ohm resistor
K(16) GND

In some sources, the “pinout” on the Arduino side is different, but it was more convenient for me this way. Connecting the watch also did not cause any problems:

Watch DS1302 Arduino Note
VCC +5V
GND GND Here I connected it through a 10 kOhm resistor.
CLK 0 Not to be confused with GND!!! The pin is also called SCLK
DAT 1 Contact is also called IO
RST 3 Contact is also called CE

You can connect it with wires or a cable; I personally assembled it on a breadboard.

The problems started when the demosketch was loaded and the watch started working. True, they showed the year 2165, month 45, week 85... Probably this is according to the “Uranian” or “Neptune” calendar... But I’m not going to live on Earth, and I’m not going to Uranus and Neptune yet. In general, something needs to be done. Soldering a 10kOhm resistor into the GND->GND circuit did not help. The problem turned out to be an incorrect library. I’ll say right away that the correct library can be taken. This is for the watch. The little screen successfully uses the library from standard set, which is called LiquidCrystal.h.

Problem #2. Each time the clock starts, it starts counting from the time that is “stitched” in the program. There is a complex solution to this problem. Create a hash, write it to the clock memory, then, when starting, read it from there, compare it... In general, for a beginner in Arduino engineering, it’s a bit complicated. As it turns out, there is a simple solution. or rather very simple. Namely, flash it 2 times. The first time - flash it with setting the date and time, the second time flash it, having previously “commented out” (putting a // sign at the very beginning of the line) the lines with setting this very date.

Actually the sketch:

// DS1302_LCD (C)2010 Henning Karlsen
// web: http://www.henningkarlsen.com/electronics
// A quick demo of how to use my DS1302-library to make a quick
// clock using a DS1302 and a 20x2 LCD.
// Correspondence between the clock pins and the Arduino pinpm screen.
// DS1302: CE pin -> Arduino Digital 3
// I/O pin -> Arduino Digital 1
// SCLK pin -> Arduino Digital 0
// LCD: DB7 -> Arduino Digital 13
// DB6 -> Arduino Digital 12
// DB5 -> Arduino Digital 11
// DB4 -> Arduino Digital 10
// E -> Arduino Digital 5
// RS -> Arduino Digital 4

#include // Connecting the screen library.
#include // Connecting the clock library.

// Initialize clock pins
DS1302 rtc(3, 1, 0);
// Initialize screen pins
LiquidCrystal lcd(4, 5, 10, 11, 12, 13);

void setup()
{
// Start the clock
rtc.halt(false);
rtc.writeProtect(false);

// Launch a screen indicating the number of characters and lines
lcd.begin(20, 2);

// The three bottom lines are uncommented for the first time; we indicate the current date and time in them. The second time - let's comment out.
//rtc.setDOW(THURSDAY); // Day of the week, if it’s Friday, then don’t write FRIDAY in Russian!
//rtc.setTime(11, 41, 0); // Hours, minutes, seconds in 24-hour format.
//rtc.setDate(13, 6, 2013); // Date of. IN NUMBERS!!! You don't have to put a zero in front of a single digit!
}

void loop()
{
// Display time centered on the upper line
lcd.setCursor(6, 0); // Set the cursor to print the time in the top line
lcd.print(rtc.getTimeStr()); // Print the time

// Display abbreviated Day-of-Week in the lower left corner
lcd.setCursor(0, 1); // Set the cursor at the bottom left to print the day of the week
lcd.print(rtc.getDOWStr(FORMAT_LONG)); // Print the day of the week in full, since the screen allows it.

// Display date in the lower right corner
lcd.setCursor(9, 1); // Set the cursor to print the date
lcd.print(rtc.getDateStr()); // Print the date

// Wait one second before repeating
delay(1000); // Pause 1 second and start again!
}