arduino real time clock ds3231 with lcd display free sample

In this Arduino Tutorial we will learn how to use the DS3231 Real Time Clock Module. You can watch the following video or read the written tutorial below.

The first question that comes here is why we actually need a separate RTC for our Arduino Project when the Arduino itself has built-in timekeeper. Well the point is that the RTC module runs on a battery and can keep track of the time even if we reprogram the microcontroller or disconnect the main power.

The DS3231 is a low-cost, highly accurate Real Time Clock which can maintain hours, minutes and seconds, as well as, day, month and year information. Also, it has automatic compensation for leap-years and for months with fewer than 31 days.

Once we connect the module we need to program the Arduino Board to work with the Real Time Clock. However, when it comes to programing a communication between Arduino and an I2C module the code isn’t that small and easy. Luckily, there are already several libraries for the DS3231 RTC which can be found on the internet.

So once we download and install the library we can use its first demo example to initially activate the clock of the RTC module. In the setup section of the demo example code we can notice that there are three line that we need to uncomment in order to initially set the day of the week, the time and the data.

The first line is for setting the day of the week, the second line is for setting the time in hours, minutes and seconds, and the third line is for setting the date in days, months and years.

Now even if we disconnect the Arduino power and then reconnect it and run the Serial Monitor again we can notice that the time keeps going without being reset.

So now we have our Real Time Clock up and running and we can use in any Arduino Project. As a second example I connected an LCD to the Arduino and printed the time and the date on it.

arduino real time clock ds3231 with lcd display free sample

In this tutorial, we will discuss the purpose of getting the current date and time on the Arduino, what is a Real-Time Clock, what is a DS3231 RTC module and we will build a project using a DS3231 RTC module, a 16×2 I2C LCD and an Arduino Uno.

Keeping track of the current date/time for an Arduino has many purposes. One use for it is for recording/log purposes. For example, an Arduino Weather Station needs timestamps in recording weather data. Another example is for an Arduino digital clock or calendar. Arduino-based clocks use the current time as a timer for reminders or to execute a scheduled command via the Arduino’s I/O pins. Depending on the project, having a way to get the current date and time is very useful.

Real-Time Clock (RTC) – A Real-Time Clock, or RTC for short, is an integrated circuit that keeps track of time. It uses a back-up battery to maintain the time in the event that the main power source is removed.

Global Positioning Device (GPS) – A GPS device communicates with satellites to determine its location anywhere in the world. Its GPS data also contains time data.

Time Server– A Time Server is a computer on a network that reads the time from some reference clock and distributes it to the network. The clock source of a time server can be another time server, an atomic clock, or a radio clock.

If you want to learn how to communicate with an internet time server to get the current time and date, please read How to Keep Track of the Date and Time on an Arduino.

The DS3231 RTC module is a real-time clock module using the DS3231 IC. The DS3231 IC is a very affordable and extremely accurate RTC with an I2C interface. It is very accurate because it uses an integrated temperature-compensated crystal oscillator (TCXO) along with a crystal. To keep track of time even if the main power source is removed, the DS3231 has a backup battery mounted at the back of the module. The chip automatically switches between main and backup power sources when necessary.

The RTC keeps track of seconds, minutes, hours, day, date, month, and year data. It also automatically adjusts for months with less than 31 days and also for leap years. The clock can operate in either 24H or 12H (with AM/PM) formats. There are also two programmable time-of-day alarms and also a programmable square-wave output. Communication with the RTC is done through an I2C interface with a fixed default address of 0x68.

Aside from the RTC chip, this particular module also has a 24C32 EEPROM chip. An EEPROM is a kind of data storage device wherein you can read/write data. The 24C32 has 32 bytes of available data storage space. It shares the module’s I2C bus with the DS3231 and has the default address of 0x57. We can change the EEPROM’s default address by bridging the solder pads indicated by A0, A1, and A2 as shown in Figure 2.

SQW – outputs a square-wave signal from the DS3231 chip. The frequency of the square-wave can be changed between 1Hz, 4kHz, 8kHz, or 32kHz programmatically. this pin can also be used programmed as an interrupt output.

After learning about timekeeping and the DS3231 RTC, it is now time to build a project using the DS3231 RTC. For this project, we will make a simple Arduino Calendar Clock using a DS3231 module, a 16×2 I2C LCD, and an Arduino Uno board.

If you want to learn more about the Arduino, check out our Ultimate Guide to the Arduino video course. You’ll learn basic to advanced Arduino programming and circuit building techniques that will prepare you to build any project.

To start our sketch, add the abovementioned libraries to our code by using the keyword #include. We will also initialize two objects lcd() and rtc to be used for communicating with the LCD and DS3231 respectively.

The first function we will code is the function updateRTC(). This function will be responsible for asking the user for the date and time and updating the RTC’s internal clock with the user’s input data. After getting the user input, we can update the RTC’s internal clock by using the function rtc.adjust() from the RTCLib.h library. The rtc.adjust() function receives a parameter with type DataTime which it uses to update the rtc’s internal time and date.

The second custom function we will create is the function updateLCD(). This function will update or refresh the text displayed on the LCD. Inside this function, we will first get the time and date from the RTC. This is done by calling rtc.now() function which is included in the RTCLib.h library.

The function rtc.now() in our code returns a DateTime data type that contains the current date and time of the rtc. We then assign the data to different variables for additional formatting on the LCD. After assigning the variables, we use the functions lcd.setCursor() and lcd.print() from the LiquidCrystal_I2C.hto position the cursor and to display the text respectively on the LCD. The code below shows how these functions come together to get the rtc time, format the text and display it to the LCD.

Inside setup(), we will initialize the serial interface, the lcd and the rtc objects. To initialize the serial with a baud rate of 9600 bps, we will use the code Serial.begin(9600);. For the LCD, we need to initialize the LCD object and switch-on the backlight of the display. This is achieved by the codes lcd.init(); and lcd.backlight();. And finally, we add the code rtc.begin(); to initialize the rtc object.

For the loop() function, we will update the text displayed on the LCD by calling updateLCD();. We will also add the capability to accept user input to update the RTC’s internal clock. If the user sends the char ‘u’ via the serial monitor, it means the user wants to modify the set time and date of the rtc. If this is the case, then we call the function updateRTC(); to handle user input and update the RTC internal clock.

To change the date/time, open your Serial Monitor, and send the letter ‘u’. And then just follow the on-screen prompts to enter the new date and time.

In summary, an RTC module is an easy and inexpensive way to add timekeeping capability to an Arduino based project. This tutorial just showed the basic capability of the DS3231 RTC module. And with more tinkering, you can find lots of uses for this module. Feel free to leave a comment below if you have any questions.

arduino real time clock ds3231 with lcd display free sample

In this project, I will discuss about DS3231 RTC Module, important components and features of this module and finally show you how to Interface a DS3231 Real Time Clock (RTC) Module with Arduino.

Real Time Clock or RTC is a timekeeping device in the form of an Integrated Circuit or IC. RTC is an integral component of many time critical applications and devices like Servers, GPS, Data Loggers etc.

With 8051, I have used DS1307 RTC Module in a project called RFID BASED CAR PARKING SYSTEM. Coming to Arduino, I have used the same DS1307 RTC in ARDUINO ALARM CLOCK and ARDUINO REAL TIME CLOCK TUTORIAL USING DS1307. If you want a quick reference, you can go through the provided links.

Also, in the Arduino Real Time Clock Tutorial using DS1307 project, I have talked about the need for an RTC. So, I won’t go into that aspect again. I will directly jump into the IC of interest: the DS3231 RTC IC.

The DS3231 is an RTC IC developed by Maxim Integrated. It is a low cost, extremely accurate RTC IC with communication over I2C Interface. An interesting feature of DS3231 RTC IC is that it has integrated crystal oscillator and temperature sensor and hence you don’t have to connect an external crystal.

Using DS3231 IC as the main component, several manufacturers developed DS3231 RTC Modules with all the necessary components. Almost all the modules available today consists of an additional IC, 24C32N (or something similar). This secondary IC is an EEPROM IC of 32Kb size.

Since RTC is all about maintaining time irrespective of the power supply, you can connect a 3V CR2032 Lithium Battery to the RTC IC to keep the clock ticking. In the DS3231 Module, there is a provision for you to connect a battery using the battery holder provided on the back.

As mentioned earlier, DS3231 IC and 24C32 EEPROM IC are the main components on a typical DS3231 RTC Module board. Apart from that, there are a few other components like Power ON LED, few resistors, capacitors, a battery holder and pins for connecting with microcontroller.

First, let me begin the connections between Arduino and DS3231. Since the interface between them is I2C, identify the I2C Pins on your Arduino Board (if you are using any other board than UNO).

In Arduino UNO, A4 and A5 are SDA and SCL pins. Connect these pins with corresponding SDA and SCL pins of the DS3231 Module. Also, connect the VCC and GND of the RTC Module to +5V and GND of Arduino.

I have used a special library called “RTClib” from Adafruit (which is a forked version of JeeLab’s RTC Library). Download the library from this link and place the extracted folder in the libraries directory of Arduino.

The working of the Arduino DS3231 RTC Module Interface is very easy. Arduino first initializes the RTC Module with its slave address (0x68 for DS3231 IC).

Arduino then updates the internal registers of the RTC IC with the date and time at which the code is compiled and uploaded to Arduino. The uploaded date and time can be viewed on the LCD display.

arduino real time clock ds3231 with lcd display free sample

In today"s world, time is everything, and when it comes to specific electronics, timing is critical; just like us, humans, they also need a way to keep track of time. So how do electronics do it? The answer is DS3231, a Real-Time Clock, often known as an RTC, is a timekeeping device built into an Integrated Circuit, or IC. It is used in many time-critical applications and devices, such as servers, GPS, and data loggers. Let"s see what makes it TICK.

The DS3231 is an I2C real-time clock (RTC) with an inbuilt temperature compensated crystal oscillator (TCXO) and crystal that is both low-cost and exceptionally precise. When the module"s power is interrupted, the device has a battery input and keeps a precise time. The device"s long-term precision is improved by the inclusion of the crystal oscillator. The RTC keeps track of seconds, minutes, hours, days, dates, months, and years. For months with less than 31 days, the date at the end of the month is automatically modified, including leap year corrections. The clock has an AM/PM indication and works in either a 24-hour or 12-hour mode. Two programmable time-of-day alarms are included, as well as a programmable square-wave output. An I2C bidirectional bus is used to transport address and data serially.

The key components of a typical DS3231 RTC Module board are the DS3231 IC and the AT24C32 EEPROM IC to store the time and date data. Other components include a Power ON LED, a few resistors, capacitors, a battery holder, and pins for connecting to the microcontroller.

When the main power to the module is stopped, the DS3231 contains a battery input and maintains accurate time. The built-in power-sense circuit constantly checks the condition of VCC to identify power outages and switches to the backup supply automatically. So, even if the power goes out, your MCU will still be able to maintain track of time. On the DS3231 RTC Module, there is a CR2032 battery holder. A battery holder for a 20mm 3V lithium coin cell is located on the board"s bottom side. Any CR2032 battery will work.

The most significant difference between the DS3231 and the DS1370 is the timekeeping accuracy. For timekeeping, the DS1307 has an external 32kHz crystal oscillator, while the DS3231 has an internal oscillator.

The temperature-compensated crystal oscillator (TCXO) in the DS3231 and DS3234 fits the bill, with precision as good as ±2 ppm in temperatures ranging from 0°C to +40°C.

After making the above connections, you need to connect the Arduino UNO to your PC, open Arduino IDE, and install Arduino DS3231 Time Set Library. Open the Arduino IDE and select Library Manager from the menu bar. Now look for RTCLiband DS3231 and get the most recent version, as shown in the figure below.

You may manually set the time in this line by passing the date-time value to the function in the following order: year, month, date, hour, minute, and second. We"ll set the time of the system in the code below. As a result, we have commented out this line.

We include the below header files to the code, Wire.h to use I2C to communicate with the module, LiquidCrystal.h to show time on the LCD display, RTClib.h to set time to the display and format it.

If in case the RTC loses power and the time in the module goes wrong, the code will automatically set the time in the module and it will take the time from the computer"s clock. So make sure while setting time, the clock on your PC is set at the right time.

arduino real time clock ds3231 with lcd display free sample

This post is about how to use the DS1307 Real Time Clock (RTC) module with the Arduino. You can also follow this guide for other similar modules like the DS3231 RTC.

As you can see in the picture above, the module has a backup battery installed. This allows the module to retain the time, even when it’s not being powered up by the Arduino. This way, every time you turn on and off your module, the time doesn’t reset.

This is a very important step to set up the time in your RTC. If you don’t do this, everytime your RTC resets, it will display the time that you’ve set up previously and not the current time.

arduino real time clock ds3231 with lcd display free sample

The Arduino is an amazing device. It’s useful for prototyping and can also be used to construct a complete project. It has an analog to digital converters (ADC), digital I/O pins, it handles interrupts and it can communicate via a serial port, SPI, and I2C.

A “real time clock” is essentially a digital clock whose output can be read by a computer or microcontroller.  It has its own oscillator that it uses to count time and it has registers that allow you to set the current time and date.

The device you are using to read this article likely has a real time clock and if you are attached to the Internet you probably are synchronizing this to a network time server (if your device is a phone it may be time synchronized to your telephone companies carrier signal instead).

Unix time is the number of seconds that have elapsed since midnight January 1, 1970 (which was a Thursday if you’re interested).  If you are on Linux (or at the terminal on a Mac, which uses Unix as its underlying operating system) you can type “date +%s” to get the current Unix time.

Unix time is useful when you are writing a program that needs to calculate the time difference between two dates and times, as it involves simple addition and subtraction, without having to worry about days, months and years.

The issue with leap seconds is generally taken care of by synchronizing your real time clock with a local or network time source, which itself will have compensated for leap seconds.

The problem with 2038 is likely to be resolved within the next 19 years, I suspect just shifting to a 64-bit standard would resolve this for several millennia!

One chip is theDS3231, a highly accurate real time clock that uses an I2C interface.  This chip has its own internal crystal oscillator, so no external crystal is required.

Another very popular chip is theDS1307. Like the DS3231 it also communicates using the I2C bus, however, this chip requires an external timing crystal.

As the Tiny RTC uses the I2C bus it is very easy to hook it up to an Arduino.  The I2C bus provides power, clock and data signals, so only four connections are required.

Before you hook up your real time clock module it would be a good idea to install the coin cell battery, if you haven’t already. That way you will ensure that the device will keep time even after you power down the Arduino.

Some Arduino clones also have separateSDAandSCLpins, usually located on the same side as the digital I/O pins above theAREFpin.  You can use these connections instead of the analog pins if you wish, they are actually just duplicates.

There are several libraries available that will work with the Tiny RTC. I’m going to use two libraries that were contributed by Paul Stoffregen, a well-known figure in the Arduino community.

The Arduino Library Manager can be also used to install two updated versions of these libraries, these were updated by Michael Margolis.  You can find them as follows:

Once you have the libraries installed open your Arduino IDE and select theFilemenu item and selectExamples. A sub-menu will appear, scroll down until you get to theExamples from Custom Librariessection.

As you might have guessed from its name theSetTimesketch sets the time on the Tiny RTC module. You’ll need to run this, or something similar, before you can use the clock.

SetTime uses two functions, getTime and getDate, to retrieve the time and date respectively from your computer clock. As most Internet-connected computers synchronize to a network time protocol (NTP) server this will probably be very accurate.

Without using a data structure the time will be reported in Unix time, which I described earlier.  ThetmElements_tdata structure breaks this down into elements like seconds, minutes, hours, days, months and years.

Otherwise, the sketch is fairly straightforward. It gets the current system time from the computer running the IDE and writes it to the DS1307 chip on the Tiny RTC module. It does all of this in the Setup section so there is no code in the loop.

Al that is left is to read those time values and print them to the serial monitor. A function calledprint2digitsis used for the hours, minutes and seconds to format the display nicely, with leading zeros for numbers below 10.

The two sketches we have just looked at illustrate how to set and read the time from the Tiny RTC module, and they accomplish this very well. But the module has an additional function, the ability to output a square wave.

You can use this square wave as a timing source for another circuit. It could be used to drive a stepper motor to create an analog clock. And, as I will show you here, it can be used to generate an interrupt for your Arduino.

To use the square wave output as an interrupt for your Arduino you will need to connect the SQ output on the Tiny RTC module to one of the interrupt pins on the Arduino.

An LED is also connected to the Arduino to indicate when an interrupt is being serviced. This is actually optional as it is connected to pin 13 and the Uno also has a built-in LED connected to that pin. If you wish you can leave it out and just monitor the LED on your Uno board.

I found a great sketch that shows how to use the square wave output, it was originally published by Robert Ulbricht on theArduino Slovakia website. Fortunately, there is an English translation available.

The functionsetSQWis really where the “action” is. This function writes to the control register in the DS1307 and sets the square wave frequency to 1Hz.

ThehandleIntfunction is the interrupt handler. Every time a pulse is received on the D2 pin it will be called.  This is set up in the Setup function using theArduino attachInterrupt function.

The previous sketch illustrated how to use the SQ square wave output from the Tiny RTC module as an interrupt. And while it does a great job of displaying interrupt operation it really doesn’t have many practical uses.

After all, there are many simpler methods of blinking an LED. In fact, if you really wanted to use the Tiny RTC to blink an LED you could just attach it directly to the SQ output, eliminating the Arduino entirely (although you’d need the Arduino to set the SQ output to 1Hz first).

Take another look at theReadTestsketch from the DS1307RTC examples. You’ll notice that it reads the time and then adds two delays that total exactly one second. It then does it all over again.

If you’re just building a clock this will work well, as every second you’ll read the time and it will have advanced one second.  But what if you want to do something else in the Loop after you read and display the time?

If the ”something else” takes less than a second then you’ll be displaying the same time more than once. On a display like an LCD or OLED this is not such a bad thing as you might never notice it, but on the serial monitor it will stand out.

If the “something else” takes more than one second you’ll miss reading the clock and it wil skip one or more seconds. You can alleviate this problem somewhat by simply not displaying seconds but still, your minutes may not change at precisely the right time.

To illustrate how to take advantage of interrupts to solve the timing problem I’m going to build a temperature and humidity meter that can also tell time.  I’m going to stick to the serial monitor for my display, but you could easily modify the code to use an OLED or LCD display.

If you wish you could modify the sketch to use the DHT22 or DHT11, I used the AM2320 because I was already using I2C for the real time clock and because I had one handy!

No matter which sensor you choose for your design you’ll encounter the same dilemma – these temperature and humidity sensors require at least two seconds between readings to stabilize.  And so if you read it in the Loop you’ll get an erratic display.

The latter library is not called directly in the sketch, instead, it is used by the AM2320 Library. Without it installed your sketch will fail to compile.

TheprintCurrentTimefunction prints the time, date, temperature and humidity to the serial monitor. It takes the temperature and humidity as an input and reads the real time clock, it then writes everything to the serial monitor.

By doing this we only read the temperature and humidity sensor every 10 seconds, which gives it plenty of time to stabilize. You can reduce this number if you wish, but don’t go below two seconds.

We then check to see if the tick count is the same as it was before. If it is then we don’t do anything. If it isn’t then it means a second has elapsed, so we callprintCurrentTimeto read the time and write everything to the serial monitor.

Load the sketch and give it a test. Note that since the temperature and humidity are only updated every 10 seconds it won’t immediately respond to a change in these values. In normal situations this shouldn’t really be an issue.

Adding a real time clock to an Arduino makes it possible to build devices that are aware of the current time and date. This can allow you to create fancy timers and delay circuits, or just build a really cool and unique digital clock.

A Real Time Clock can be added to your Arduino project in order to tell the time. Today I will show you how to use the Tiny RTC, a real time clock based upon the popular DS1307 chip.

arduino real time clock ds3231 with lcd display free sample

About: Maker 101; Beginner and intermediate level Maker projects! You can find projects such as "How to" and "DIY" on programmable boards such as Arduino, ESP8266, ESP32 and Raspberry Pi on this channel. The projects…

arduino real time clock ds3231 with lcd display free sample

Hi guys, welcome to this tutorial. One of the most important things everyone wants to keep track of daily is, time and with easy to use platforms like the arduino it is very easy to create your own timepiece and in the case of this tutorial add a temperature monitor to it.

The DS3231 is a very low power RTC chip, it has the ability to keep time with incredible accuracy such that even after power has been disconnected from your product, it can run for years on a connected coin cell battery. This module has the ability to communicate via I2C or SPI but for this tutorial we will be using the I2C mode for communications between our arduino and the DS3231. The module also comes with a quite accurate temperature sensor which we will be using to get temperature readings. The collected temperature and clock data is then displayed on the 16×2 LCD via the Arduino.

Since the DS3231 is going to communicate via I2C then its I2C pins will be connected to the arduino’s I2C (SDA and SCL) pins which on the mega are located on pin A0 and A1 or pin 20 (SDA) and 21 (SCL) of the arduino mega.

Next connection is between the LCD and the Arduino. If you are using the screen and keypad shield whose link is attached above, all you will just need to do is plug it in to your arduino as shown below.

The first thing we need to do is to download the arduino library for the ds3231 RTC. The library can be found here and is also attached at the end of this project. Rename the library to “RTC” and install it, by copying and pasting into the Arduino libraries folder.

To do a break down of the code, the first thing we do in the code is to include the libraries that carry some of the dependencies needed for our code to run. The Libraries include wire.h to enable I2C communication, Ds3231.h and rtc_ds3231.h to enable the RTC to work and the Liquidcrystal.h which makes it easy for us to work with the LCD.

The code is a modified version of the example found in the arduino library. The first thing we will be doing with the code is setting the time of the ds3231. The time is set using this line under the setup section.

The next thing after this is to move into the loop function. The loop function displays the time and temperature on the LCD after querying the DS3231 module.

arduino real time clock ds3231 with lcd display free sample

rtc module clock arduino rtc arduino clock clock real time arduino clock rtc ds1307 arduino clock rtc 3231 clock raspberry rtc ds3231 ds3231 rtc real time clock rtc raspberry nano shield real time clock arduino clock rtc rtc module rtc module rtc module rtc arduino adduino arduous raspberry afruit ino ds3231 raspberry clock arduino time arduino rtc module rtc module ds3231 module ds3231 module ds1307 time arduino rtc ds1307 arduino adafruit arduino i2c arduino real time modul horlog arduino horlog camera ds 3231 rtc modul ds. 3231 arduino arduino real time clock raspberry rtc arduino ds1307 azdelivery rtc clock rtc arduino arduino rtc ds3231 arduino time azdelivery real time clock ds 1307 clock ds3231 i2c clock real time clock module real time raspberry rtc ds 1307 rtc i2c module clock arduino ds1 307 module rtc ds1307 pi rtc rtc 1307 ds3231 at24c32 clock rtc raspberry module time arduino arduino rtc clock ds3231 and battery horlog arduino azdelivery arduino rtc module arduino ds1307 arduino arduino arduino clock module ds1307 rtc rtc clock DS3231 rtc module

arduino real time clock ds3231 with lcd display free sample

The sprintf()/snprintf() functions are pretty standard formatting functions in C/C++. You can look up the usage of those functions in every C beginners tutorial. The AVR GCC version for Arduino has just one limitation: You cannot use sprintf()/snprintf() for "float" variable formatting.

One other thing I"d like to do (not sure if I should start a new thread for this now), is to use this not only for the current time on my scoreboard, but also to use it for the timer (if possible / easy). My guess is that it might not be the best idea. I have written code to count/pause and reset via the millis function already. Should I use this instead? If so, the only thing that would be really nice, is to have the count sync with the clock (i.e. the flashing colon). Can I write something that check when a second changes and that drives my counter?

The main disadvantages in RTC timing with a one second resolution is: Each pause/start of the timer leads an inaccuracy of maybe 0.5 seconds, statistically. You could reduce that by using the square wave output of the RTC for time counting. For example you could program the DS3231 to generate a 1024 Hz square wave output, which could be counted with timer interrupts. That way you would be able to achieve a highly accurate timing using a RTC.

But in any case: If you don"t pause/start your counting timer always at the full second, the seconds timing of the counting timer and the realtime clock will always count asynchronous. The realtime clock counts seconds as they pass by naturally. And the counting timers counts seconds or not, depending on the pause/start state. So the change of the second on the RTC and on the timer will happen at different moments. Of course you could synchronize it while updating the displays, for example like that:

The most popular sport in Germany is soccer, and that game has a 2*45 minute timing with no clock pausing, and at the end of each halftime, the referee decides for a few extra minutes as additional time by doing a rule of thumb estimation.

BTW: As I have seen you still include an extra DS3231 library, just to get the temperature. Of course you can put functions reading the temperature into my library, too. For example here are two functions for reading Celsius and Fahrenheit temperatures as integer values, the return value is "hundredths of degrees". Just copy into my library code and you will need no extra library to read the temperature.

If you need to format output for 7-segment displays it may be better to have values as integer numbers for formatting each digit than to have a float variable.

arduino real time clock ds3231 with lcd display free sample

Recently I"ve been developing a new project that requires a sensor to be checked at a certain time of day. The unit will be battery powered, I didn"t want to be counting time continuously so I opted for a Real Time Clock (RTC) to trigger an interrupt pin at a specific time each day.

As with all Arduino projects there isn"t an automatic user interface and I wanted a way to set the clocks without having to set up a board and plug them into the laptop each time so I thought I"d get an LCD with a keypad and build a simple interface to set the RTCs up.

There was a learning curve:I had to learn about LCDsI had to learn about Keypads going to one analogue pinI discovered an issues with cheaper generic LCD Keypad shieldsI had to learn about manipulating bytes and, as it turned out, initiating them

The DS3231 has the ability to store:dates using two digit years,the current day of the week,time in hours, minutes & secondstime as 24 hour or 12 hour (with am and pm data)an alarm (alarm 1) that can be set from days to seconds and has five different methods of triggeringan alarm (alarm 2) that can be set from days to minutes and has three different methods of triggering

For my application I made a couple of decisions:I"m not bothered about 12 hour clocks so I was going to only use the clock in 24 hour mode.I only read dates in dd/mm/yy format so I wasn"t going to give the user an option to show dates in mm/dd/yy format. If that is your preference then the code is easy to adjust but you would have to pay attention to the sequencing during the date set up routine.

The first decision to be made was the sequencing of options for the user. The LCD has two lines of display so each step had to accommodate that. I didn"t want the LCD to scroll a new line up or down each time so I though it would be better if each screen presented had a theme.

When I first created the project I used the following sequences:Date & TimeAlarm 1Alarm 2Set DateSet TimeSet Alarm 1 On or OffSet Alarm 1 Date and/or timeSet Alarm 1 MethodSet Alarm 2 On or OffSet Alarm 2 Date and/or timeSet Alarm 2 Method

But this method took a lot of steps to get from simply displaying Alarm 1 back to Date & Time and also from displaying Alarm 2 to setting Alarm 2 so I changed the sequence:

I maintained the wiring for the LCD as if it had been plugged into an Arduino UNO so the code for initiating looks like:#include #include #include DS3231 Clock;LiquidCrystal lcd(8, 9, 4, 5, 6, 7);void setup() {// Start the lcd and set the cursorlcd.begin(16,2);lcd.setCursor(0,0);// Start the I2C interfaceWire.begin();}

I used the same variables for each of the buttons pressed. There is a lot of information on the internet about managing button bounce, I controlled it with a 50ms debounce delay. To learn more about debounce try this vide:

I also added a variable to store the last button pressed, this avoids the issue of long button presses. Because the Arduino loop runs very often every time it entered the loop after the debounce delay the code would act as if a new button had been pressed without this code.// check the key press against the previous key press to avoid issues from long key pressesif (oldKey!=lcd_key) {// depending on which button was pushed, we perform an actionswitch (lcd_key){case btnRIGHT:

Below is the initial code for the display sequencing, the first block is taken straight from the datasheet:/ define some values used by the panel and buttonsint lcd_key = 0;int adc_key_in = 0;const int btnRIGHT = 0;const int btnUP =1;const int btnDOWN =2;const int btnLEFT =3;const int btnSELECT =4;const int btnNONE =5;int bounceDelay;int oldKey = 0;/**************************************************************** Functions to read the buttons***************************************************************/// read the buttonsint read_LCD_buttons(){adc_key_in = analogRead(0); // read the value from the sensor// my buttons when read are centered at these valies: 0, 144, 329, 504, 741// we add approx 50 to those values and check to see if we are closeif (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result// For V1.1 us this thresholdif (adc_key_in < 50) return btnRIGHT;if (adc_key_in < 250) return btnUP;if (adc_key_in < 450) return btnDOWN;if (adc_key_in < 650) return btnLEFT;if (adc_key_in < 850) return btnSELECT;return btnNONE; // when all others fail, return this...}void loop() {//Set the menu item or display text for the usersetMenu();// read the buttonslcd_key = read_LCD_buttons();// check the key press against the previous key press to avoid issues from long key pressesif (oldKey!=lcd_key) {// depending on which button was pushed, we perform an actionswitch (lcd_key){case btnRIGHT:{oldKey = btnRIGHT;if (currentMode==modeSHOWDATETIME){currentMode=modeSHOWALARM1;}else if (currentMode==modeSHOWALARM1){currentMode=modeSHOWALARM2;}else if (currentMode==modeSHOWALARM2){currentMode=modeSHOWDATETIME;}delay(50);break;}case btnLEFT:{oldKey = btnLEFT;delay(50);break;}case btnUP:{oldKey = btnUP;delay(50);break;}case btnDOWN:{oldKey = btnDOWN;delay(50);break;}case btnSELECT:{oldKey = btnSELECT;if (currentMode==modeSHOWDATETIME){currentMode=modeSETDATE;}else if (currentMode==modeSHOWALARM1){currentMode=modeSETALARM1ON;}else if (currentMode==modeSHOWALARM2){currentMode=modeSETALARM2ON;}else if (currentMode==modeSETDATE){currentMode=modeSETTIME;}else if (currentMode==modeSETTIME){currentMode=modeSHOWDATETIME;}else if (currentMode==modeSETALARM1ON && Clock.checkAlarmEnabled(1)){currentMode=modeSETALARM1;}else if (currentMode==modeSETALARM1ON && !Clock.checkAlarmEnabled(1)){currentMode=modeSHOWALARM1;}else if (currentMode==modeSETALARM1){currentMode=modeSETALARM1METHOD;}else if (currentMode==modeSETALARM1METHOD){currentMode=modeSHOWALARM1;}else if (currentMode==modeSETALARM2ON && Clock.checkAlarmEnabled(2)){currentMode=modeSETALARM2;}else if (currentMode==modeSETALARM2ON && !Clock.checkAlarmEnabled(2)){currentMode=modeSHOWALARM2;}else if (currentMode==modeSETALARM2){currentMode=modeSETALARM2METHOD;}else if (currentMode==modeSETALARM2METHOD){currentMode=modeSHOWALARM2;};break;}case btnNONE:{oldKey=btnNONE;break;}}}}

When I entered the adjustment modes I need a way to show the user which part of the display they could adjust with the up or down arrows. I resolved this in four parts:an integer that changed as the user selected each different section of the display (with the left or right buttons)an integer to hold the maximum value for the blink integer, so that if the maximum number of blink stages (items on display) couldn"t be exceededa variable to hold the blink status (either true or false)a variable to hold the time in milliseconds since the blink status last changed, once that exceeded a set value the blink status changed from true to false or false to true as required.

Code added to the loop() function:void loop() {//Set the menu item or display text for the usersetMenu();// read the buttonslcd_key = read_LCD_buttons();// check the blink counter isn"t too highif (blinkInt > maxBlinkInt){blinkInt=maxBlinkInt;}// Set the current blink statusif (currentMode>modeSHOWALARM2 && ((millis()-blinkStart)>blinkDelay)){blinkNow=!blinkNow;blinkStart=millis();}else if (currentMode<=modeSHOWALARM2){blinkNow=false;}// check the key press against the previous key press to avoid issues from long key pressesif (oldKey!=lcd_key) {

This gave the following full setup and loop functions :void setup() {// Start the serial portSerial.begin(9600);Serial.println("Starting");// Set the bounce delaybounceDelay=50;// Start the lcd and set the cursorlcd.begin(16,2);lcd.setCursor(0,0);// Start the I2C interfaceWire.begin();}void loop() {//Set the menu item or display text for the usersetMenu();// read the buttonslcd_key = read_LCD_buttons();// check the blink counter isn"t too highif (blinkInt > maxBlinkInt){blinkInt=maxBlinkInt;}// Set the current blink statusif (currentMode>modeSHOWALARM2 && ((millis()-blinkStart)>blinkDelay)){blinkNow=!blinkNow;blinkStart=millis();}else if (currentMode<=modeSHOWALARM2){blinkNow=false;}// check the key press against the previous key press to avoid issues from long key pressesif (oldKey!=lcd_key) {// depending on which button was pushed, we perform an actionswitch (lcd_key){case btnRIGHT:{oldKey = btnRIGHT;if (blinkInt1) {blinkInt-=1;}delay(50);break;}case btnUP:{oldKey = btnUP;if (currentMode==modeSETDATE){if (blinkInt==1){increaseDate();}if (blinkInt==2){increaseMonth();}if (blinkInt==3){increaseYear();}}if (currentMode==modeSETTIME){if (blinkInt==1){increaseHour();}if (blinkInt==2){increaseMinute();}}if (currentMode==modeSETALARM1ON) {if (Clock.checkAlarmEnabled(1)) {AlarmOn(1, false);}}if (currentMode==modeSETALARM1) {if (blinkInt==1){changeAlarmDayOption(1);}if (blinkInt==2){ChangeAlarm(1, 1, 0, 0,0);}if (blinkInt==3){ChangeAlarm(1, 0, 1, 0,0);}if (blinkInt==4){ChangeAlarm(1, 0, 0, 1,0);}if (blinkInt==5){ChangeAlarm(1, 0, 0, 0,1);}}if (currentMode==modeSETALARM1METHOD) {changeAlarmMethod(1, 1);}if (currentMode==modeSETALARM2ON) {if (Clock.checkAlarmEnabled(2)) {AlarmOn(2, false);}}if (currentMode==modeSETALARM2) {if (blinkInt==1){changeAlarmDayOption(2);}if (blinkInt==2){ChangeAlarm(2, 1, 0, 0,0);}if (blinkInt==3){ChangeAlarm(2, 0, 1, 0,0);}if (blinkInt==4){ChangeAlarm(2, 0, 0, 1,0);}if (blinkInt==5){ChangeAlarm(2, 0, 0, 0,1);}}if (currentMode==modeSETALARM2METHOD) {changeAlarmMethod(2, 1);}delay(50);break;}case btnDOWN:{oldKey = btnDOWN;if (currentMode==modeSETDATE){if (blinkInt==1){decreaseDate();}if (blinkInt==2){decreaseMonth();}if (blinkInt==3){decreaseYear();}}if (currentMode==modeSETTIME){if (blinkInt==1){decreaseHour();}if (blinkInt==2){decreaseMinute();}}if (currentMode==modeSETALARM1ON) {if (!Clock.checkAlarmEnabled(1)) {AlarmOn(1, true);}}if (currentMode==modeSETALARM1) {if (blinkInt==1){changeAlarmDayOption(1);}if (blinkInt==2){ChangeAlarm(1, -1, 0, 0,0);}if (blinkInt==3){ChangeAlarm(1, 0, -1, 0,0);}if (blinkInt==4){ChangeAlarm(1, 0, 0, -1,0);}if (blinkInt==5){ChangeAlarm(1, 0, 0, 0,-1);}}if (currentMode==modeSETALARM1METHOD) {changeAlarmMethod(1, 0);}if (currentMode==modeSETALARM2ON) {if (!Clock.checkAlarmEnabled(2)) {AlarmOn(2, true);}}if (currentMode==modeSETALARM2) {if (blinkInt==1){changeAlarmDayOption(2);}if (blinkInt==2){ChangeAlarm(2, -1, 0, 0,0);}if (blinkInt==3){ChangeAlarm(2, 0, -1, 0,0);}if (blinkInt==4){ChangeAlarm(2, 0, 0, -1,0);}if (blinkInt==5){ChangeAlarm(2, 0, 0, 0,-1);}}if (currentMode==modeSETALARM2METHOD) {changeAlarmMethod(2, 0);}delay(50);break;}case btnSELECT:{blinkInt=1;oldKey = btnSELECT;if (currentMode==modeSHOWDATETIME){currentMode=modeSETDATE;}else if (currentMode==modeSHOWALARM1){currentMode=modeSETALARM1ON;}else if (currentMode==modeSHOWALARM2){currentMode=modeSETALARM2ON;}else if (currentMode==modeSETDATE){currentMode=modeSETTIME;}else if (currentMode==modeSETTIME){currentMode=modeSHOWDATETIME;}else if (currentMode==modeSETALARM1ON && Clock.checkAlarmEnabled(1)){currentMode=modeSETALARM1;}else if (currentMode==modeSETALARM1ON && !Clock.checkAlarmEnabled(1)){currentMode=modeSHOWALARM1;}else if (currentMode==modeSETALARM1){currentMode=modeSETALARM1METHOD;}else if (currentMode==modeSETALARM1METHOD){currentMode=modeSHOWALARM1;}else if (currentMode==modeSETALARM2ON && Clock.checkAlarmEnabled(2)){currentMode=modeSETALARM2;}else if (currentMode==modeSETALARM2ON && !Clock.checkAlarmEnabled(2)){currentMode=modeSHOWALARM2;}else if (currentMode==modeSETALARM2){currentMode=modeSETALARM2METHOD;}else if (currentMode==modeSETALARM2METHOD){currentMode=modeSHOWALARM2;};break;}case btnNONE:{oldKey=btnNONE;break;}}}}

Reading the tips and tricks from the BaldEngineer I noticed that it was best to send a full line of text to the LCD to overwrite everything as it can sometimes leave some cells with text. For example, if I sent a line saying 108 and then updated with text saying 22 it would actually say 228 because the LCD wouldn"t overwrite the 8 at cell 3.

The solution is to create a function to write the text to the LCD:void displayText(String line0Text, String line1Text){lcd.setCursor(0,0);sprintf(line0,"%-21s", line0Text.c_str());lcd.print(String(line0));lcd.setCursor(0,1);sprintf(line1,"%-21s", line1Text.c_str());lcd.print(String(line1));}

There was also an issue with sending numbers to the LCD, they would only ever show up as the figure 10. This was resolved with another function that I copied from the internet where it is often cited and resolves the issue:String twoDigitNumber(byte number){char buffer[3];snprintf(buffer,sizeof(buffer), "%02d", number );return String(buffer);}

This is so that the DateText and TimeText can be reused when adjusting the date and time. They read the value of blinkInt and the state of the blinkNow to determine if some of the text should be hidden to give the impression of blinking.String dateText() {String result="Date: ";if (blinkInt!=1 || blinkNow==false){result+=twoDigitNumber(Clock.getDate());}else{result+=" ";}result+="/";if (blinkInt!=2 || blinkNow==false){result+=twoDigitNumber(Clock.getMonth(Century));}else{result+=" ";}result+="/";if (blinkInt!=3 || blinkNow==false){result+=twoDigitNumber(Clock.getYear());}else{result+=" ";}return result;}String timeText() {String result="Time: ";if (blinkInt!=1 || blinkNow==false){result+=twoDigitNumber(Clock.getHour(h12, PM));}else{result+=" ";}result+=":";if (blinkInt!=2 || blinkNow==false){result+=twoDigitNumber(Clock.getMinute());}else{result+=" ";}result+=":";result+=twoDigitNumber(Clock.getSecond());return result;}void showDateTime(){displayText(dateText(), timeText());}

The two separate functions called setDate and setTime simple adjust the display and set the maxBlink variable. For the time I"ve not made an allowance for setting seconds manually, when minutes are changed seconds automatically go to 0. I don"t need a clock to be that accurate, if you do you could easily alter this but you might need to account for lag in processing the command.void setDate(){displayText("Set the date:", dateText());maxBlinkInt=3;}void setTime(){displayText("Set the time:", timeText());maxBlinkInt=2;}

It is the up, down and right buttons that call the necessary functions to change the date and time. The right buttons changes the blinkInt valuecase btnRIGHT:{oldKey = btnRIGHT;if (blinkInt

The up and down buttons adjust the valuescase btnUP:{oldKey = btnUP;if (currentMode==modeSETDATE){if (blinkInt==1){increaseDate();}if (blinkInt==2){increaseMonth();}if (blinkInt==3){increaseYear();}}if (currentMode==modeSETTIME){if (blinkInt==1){increaseHour();}if (blinkInt==2){increaseMinute();}}case btnDOWN:{oldKey = btnDOWN;if (currentMode==modeSETDATE){if (blinkInt==1){decreaseDate();}if (blinkInt==2){decreaseMonth();}if (blinkInt==3){decreaseYear();}}if (currentMode==modeSETTIME){if (blinkInt==1){decreaseHour();}if (blinkInt==2){decreaseMinute();}}

The functions to increase the various date and time parts use the DS3231 library. One of the decisions I made here was to keep scrolling through potential values rather than going to a dead end. For example, for minutes, instead of stopping at 59 and having to go down again to get to 0 I simply allow the sequence to go from 59 to 0. I also factor for the maximum days in a month, not just when setting days but also when setting months or years, just in case the day is set to 31 and the user adjusts to a month that only has 30 days or less. Leap years are adjusted for as well./**************************************************************** Functions to increase and decrease time elements***************************************************************/void increaseYear(){Year=Clock.getYear();if (Year<99){Year = Year + 1;}else{Year = 00;}Clock.setYear(Year);if (Clock.getDate()>monthMaxDays(Clock.getMonth(Century))){Clock.setDate(monthMaxDays(Clock.getMonth(Century)));}}void decreaseYear(){Year=Clock.getYear();if (Year>1){Year = Year - 1;}else{Year = 99;}Clock.setYear(Year);if (Clock.getDate()>monthMaxDays(Clock.getMonth(Century))){Clock.setDate(monthMaxDays(Clock.getMonth(Century)));}}void increaseMonth(){Month=Clock.getMonth(Century);if (Month<12) {Month = Month + 1;}else{Month = 1;}Clock.setMonth(Month);if (Clock.getDate()>monthMaxDays(Clock.getMonth(Century))){Clock.setDate(monthMaxDays(Clock.getMonth(Century)));}}void decreaseMonth(){Month=Clock.getMonth(Century);if (Month>1) {Month = Month - 1;}else{Month = 12;}Clock.setMonth(Month);if (Clock.getDate()>monthMaxDays(Clock.getMonth(Century))){Clock.setDate(monthMaxDays(Clock.getMonth(Century)));}}void increaseDate(){Date=Clock.getDate();if (Date1) {Date = Date- 1;}else {Date = monthMaxDays(Clock.getMonth(Century));}Clock.setDate(Date);}void increaseHour(){Hour=Clock.getHour(h12, PM);if (Hour<24){Hour = Hour + 1;}else{Hour = 1;}Clock.setHour(Hour);}void decreaseHour(){Hour=Clock.getHour(h12, PM);if (Hour>1){Hour = Hour - 1;}else{Hour = 24;}Clock.setHour(Hour);}void increaseMinute(){Minute=Clock.getMinute();if (Minute<60){Minute = Minute + 1;}else{Minute = 1;}Clock.setMinute(Minute);Clock.setSecond(0);}void decreaseMinute(){Minute=Clock.getMinute();if (Minute>0){Minute = Minute - 1;}else{Minute = 60;}Clock.setMinute(Minute);Clock.setSecond(0);}int monthMaxDays(int monthNumber){switch (monthNumber){case 1:case 3:case 5:case 7:case 8:case 10:case 12:return 31;case 4:case 6:case 9:case 11:return 30;case 2:int remainingYears;remainingYears=((Clock.getYear()-2020)%4);if (remainingYears==0){return 29;}else{return 28;}default:return 0;}}

Setting the alarms on or off was fairly simple, there are three functions available in the DS3231 library. These are turnOnAlarm, turnOffAlarm and checkAlarmEnabled. I used the checkAlarmEnabled function to decide if the user needed to see the displays to set the rest of the alarm, if the user had turned the alarm off this all seemed redundant.case btnSELECT:{blinkInt=1;oldKey = btnSELECT;if (currentMode==modeSHOWDATETIME){currentMode=modeSETDATE;}else if (currentMode==modeSHOWALARM1){currentMode=modeSETALARM1ON;}else if (currentMode==modeSHOWALARM2){currentMode=modeSETALARM2ON;}else if (currentMode==modeSETDATE){currentMode=modeSETTIME;}else if (currentMode==modeSETTIME){currentMode=modeSHOWDATETIME;}else if (currentMode==modeSETALARM1ON && Clock.checkAlarmEnabled(1)){currentMode=modeSETALARM1;}else if (currentMode==modeSETALARM1ON && !Clock.checkAlarmEnabled(1)){currentMode=modeSHOWALARM1;}else if (currentMode==modeSETALARM1){currentMode=modeSETALARM1METHOD;}else if (currentMode==modeSETALARM1METHOD){currentMode=modeSHOWALARM1;}else if (currentMode==modeSETALARM2ON && Clock.checkAlarmEnabled(2)){currentMode=modeSETALARM2;}else if (currentMode==modeSETALARM2ON && !Clock.checkAlarmEnabled(2)){currentMode=modeSHOWALARM2;}else if (currentMode==modeSETALARM2){currentMode=modeSETALARM2METHOD;}else if (currentMode==modeSETALARM2METHOD){currentMode=modeSHOWALARM2;};break;}

The blinking was set to match the currently selected on or off option.void setAlarmOnOff(int alarmNum){if (alarmNum>0 && alarmNum<3) {maxBlinkInt=1;if(Clock.checkAlarmEnabled(alarmNum)){blinkInt=2;}else {blinkInt=1;}if (blinkInt==1 && blinkNow==true){displayText("", "Alarm" + String(alarmNum) + ": ON");}else if (blinkInt==2 && blinkNow==true){displayText("Alarm" + String(alarmNum) + ": OFF", "");}else{ displayText("Alarm" + String(alarmNum) + ": OFF", "Alarm" + String(alarmNum) + ": ON");}}}

The alarm is then set:void AlarmOn(int alarmNum, bool setOn){if (alarmNum>0 && alarmNum<3) {if (setOn){Clock.turnOnAlarm(alarmNum);}else {Clock.turnOffAlarm(alarmNum);}}}

There are now only two other options for each alarm that we can use to help with displaying and setting the alarms:getA1Time(ADay, AHour, AMinute, ASecond, ABits, ADy, A12h, Apm);setA1Time(ADay, AHour, AMinute, ASecond, ABits, ADy, A12h, Apm);getA2Time(ADay, AHour, AMinute, ABits, ADy, A12h, Apm);setA2Time(ADay, AHour, AMinute, ABits, ADy, A12h, Apm);

I created two separate functions for changing the day/date options and for changing the time for simplicity of reading the code:void changeAlarmDayOption(int alarmNum){byte ADay, AHour, AMinute, ASecond, ABits;bool ADy, A12h, Apm;//Collect the current alarm settingsif (alarmNum==1){Clock.getA1Time(ADay, AHour, AMinute, ASecond, ABits, ADy, A12h, Apm);}if (alarmNum==2){Clock.getA2Time(ADay, AHour, AMinute, ABits, ADy, A12h, Apm);}ADy=!ADy;if (ADy && ADay>7) {ADay=7;}//Reset the alarm settingsif (alarmNum==1){Clock.setA1Time(ADay, AHour, AMinute, ASecond, ABits, ADy, A12h, Apm);}if (alarmNum==2){Clock.setA2Time(ADay, AHour, AMinute, ABits, ADy, A12h, Apm);}}void ChangeAlarm(int alarmNum, int dayAdjust, int hourAdjust, int minAdjust,int secAdjust){byte ADay, AHour, AMinute, ASecond, ABits;bool ADy, A12h, Apm;//Collect the current alarm settingsif (alarmNum==1){Clock.getA1Time(ADay, AHour, AMinute, ASecond, ABits, ADy, A12h, Apm);}if (alarmNum==2){Clock.getA2Time(ADay, AHour, AMinute, ABits, ADy, A12h, Apm);}//Adjust the dateADay+=dayAdjust;if (ADy){if (ADay<1){ADay=7;}if (ADay>7){ADay=1;}}else {if (ADay<1){ADay=31;}if (ADay>31){ADay=1;}}//Adjust the hourAHour+=hourAdjust;if (AHour<0){AHour=23;}if (AHour>23){AHour=0;}//Adjust the minuteAMinute+=minAdjust;if (AMinute<0){AMinute=59;}if (AMinute>59){AMinute=0;}//Adjust the secondif (alarmNum==1){ASecond+=secAdjust;if (ASecond<0){ASecond=59;}if (ASecond>59){ASecond=0;}}//Reset the alarm settingsif (alarmNum==1){Clock.setA1Time(ADay, AHour, AMinute, ASecond, ABits, ADy, A12h, Apm);}if (alarmNum==2){Clock.setA2Time(ADay, AHour, AMinute, ABits, ADy, A12h, Apm);}}

All of the previous steps were fairly painless, a bit of research and applying what I"d learnt. Not so with setting the alarm modes. This was a headache.

The alarm modes are held in memory in various locations and the DS3231 kindly collects this data, stores it in a byte and returns it to the user. In the previous codes this is the ABits variable.

There are a set of masks stated on the data sheet and I copied the constants fromhttps://github.com/mlepard/ArduinoChicken/blob/master/roboCoop/alarmControl.ino// These are the ALARM Bits that can be used// They need to be combined into a single value (see below)// Found here: https://github.com/mlepard/ArduinoChicken/blob/master/roboCoop/alarmControl.ino#define ALRM1_MATCH_EVERY_SEC 0b1111 // once a second#define ALRM1_MATCH_SEC 0b1110 // when seconds match#define ALRM1_MATCH_MIN_SEC 0b1100 // when minutes and seconds match#define ALRM1_MATCH_HR_MIN_SEC 0b1000 // when hours, minutes, and seconds match#define ALRM1_MATCH_DY_HR_MIN_SEC 0b0000 // when hours, minutes, and seconds match#define ALRM2_ONCE_PER_MIN 0b111 // once per minute (00 seconds of every minute)#define ALRM2_MATCH_MIN 0b110 // when minutes match#define ALRM2_MATCH_HR_MIN 0b100 // when hours and minutes match

Some places on-line suggest that you have to create a seven digit byte and set both alarms 1 and 2 at the same time. I discovered this isn"t so from reading the DS3231 library. The alarm 1 reads the first four (from the right hand) digits of a byte sent to it, alarm2 reads digits 5, 6, & 7.

I was still hitting problems though. Sometimes the scrolling of the current status would work, sometimes the status would update, sometimes it wouldn"t.

After posting online in the forum (https://forum.arduino.cc/index.php?topic=719176.0) cattledog highlighted that I could have dirty bytes that could be corrupting what I was sending to the DS3231 library. I explicitly set the bytes, made sure I didn"t recall an old byte variable, and it all worked.void setAlarmMethod(int alarmNum){if (alarmNum>0 && alarmNum<3) {if (alarmNum==1){maxBlinkInt=1;showAlarmMethod(1);}if (alarmNum==2){maxBlinkInt=1;showAlarmMethod(2);}}}void showAlarmMethod(int alarmNum) {String myString1="";String myString2="";byte ADay, AHour, AMinute, ASecond, ABitsOP=0b0;bool ADy, A12h, Apm;if (alarmNum==1){myString1 = "Alarm 1 Method:";Clock.getA1Time(ADay, AHour, AMinute, ASecond, ABitsOP, ADy, A12h, Apm);ABitsOP = ABitsOP & 0b1111;if (ABitsOP==ALRM1_MATCH_EVERY_SEC) {myString2 = "Once per Second";}else if (ABitsOP==ALRM1_MATCH_SEC) {myString2 = "Seconds Match";}else if (ABitsOP==ALRM1_MATCH_MIN_SEC) {myString2 = "Min & Secs Match";}else if (ABitsOP==ALRM1_MATCH_HR_MIN_SEC) {myString2 = "Hr, Min & Sec Match";}else if (ABitsOP==ALRM1_MATCH_DY_HR_MIN_SEC) {myString2 = "Dy, Hr, Mn & Sec";}} else {Clock.getA2Time(ADay, AHour, AMinute, ABitsOP, ADy, A12h, Apm);myString1 = "Alarm 2 Method:";if ((ABitsOP>>4)==ALRM2_ONCE_PER_MIN) {myString2 = "Once per Minute";}else if ((ABitsOP>>4)==ALRM2_MATCH_MIN) {myString2 = "Match Minute";}else {myString2 = "Match Hour & Min";}}displayText(myString1 , myString2);}

In the changeAlarmMethod function to can see that:Abits is explicitly set to zeroFor Alarm1 Abits is then masked to return the first four digits (&0b1111).For Alarm2 Abits is pushed to the right four places to return only digits 5, 6 & 7 (>> 4).For both alarms a new variable is created to hold the new alarm mode to ensure there isn"t any contamination of data from the old variableFor Alarm2 the new variable is pushed to the left four places to correctly set digits 5, 6 & 7 (>> 4).void changeAlarmMethod(int alarmNum, int dir) {byte ADay1, AHour1, AMinute1, ASecond1, ADay2, AHour2, AMinute2, ABits=0b0;bool ADy1, A12h1, Apm1, ADy2, A12h2, Apm2;int AlarmBits;if (alarmNum==1){Clock.getA1Time(ADay1, AHour1, AMinute1, ASecond1, ABits, ADy1, A12h1, Apm1);ABits = ABits & 0b1111;if (dir == 1) {if (ABits==ALRM1_MATCH_EVERY_SEC) {AlarmBits |= ALRM1_MATCH_SEC;}else if (ABits==ALRM1_MATCH_SEC) {AlarmBits |= ALRM1_MATCH_MIN_SEC;}else if (ABits==ALRM1_MATCH_MIN_SEC) {AlarmBits |= ALRM1_MATCH_HR_MIN_SEC;}else if (ABits==ALRM1_MATCH_HR_MIN_SEC) {AlarmBits |= ALRM1_MATCH_DY_HR_MIN_SEC;}else if (ABits==ALRM1_MATCH_DY_HR_MIN_SEC) {AlarmBits |= ALRM1_MATCH_EVERY_SEC;}}else if (dir == 0) {if (ABits==ALRM1_MATCH_EVERY_SEC) {AlarmBits |= ALRM1_MATCH_DY_HR_MIN_SEC;}else if (ABits==ALRM1_MATCH_SEC) {AlarmBits |= ALRM1_MATCH_EVERY_SEC;}else if (ABits==ALRM1_MATCH_MIN_SEC) {AlarmBits |= ALRM1_MATCH_SEC;}else if (ABits==ALRM1_MATCH_HR_MIN_SEC) {AlarmBits |= ALRM1_MATCH_MIN_SEC;}else {AlarmBits |= ALRM1_MATCH_HR_MIN_SEC;}}else {AlarmBits |= ABits;}Clock.setA1Time(ADay1, AHour1, AMinute1, ASecond1, AlarmBits, ADy1, A12h1, Apm1);} else {Clock.getA2Time(ADay2, AHour2, AMinute2, ABits, ADy2, A12h2, Apm2);ABits = ABits >> 4;if (dir == 1) {if (ABits==ALRM2_ONCE_PER_MIN) {AlarmBits = ALRM2_MATCH_MIN;}else if (ABits==ALRM2_MATCH_MIN) {AlarmBits = ALRM2_MATCH_HR_MIN;}else {AlarmBits = ALRM2_ONCE_PER_MIN;}}if (dir == 0) {if (ABits==ALRM2_ONCE_PER_MIN) {AlarmBits = ALRM2_MATCH_HR_MIN;}else if (ABits==ALRM2_MATCH_HR_MIN) {AlarmBits = ALRM2_MATCH_MIN;}else {AlarmBits = ALRM2_ONCE_PER_MIN;}}AlarmBits = AlarmBits << 4;Clock.setA2Time(ADay2, AHour2, AMinute2, AlarmBits, ADy2, A12h2, Apm2);byte newBits;Clock.getA2Time(ADay2, AHour2, AMinute2, newBits, ADy2, A12h2, Apm2);}}

The constants used for the current status are shown below.// define some values used by the menu controllerconst int modeSHOWDATETIME = 0;const int modeSHOWALARM1 = 1;const int modeSHOWALARM2 = 2;const int modeSETDATE = 3;const int modeSETTIME = 4;const int modeSETALARM1ON = 5;const int modeSETALARM1 = 6;const int modeSETALARM1METHOD = 7;const int modeSETALARM2ON = 8;const int modeSETALARM2 = 9;const int modeSETALARM2METHOD = 10;int currentMode = modeSHOWDATETIME;

I"ve created a simple casing/holder for the shield and breadboard. it is 2-piece for two reasons. Firstly, the frame around the LCD would have needed supports and scondly, I"ve found that the positions of the buttons is a bit erratic and so this design allows anyone replicating the design to tweak the LCD panel. The stl files are included.

One of the tings I noticed with this code was the amount of memory it used. I"m not great at understanding how to control memory but I did a couple of things after I wrote the instructions above:I changed all #Define to const as I had read it was better for memory. It had limited effect.I changed all integer flags to bytes to reduce memory usage, this had some effect.I removed global variables where they could be local variables, again this had limited effect.

The next step with memory was to remove references to Serial from the SetUp function. This reduces the memory usage to 50% of storage and global variables occupying 30% of dynamic memory. So there is a lesson to comment out or remove all debugging statements once complete.

When I"ve used the RTC in projects I"ve found two issues:The status register of the DS3231 RTC doesn"t appear to clear correctly, locking the RTC alarm into a low state, this is resolved athttps://electronics.stackexchange.com/questions/445256/ds3231-stops-working-on-vbat

arduino real time clock ds3231 with lcd display free sample

The DS3231 AT24C32 Real Time Clock Module adds timestamp and event scheduling information to your microcontroller projects. This module generates seconds, minutes, hours, day, date, month and year, and provides timekeeping until 2100 while compensating for leap years.

This device was added to Parallax inventory as a quick demonstration to the sample code for the Propeller 2 SPIN/PASM SPI Driver used in the Propeller 2 Live Forum and P2 Quick Byte “SPI Driver Object”. It is compatible with all Parallax microcontrollers, to provide simple visual feedback for numbers and data.

arduino real time clock ds3231 with lcd display free sample

This is a tutorial of an open source Arduino library, which lets you turn your Arduino to a “Clock”, with a Maxim Integrated DS3232 Real Time Clock module. I will show you how to install the library to Arduino IDE and make an example project with the library, throughout this tutorial while giving information digital clocks and their working principle.

A digital clock is a clock consisting of a power supply, a circuit consisting of an crystal oscillator and a display to show the time, which shows the time digitally unlike traditional analog clocks. First digital clock is made by an Austrian engineer named Josef Pallweber using a jump hour mechanism. Digital clocks have the same fundamental working principle as the analog clocks. They need a source of power to run the clock, which is the power supply, a battery or AC power, a display which can be a LED, LCD display or a seven segment display, and a time base that keeps track of the time which is the time c