Step 8: Problematic DateFormat Function
The library I am using in this tutorial provide one extra function called DateFormat. This is a powerful function which helps us to format the time/date read of the RTC module anyway we want easy and without the need of writing additional functions like we did in our code.
I am providing syntax of this function here with examples.
There is a problem with that function though. It requires a lot of memory and if you coose to use it with OLED display your sketch would run out of memory. This problem was reported to library creator, but it seems he has stopped working on this library, and this problem may never be fixed.
You can still use this function with arduino compatible microcontrollers thathave more than 2k of Sram (Arduino Mega, Bluepill etc).
I will provide in the closing chapter a link to the code that is using this DateFormat format to achieve the same result as our code here, and you will see that this greatly simplifies the code.
Real-Time Clock (RTC)
The RTC on the UNO R4 WiFi can be accessed using the RTC library that is included in the UNO R4 Board Package. This library allows you to set/get the time as well as using alarms to trigger interrupts.
The UNO R4 WiFi features a VRTC pin, that is used to keep the onboard RTC running, even when the boards power supply is is cut off. In order to use this, apply a voltage in the range of 1.6 – 3.6 V to the VRTC pin.
There are many practical examples using an RTC, and the examples provided in this page will help you get started with it.
Set Time
-
RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE)
-
RTC.setTime(startTime)
To set the starting time for the RTC, you can create an
object. Here you can specify the day, month, year, hour, minute, second, and specify day of week as well as daylight saving mode.
RTCTime
Then to set the time, use the
method.
setTime()
Example:
1#include “RTC.h”23void setup() {4 Serial.begin(9600);56 RTC.begin();78 RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);910 RTC.setTime(startTime);11}1213void loop(){14}
Get Time
-
RTC.getTime(currentTime)
To retrieve the time, we need to create a
object, and use the
RTCTime
method to retrieve the current time.
getTime()
This example sets & gets the time and stores it in an
object called
RTCTime
.
currentTime
1#include “RTC.h”23void setup() {4 Serial.begin(9600);56 RTC.begin();78 RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);910 RTC.setTime(startTime);11}1213void loop(){14RTCTime currentTime;1516// Get current time from RTC17RTC.getTime(currentTime);18}
Print Date & Time
The above examples show how to set & get the time and store it in an object. This data can be retrieved by a series of methods:
-
getDayOfMonth()
-
getMonth()
-
getYear()
-
getHour()
-
getMinutes()
-
getSeconds()
The example below prints out the date and time from the
object.
currentTime
1#include “RTC.h”23void setup() {4 Serial.begin(9600);56 RTC.begin();78 RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);910 RTC.setTime(startTime);11}1213void loop() {14 RTCTime currentTime;1516 // Get current time from RTC17 RTC.getTime(currentTime);1819 // Print out date (DD/MM//YYYY)20 Serial.print(currentTime.getDayOfMonth());21 Serial.print(“/”);22 Serial.print(Month2int(currentTime.getMonth()));23 Serial.print(“/”);24 Serial.print(currentTime.getYear());25 Serial.print(” – “);2627 // Print time (HH/MM/SS)28 Serial.print(currentTime.getHour());29 Serial.print(“:”);30 Serial.print(currentTime.getMinutes());31 Serial.print(“:”);32 Serial.println(currentTime.getSeconds());3334 delay(1000);35}
Unix
-
currentTime.getUnixTime()
To retrieve the Unix timestamp, use the
method.
getUnixTime()
1#include “RTC.h”23void setup() {4 Serial.begin(9600);56 RTC.begin();78 RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);910 RTC.setTime(startTime);11}1213void loop() {14 RTCTime currentTime;1516 // Get current time from RTC17 RTC.getTime(currentTime);1819 //Unix timestamp20 Serial.print(“Unix timestamp: “);21 Serial.println(currentTime.getUnixTime());2223 delay(1000);24}
Periodic Interrupt
A periodic interrupt allows you to set a recurring callback.
To use this, you will need to initialize the periodic callback, using the
method:
setPeriodicCallback()
-
RTC.setPeriodicCallback(periodic_cbk, Period::ONCE_EVERY_2_SEC)
You will also need to create a function that will be called:
-
void periodicCallback() { code to be executed }
Note the IRQ has a very fast execution time. Placing a lot of code is not a good practice, so in the example below we are only switching a single flag,
irqFlag
The example below blinks a light every 2 seconds:
1#include “RTC.h”23volatile bool irqFlag = false;4volatile bool ledState = false;56const int led = LED_BUILTIN;78void setup() {9 pinMode(led, OUTPUT);1011 Serial.begin(9600);1213 // Initialize the RTC14 RTC.begin();1516 // RTC.setTime() must be called for RTC.setPeriodicCallback to work, but it doesn’t matter17 // what date and time it’s set to18 RTCTime mytime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);19 RTC.setTime(mytime);2021 if (!RTC.setPeriodicCallback(periodicCallback, Period::ONCE_EVERY_2_SEC)) {22 Serial.println(“ERROR: periodic callback not set”);23 }24}2526void loop(){27 if(irqFlag){28 Serial.println(“Timed CallBack”);29 ledState = !ledState;30 digitalWrite(LED_BUILTIN, ledState);31 irqFlag = false;32 }33}3435void periodicCallback()36{37 irqFlag = true;38}
The period can be specified using the following enumerations:
-
ONCE_EVERY_2_SEC
-
ONCE_EVERY_1_SEC
-
N2_TIMES_EVERY_SEC
-
N4_TIMES_EVERY_SEC
-
N8_TIMES_EVERY_SEC
-
N16_TIMES_EVERY_SEC
-
N32_TIMES_EVERY_SEC
-
N64_TIMES_EVERY_SEC
-
N128_TIMES_EVERY_SEC
-
N256_TIMES_EVERY_SEC
Alarm Callback
-
RTC.setAlarmCallback(alarm_cbk, alarmtime, am)
1unsigned long previousMillis = 0;2const long interval = 1000;3bool ledState = false;45// Include the RTC library6#include “RTC.h”78void setup() {9 //initialize Serial Communication10 Serial.begin(9600);1112 //define LED as output13 pinMode(LED_BUILTIN, OUTPUT);1415 // Initialize the RTC16 RTC.begin();1718 // RTC.setTime() must be called for RTC.setAlarmCallback to work, but it doesn’t matter19 // what date and time it’s set to in this example20 RTCTime initialTime(7, Month::JUNE, 2023, 13, 03, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);21 RTC.setTime(initialTime);2223 // Trigger the alarm every time the seconds are zero24 RTCTime alarmTime;25 alarmTime.setSecond(0);2627 // Make sure to only match on the seconds in this example – not on any other parts of the date/time28 AlarmMatch matchTime;29 matchTime.addMatchSecond();3031 //sets the alarm callback32 RTC.setAlarmCallback(alarmCallback, alarmTime, matchTime);33}3435void loop() {3637 // in the loop, we continuously print the alarm’s current state38 // this is for debugging only and has no effect on the alarm whatsoever39 unsigned long currentMillis = millis();40 if (currentMillis – previousMillis >= interval) {41 // save the last time you blinked the LED42 previousMillis = currentMillis;43 Serial.print(“Alarm state: “);44 Serial.println(ledState);45 }46}4748// this function activates every minute49// and changes the ledState boolean50void alarmCallback() {51 if (!ledState) {52 digitalWrite(LED_BUILTIN, HIGH);53 } else {54 digitalWrite(LED_BUILTIN, LOW);55 }56 ledState = !ledState;57}
Step 6: Custom Functions Needed to Display Time in a Proper Format.
We need to write following function to be able to format the output the values read from RTC module into desired date and time format:
- DayOfTheWeek – It convert the day of the week reading into full name of the day (1-7->Mon-Sun)DayMonthYear – converts day month and year into single stringl. It bilds it from short name of the month, ordinal representation of the day of the month and then full year.
- AddLeadingZero – used to add leading zero to single digit readings for hour , minutes, and seconds
- CurrentTime – takes hours and minutes reading. Makes sure that the necessary leading zeros are provided and builds the string from hour and minutes separated by a colon
Chi tiết sản phẩm
Module Thời Gian Thực RTC DS3231 là IC thời gian thực giá rẻ, rất chính xác với thạch anh tích hợp sẵn có khả năng điều chỉnh nhiệt. IC có đầu vào cho pin riêng, tách biệt khỏi nguồn chính đảm bảo cho việc giữ thời gian chính xác. Thạch anh tích hợp sẵn giúp tăng độ chính xác trong thời gian dài hoạt động và giảm số lượng linh kiện cần thiết khi làm board.
Thời gian trong IC được giữ ở dạng: giờ, phút, giây, ngày, thứ, tháng, năm. Các tháng có ít hơn 31 ngày sẽ tự động được điều chỉnh, các năm Nhuận cũng được chỉnh đúng số ngày. Thời gian có thể hoạt động ở chế độ 24h hoặc 12h AmPM. IC còn có chức năng báo động, có thể cài đặt 2 thời gian báo và lịch, có tín hiệu ra là xung vuông. Giao tiếp với IC được thực hiện thông qua I2C bus.
Trong chip có mạch điện áp chuẩn dùng để theo dõi trạng thái của nguồn VCC, phát hiện lỗi nguồn, tự động chuyển nguồn khi có vấn đề. Có tín hiệu Reset xuất ra cho mạch ngoài, MCU khi nguồn điện phục hồi trạng thái. Ngoài ra trong IC còn có sẵn cảm biến nhiệt độ, có độ chính xác là ± 3°C.
THÔNG SỐ MODULE THỜI GIAN THỰC RTC DS3231
- Size: dài 38mm, rộng 22mm, cao 14mm
- Khối lượng 8g
- Điện thế hoạt động 3.3 – 5.5V
- Clock: high-precision clock on chip DS3231
- Clock Accuracy: 040 ℃ range, the accuracy 2ppm, the error was about 1 minute
- Thông tin Thời gian: giờ, phút, giây, ngày, thứ, tháng, năm, đến 2100.
- Cảm biến nhiệt trên IC có độ chính xác ± 3 ℃
- I2C bus có tốc độ tối đa 400Khz
- Kèm thêm pin sạc được CR2032
- Kèm thêm memory IC AT24C32 (32k bits)
SƠ ĐỒ KẾT NỐI
HÌNH ẢNH SẢN PHẨM
————————CODE THAM KHẢO———————–
// DS3231_Serial_Easy // Copyright (C)2015 Rinky-Dink Electronics, Henning Karlsen. All right reserved // web: http://www.RinkyDinkElectronics.com/ // // A quick demo of how to use my DS3231-library to // quickly send time and date information over a serial link // // To use the hardware I2C (TWI) interface of the Arduino you must connect // the pins as follows: // // Arduino Uno/2009: // ———————- // DS3231: SDA pin -> Arduino Analog 4 or the dedicated SDA pin // SCL pin -> Arduino Analog 5 or the dedicated SCL pin // // Arduino Leonardo: // ———————- // DS3231: SDA pin -> Arduino Digital 2 or the dedicated SDA pin // SCL pin -> Arduino Digital 3 or the dedicated SCL pin // // Arduino Mega: // ———————- // DS3231: SDA pin -> Arduino Digital 20 (SDA) or the dedicated SDA pin // SCL pin -> Arduino Digital 21 (SCL) or the dedicated SCL pin // // Arduino Due: // ———————- // DS3231: SDA pin -> Arduino Digital 20 (SDA) or the dedicated SDA1 (Digital 70) pin // SCL pin -> Arduino Digital 21 (SCL) or the dedicated SCL1 (Digital 71) pin // // The internal pull-up resistors will be activated when using the // hardware I2C interfaces. // // You can connect the DS3231 to any available pin but if you use any // other than what is described above the library will fall back to // a software-based, TWI-like protocol which will require exclusive access // to the pins used, and you will also have to use appropriate, external // pull-up resistors on the data and clock signals. // #include
// Init the DS3231 using the hardware interface DS3231 rtc(SDA, SCL); void setup() { // Setup Serial connection Serial.begin(115200); // Uncomment the next line if you are using an Arduino Leonardo //while (!Serial) {} // Initialize the rtc object rtc.begin(); // The following lines can be uncommented to set the date and time //rtc.setDOW(WEDNESDAY); // Set Day-of-Week to SUNDAY //rtc.setTime(12, 0, 0); // Set the time to 12:00:00 (24hr format) //rtc.setDate(1, 1, 2014); // Set the date to January 1st, 2014 } void loop() { // Send Day-of-Week Serial.print(rtc.getDOWStr()); Serial.print(” “); // Send date Serial.print(rtc.getDateStr()); Serial.print(” — “); // Send time Serial.println(rtc.getTimeStr()); // Wait one second before repeating 🙂 delay (1000); }
KẾT QUẢ
Nshopvn.com · 07/03/2019 10:44 AM
Module Thời Gian Thực RTC DS3231 giá chỉ 45.000₫
Introduction: How to Create a Clock Using Arduino , DS3231 RTC Module and OLED Display
I have made a couple of clock project in the past. I have always used DS1306 module to do it. I received the backlash from my viewers. They questioned why I would use that particuler RTC module labeling it as not relaible. Now that I think of it I had issues with those RTC modules being off by a minute or two after operating for a week. Everyone pointed to DS3231 as a much more precise module. I thought to myself : “I have to give it a try”.
So here is a tutorial how to build cool looking clock using Arduino, DS3231 and OLED display.
The DS3231 Real Time Clock Module
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.
Module Pinouts
- 32K – outputs from the DS3231 chip a very accurate 32KHz oscillator
- 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.
- SCL – input pin for I2C Serial Clock
- SDA – input/output pin for I2C Serial Data
- VCC – power source input pin for the module; can be any voltage from +3.3V to +5.5V DC
- GND – Ground pin connection
- The SCL, SDA, VCC, and GND pins at the right side of the module are connected internally at the left side pins with the same label.
Step 5: Adding OLED Display Into the Project
Now that we know how to controle this type or rtc module lets move away from serial monitor and try to display time on the small OLED display. When I wanted to connect it to arduino I realised that it also needs to be connected via pins A4 and A5 as this OLED display is also an I2C device. So what now. Those pins are already taken. You have to realise that those pins are not dedicated to any particular device. They can be shared accross many devices as they connect those devices to I2c bus. So for starters lets connect VCC and ground of the oled display to arduino
Then lets envisage the I2C bus with the Serial Data line called SDA in short and Serial Clock line called SCL. Arduino is connected to that bus via analog pin a4 to SDA and via analog pin A5 to SCL. Microcontroller is a master device.
The way of Connecting to I2C bus may differ depending on which arduino board you use. e.g in Uno A4 And A5 pins would work but there are also dedicated I2C ports. In Arduino Mega on the other hand A4 and A5 cannot be used for that purpose. So check the documentation of the board you are planning to use.
Now we can connect the rtc module to that bus as a slave and OLED display in the same way as a second slave device. Ok. But how would Arduino recognise which device is which to communicate with it. Each device have its unique address. So DS3231 RTC module should be avaiable at 68hex address while OLED display should be at 3C hex. If however you come accross issues while connecting any of the commponents you can use I2c scanner sketch to detect all avaialble devices connected to the bus and their addresses.
Here is the url you can find a I2C scanner sketch.
https://playground.arduino.cc/Main/I2cScanner/
Paste it to the arduino IDE and execute it. For my little set up the I2c scanner detects following devices (see attached screenshot)
Step 2: Connecting DS3231 to Arduino
Finally the project where the connectivity is super simple. To connect this RTC module to Arduino we need to:
- Connect VCC pin to arduino 5v pin.
- Ground to ground.
- SDA pin to arduino analog pin A4
- SCL pin to Arduino Analog pin A5.
We have to use exactly those pins as they are meant for I2C comunication.
Summary
This tutorial shows how to use the RTC on the UNO R4 WiFi, such as setting a start time, setting an alarm, or obtaining time in calendar or unix format.
Read more about this board in the Arduino UNO R4 WiFi documentation.
Suggested changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. You can read more on how to contribute in the contribution policy.
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.
Components and supplies
Tactile Switch, Top Actuated
Arduino Nano R3
Alphanumeric LCD, 16 x 2
Trimmer Potentiometer, 10 kohm
Jumper wires
Project description
Code
Clock programme
arduino
Accurate clock with date just using and Arduino
1// Paul Brace – Feb 2021 2// Simple Clock with Date created just using a Arduino – no RTC module 3// Program incorporates a time correction adjustment to compensate for the internal 4// clock speed not being 100% accurate. 5// Once correct speed adjustment set the clock is surprisingly accurate. 6// In my test it did not lose or gain any time over a 5 day period. 7// Displays time on a 16×2 LCD display 8// Buttons to set time 9// Mode button (pin 2) toggles set time, set date and run 10// Button 1 (pin 3) Increments Minutes and Month and decreases Year/speed adj 11// Button 2 (pin 4) Increments Hour and Day and increases Year./speed adj 12// 24 Hour display 13 14// Include the library driver for display: 15#include
16 17// LiquidCrystal lcd( RS, EN, D4,D5, D6, D7) 18LiquidCrystal lcd(12, 13, 6, 7, 8, 9); // create an lcd object and assign the pins 19 20// Define buttons and buzzer connections 21#define MODE_BUTTON 2 22#define HOUR_BUTTON 3 // Same button different definitions to 23#define UP_BUTTON 3 // make code easier to understand 24#define DAY_BUTTON 3 25#define MINUTE_BUTTON 4 // Same button different definitions to 26#define DOWN_BUTTON 4 // make code easier to understand 27#define MONTH_BUTTON 4 28 29// Current mode settings 30#define SHOW_TIME 1 // 1 = running – show time 31#define SET_TIME 2 // 2 = time set 32#define SET_YEAR 3 // 3 = year set 33#define SET_DATE 4 // 4 = day/month set 34#define SET_SPEED_ADJ 5 // 5 = amend the speedCorrection variable 35 36int speedCorrection = 3545; // Number of milliseconds my Nano clock runs slow per hour 37// negative number here if it is running fast 38// change to match your Arduino 39 40// Volatile variables as changed in an interrupt and we 41// need to force the system to read the actual variable 42// when used outside the interrupt and not use a cached version 43volatile unsigned long currentTime; // Duration in milliseconds from midnight 44unsigned long lastTime = -1000; // lastTime that ShowTime was called initialised to -1000 so shows immediately 45volatile unsigned long elapsed; // Timer used for delay and hour count 46 47unsigned long millisecondsInADay; // Milliseconds in 24 hours 48unsigned long millisecondsInHour; // Milliseconds in 1 hour 49int currentMode; // 1 = running – show time 50// 2 = time set 51// 3 = year set 52// 4 = day/month set 53 54float currentDate; // Julian date 55float lastDate = 0.0; // last date that ShowDate was called 56int currentDay; 57int currentMonth; 58int currentYear; 59 60char *dayArray[] = { “Tue. “, // Will show a compiler warning but works fine 61 “Wed. “, 62 “Thur. “, 63 “Fri. “, 64 “Sat. “, 65 “Sun. “, 66 “Mon. ” 67 }; 68 69void setup() { 70 // Set up time interrupt – millis() rolls over after 50 days so 71 // we are using our own millisecond counter which we can reset at 72 // the end of each day 73 TCCR0A = (1 << WGM01); //Set the CTC mode Compare time and trigger interrupt 74 OCR0A = 0xF9; //Set value for time to compare to ORC0A for 1ms = 249 (8 bits so max is 256) 75 //[(Clock speed/Prescaler value)*Time in seconds] – 1 76 //[(16,000,000/64) * .001] – 1 = 249 = 1 millisecond 77 TIMSK0 |= (1 << OCIE0A); //set timer compare interrupt 78 TCCR0B |= (1 << CS01); //Set the prescale 1/64 clock 79 TCCR0B |= (1 << CS00); // ie 110 for last 3 bits 80 TCNT0 = 0; //initialize counter value to 0 81 sei(); //Enable interrupt 82 83 pinMode(MINUTE_BUTTON, INPUT_PULLUP); 84 pinMode(HOUR_BUTTON, INPUT_PULLUP); 85 pinMode(MODE_BUTTON, INPUT_PULLUP); 86 //pinMode(BUZZER, OUTPUT); 87 currentTime = 0; // Set to current time to mindnight 88 currentDate = JulianDate(1, 1, 2021); // Set base date 89 elapsed = 0; // Set period counter to 0 90 millisecondsInADay = 24ul * 60 * 60 * 1000; 91 millisecondsInHour = 60ul * 60 * 1000; 92 currentMode = SHOW_TIME; // Initial mode is running and showing time and date 93 // Setup LCD 94 lcd.begin(16, 2); 95 lcd.noAutoscroll(); 96 lcd.display(); 97 lcd.clear(); 98 ShowTime(currentTime); 99} 100 101void loop() { 102 // loop runs every 150 milliseconds 103 104 // If at end of the day reset time and increase date 105 if ((currentMode == SHOW_TIME) && 106 (currentTime > millisecondsInADay)) { 107 //Next day 108 // Stop interrupts while reset time 109 noInterrupts(); 110 currentTime -= millisecondsInADay; 111 interrupts(); 112 currentDate++; 113 } 114 // At the end of each hour adjust the elapsed time for 115 // the inacuracy in the Arduino clock 116 if (elapsed >= millisecondsInHour) { 117 noInterrupts(); 118 // Adjust time for slow/fast running Arduino clock 119 currentTime += speedCorrection; 120 // Reset to count the next hour 121 elapsed = 0; 122 interrupts(); 123 } 124 125 // Check if any buttons have been pressed 126 CheckButtons(); 127 128 // Show display based on current mode 129 switch (currentMode) { 130 case SHOW_TIME: 131 // Display current time and date 132 ShowTime(currentTime); 133 ShowDate(currentDate); 134 break; 135 case SET_TIME: 136 // Display screen for setting the time 137 ShowTimeSet(currentTime); 138 break; 139 case SET_YEAR: 140 // Display screen for setting the year 141 ShowYearSet(currentDate); 142 break; 143 case SET_DATE: 144 // Display screen for setting the day and month 145 ShowDDMMSet(currentDate); 146 break; 147 case SET_SPEED_ADJ: 148 // Display screen for adjusting the speed correction 149 ShowSpeedSet(); 150 break; 151 } 152 Wait(150); 153} 154 155// This is interrupt is called when the compare time has been reached 156// hence will be called once a millisecond based on the 157// OCR0A register setting. 158ISR(TIMER0_COMPA_vect) { 159 if (currentMode != SET_TIME) 160 currentTime++; 161 elapsed++; 162} 163 164float JulianDate(int iday, int imonth, int iyear) { 165 // Calculate julian date (tested up to the year 20,000) 166 unsigned long d = iday; 167 unsigned long m = imonth; 168 unsigned long y = iyear; 169 if (m < 3) { 170 m = m + 12; 171 y = y – 1; 172 } 173 unsigned long t1 = (153 * m – 457) / 5; 174 unsigned long t2 = 365 * y + (y / 4) – (y / 100) + (y / 400); 175 return 1721118.5 + d + t1 + t2; 176} 177 178void GregorianDate(float jd, int &iday, int &imonth, int &iyear) { 179 // Note 2100 is the next skipped leap year – compensates for skipped leap years 180 unsigned long f = jd + 68569.5; 181 unsigned long e = (4.0 * f) / 146097; 182 unsigned long g = f – (146097 * e + 3) / 4; 183 unsigned long h = 4000ul * (g + 1) / 1461001; 184 unsigned long t = g – (1461 * h / 4) + 31; 185 unsigned long u = (80ul * t) / 2447; 186 unsigned long v = u / 11; 187 iyear = 100 * (e – 49) + h + v; 188 imonth = u + 2 – 12 * v; 189 iday = t – 2447 * u / 80; 190} 191 192void SplitTime(unsigned long curr, unsigned long &ulHour, 193 unsigned long &ulMin, unsigned long &ulSec) { 194 // Calculate HH:MM:SS from millisecond count 195 ulSec = curr / 1000; 196 ulMin = ulSec / 60; 197 ulHour = ulMin / 60; 198 ulMin -= ulHour * 60; 199 ulSec = ulSec – ulMin * 60 – ulHour * 3600; 200} 201 202unsigned long SetTime(unsigned long ulHour, unsigned long ulMin, 203 unsigned long ulSec) { 204 // Sets the number of milliseconds from midnight to current time 205 return (ulHour * 60 * 60 * 1000) + 206 (ulMin * 60 * 1000) + 207 (ulSec * 1000); 208} 209 210void Wait(unsigned long value) { 211 // Create our own dealy function 212 // We have set our own interrupt on TCCR0A 213 // hence millis() and delay() will no longer work 214 unsigned long startTime = elapsed; 215 while ((elapsed – startTime) < value) { 216 // Just wait 217 } 218} 219 220void CheckButtons() { 221 // If the mode button has been pressed pin will go LOW 222 if (digitalRead(MODE_BUTTON) == LOW) { 223 // Advance to next mode 224 switch (currentMode) { 225 case SHOW_TIME: 226 currentMode = SET_TIME; 227 lcd.clear(); 228 break; 229 case SET_TIME: 230 currentMode = SET_YEAR; 231 lcd.clear(); 232 break; 233 case SET_YEAR: 234 currentMode = SET_DATE; 235 lcd.clear(); 236 break; 237 case SET_DATE: 238 currentMode = SET_SPEED_ADJ; 239 lcd.clear(); 240 break; 241 case SET_SPEED_ADJ: 242 currentMode = SHOW_TIME; 243 lcd.clear(); 244 // Reset variables so that the display will be forced to update 245 // the next time ShowTime and ShowDate are called 246 lastTime = 0; 247 lastDate = 0.0; 248 break; 249 } 250 } 251 if (currentMode != SHOW_TIME) { 252 switch (currentMode) { 253 // If mode anyhting other than SHOW_TIME check buttons 254 // Pin goes LOW when ssociated button pressed 255 case SET_TIME: 256 if (digitalRead(MINUTE_BUTTON) == LOW) { 257 // Advance minute 258 unsigned long iHours; 259 unsigned long iMinutes; 260 unsigned long iSeconds; 261 SplitTime(currentTime, iHours, iMinutes, iSeconds); 262 if (iMinutes < 59) { 263 iMinutes++; 264 } 265 else { 266 iMinutes = 0; 267 } 268 // Set stored milliseconds based on current setting 269 noInterrupts(); 270 currentTime = SetTime(iHours, iMinutes, 0); 271 elapsed = 0; 272 interrupts(); 273 } 274 if (digitalRead(HOUR_BUTTON) == LOW) { 275 // Advance hour 276 unsigned long iHours; 277 unsigned long iMinutes; 278 unsigned long iSeconds; 279 SplitTime(currentTime, iHours, iMinutes, iSeconds); 280 if (iHours < 23) { 281 iHours++; 282 } 283 else { 284 iHours = 0; 285 } 286 // Set stored milliseconds based on current setting 287 noInterrupts(); 288 currentTime = SetTime(iHours, iMinutes, 0); 289 elapsed = 0; 290 interrupts(); 291 } 292 break; 293 case SET_YEAR: 294 if (digitalRead(UP_BUTTON) == LOW) { 295 // Increase year 296 int iDay; 297 int iMonth; 298 int iYear; 299 GregorianDate(currentDate, iDay, iMonth, iYear); 300 iYear++; 301 // Set stored date based on current settings 302 currentDate = JulianDate(iDay, iMonth, iYear); 303 } 304 if (digitalRead(DOWN_BUTTON) == LOW) { 305 // Decrease year 306 int iDay; 307 int iMonth; 308 int iYear; 309 GregorianDate(currentDate, iDay, iMonth, iYear); 310 iYear–; 311 // Set stored date based on current settings 312 currentDate = JulianDate(iDay, iMonth, iYear); 313 } 314 break; 315 case SET_DATE: 316 if (digitalRead(MONTH_BUTTON) == LOW) { 317 // Advance month 318 int iDay; 319 int iMonth; 320 int iYear; 321 GregorianDate(currentDate, iDay, iMonth, iYear); 322 iMonth++; 323 if (iMonth > 12) { 324 iMonth = 1; 325 } 326 // Set stored date based on current settings 327 currentDate = JulianDate(iDay, iMonth, iYear); 328 } 329 if (digitalRead(DAY_BUTTON) == LOW) { 330 // Advance day 331 int iDay; 332 int iMonth; 333 int iYear; 334 GregorianDate(currentDate, iDay, iMonth, iYear); 335 iDay++; 336 if (iDay > 31) { 337 iDay = 1; 338 } 339 if (((iMonth == 4) || (iMonth == 6) || (iMonth == 9) || (iMonth == 11)) 340 && (iDay > 30)) { 341 iDay = 1; 342 } 343 if ((iMonth == 2) && (iDay > 29)) { 344 iDay = 1; 345 } 346 if ((iMonth == 2) && ((iYear % 4) != 0) && (iDay > 28)) { 347 iDay = 1; 348 } 349 // Set stored date based on current settings 350 // If subsequently adjust the month so day is not valid 351 // then display will advance to next valid date 352 currentDate = JulianDate(iDay, iMonth, iYear); 353 } 354 break; 355 case SET_SPEED_ADJ: 356 // increase or decrease correcton by 5 milliseconds 357 if (digitalRead(UP_BUTTON) == LOW) { 358 speedCorrection += 5; 359 } 360 if (digitalRead(DOWN_BUTTON) == LOW) { 361 speedCorrection -= 5; 362 } 363 break; 364 } 365 } 366} 367 368String FormatNumber(int value) { 369 // To add a leading 0 if required 370 if (value < 10) { 371 return “0” + String(value); 372 } 373 else { 374 return String(value); 375 } 376} 377 378void ShowTime(unsigned long value) { 379 // Update display once a second 380 // or when rolls over midnight 381 if ((value > lastTime + 1000) || (value < lastTime)) { 382 lastTime = value; 383 unsigned long iHours; 384 unsigned long iMinutes; 385 unsigned long iSeconds; 386 SplitTime(value, iHours, iMinutes, iSeconds); 387 388 // Display the time on line 0 389 lcd.setCursor(0, 0); 390 lcd.print(“Time: ” + FormatNumber(iHours) + “:” + 391 FormatNumber(iMinutes) + “:” + 392 FormatNumber(iSeconds)); 393 } 394} 395 396void ShowDate(float value) { 397 // Update display if date has changed since 398 // the date was last displayed 399 if (lastDate != value) { 400 lastDate = value; 401 int iday; 402 int imonth; 403 int iyear; 404 String currentDay; 405 GregorianDate(value, iday, imonth, iyear); 406 int dayOfWeek = (unsigned long)value % 7; 407 // Display the date on line 0 408 lcd.setCursor(0, 1); 409 lcd.print(dayArray[dayOfWeek]); 410 lcd.print(FormatNumber(iday) + “:” + 411 FormatNumber(imonth) + “:” + 412 iyear); 413 } 414} 415 416void ShowDDMMSet(float value) { 417 int iday; 418 int imonth; 419 int iyear; 420 String currentDay; 421 GregorianDate(value, iday, imonth, iyear); 422 // Display day and month for adjusting 423 lcd.setCursor(0, 0); 424 lcd.print(“Set day & month:”); 425 lcd.setCursor(0, 1); 426 lcd.print(“Day:” + FormatNumber(iday) + ” Month:” + 427 FormatNumber(imonth)); 428} 429 430 431void ShowYearSet(float jd) { 432 int iday; 433 int imonth; 434 int iyear; 435 GregorianDate(jd, iday, imonth, iyear); 436 // Display year for adjusting 437 lcd.setCursor(0, 0); 438 lcd.print(“Set year:”); 439 lcd.setCursor(0, 1); 440 lcd.print(“Year: ” + FormatNumber(iyear)); 441} 442 443void ShowTimeSet(unsigned long value) { 444 unsigned long iHours; 445 unsigned long iMinutes; 446 unsigned long iSeconds; 447 // Display time for adjusting 448 SplitTime(value, iHours, iMinutes, iSeconds); 449 lcd.setCursor(0, 0); 450 lcd.print(“Set time:”); 451 lcd.setCursor(0, 1); 452 lcd.print(“Hours:” + FormatNumber(iHours) + ” Mins:” + 453 FormatNumber(iMinutes)); 454} 455 456void ShowSpeedSet() { 457 // Display speed correction figure for adjusting 458 // could be + or – 459 lcd.setCursor(0, 0); 460 lcd.print(“Set speed adj:”); 461 lcd.setCursor(0, 1); 462 lcd.print(“Millis: “); 463 lcd.print(speedCorrection); 464 lcd.print(” “); 465}
Processing timer testing script
processing
This is the script for Processing that will read the milliseconds sent from the Arduino and compare it to the elapsed milliseconds in processing.
1// Paul Brace Feb 2021 2// Script to accept millis() from Arduino 3// and compare it to internal millis() to 4// assess inaccuracy of the Arduino clock. 5// Assumes that the computer clock is accurate 6// -ve = Arduino is running slow so enter as a +ve adjustment in the clock program 7// +ve = Arduino is running fast so enter as a -ve adjustment to slow the clock down 8 9import processing.serial.*; 10 11Serial theSerialPort; // create the serial port object 12 13int[] serialBytesArray = new int[15]; // array to store incoming bytes 14int bytesCount = 0; // current number of bytes received 15boolean init = false; // false until handshake completed by receiving the character Z 16int fillColor = 255; // defining the initial fill colour 17long mills = 0; // last reading received 18long first = 0; // time of first mills received so we can calculate the difference over an hour 19long now; // number of millis elapsed since first mills received 20long firstReading = 100000; // millis() in processing of first message received from Arduino 21long DiffPerHour = 0; // the difference after the first hour has passed 22int inByte; // last byte read 23 24void setup() { 25 // define some canvas and drawing parameters 26 size(500, 500); 27 background(70); 28 noStroke(); 29 30 // print the list of all serial devices so you know which one to set for the Arduino 31 // will need to run program and edit if the correct port is not set below 32 printArray(Serial.list()); 33 // instantate the Serial Communication 34 String thePortName = Serial.list()[1]; 35 theSerialPort = new Serial(this, thePortName, 9600); 36} 37void draw() { 38 // Display time settings 39 background(70); 40 fill(fillColor); 41 textSize(25); 42 text(hour() + “:” + minute() + “:” + second(), 50, 50); 43 // the last read millis sent by the Arduino 44 text(“Incoming elapsed: ” + mills, 50, 100); 45 // the current elapsed since first read in Processing 46 text(“Local elapsed: ” + (now – firstReading), 50, 150); 47 // display the current difference 48 text(“Diff: ” + (mills – (now – firstReading)), 50, 200); 49 // Check if 1 hour has passed and if the first hour store the difference 50 if (((now – firstReading)>= 3600000) && (DiffPerHour == 0)){ 51 DiffPerHour = mills – (now – firstReading); 52 } 53 // Display the first difference and the difference after the first hour 54 text(“Diff after 1 hour: ” + DiffPerHour, 50, 300); 55} 56 57void serialEvent(Serial myPort) { 58 // read a byte from the serial port 59 inByte = myPort.read(); 60 if (init == false) { // if not yet handshaked the see if handshake byte 61 if (inByte == ‘Z’) { // if the byte read is Z 62 myPort.clear(); // clear the serial port buffer 63 init = true; // store the fact we had the first hello 64 myPort.write(‘Z’); // tell the Arduino to send more 65 if (first == 0){ 66 first = millis(); 67 } 68 } 69 } 70 else { 71 // if there already was the first hello 72 // Add the latest byte from the serial port to array 73 if (inByte != 69) { // Check not the end of message character E 74 if (bytesCount < 14) { 75 serialBytesArray[bytesCount] = inByte; 76 bytesCount++; 77 } 78 } 79 if (inByte == 69) { 80 // End of message 81 // store local time elapsed 82 now = millis(); 83 // calculate incoming millis() 84 mills = 0; 85 for (int i = 1; i <= bytesCount; i++) { 86 mills += (serialBytesArray[i – 1] – 48) * pow(10, (bytesCount – i)); 87 } 88 // Say we are ready to accept next message 89 // if this is the first reading then set the first difference 90 if (firstReading == 100000) { 91 firstReading = now; 92 } 93 myPort.write(‘Z’); 94 // Reset bytesCount: 95 bytesCount = 0; 96 } 97 } 98}
Arduino timer program
arduino
This program sends the number of elapsed milliseconds to the serial port evert 2 seconds.
1// Paul Brace Feb 2021 2// For use with corresponding Processing script 3// to compare millis() from here to millis() in 4// Processing using the computer clock 5 6int inByte = 0; 7unsigned long firstReading = 100000; // millis() when first reading sent 8 9void setup() { 10 Serial.begin(9600); 11 // Send the hello byte to Processing 12 sayHello(); 13} 14 15void loop() { 16 // if a byte is received on the serial port 17 // then read and discard it and send current 18 // value of millis() 19 if (Serial.available() > 0){ 20 // get incoming byte 21 inByte = Serial.read(); 22 // send time elapsed since first reading processing 23 Serial.print(millis() – firstReading); 24 Serial.print(‘E’); 25 // repeat every 2 seconds 26 delay(2000); 27 } 28} 29 30void sayHello(){ 31 // Wait until the serial port is available 32 // then send hello byte to start handshake 33 while (Serial.available() <=0){ 34 Serial.print(‘Z’); // Send Z to processing to say Hello 35 delay(200); 36 } 37 firstReading = millis(); 38}
Processing timer testing script
processing
This is the script for Processing that will read the milliseconds sent from the Arduino and compare it to the elapsed milliseconds in processing.
1// Paul Brace Feb 2021 2// Script to accept millis() from Arduino 3// 4 and compare it to internal millis() to 5// assess inaccuracy of the Arduino clock. 6// 7 Assumes that the computer clock is accurate 8// -ve = Arduino is running slow 9 so enter as a +ve adjustment in the clock program 10// +ve = Arduino is running 11 fast so enter as a -ve adjustment to slow the clock down 12 13import processing.serial.*; 14 15Serial 16 theSerialPort; // create the serial port object 17 18int[] serialBytesArray 19 = new int[15]; // array to store incoming bytes 20int bytesCount = 0; // 21 current number of bytes received 22boolean init = false; // false 23 until handshake completed by receiving the character Z 24int fillColor = 255; // 25 defining the initial fill colour 26long mills = 0; // last 27 reading received 28long first = 0; // time of first mills 29 received so we can calculate the difference over an hour 30long now; // 31 number of millis elapsed since first mills received 32long firstReading = 100000; 33 // millis() in processing of first message received from Arduino 34long 35 DiffPerHour = 0; // the difference after the first hour has passed 36 37int inByte; // last byte read 38 39void setup() 40 { 41 // define some canvas and drawing parameters 42 size(500, 500); 43 background(70); 44 45 noStroke(); 46 47 // print the list of all serial devices so you know which 48 one to set for the Arduino 49 // will need to run program and edit if the correct 50 port is not set below 51 printArray(Serial.list()); 52 // instantate the Serial 53 Communication 54 String thePortName = Serial.list()[1]; 55 theSerialPort = new 56 Serial(this, thePortName, 9600); 57} 58void draw() { 59 // Display time settings 60 61 background(70); 62 fill(fillColor); 63 textSize(25); 64 text(hour() + “:” 65 + minute() + “:” + second(), 50, 50); 66 // the last read millis sent by the 67 Arduino 68 text(“Incoming elapsed: ” + mills, 50, 100); 69 // the current 70 elapsed since first read in Processing 71 text(“Local elapsed: ” + (now – firstReading), 72 50, 150); 73 // display the current difference 74 text(“Diff: ” + (mills – 75 (now – firstReading)), 50, 200); 76 // Check if 1 hour has passed and if the first 77 hour store the difference 78 if (((now – firstReading)>= 3600000) && (DiffPerHour 79 == 0)){ 80 DiffPerHour = mills – (now – firstReading); 81 } 82 // Display 83 the first difference and the difference after the first hour 84 text(“Diff after 85 1 hour: ” + DiffPerHour, 50, 300); 86} 87 88void serialEvent(Serial myPort) 89 { 90 // read a byte from the serial port 91 inByte = myPort.read(); 92 if 93 (init == false) { // if not yet handshaked the see if handshake byte 94 95 if (inByte == ‘Z’) { // if the byte read is Z 96 myPort.clear(); 97 // clear the serial port buffer 98 init = true; // store 99 the fact we had the first hello 100 myPort.write(‘Z’); // tell the Arduino 101 to send more 102 if (first == 0){ 103 first = millis(); 104 } 105 106 } 107 } 108 else { 109 // if there already was 110 the first hello 111 // Add the latest byte from the serial port to array 112 113 if (inByte != 69) { // Check not the end of message character E 114 115 if (bytesCount < 14) { 116 serialBytesArray[bytesCount] = inByte; 117 118 bytesCount++; 119 } 120 } 121 if (inByte == 69) { 122 // 123 End of message 124 // store local time elapsed 125 now = millis(); 126 127 // calculate incoming millis() 128 mills = 0; 129 for (int i = 1; 130 i <= bytesCount; i++) { 131 mills += (serialBytesArray[i – 1] – 48) * pow(10, 132 (bytesCount – i)); 133 } 134 // Say we are ready to accept next message 135 136 // if this is the first reading then set the first difference 137 if 138 (firstReading == 100000) { 139 firstReading = now; 140 } 141 myPort.write(‘Z’); 142 143 // Reset bytesCount: 144 bytesCount = 0; 145 } 146 } 147}
Clock programme
arduino
Accurate clock with date just using and Arduino
1// Paul Brace – Feb 2021 2// Simple Clock with Date created just using a Arduino – no RTC module 3// Program incorporates a time correction adjustment to compensate for the internal 4// clock speed not being 100% accurate. 5// Once correct speed adjustment set the clock is surprisingly accurate. 6// In my test it did not lose or gain any time over a 5 day period. 7// Displays time on a 16×2 LCD display 8// Buttons to set time 9// Mode button (pin 2) toggles set time, set date and run 10// Button 1 (pin 3) Increments Minutes and Month and decreases Year/speed adj 11// Button 2 (pin 4) Increments Hour and Day and increases Year./speed adj 12// 24 Hour display 13 14// Include the library driver for display: 15#include
16 17// LiquidCrystal lcd( RS, EN, D4,D5, D6, D7) 18LiquidCrystal lcd(12, 13, 6, 7, 8, 9); // create an lcd object and assign the pins 19 20// Define buttons and buzzer connections 21#define MODE_BUTTON 2 22#define HOUR_BUTTON 3 // Same button different definitions to 23#define UP_BUTTON 3 // make code easier to understand 24#define DAY_BUTTON 3 25#define MINUTE_BUTTON 4 // Same button different definitions to 26#define DOWN_BUTTON 4 // make code easier to understand 27#define MONTH_BUTTON 4 28 29// Current mode settings 30#define SHOW_TIME 1 // 1 = running – show time 31#define SET_TIME 2 // 2 = time set 32#define SET_YEAR 3 // 3 = year set 33#define SET_DATE 4 // 4 = day/month set 34#define SET_SPEED_ADJ 5 // 5 = amend the speedCorrection variable 35 36int speedCorrection = 3545; // Number of milliseconds my Nano clock runs slow per hour 37// negative number here if it is running fast 38// change to match your Arduino 39 40// Volatile variables as changed in an interrupt and we 41// need to force the system to read the actual variable 42// when used outside the interrupt and not use a cached version 43volatile unsigned long currentTime; // Duration in milliseconds from midnight 44unsigned long lastTime = -1000; // lastTime that ShowTime was called initialised to -1000 so shows immediately 45volatile unsigned long elapsed; // Timer used for delay and hour count 46 47unsigned long millisecondsInADay; // Milliseconds in 24 hours 48unsigned long millisecondsInHour; // Milliseconds in 1 hour 49int currentMode; // 1 = running – show time 50// 2 = time set 51// 3 = year set 52// 4 = day/month set 53 54float currentDate; // Julian date 55float lastDate = 0.0; // last date that ShowDate was called 56int currentDay; 57int currentMonth; 58int currentYear; 59 60char *dayArray[] = { “Tue. “, // Will show a compiler warning but works fine 61 “Wed. “, 62 “Thur. “, 63 “Fri. “, 64 “Sat. “, 65 “Sun. “, 66 “Mon. ” 67 }; 68 69void setup() { 70 // Set up time interrupt – millis() rolls over after 50 days so 71 // we are using our own millisecond counter which we can reset at 72 // the end of each day 73 TCCR0A = (1 << WGM01); //Set the CTC mode Compare time and trigger interrupt 74 OCR0A = 0xF9; //Set value for time to compare to ORC0A for 1ms = 249 (8 bits so max is 256) 75 //[(Clock speed/Prescaler value)*Time in seconds] – 1 76 //[(16,000,000/64) * .001] – 1 = 249 = 1 millisecond 77 TIMSK0 |= (1 << OCIE0A); //set timer compare interrupt 78 TCCR0B |= (1 << CS01); //Set the prescale 1/64 clock 79 TCCR0B |= (1 << CS00); // ie 110 for last 3 bits 80 TCNT0 = 0; //initialize counter value to 0 81 sei(); //Enable interrupt 82 83 pinMode(MINUTE_BUTTON, INPUT_PULLUP); 84 pinMode(HOUR_BUTTON, INPUT_PULLUP); 85 pinMode(MODE_BUTTON, INPUT_PULLUP); 86 //pinMode(BUZZER, OUTPUT); 87 currentTime = 0; // Set to current time to mindnight 88 currentDate = JulianDate(1, 1, 2021); // Set base date 89 elapsed = 0; // Set period counter to 0 90 millisecondsInADay = 24ul * 60 * 60 * 1000; 91 millisecondsInHour = 60ul * 60 * 1000; 92 currentMode = SHOW_TIME; // Initial mode is running and showing time and date 93 // Setup LCD 94 lcd.begin(16, 2); 95 lcd.noAutoscroll(); 96 lcd.display(); 97 lcd.clear(); 98 ShowTime(currentTime); 99} 100 101void loop() { 102 // loop runs every 150 milliseconds 103 104 // If at end of the day reset time and increase date 105 if ((currentMode == SHOW_TIME) && 106 (currentTime > millisecondsInADay)) { 107 //Next day 108 // Stop interrupts while reset time 109 noInterrupts(); 110 currentTime -= millisecondsInADay; 111 interrupts(); 112 currentDate++; 113 } 114 // At the end of each hour adjust the elapsed time for 115 // the inacuracy in the Arduino clock 116 if (elapsed >= millisecondsInHour) { 117 noInterrupts(); 118 // Adjust time for slow/fast running Arduino clock 119 currentTime += speedCorrection; 120 // Reset to count the next hour 121 elapsed = 0; 122 interrupts(); 123 } 124 125 // Check if any buttons have been pressed 126 CheckButtons(); 127 128 // Show display based on current mode 129 switch (currentMode) { 130 case SHOW_TIME: 131 // Display current time and date 132 ShowTime(currentTime); 133 ShowDate(currentDate); 134 break; 135 case SET_TIME: 136 // Display screen for setting the time 137 ShowTimeSet(currentTime); 138 break; 139 case SET_YEAR: 140 // Display screen for setting the year 141 ShowYearSet(currentDate); 142 break; 143 case SET_DATE: 144 // Display screen for setting the day and month 145 ShowDDMMSet(currentDate); 146 break; 147 case SET_SPEED_ADJ: 148 // Display screen for adjusting the speed correction 149 ShowSpeedSet(); 150 break; 151 } 152 Wait(150); 153} 154 155// This is interrupt is called when the compare time has been reached 156// hence will be called once a millisecond based on the 157// OCR0A register setting. 158ISR(TIMER0_COMPA_vect) { 159 if (currentMode != SET_TIME) 160 currentTime++; 161 elapsed++; 162} 163 164float JulianDate(int iday, int imonth, int iyear) { 165 // Calculate julian date (tested up to the year 20,000) 166 unsigned long d = iday; 167 unsigned long m = imonth; 168 unsigned long y = iyear; 169 if (m < 3) { 170 m = m + 12; 171 y = y – 1; 172 } 173 unsigned long t1 = (153 * m – 457) / 5; 174 unsigned long t2 = 365 * y + (y / 4) – (y / 100) + (y / 400); 175 return 1721118.5 + d + t1 + t2; 176} 177 178void GregorianDate(float jd, int &iday, int &imonth, int &iyear) { 179 // Note 2100 is the next skipped leap year – compensates for skipped leap years 180 unsigned long f = jd + 68569.5; 181 unsigned long e = (4.0 * f) / 146097; 182 unsigned long g = f – (146097 * e + 3) / 4; 183 unsigned long h = 4000ul * (g + 1) / 1461001; 184 unsigned long t = g – (1461 * h / 4) + 31; 185 unsigned long u = (80ul * t) / 2447; 186 unsigned long v = u / 11; 187 iyear = 100 * (e – 49) + h + v; 188 imonth = u + 2 – 12 * v; 189 iday = t – 2447 * u / 80; 190} 191 192void SplitTime(unsigned long curr, unsigned long &ulHour, 193 unsigned long &ulMin, unsigned long &ulSec) { 194 // Calculate HH:MM:SS from millisecond count 195 ulSec = curr / 1000; 196 ulMin = ulSec / 60; 197 ulHour = ulMin / 60; 198 ulMin -= ulHour * 60; 199 ulSec = ulSec – ulMin * 60 – ulHour * 3600; 200} 201 202unsigned long SetTime(unsigned long ulHour, unsigned long ulMin, 203 unsigned long ulSec) { 204 // Sets the number of milliseconds from midnight to current time 205 return (ulHour * 60 * 60 * 1000) + 206 (ulMin * 60 * 1000) + 207 (ulSec * 1000); 208} 209 210void Wait(unsigned long value) { 211 // Create our own dealy function 212 // We have set our own interrupt on TCCR0A 213 // hence millis() and delay() will no longer work 214 unsigned long startTime = elapsed; 215 while ((elapsed – startTime) < value) { 216 // Just wait 217 } 218} 219 220void CheckButtons() { 221 // If the mode button has been pressed pin will go LOW 222 if (digitalRead(MODE_BUTTON) == LOW) { 223 // Advance to next mode 224 switch (currentMode) { 225 case SHOW_TIME: 226 currentMode = SET_TIME; 227 lcd.clear(); 228 break; 229 case SET_TIME: 230 currentMode = SET_YEAR; 231 lcd.clear(); 232 break; 233 case SET_YEAR: 234 currentMode = SET_DATE; 235 lcd.clear(); 236 break; 237 case SET_DATE: 238 currentMode = SET_SPEED_ADJ; 239 lcd.clear(); 240 break; 241 case SET_SPEED_ADJ: 242 currentMode = SHOW_TIME; 243 lcd.clear(); 244 // Reset variables so that the display will be forced to update 245 // the next time ShowTime and ShowDate are called 246 lastTime = 0; 247 lastDate = 0.0; 248 break; 249 } 250 } 251 if (currentMode != SHOW_TIME) { 252 switch (currentMode) { 253 // If mode anyhting other than SHOW_TIME check buttons 254 // Pin goes LOW when ssociated button pressed 255 case SET_TIME: 256 if (digitalRead(MINUTE_BUTTON) == LOW) { 257 // Advance minute 258 unsigned long iHours; 259 unsigned long iMinutes; 260 unsigned long iSeconds; 261 SplitTime(currentTime, iHours, iMinutes, iSeconds); 262 if (iMinutes < 59) { 263 iMinutes++; 264 } 265 else { 266 iMinutes = 0; 267 } 268 // Set stored milliseconds based on current setting 269 noInterrupts(); 270 currentTime = SetTime(iHours, iMinutes, 0); 271 elapsed = 0; 272 interrupts(); 273 } 274 if (digitalRead(HOUR_BUTTON) == LOW) { 275 // Advance hour 276 unsigned long iHours; 277 unsigned long iMinutes; 278 unsigned long iSeconds; 279 SplitTime(currentTime, iHours, iMinutes, iSeconds); 280 if (iHours < 23) { 281 iHours++; 282 } 283 else { 284 iHours = 0; 285 } 286 // Set stored milliseconds based on current setting 287 noInterrupts(); 288 currentTime = SetTime(iHours, iMinutes, 0); 289 elapsed = 0; 290 interrupts(); 291 } 292 break; 293 case SET_YEAR: 294 if (digitalRead(UP_BUTTON) == LOW) { 295 // Increase year 296 int iDay; 297 int iMonth; 298 int iYear; 299 GregorianDate(currentDate, iDay, iMonth, iYear); 300 iYear++; 301 // Set stored date based on current settings 302 currentDate = JulianDate(iDay, iMonth, iYear); 303 } 304 if (digitalRead(DOWN_BUTTON) == LOW) { 305 // Decrease year 306 int iDay; 307 int iMonth; 308 int iYear; 309 GregorianDate(currentDate, iDay, iMonth, iYear); 310 iYear–; 311 // Set stored date based on current settings 312 currentDate = JulianDate(iDay, iMonth, iYear); 313 } 314 break; 315 case SET_DATE: 316 if (digitalRead(MONTH_BUTTON) == LOW) { 317 // Advance month 318 int iDay; 319 int iMonth; 320 int iYear; 321 GregorianDate(currentDate, iDay, iMonth, iYear); 322 iMonth++; 323 if (iMonth > 12) { 324 iMonth = 1; 325 } 326 // Set stored date based on current settings 327 currentDate = JulianDate(iDay, iMonth, iYear); 328 } 329 if (digitalRead(DAY_BUTTON) == LOW) { 330 // Advance day 331 int iDay; 332 int iMonth; 333 int iYear; 334 GregorianDate(currentDate, iDay, iMonth, iYear); 335 iDay++; 336 if (iDay > 31) { 337 iDay = 1; 338 } 339 if (((iMonth == 4) || (iMonth == 6) || (iMonth == 9) || (iMonth == 11)) 340 && (iDay > 30)) { 341 iDay = 1; 342 } 343 if ((iMonth == 2) && (iDay > 29)) { 344 iDay = 1; 345 } 346 if ((iMonth == 2) && ((iYear % 4) != 0) && (iDay > 28)) { 347 iDay = 1; 348 } 349 // Set stored date based on current settings 350 // If subsequently adjust the month so day is not valid 351 // then display will advance to next valid date 352 currentDate = JulianDate(iDay, iMonth, iYear); 353 } 354 break; 355 case SET_SPEED_ADJ: 356 // increase or decrease correcton by 5 milliseconds 357 if (digitalRead(UP_BUTTON) == LOW) { 358 speedCorrection += 5; 359 } 360 if (digitalRead(DOWN_BUTTON) == LOW) { 361 speedCorrection -= 5; 362 } 363 break; 364 } 365 } 366} 367 368String FormatNumber(int value) { 369 // To add a leading 0 if required 370 if (value < 10) { 371 return “0” + String(value); 372 } 373 else { 374 return String(value); 375 } 376} 377 378void ShowTime(unsigned long value) { 379 // Update display once a second 380 // or when rolls over midnight 381 if ((value > lastTime + 1000) || (value < lastTime)) { 382 lastTime = value; 383 unsigned long iHours; 384 unsigned long iMinutes; 385 unsigned long iSeconds; 386 SplitTime(value, iHours, iMinutes, iSeconds); 387 388 // Display the time on line 0 389 lcd.setCursor(0, 0); 390 lcd.print(“Time: ” + FormatNumber(iHours) + “:” + 391 FormatNumber(iMinutes) + “:” + 392 FormatNumber(iSeconds)); 393 } 394} 395 396void ShowDate(float value) { 397 // Update display if date has changed since 398 // the date was last displayed 399 if (lastDate != value) { 400 lastDate = value; 401 int iday; 402 int imonth; 403 int iyear; 404 String currentDay; 405 GregorianDate(value, iday, imonth, iyear); 406 int dayOfWeek = (unsigned long)value % 7; 407 // Display the date on line 0 408 lcd.setCursor(0, 1); 409 lcd.print(dayArray[dayOfWeek]); 410 lcd.print(FormatNumber(iday) + “:” + 411 FormatNumber(imonth) + “:” + 412 iyear); 413 } 414} 415 416void ShowDDMMSet(float value) { 417 int iday; 418 int imonth; 419 int iyear; 420 String currentDay; 421 GregorianDate(value, iday, imonth, iyear); 422 // Display day and month for adjusting 423 lcd.setCursor(0, 0); 424 lcd.print(“Set day & month:”); 425 lcd.setCursor(0, 1); 426 lcd.print(“Day:” + FormatNumber(iday) + ” Month:” + 427 FormatNumber(imonth)); 428} 429 430 431void ShowYearSet(float jd) { 432 int iday; 433 int imonth; 434 int iyear; 435 GregorianDate(jd, iday, imonth, iyear); 436 // Display year for adjusting 437 lcd.setCursor(0, 0); 438 lcd.print(“Set year:”); 439 lcd.setCursor(0, 1); 440 lcd.print(“Year: ” + FormatNumber(iyear)); 441} 442 443void ShowTimeSet(unsigned long value) { 444 unsigned long iHours; 445 unsigned long iMinutes; 446 unsigned long iSeconds; 447 // Display time for adjusting 448 SplitTime(value, iHours, iMinutes, iSeconds); 449 lcd.setCursor(0, 0); 450 lcd.print(“Set time:”); 451 lcd.setCursor(0, 1); 452 lcd.print(“Hours:” + FormatNumber(iHours) + ” Mins:” + 453 FormatNumber(iMinutes)); 454} 455 456void ShowSpeedSet() { 457 // Display speed correction figure for adjusting 458 // could be + or – 459 lcd.setCursor(0, 0); 460 lcd.print(“Set speed adj:”); 461 lcd.setCursor(0, 1); 462 lcd.print(“Millis: “); 463 lcd.print(speedCorrection); 464 lcd.print(” “); 465}
Arduino timer program
arduino
This program sends the number of elapsed milliseconds to the serial port evert 2 seconds.
1// Paul Brace Feb 2021 2// For use with corresponding Processing script 3// 4 to compare millis() from here to millis() in 5// Processing using the computer 6 clock 7 8int inByte = 0; 9unsigned long firstReading = 100000; // millis() 10 when first reading sent 11 12void setup() { 13 Serial.begin(9600); 14 // Send 15 the hello byte to Processing 16 sayHello(); 17} 18 19void loop() { 20 // 21 if a byte is received on the serial port 22 // then read and discard it and send 23 current 24 // value of millis() 25 if (Serial.available() > 0){ 26 // get 27 incoming byte 28 inByte = Serial.read(); 29 // send time elapsed since first 30 reading processing 31 Serial.print(millis() – firstReading); 32 Serial.print(‘E’); 33 34 // repeat every 2 seconds 35 delay(2000); 36 } 37} 38 39void sayHello(){ 40 41 // Wait until the serial port is available 42 // then send hello byte to start 43 handshake 44 while (Serial.available() <=0){ 45 Serial.print(‘Z’); // 46 Send Z to processing to say Hello 47 delay(200); 48 } 49 firstReading = 50 millis(); 51}
Downloadable files
Clock LCD 16×2 Breadboard
Clock LCD 16×2 Breadboard
Clock LCD 16×2 Breadboard
Clock LCD 16×2 Breadboard
Clock LCD 16×2 Schematic
Clock LCD 16×2 Schematic
Comments
Only logged in users can leave comments
paulsb
0 Followers
•
0 Projects
Table of contents
Intro
31
Why Keep Track of the Date and Time?
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.
Comments
of what essence is the…
of what essence is the EEPROM. will the ds3231 still function if i reove it?
Module Thời Gian Thực RTC DS3231
DS3231 Real-time Clock Module
Mã sản phẩm: 6W68
Có 1 chi nhánh đang còn hàng.
Xem chi nhánh còn hàng
Module Thời Gian Thực RTC DS3231 Điện thế hoạt động 3.3 – 5.5V, I2C bus có tốc độ tối đa 400Khz, Khối lượng 8g
- Cộng thêm 4 điểm tích lũy
-
TP.HCM: Miễn phí vận chuyển đơn hàng từ 300k
Tỉnh thành khác: Miễn phí vận chuyển đơn hàng từ 500k
Xem thêm các khuyến mãi vận chuyển khác.
Step 9: Conclusion
Thank you for spending time reading through this tutorial.
I stronglt encourage you to watch the Youtube video at the beginnig of this tutorial which shows the code creation and you can see the final result.
If you find this tutorial useful please give this youtube video a like. It helps me to create similar content.
Here you will find link to the code:
If you like this content and you want to support me in creating similar videos go to my Patreon webpage https://www.patreon.com/MariosIdeas Or Paypal
Written by David Meaney, Vice President of Global Technical Sales and Marketing at ECS Inc. International
Lời kết
Bài viết khá dài nên mình sẽ tạm dừng ở đây, trong bài viết tiếp theo mình sẽ hướng dẫn các bạn cách hiển thị thời gian thực DS1307 lên màn hình LCD16X2 các bạn đón xem nhé.
Tham gia cộng đồng Arduino KIT Để nhận được nhiều kiến thức bổ ích, các bạn Đăng ký để nhận thông báo khi có bài viết mới nhé. Tham gia Cộng đồng Arduino KIT để cùng nhau thảo luận và chia sẽ kiến thức về lập trình Arduino. Nếu các bạn thấy bài viết bổ ích nhớ Like và Share cho mọi người cùng học nhé. |
Chúc các bạn thành công.
Trân trọng.
Arduino UNO R4 Minima Real-Time Clock
Learn how to access the real-time clock (RTC) on the UNO R4 Minima.
In this tutorial you will learn how to access the real-time clock (RTC) on an Arduino UNO R4 Minima board. The RTC is embedded in the UNO R4 Minima’s microcontroller (RA4M1).
How to Get the Current Date and Time on an Arduino
There are several ways to get the current date and time. We can get it from a Real-Time Clock (RTC), a GPS device, or a time server.
- 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.
An RTC is a very popular and accurate source of time and date in an embedded system like an Arduino because it has low power consumption.
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.
Code:
#include
#include#include “RTClib.h” RTC_DS1307 rtc; char daysOfTheWeek[7][12] = {“Sun”, “Mon”, “Tue”, “Wed”, “Thu”, “Fri”, “Sat”}; void setup () { Serial.begin(9600); if (! rtc.begin()) { Serial.print(“Couldn’t find RTC”); while (1); } if (! rtc.isrunning()) { Serial.print(“RTC is NOT running!”); Serial.println(); } rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); //rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); } void loop () { DateTime now = rtc.now(); if(now.hour()<=9) { Serial.print(“0”); Serial.print(now.hour()); } else { Serial.print(now.hour()); } Serial.print(‘:’); if(now.minute()<=9) { Serial.print(“0”); Serial.print(now.minute()); } else { Serial.print(now.minute()); } Serial.print(‘:’); if(now.second()<=9) { Serial.print(“0”); Serial.print(now.second()); } else { Serial.print(now.second()); } Serial.println(); Serial.print(daysOfTheWeek[now.dayOfTheWeek()]); Serial.print(“,”); if(now.day()<=9) { Serial.print(“0”); Serial.print(now.day()); } else { Serial.print(now.day()); } Serial.print(‘/’); if(now.month()<=9) { Serial.print(“0”); Serial.print(now.month()); } else { Serial.print(now.month()); } Serial.print(‘/’); if(now.year()<=9) { Serial.print(“0”); Serial.print(now.year()); } else { Serial.print(now.year()); } Serial.println(); delay(1000); }
Introduction to Real Time Clocks
At ECS Inc. International, we offer the widest breadth of product in the electronics industry. Our portfolio includes tuning fork watch crystals, quartz crystals, oscillators, VCXOs, TCXOs, OCXOs, real time clocks (RTC), and miniature shielded power inductors. ECS Inc. is a recognized industry leader in frequency control and power management products. Our products are widely used in IoT, wearables, consumer products, automotive electronics, and medical products.
DS3231 Real Time Clock
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.
The module can work on either 3.3 or 5 V which makes it suitable for many development platforms or microcontrollers. The battery input is 3V and a typical CR2032 3V battery can power the module and maintain the information for more than a year.
The module uses the I2C Communication Protocol which makes the connection to the Arduino Board very easy.
Here’s the circuit schematics:
So all we need is 4 wires, the VCC and the GND pins for powering the module, and the two I2C communication pins, SDA and SCL.
You can get the components needed for this Arduino Tutorial from the links below:
- DS3231 Real Time Clock…………….. Amazon / Banggood / AliExpress
- Arduino Board …………………………… Amazon / Banggood / AliExpress
- Breadboard and Jump Wires ……… Amazon / Banggood / AliExpress
Disclosure: These are affiliate links. As an Amazon Associate I earn from qualifying purchases.
Sơ đồ đấu nối
Arduino UNO | Module RTC DS1307 |
GND | GND |
5V | GND |
A4 | SDA |
A5 | SCL |
Các linh kiện cần thiết cho dự án:
Tên linh kiện | Số lượng | Shopee |
Arduino Uno R3 | Mua ngay | |
Cáp nạp | Mua ngay | |
RTC DS1307 | Mua ngay | |
Dây cắm (Đực – Cái) | Mua ngay |
Bạn sẽ học được gì
- Có kiến thức cơ bản về Robotics
- Chế tạo Robot dò đường thông minh
- Đánh thức nhà khoa học bên trong bạn
- Tìm hiểu thêm về Robotics, các thuật toán Robot tự động
- Kiến thức nền tảng để chế tạo các máy móc tự động phục vụ đời sống sinh hoạt, lao động sản xuất
- Kiến thức để chế tạo sản phẩm, tham gia các cuộc thi khoa học công nghệ trong nước và quốc tế
What is a Real Time Clock (RTC)?
A real time clock, or RTC, is a digital clock with a primary function to keep accurate track of time even when a power supply is turned off or a device is placed in low power mode. RTC’s are comprised of a controller, oscillator, and an embedded quartz crystal resonator. They are engineered as all-in-one devices to provide better performances than discrete components, simplify integration in new designs, and accelerate time to market.
Functions of the RTC are called registers. Register data is programmed into RAM memory. The registers are updated periodically – even during normal RTC operation. The RTC design also includes a power switch function to battery operation or another low power backup power source. This allows the RTC to maintain precise and continuous time counts even if the unit goes into sleep mode or if main power is lost. It also alleviates the need for the user to reset the time and date every time the device supply is cycled.
RTCs are used in a variety of applications where they play a critical role in keeping accurate track of the current time while also providing alarms, timers, and interrupt functions and helping to reduce power consumption.
How RTCs are used today
Many of today’s products are powered by batteries and have limited or no access to battery replacements or recharging power sources. Because of the lack of power sources, having all systems and sensor functions running continuously would quickly drain the battery of these devices. The solution is to have scheduled intermittent activation of the product to greatly extend the life of the battery. The use of a RTC allows the designer to power down the high current usage microcontroller when no task is required, resulting in significant power savings. When microcontrollers are in a deep sleep or low-power mode, the RTCs internal clock and circuitry will keep running to maintain accurate timekeeping and alarm functions. In this mode, the current draw will be as low as 0.5uA.
The real time clock (RTC) module solves the current draw problem by always staying on and being the lowest current usage device when no other task is required. Even when the RTC is not used as a power saving device, the continuous timekeeping function is critical for the proper function of today’s electronics, medical devices, and industrial products where power savings and backup timekeeping are at premium.
Overview of ECSRTC Modules
ECS Inc. International’s ECS-RTC-3225-5609 and ECS-RTC-3225-5699HS are small form factor I2C bus interface real time clocks with low power consumption and an embedded 32.768 kHz TCXO. The precise temperature sensor and temperature compensated circuit ensure clock accuracy. They support specialized calendar and timer functions and are ideal for portable and small electronic devices. The real time clock module offers selectable output frequencies (32.768 kHz, 1024 Hz, 1 Hz) and enabled/disabled single CMOS output for peripheral devices.
The ECS-RTC-3225-5609 and ECS-RTC-3225-5609 real time clocks use a precise quartz resonator driving a microcontroller to control time-based functions. These real time clock modules allow engineers the flexibility to overcome modern design-based challenges. Our connected world requires interoperability with increased performance and reduced power consumption.
The real time clock module saves space, time, and money by designing the entire integrated circuit into a small form factor package. This allows engineers to reduce part counts and minimize the footprint. Because real time clocks are factory calibrated, they do not require additional oscillator adjustment during the design phase or tuning during operation.
Size and interface of the ECSRTC Modules
To minimize the impact on the system board, both the ECS-RTC-3225-5609 and -5699HS are available in a 3.2mm x 2.5 mm x 1.0mm package.
An I2C interface is a simple, bidirectional two-wire synchronous serial bus. I2C bus supports bi-directional communications through a serial clock line (SCL) pin 5 and a serial data line in/out (SDA) pin 7. I2C bus device can be defined as ‘master’ and ‘slave’. The ECS RTC modules can only be used as slave. I2C bus interface supports single byte read/write operations as well as multiple bytes incremental access.
Stability of the ECSRTC Modules
The stability is linked to the performance of the 32.768 kHz crystal and oscillator embedded in the RTC. Its performance may deteriorate by changes in temperature or effects caused by the aging. With the ECS-RTC-3225-5609 and ECS-RTC-3225-5699HS being hermetically sealed, having integrated crystal resonators, and RTC circuitry, they minimize the effects temperature, pressure, and humidity have on the performance of the module.
- Operation tamperature range: -40ºC ~ +85ºC
-
Stability over temperature:
-
ECS-RTC-3225-5609
- < ±5ppm @ -20ºC ~ +70ºC
- < ±20ppm @ -40ºC ~ +85ºC
-
ECS-RTC-3225-5699HS
- < ±5ppm @ -40ºC ~ +85ºC
-
ECS-RTC-3225-5609
- ECS-RTC-3225-5609
RTC interrupts and variations
The RTC can produce various types of interrupts (pin 10). During operation, the RTC can be programmed to send out an alarm or trigger flag to provide an entire clock and calendar. These interrupt functions are active when the RTC is operating on the backup source (Vbat power state). For every interrupt occurrence and variation, the RTC will create a digital timestamp of the event to review consistencies.
Examples of RTC interrupts include periodic time updates, periodic countdown for timers, low voltage detectors, automatic power source switchover, power on reset, and alarms. Alarms are based on timing settings in the registers. An alarm interrupt is generated with then time matches the setting’s registers, then the /INT pin 10 goes to low level and triggers the alarm interrupt. This will be the same for the countdown timers for a notification that an event has occurred.
Do the ECSRTC modules need to be calibrated?
No user calibration is required with the ECS-RTC-3225-5609 or ECS-RTC-3225-5699HS as they are accurately calibrated during manufacturing process using highly accurate timing reference units. Because the devices are calibrated, all errors involved in timing, measurement, and digitizing temperature values are included in the specifications.
Potential RTC power supply and backup sources
An RTC will typically be powered by a main system power supply during normal operation. However, a dedicated backup power source is required for an RTC to keep accurate track of time without interruption and maintain timekeeping after a power outage. The ECS Inc. ECS-RTC-3225-5609 and ECS-RTC-3225-5699HS are built to detect low level or missing main supply voltage and will automatically switch to a battery or secondary supply that maintains the internal clock. It will continue to draw on the backup source until the main system power has been restored or battery recharged.
The most common source of backup power will be a coin cell or rechargeable battery. Other options are a MLCC or super capacitor. Power may also be available from another nearby source.
For more information on ECS Inc. International’s full real time clock catalog, click here.
To see ECS Inc. International’s full product catalog, click here.
For additional video resources, click here.
Please contact us if you need additional information or have a specific requirement in your application.
ECS Inc. International15351 West 109th StreetLenexa, KS 66219
Tel: 913-782-7787Toll Free: 1-800-237-1041Fax: 913-782-6991
Đồng hồ thời gian thực (Read Time Clock – DS1307) sử dụng Arduino
Đồng hồ thời gian thực hay còn gọi với cái tên là Read Time Clock sử dụng Module DS1307. Được sử dụng rất phổ biến trong các ứng dụng của Arduino.
Để có thể làm việc với module này chúng ta cần sử dụng một chuẩn giao tiếp cũng khá quen thuộc là I2C Bus.
Để các bạn có thể hiểu rõ hơn chúng ta đi ngay vào bài viết nhé.
Xem thêm: Hướng dẫn sử dụng Module thời gian thực RTC DS3231 với Arduino
Programming
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.
For this tutorial I chose to use the Library made by Henning Karlsen which can be found and downloaded from his website, www.rinkydinkelectronics.com.
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.
// Code from the Demo Example of the DS3231 Library void setup() { // Setup Serial connection Serial.begin(115200); // Uncomment the next line if you are using an Arduino Leonardo //while (!Serial) {} // Initialize the rtc object rtc.begin(); // The following lines can be uncommented to set the date and time //rtc.setDOW(WEDNESDAY); // Set Day-of-Week to SUNDAY //rtc.setTime(12, 0, 0); // Set the time to 12:00:00 (24hr format) //rtc.setDate(1, 1, 2014); // Set the date to January 1st, 2014 }
Code language: Arduino (arduino)
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.
Once we upload this code we need to comment back the three lines and re-upload the code again.
// Code from the Demo Example of the DS3231 Library void loop() { // Send Day-of-Week Serial.print(rtc.getDOWStr()); Serial.print(" "); // Send date Serial.print(rtc.getDateStr()); Serial.print(" -- "); // Send time Serial.println(rtc.getTimeStr()); // Wait one second before repeating delay (1000); }
Code language: Arduino (arduino)
If we take a look at the loop section of the code we can see that now using the three custom functions we get the information from the RTC and print them in the Serial Monitor. Here’s how they appear in the Serial Monitor.
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.
Here’s the source code of this example:
/* * Arduino DS3231 Real Time Clock Module Tutorial * * Crated by Dejan Nedelkovski, * www.HowToMechatronics.com * * DS3231 Library made by Henning Karlsen which can be found and downloaded from his website, www.rinkydinkelectronics.com. * */ DS3231 rtc(SDA, SCL); LiquidCrystal lcd(1, 2, 4, 5, 6, 7); // Creates an LC object. Parameters: (rs, enable, d4, d5, d6, d7) void setup() { rtc.begin(); // Initialize the rtc object lcd.begin(16,2); // Initializes the interface to the LCD screen, and specifies the dimensions (width and height) of the display } } void loop() { lcd.setCursor(0,0); lcd.print("Time: "); lcd.print(rtc.getTimeStr()); lcd.setCursor(0,1); lcd.print("Date: "); lcd.print(rtc.getDateStr()); delay(1000); }
Code language: Arduino (arduino)
That’s all for this Arduino Tutorial, feel free to ask any question in the comments section below.
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.
Network Time Protocol (NTP)
To retrieve and store the current time, we can make a request to an NTP server,
. This will retrieve the UNIX time stamp and store it in an
pool.ntp.org
object.
RTC
Please also note that you will need to create a new tab called
. This is used to store your credentials. In this file, you will need to add:
arduino_secrets.h
1#define SECRET_SSID “” //network name2#define SECRET_PASS “” //network password
Step 3: Writing Simple Code to Display Time
Before we look at the code we need to import DS3231 library. There are a few of them available on Github. Here is the link to the library I am going to use.
To get it in you need to download the zip file. Then open this zip file in Arduino IDE. With each library come some example sketches and this one is no different. As you can see there are few of them.
Now to the code . Lets create the simplest scetch to display date and time in the most basic format.
We start with declaring the libraries.
#include
#include
First one enables us to use I2C comunication and the second one is the one we just installed which will help us with controlling RTC module.The we declare the RTC module and also we declare the of RTCDateTime object .
DS3231 clock;RTCDateTime dt;
RTCDateTime type consists of following components .
- uint16_t year,
- uint8_t month,
- uint8_t dayOfWeek,
- uint8_t hour,
- uint8_t minute,
- uint8_t second
In setup function we open serial monitor to be able to see the scetch results and then we initiate the RTC module. And finally we set the time to the time the scetch was compiled at. That is very handy functionality which makes setting up current time on the RTC very easy
void setup() { Serial.begin(9600); clock.begin(); // Set sketch compiling time clock.setDateTime( __DATE__ , __TIME__ );
In the main loop we run clock.getDateTime() time method to read current date and time to the dt object we have previously defined. And then with print function we output the time serial monitor. As you can see the format is very basic. You do not see the leading zeros where they should be so if you wanted to output date in time in the other way there would still be some string operations required.
void loop(){dt = clock.getDateTime();Serial.print(dt.year); Serial.print(“-“);Serial.print(dt.month); Serial.print(“-“);Serial.print(dt.day); Serial.print(” “);Serial.print(dt.hour); Serial.print(“:”);Serial.print(dt.minute); Serial.print(“:”);Serial.print(dt.second); Serial.println(“”);delay(1000);}
Step 4: Reading Temperature With DS3231
The DS3231 RTC has a built-in temperature sensor with a resolution of 0.25 and an accuracy of ±3°C .
The temperature registers are updated after every 64-second conversion.If you want force temperature conversion use forceConversion()
So if you want to display temperature in the main loop you have to add following lines of code
clock.forceConversion(); Serial.print(“Temperature: “); Serial.println(clock.readTemperature());
Real Time Clock DS1307(RTC)
Module DS1307 là một trong những module RTC giá cả phải chăng và được sử dụng phổ biến nhất. Nó có thể theo dõi chính xác giây, phút, giờ, ngày, tháng và năm.
Một số tính năng quan trọng của DS1307 là:
- Khả năng tạo sóng vuông có thể lập trình.
- Dòng điện thấp, dưới 500mA trong chế độ sao lưu pin.
- Khả năng thiết lập ngày đến năm 2100.
- Sử dụng chuẩn giao tiếp I2C.
Module DS1307 sử dụng pin CR2023 3 volt. Bộ nhớ EEPROM 24c32 nhúng trên mô-đun này có thể tiết kiệm 32kb dữ liệu.
Ngoài ra, các bạn có thể đo nhiệt độ môi trường bằng cách sử dụng cảm biến DS18B20 đã được tích hợp sẵn trên board mạch.
Đọc giá trị điện áp của pin từ chân BAT.
Các chân chức năng:
PIN | Chức năng |
VCC | Cấp nguồn từ 3.3V – 5.5V |
GND | Nối vào cực âm của mạch |
SCL | |
SDA | |
DS |
- Các bạn tải và cài đặt thư viện hỗ trợ sử dụng Module RTC DS1307: Tại đây
- Xem thêm: Hướng dẫn cách cài thư viện trên Arduino IDE.
Real-Time Clock (RTC)
The RTC on the UNO R4 WiFi can be accessed using the RTC library that is included in the UNO R4 Board Package. This library allows you to set/get the time as well as using alarms to trigger interrupts.
The UNO R4 WiFi features a VRTC pin, that is used to keep the onboard RTC running, even when the boards power supply is is cut off. In order to use this, apply a voltage in the range of 1.6 – 3.6 V to the VRTC pin.
There are many practical examples using an RTC, and the examples provided in this page will help you get started with it.
Set Time
-
RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE)
-
RTC.setTime(startTime)
To set the starting time for the RTC, you can create an
object. Here you can specify the day, month, year, hour, minute, second, and specify day of week as well as daylight saving mode.
RTCTime
Then to set the time, use the
method.
setTime()
Example:
1#include “RTC.h”23void setup() {4 Serial.begin(9600);56 RTC.begin();78 RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);910 RTC.setTime(startTime);11}1213void loop(){14}
Get Time
-
RTC.getTime(currentTime)
To retrieve the time, we need to create a
object, and use the
RTCTime
method to retrieve the current time.
getTime()
This example sets & gets the time and stores it in an
object called
RTCTime
.
currentTime
1#include “RTC.h”23void setup() {4 Serial.begin(9600);56 RTC.begin();78 RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);910 RTC.setTime(startTime);11}1213void loop(){14RTCTime currentTime;1516// Get current time from RTC17RTC.getTime(currentTime);18}
Print Date & Time
The above examples show how to set & get the time and store it in an object. This data can be retrieved by a series of methods:
-
getDayOfMonth()
-
getMonth()
-
getYear()
-
getHour()
-
getMinutes()
-
getSeconds()
The example below prints out the date and time from the
object.
currentTime
1#include “RTC.h”23void setup() {4 Serial.begin(9600);56 RTC.begin();78 RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);910 RTC.setTime(startTime);11}1213void loop() {14 RTCTime currentTime;1516 // Get current time from RTC17 RTC.getTime(currentTime);1819 // Print out date (DD/MM//YYYY)20 Serial.print(currentTime.getDayOfMonth());21 Serial.print(“/”);22 Serial.print(Month2int(currentTime.getMonth()));23 Serial.print(“/”);24 Serial.print(currentTime.getYear());25 Serial.print(” – “);2627 // Print time (HH/MM/SS)28 Serial.print(currentTime.getHour());29 Serial.print(“:”);30 Serial.print(currentTime.getMinutes());31 Serial.print(“:”);32 Serial.println(currentTime.getSeconds());3334 delay(1000);35}
Unix
-
currentTime.getUnixTime()
To retrieve the Unix timestamp, use the
method.
getUnixTime()
1#include “RTC.h”23void setup() {4 Serial.begin(9600);56 RTC.begin();78 RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);910 RTC.setTime(startTime);11}1213void loop() {14 RTCTime currentTime;1516 // Get current time from RTC17 RTC.getTime(currentTime);1819 //Unix timestamp20 Serial.print(“Unix timestamp: “);21 Serial.println(currentTime.getUnixTime());2223 delay(1000);24}
Periodic Interrupt
A periodic interrupt allows you to set a recurring callback.
To use this, you will need to initialize the periodic callback, using the
method:
setPeriodicCallback()
-
RTC.setPeriodicCallback(periodic_cbk, Period::ONCE_EVERY_2_SEC)
You will also need to create a function that will be called:
-
void periodicCallback() { code to be executed }
Note the IRQ has a very fast execution time. Placing a lot of code is not a good practice, so in the example below we are only switching a single flag,
irqFlag
The example below blinks a light every 2 seconds:
1#include “RTC.h”23volatile bool irqFlag = false;4volatile bool ledState = false;56const int led = LED_BUILTIN;78void setup() {9 pinMode(led, OUTPUT);1011 Serial.begin(9600);1213 // Initialize the RTC14 RTC.begin();1516 // RTC.setTime() must be called for RTC.setPeriodicCallback to work, but it doesn’t matter17 // what date and time it’s set to18 RTCTime mytime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);19 RTC.setTime(mytime);2021 if (!RTC.setPeriodicCallback(periodicCallback, Period::ONCE_EVERY_2_SEC)) {22 Serial.println(“ERROR: periodic callback not set”);23 }24}2526void loop(){27 if(irqFlag){28 Serial.println(“Timed CallBack”);29 ledState = !ledState;30 digitalWrite(LED_BUILTIN, ledState);31 irqFlag = false;32 }33}3435void periodicCallback()36{37 irqFlag = true;38}
The period can be specified using the following enumerations:
-
ONCE_EVERY_2_SEC
-
ONCE_EVERY_1_SEC
-
N2_TIMES_EVERY_SEC
-
N4_TIMES_EVERY_SEC
-
N8_TIMES_EVERY_SEC
-
N16_TIMES_EVERY_SEC
-
N32_TIMES_EVERY_SEC
-
N64_TIMES_EVERY_SEC
-
N128_TIMES_EVERY_SEC
-
N256_TIMES_EVERY_SEC
Alarm Callback
-
RTC.setAlarmCallback(alarm_cbk, alarmtime, am)
1unsigned long previousMillis = 0;2const long interval = 1000;3bool ledState = false;45// Include the RTC library6#include “RTC.h”78void setup() {9 //initialize Serial Communication10 Serial.begin(9600);1112 //define LED as output13 pinMode(LED_BUILTIN, OUTPUT);1415 // Initialize the RTC16 RTC.begin();1718 // RTC.setTime() must be called for RTC.setAlarmCallback to work, but it doesn’t matter19 // what date and time it’s set to in this example20 RTCTime initialTime(7, Month::JUNE, 2023, 13, 03, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);21 RTC.setTime(initialTime);2223 // Trigger the alarm every time the seconds are zero24 RTCTime alarmTime;25 alarmTime.setSecond(0);2627 // Make sure to only match on the seconds in this example – not on any other parts of the date/time28 AlarmMatch matchTime;29 matchTime.addMatchSecond();3031 //sets the alarm callback32 RTC.setAlarmCallback(alarmCallback, alarmTime, matchTime);33}3435void loop() {3637 // in the loop, we continuously print the alarm’s current state38 // this is for debugging only and has no effect on the alarm whatsoever39 unsigned long currentMillis = millis();40 if (currentMillis – previousMillis >= interval) {41 // save the last time you blinked the LED42 previousMillis = currentMillis;43 Serial.print(“Alarm state: “);44 Serial.println(ledState);45 }46}4748// this function activates every minute49// and changes the ledState boolean50void alarmCallback() {51 if (!ledState) {52 digitalWrite(LED_BUILTIN, HIGH);53 } else {54 digitalWrite(LED_BUILTIN, LOW);55 }56 ledState = !ledState;57}
Summary
This tutorial shows how to use the RTC on the UNO R4 WiFi, such as setting a start time, setting an alarm, or obtaining time in calendar or unix format.
Read more about this board in the Arduino UNO R4 WiFi documentation.
Suggested changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. You can read more on how to contribute in the contribution policy.
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.
Arduino UNO R4 WiFi Real-Time Clock
Learn how to access the real-time clock (RTC) on the UNO R4 WiFi.
In this tutorial you will learn how to access the real-time clock (RTC) on an Arduino UNO R4 WiFi board. The RTC is embedded in the UNO R4 WiFi’s microcontroller (RA4M1).
Project: Arduino Calendar Clock
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.
Components Required
Wiring Diagram
The wiring diagram for our project is shown in Figure 4. Because we are using I2C, all devices share a common bus consisting of only 4 wires.
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.
Arduino Sketch
To make it easy for us to develop the code of our project, we will use libraries and create custom functions to make our code easier to read.
Libraries
Our project will include the following libraries. See Figure 5 to check which libraries to install using the Arduino IDE’s built-in Library Manager.
-
Wire.h
library for the I2C interface (included in Arduino IDE) -
LiquidCrystal_I2C.h
library (by Frank de Brabander) for the I2C 16×2 LCD module (GitHub link) -
RTClib.h
library (by Adafruit) for the DS3231 RTC module (GitHub link)
The
Wire.h
library and the I2C protocol were already discussed in previous articles (here and here) and therefore will not be addressed in this tutorial.
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.
#include
// for I2C communication #include// for LCD #include
// for RTC LiquidCrystal_I2C lcd(0x27, 16, 2); // create LCD with I2C address 0x27, 16 characters per line, 2 lines RTC_DS3231 rtc; // create rtc for the DS3231 RTC module, address is fixed at 0x68
Custom Functions: updateRTC() and updateLCD()
To make our code easier to manage, we will create two custom functions.
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.
/* function to update RTC time using user input */ void updateRTC() { lcd.clear(); // clear LCD display lcd.setCursor(0, 0); lcd.print("Edit Mode..."); // ask user to enter new date and time const char txt[6][15] = { "year [4-digit]", "month [1~12]", "day [1~31]", "hours [0~23]", "minutes [0~59]", "seconds [0~59]"}; String str = ""; long newDate[6]; while (Serial.available()) { Serial.read(); // clear serial buffer } for (int i = 0; i < 6; i++) { Serial.print("Enter "); Serial.print(txt[i]); Serial.print(": "); while (!Serial.available()) { ; // wait for user input } str = Serial.readString(); // read user input newDate[i] = str.toInt(); // convert user input to number and save to array Serial.println(newDate[i]); // show user input } // update RTC rtc.adjust(DateTime(newDate[0], newDate[1], newDate[2], newDate[3], newDate[4], newDate[5])); Serial.println("RTC Updated!"); }
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.h
to 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.
/* function to update LCD text */ void updateLCD() { /* create array to convert digit days to words: 0 = Sunday | 4 = Thursday 1 = Monday | 5 = Friday 2 = Tuesday | 6 = Saturday 3 = Wednesday | */ const char dayInWords[7][4] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"}; /* create array to convert digit months to words: 0 = [no use] | 1 = January | 6 = June 2 = February | 7 = July 3 = March | 8 = August 4 = April | 9 = September 5 = May | 10 = October 6 = June | 11 = November 7 = July | 12 = December */ const char monthInWords[13][4] = {" ", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"}; // get time and date from RTC and save in variables DateTime rtcTime = rtc.now(); int ss = rtcTime.second(); int mm = rtcTime.minute(); int hh = rtcTime.twelveHour(); int DD = rtcTime.dayOfTheWeek(); int dd = rtcTime.day(); int MM = rtcTime.month(); int yyyy = rtcTime.year(); // move LCD cursor to upper-left position lcd.setCursor(0, 0); // print date in dd-MMM-yyyy format and day of week if (dd < 10) lcd.print("0"); // add preceeding '0' if number is less than 10 lcd.print(dd); lcd.print("-"); lcd.print(monthInWords[MM]); lcd.print("-"); lcd.print(yyyy); lcd.print(" "); lcd.print(dayInWords[DD]); // move LCD cursor to lower-left position lcd.setCursor(0, 1); // print time in 12H format if (hh < 10) lcd.print("0"); lcd.print(hh); lcd.print(':'); if (mm < 10) lcd.print("0"); lcd.print(mm); lcd.print(':'); if (ss < 10) lcd.print("0"); lcd.print(ss); if (rtcTime.isPM()) lcd.print(" PM"); // print AM/PM indication else lcd.print(" AM"); }
Standard Functions: setup() and loop()
The last phase in completing our code for an Arduino Calendar Clock is to add the standard Arduino functions
setup()
and
loop()
.
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.
void setup() { Serial.begin(9600); // initialize serial lcd.init(); // initialize lcd lcd.backlight(); // switch-on lcd backlight rtc.begin(); // initialize rtc }
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.
void loop() { updateLCD(); // update LCD text if (Serial.available()) { char input = Serial.read(); if (input == 'u') updateRTC(); // update RTC time } }
Our sketch is now complete. Save the sketch as arduino-rtc-tutorial.ino and upload it to your Arduino Uno.
Project Test
After uploading the sketch, your Arduino Uno should display the date and time on the LCD as shown in Figure 6.
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 UNO R4 WiFi Real-Time Clock
Learn how to access the real-time clock (RTC) on the UNO R4 WiFi.
In this tutorial you will learn how to access the real-time clock (RTC) on an Arduino UNO R4 WiFi board. The RTC is embedded in the UNO R4 WiFi’s microcontroller (RA4M1).
Summary
This tutorial shows how to use the RTC on the UNO R4 Minima, such as setting a start time, setting an alarm, or obtaining time in calendar or unix format.
Read more about this board in the Arduino UNO R4 Minima documentation.
Suggested changes
The content on docs.arduino.cc is facilitated through a public GitHub repository. You can read more on how to contribute in the contribution policy.
License
The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.
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.
DS3231 RTC Module Introduction
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.
DS3231 Module Pinout
The DS3231 module has 6 pins to get data from the module and supply power to the board. The pinout of DS3231 is as follows:-
32K 32K oscillator output
SQW Square Wave output pin
SCL Serial Clock pin (I2C interface)
SDA Serial Data pin (I2C interface)
VCC Connected to the positive of power source
GND connected to the ground
When we probe the DS3231 Module’s 32k pin using an Oscilloscope, we get a 32kHz signal from the IC’s internal oscillator.
DS3231 Module Parts
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.
Charging Capability:
The module is designed in such a way that when powered externally, it can charge the battery installed on the module. But one must be careful while using a non-rechargeable CR2032 Cell, as the module will also charge the cell. The CR2032 is a 3V cell that is not rechargeable, but a rechargeable cell can be charged to 4.2V. To stop the module from charging the CR2032 non-rechargeable cell, the U4(220R) Resistor or D1 (1N4148) Diode should be desoldered.
Frequently Asked Questions about the DS3231
Q. What is the difference between DS1307 and DS3231?
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.
Q. How accurate is DS3231?
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.
Q. What battery does DS3231 use?
The DS3231 uses a CR2032 rechargeable cell but if one wants to use a non-rechargeable cell, a minor modification is to be made to the module.
DS3231 Module Schematic
Programming the DS3231 and Setting Time
Setting up time in the DS3231 module is fairly simple. All you need to do is connect it to the Arduino in the below configuration.
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 RTCLib and DS3231 and get the most recent version, as shown in the figure below.
Code for Setting time in DS3231
The code is quite straightforward. It will set the time and then show it on the serial monitor.
rtc.adjust(DateTime(F(__DATE__),F(__TIME__)));
The rtc object sets the time according to the time on your computer in this line. It will change your system’s current clock time.
rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
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.
#include
#include
RTC_DS3231 rtc; char t[32]; void setup() { Serial.begin(9600); Wire.begin(); rtc.begin(); rtc.adjust(DateTime(F(__DATE__),F(__TIME__))); //rtc.adjust(DateTime(2019, 1, 21, 5, 0, 0)); } void loop() { DateTime now = rtc.now(); sprintf(t, “%02d:%02d:%02d %02d/%02d/%02d”, now.hour(), now.minute(), now.second(), now.day(), now.month(), now.year()); Serial.print(F(“Date/Time: “)); Serial.println(t); delay(1000); }
Now Let’s Make a DIY Arduino Digital Clock using DS3231 and LCD
Material Required:
- Arduino Uno
- DS3231 RTC Module
- LCD Display 16*2
- Jumper Wire
- 10K Preset
- 3V coin cell (CR2032)
Arduino Digital Clock Circuit Diagram
- Connect SCL of RTC module to the Arduino A5
- Connect SDA of RTC module to the Arduino A4
- Connect VCC to 5v and GND to GND
- Connect RS of LCD to pin 7 of Arduino
- Connect E of LCD to pin 6 of Arduino
- Connect D7 of LCD to pin 2 of Arduino
- Connect D6 of LCD to pin 3 of Arduino
- Connect D5 of LCD to pin 4 of Arduino
- Connect D4 of LCD to pin 5 of Arduino
- Connect VSS,K,RW,D0,D1,D2,D3 to the GND
- Connect VDD & A to the 5v
- Connect VO to the potentiometer output pin ( To control the contrast of text)
Code to display time on LCD
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.
#include
#include#include
This line in the code specifies which pin of the LCD is connected to which pin of the Arduino.
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // (rs, e, d4, d5, d6, d7)
If the project is fired up with some break in the connection, the code will print RTC Module not Present, in the serial monitor.
if (! rtc.begin()) { Serial.println(” RTC Module not Present”); while (1); }
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.
if (rtc.lostPower()) { Serial.println(“RTC power failure, reset the time!”); rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); }
This section of the code sets the cursor on the LCD to 0 and prints the date in the format Date/Month/Year.
void displayDate() { lcd.setCursor(0,0); lcd.print(“Date:”); lcd.print(now.day()); lcd.print(‘/’); lcd.print(now.month()); lcd.print(‘/’); lcd.print(now.year()); }
This section of the code sets the cursor to 1 and prints the time in the format Hour:Minute:Second.
void displayTime() { lcd.setCursor(0,1); lcd.print(“Time:”); lcd.print(now.hour()); lcd.print(‘:’); lcd.print(now.minute()); lcd.print(‘:’); lcd.print(now.second()); lcd.print(” “); }
After uploading the code you will be able to see the date and time on the LCD screen.
Supporting Files
#include
#include
#include
DateTime now;
RTC_DS3231 rtc;
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // (rs, e, d4, d5, d6, d7)
void displayDate(void);
void displayTime(void);
void setup ()
Serial.begin(9600);
lcd.begin(16,2);
if (! rtc.begin())
Serial.println(” RTC Module not Present”);
while (1);
if (rtc.lostPower())
Serial.println(“RTC power failure, reset the time!”);
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
void loop ()
now = rtc.now();
displayDate();
displayTime();
void displayDate()
lcd.setCursor(0,0);
lcd.print(“Date:”);
lcd.print(now.day());
lcd.print(‘/’);
lcd.print(now.month());
lcd.print(‘/’);
lcd.print(now.year());
void displayTime()
lcd.setCursor(0,1);
lcd.print(“Time:”);
lcd.print(now.hour());
lcd.print(‘:’);
lcd.print(now.minute());
lcd.print(‘:’);
lcd.print(now.second());
lcd.print(” “);
To set the Time
#include
#include
RTC_DS3231 rtc;
char t[32];
void setup()
Serial.begin(9600);
Wire.begin();
rtc.begin();
rtc.adjust(DateTime(F(__DATE__),F(__TIME__)));
//rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
void loop()
DateTime now = rtc.now();
sprintf(t, “%02d:%02d:%02d %02d/%02d/%02d”, now.hour(), now.minute(), now.second(), now.day(), now.month(), now.year());
Serial.print(F(“Date/Time: “));
Serial.println(t);
delay(1000);
Giải thích code
RTC_DS1307 rtc; char daysOfTheWeek[7][12] = {“Sun”, “Mon”, “Tue”, “Wed”, “Thu”, “Fri”, “Sat”};
Ban đầu chúng ta tạo một đối tượng của thư viện RTClib là rtc và xác định mảng ký tự daysOfTheWeek để lưu trữ thông tin ngày trong tuần.
Hàm rtc.begin() và rtc.isrunning()
Hàm rtc.begin() là hàm khởi tạo để đảm bảo module RTC được kết nối.
Hàm rtc.isrunning() là hàm đọc các thanh ghi bên trong I2C của DS1307 để kiểm tra xem chip có trả về thời gian hay không.
Nếu hàm trả về giá trị False thì đặt lại thời gian.
Hàm rtc.adjust()
Hàm rtc.adjust() là hàm đặt ngày và giờ.
Chúng ta có 2 cách đặt ngày giờ:
- DateTime(F(__DATE__), F(__TIME__)) cách này chúng ta cập nhật thời gian tự động từ máy tính.
- DateTime(YYY, M, D, H, M, s) cách này chúng ta thiết lập giờ thủ công.
Ví dụ: Đặt ngày 12 tháng 5 năm 2019 vào lúc 14:07 thì chúng ta sẽ gọi hàm DateTime(2019, 5, 12, 14, 07, 00).
Một số hàm khác:
Hàm rtc.now() | Trả về ngày & giờ hiện tại. Giá trị trả về của nó thường được lưu trữ trong biến của kiểu dữ liệu DateTime. |
Hàm year() | Trả về năm hiện tại. |
Hàm month() | Trả về tháng hiện tại. |
Hàm day() | Trả về ngày hiện tại. |
Hàm daysOfTheWeek() | Trả về ngày hiện tại trong tuần. |
Hàm hour() | Trả về giờ hiện tại. |
Hàm minute() | Trả về phút hiện tại. |
Hàm second() | Trả về giây hiện tại. |
Network Time Protocol (NTP)
To retrieve and store the current time, we can make a request to an NTP server,
. This will retrieve the UNIX time stamp and store it in an
pool.ntp.org
object.
RTC
Please also note that you will need to create a new tab called
. This is used to store your credentials. In this file, you will need to add:
arduino_secrets.h
1#define SECRET_SSID “” //network name2#define SECRET_PASS “” //network password
Real-Time Clock (RTC)
The RTC on the UNO R4 Minima can be accessed using the RTC library that is included in the UNO R4 Board Package. This library allows you to set/get the time as well as using alarms to trigger interrupts.
There are many practical examples using an RTC, and the examples provided in this page will help you get started with it.
Set Time
-
RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE)
-
RTC.setTime(startTime)
To set the starting time for the RTC, you can create an
object. Here you can specify the day, month, year, hour, minute, second, and specify day of week as well as daylight saving mode.
RTCTime
Then to set the time, use the
method.
setTime()
Example:
1#include “RTC.h”23void setup() {4 Serial.begin(9600);56 RTC.begin();78 RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);910 RTC.setTime(startTime);11}1213void loop(){14}
Get Time
-
RTC.getTime(currentTime)
To retrieve the time, we need to create a
object, and use the
RTCTime
method to retrieve the current time.
getTime()
This example sets & gets the time and stores it in an
object called
RTCTime
.
currentTime
1#include “RTC.h”23void setup() {4 Serial.begin(9600);56 RTC.begin();78 RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);910 RTC.setTime(startTime);11}1213void loop(){14RTCTime currentTime;1516// Get current time from RTC17RTC.getTime(currentTime);18}
Print Date & Time
The above examples show how to set & get the time and store it in an object. This data can be retrieved by a series of methods:
-
getDayOfMonth()
-
getMonth()
-
getYear()
-
getHour()
-
getMinutes()
-
getSeconds()
The example below prints out the date and time from the
object.
currentTime
1#include “RTC.h”23void setup() {4 Serial.begin(9600);56 RTC.begin();78 RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);910 RTC.setTime(startTime);11}1213void loop() {14 RTCTime currentTime;1516 // Get current time from RTC17 RTC.getTime(currentTime);1819 // Print out date (DD/MM//YYYY)20 Serial.print(currentTime.getDayOfMonth());21 Serial.print(“/”);22 Serial.print(Month2int(currentTime.getMonth()));23 Serial.print(“/”);24 Serial.print(currentTime.getYear());25 Serial.print(” – “);2627 // Print time (HH/MM/SS)28 Serial.print(currentTime.getHour());29 Serial.print(“:”);30 Serial.print(currentTime.getMinutes());31 Serial.print(“:”);32 Serial.println(currentTime.getSeconds());3334 delay(1000);35}
Unix
-
currentTime.getUnixTime()
To retrieve the Unix timestamp, use the
method.
getUnixTime()
1#include “RTC.h”23void setup() {4 Serial.begin(9600);56 RTC.begin();78 RTCTime startTime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);910 RTC.setTime(startTime);11}1213void loop() {14 RTCTime currentTime;1516 // Get current time from RTC17 RTC.getTime(currentTime);1819 //Unix timestamp20 Serial.print(“Unix timestamp: “);21 Serial.println(currentTime.getUnixTime());2223 delay(1000);24}
Periodic Interrupt
A periodic interrupt allows you to set a recurring callback.
To use this, you will need to initialize the periodic callback, using the
method:
setPeriodicCallback()
-
RTC.setPeriodicCallback(periodic_cbk, Period::ONCE_EVERY_2_SEC)
You will also need to create a function that will be called:
-
void periodicCallback() { code to be executed }
Note the IRQ has a very fast execution time. Placing a lot of code is not a good practice, so in the example below we are only switching a single flag,
irqFlag
The example below blinks a light every 2 seconds:
1#include “RTC.h”23volatile bool irqFlag = false;4volatile bool ledState = false;56const int led = LED_BUILTIN;78void setup() {9 pinMode(led, OUTPUT);1011 Serial.begin(9600);1213 // Initialize the RTC14 RTC.begin();1516 // RTC.setTime() must be called for RTC.setPeriodicCallback to work, but it doesn’t matter17 // what date and time it’s set to18 RTCTime mytime(30, Month::JUNE, 2023, 13, 37, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);19 RTC.setTime(mytime);2021 if (!RTC.setPeriodicCallback(periodicCallback, Period::ONCE_EVERY_2_SEC)) {22 Serial.println(“ERROR: periodic callback not set”);23 }24}2526void loop(){27 if(irqFlag){28 Serial.println(“Timed CallBack”);29 ledState = !ledState;30 digitalWrite(LED_BUILTIN, ledState);31 irqFlag = false;32 }33}3435void periodicCallback()36{37 irqFlag = true;38}
The period can be specified using the following enumerations:
-
ONCE_EVERY_2_SEC
-
ONCE_EVERY_1_SEC
-
N2_TIMES_EVERY_SEC
-
N4_TIMES_EVERY_SEC
-
N8_TIMES_EVERY_SEC
-
N16_TIMES_EVERY_SEC
-
N32_TIMES_EVERY_SEC
-
N64_TIMES_EVERY_SEC
-
N128_TIMES_EVERY_SEC
-
N256_TIMES_EVERY_SEC
Alarm Callback
-
RTC.setAlarmCallback(alarm_cbk, alarmtime, am)
1unsigned long previousMillis = 0;2const long interval = 1000;3bool ledState = false;45// Include the RTC library6#include “RTC.h”78void setup() {9 //initialize Serial Communication10 Serial.begin(9600);1112 //define LED as output13 pinMode(LED_BUILTIN, OUTPUT);1415 // Initialize the RTC16 RTC.begin();1718 // RTC.setTime() must be called for RTC.setAlarmCallback to work, but it doesn’t matter19 // what date and time it’s set to in this example20 RTCTime initialTime(7, Month::JUNE, 2023, 13, 03, 00, DayOfWeek::WEDNESDAY, SaveLight::SAVING_TIME_ACTIVE);21 RTC.setTime(initialTime);2223 // Trigger the alarm every time the seconds are zero24 RTCTime alarmTime;25 alarmTime.setSecond(0);2627 // Make sure to only match on the seconds in this example – not on any other parts of the date/time28 AlarmMatch matchTime;29 matchTime.addMatchSecond();3031 //sets the alarm callback32 RTC.setAlarmCallback(alarmCallback, alarmTime, matchTime);33}3435void loop() {3637 // in the loop, we continuously print the alarm’s current state38 // this is for debugging only and has no effect on the alarm whatsoever39 unsigned long currentMillis = millis();40 if (currentMillis – previousMillis >= interval) {41 // save the last time you blinked the LED42 previousMillis = currentMillis;43 Serial.print(“Alarm state: “);44 Serial.println(ledState);45 }46}4748// this function activates every minute49// and changes the ledState boolean50void alarmCallback() {51 if (!ledState) {52 digitalWrite(LED_BUILTIN, HIGH);53 } else {54 digitalWrite(LED_BUILTIN, LOW);55 }56 ledState = !ledState;57}
Step 7: Code to Display Time on the OLED Display
Having custom functions in place we can write a code that will display date and time in desired format on the oled display.
We require two more libraries for controling the display
#include
#include
Then we define its dimentions.And decalre the display itself
#define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 64 // OLED display height, in pixels #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
In setup function we add a section which checks if display properly initialised. It halts sketch execution if display is not detected.
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128×64 Serial.println(F(“SSD1306 allocation failed”)); for(;;); // Don’t proceed, loop forever } display.display(); //display initial Adafruit logo delay(2000); // Clear the display display.clearDisplay(); display.display();
Now lets look at the code of the main loop to transform reading from the RTC module to graphical representation of date and time
First we save the reading from the RTC to the dt object
dt = clock.getDateTime();
Then we draw three rectanglers/panels. First in white and since this particular display is dual color one where first 15 lines are yellow it shows in yellow. Then we draw another one in black and then another one in white which will show in blue as that part of the display is blue. (as shown on the photo)
display.fillRect(0,0,128,16,SSD1306_WHITE); display.fillRect(0,17,128,16,SSD1306_BLACK); display.fillRect(0,31,128,33,SSD1306_WHITE);
Then after selecting cursor position and font color and size we output full day of the week in top panel using
DayOfTheWeek function.
display.setCursor(1,1); display.setTextSize(2); display.setTextColor(SSD1306_BLACK); display.println(DayOfTheWeek(dt.dayOfWeek));
We continue with displaying Short name of the month day of the month and a full year in middle panel using DayMonthYear function
display.setCursor(1,18); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.println(DayMonthYear(dt.day,dt.month,dt.year));
We can also add temperature into top panel as well.
clock.forceConversion(); display.setCursor(85,18); display.setTextSize(1); display.setTextColor(SSD1306_WHITE); display.print(clock.readTemperature()); display.setCursor(117,16); display.print(“o”);
In main panel we display hours and minutes using CurrentTime function and then with the smaller font we are also displaying seconds.
display.setCursor(3,35); display.setTextSize(3); display.setTextColor(SSD1306_BLACK); display.println(CurrentTime(dt.hour,dt.minute)); display.setCursor(100,35); display.setTextSize(2); display.setTextColor(SSD1306_BLACK); display.println(AddLeadingZero(dt.second));
We ended up with fairly nice looking design of the clock.
Keywords searched by users: real time clock with arduino
Categories: Có được 77 Real Time Clock With Arduino
See more here: kientrucannam.vn
See more: https://kientrucannam.vn/vn/