I can set the day of the week as well as time no problem but it will not set the current date? any ideas? im using an arduino MEGA.
// 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 chipKit you must connect
// the pins as follows:
//
// chipKit Uno32/uC32:
// ----------------------
// DS3231: SDA pin -> Analog 4
// SCL pin -> Analog 5
// *** Please note that JP6 and JP8 must be in the I2C position (closest to the analog pins)
//
// chipKit Max32:
// ----------------------
// DS3231: SDA pin -> Digital 20 (the pin labeled SDA)
// SCL pin -> Digital 21 (the pin labeled SCL)
//
// The chipKit boards does not have pull-up resistors on the hardware I2C interface
// so external pull-up resistors on the data and clock signals are required.
//
// 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.
//
#include <DS3231.h>
// Init the DS3231 using the hardware interface
DS3231 rtc(SDA, SCL);
void setup()
{
// Setup Serial connection
Serial.begin(115200);
// 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(19,45, 0); // Set the time to 12:00:00 (24hr format)
rtc.setDate(3, 25, 2020); // 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);
}
You are using a library that is not on Github. That is problem number one, since users can not report a problem.
In the page of the Rinky-Dink DS3231 library is a note that has not be fully tested. That's problem number two.
The library can use its own software I2C or the Arduino Wire library. That software I2C is problem number three.
You are not the only one that has problems with that library. That is problem number four.
That library is from 2015, and the Arduino code improves and moves on. Maybe it is no longer 100% compatible.
First of all, you should test if the Arduino board can communicate over the I2C bus with the DS3231. Use a I2C Scanner for that.
When that is okay, find a better library.
I have successfully used the Christensen library mentioned in the previous post.
I am currently just using the wire library to deal with the RTC registers directly. The DS3231 is fairly easy to deal with and the register access is straightforward once you get the hang of it.
@Nick_Pyner, thanks, thas is a really short and nice example.
@floresta, if that short example is all that you need, then you can use that. At least put a link to that short example in your sketch. Then you have something to fall back to in case a library causes problems.
The example posted by Nick is essentially the same as the code that I first came up with and is all you really need.
Subsequently I made some changes in how the month and year are dealt with in order to make the RTC data more compatible with the time.h (lower case 't') library. By doing this I could use strftime() to easily display the results.
Code:
// read data from a DS3231RTC chip without using a dedicated RTC library
// Program information
char programName[] = "DS3231_Basic_20A.ino";
/* Program notes
- Assumes that the clock has previously been set
- Uses 24 hour clock format
- Displays date and time in ISO8601 format (YYYY-MM-DD HH:MM:SS)
- Does not display day-of-week information
- Does not have provisions to set or adjust the clock data
- Does not use any of the alarm functions
*/
/* Differences between time.h and RTC values
int tm_year; // time.h: Years since 1900
// RTC: Years since 2000
int tm_mon; // time.h: Months numbered 0-11
// RTC: Months numbered 1-12
*/
// Hardware connections
/* ESP8266 DS3231 Module
(NodeMCU etc) (ZS-042)
--------------- -----------
| | | |
| (GPIO 5)|D1 ------------> | SCL |
| (GPIO 4)|D2 <-----------> | SDA |
| |3V3 -----------> | VCC |
| |GND -----------> | GND |
| | | |
--------------- -----------
*/
// Required libraries
#include <Wire.h>
//#include <time.h> // seems to work without this declaration??
#define addr_DS3231 0x68 // I2C address
struct tm timeinfo; // timeinfo structure (defined in time.h)
// ....................................................................................
void setup()
{
Serial.begin(115200);
// display sign-on message - useful to determine exactly which version is running
Serial.println();
Serial.println();
Serial.print(programName);
Serial.println();
Wire.begin(); // enable I2C communications
setupRtc(); // get the clock into a known state
}
// ....................................................................................
void loop()
{
// get RTC data, strip extraneous bits, and convert BCD to decimal
getRtcData();
// display the date and time in ISO8601 format
displayRtcData();
// delay
delay(10000);
}
// ....................................................................................
void setupRtc()
{
// get the clock into a known state
// turn off any Alarms that may be left over from a previous use
// disable interrupts from the clock
// make sure the clock is running
/*
0 0 0 0 0 0 0 0
| | | | | | | |_____ (A1IE) - disable Alarm 1 interrupt
| | | | | | |_______ (A2IE) - disable Alarm 2 interrupt
| | | | | |_________ (INTCN) - disable interrupts from alarms
| | | | |___________ (RS1) - 1 Hz square wave (if enabled)
| | | |_____________ (RS2) -
| | |_______________ (CONV) - do not read chip temperature
| |_________________ (BBSQW) - disable square wave output
|___________________ (EOSC) - enable oscillator (low turns clock on)
*/
Wire.beginTransmission(addr_DS3231); // communicate with the RTC via I2C
Wire.write(0x0E); // Control register
Wire.write(B00000000); // write register bitmap
Wire.endTransmission();
}
// .......................................................................
void getRtcData()
{
// request seven bytes of data from DS3231 starting with register 00h
Wire.beginTransmission(addr_DS3231);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(addr_DS3231, 7);
// strip out extraneous bits used by the RTC chip and convert BCD to Decimal
timeinfo.tm_sec = bcdToDec(Wire.read() & 0x7F);
timeinfo.tm_min = bcdToDec(Wire.read() & 0x7F);
timeinfo.tm_hour = bcdToDec(Wire.read() & 0x3F);
timeinfo.tm_wday = bcdToDec(Wire.read() & 0x03);
timeinfo.tm_mday = bcdToDec(Wire.read() & 0x3F);
timeinfo.tm_mon = bcdToDec(Wire.read() & 0x1F);
timeinfo.tm_year = bcdToDec(Wire.read());
// adjust month and year values to agree with time.h format
timeinfo.tm_mon = timeinfo.tm_mon - 1;
timeinfo.tm_year = timeinfo.tm_year + 100;
}
// .......................................................................
uint8_t bcdToDec(uint8_t val)
// Convert binary coded decimal to normal decimal numbers
{
return ( (val/16*10) + (val%16) );
}
// .......................................................................
void displayRtcData()
{
// display the date and time in this form --> 2020-03-21 12:34:56
struct tm *timeinfoPtr = &timeinfo; // pointer to timeinfo structure
char strfBuf[30]; // buffer used by strftime()
Serial.print("\nThe present date and time is: ");
strftime(strfBuf, sizeof(strfBuf), "%F %T", timeinfoPtr);
Serial.print(strfBuf);
}
Output:
DS3231_Basic_20A.ino
The present date and time is: 2020-04-01 11:07:42
The present date and time is: 2020-04-01 11:07:52
Don
EDIT: I just realized that this is running on an ESP8266. I'll dig up an Arduino and check it out.
EDIT2: It's working fine on a UNO type board. The only change is that it does require the declaration for the time.h library.
Get the day-of-the-mont, the month and the year. Add zero in front with sprintf() or add them with a if-statement and check if the year is already 2020 or that it is only 20 or so. Combine them all with dots in between or use sprintf() to combine them.
The sprintf() uses %d which is expecting a 'int'. So I suggest to use extra 'int' variables because there might be differences between the time libraries.
char buffer[16]; // enough for 04.06.2020 with zero-terminator
int dayofmonth = day();
int month = month();
int year = year();
sprintf( buffer, "%02d.%02d.%d", dayofmonth, month, year);
Or cast them to 'int':
char buffer[16]; // enough for 04.06.2020 with zero-terminator
sprintf( buffer, "%02d.%02d.%d", (int) day(), (int) month(), (int) year());