Another thread got my attention so I decided to code my own sketch to set RTC breakout boards. I have few RTCs lying around so I decided to write my own sketch and publish for all forum members to use. There are no bells or whistles, so no error will be thrown if the input is not correct.
I have tried to document all procedures in the sketch, and if anyone has suggestions for improvements, I would be happy to hear them.
// Steve Clements 2019
// Get or set DS3231 registers without a DS3231 library.
// To set the registers input a string as follows
// SS MM HH DW DD MM YY - use any non-digit character as a
// spacer or just use empty spaces as shown.
// Use either single or double digits i.e. 7 or 07.
// DW is user defined and is a value between 0 and 6, depending
// on which day the user decides is the first day of the week.
#include <Wire.h>
// thanks to jscottbee(forum member) for this parsing function
#define dec2bcd(dec_in) ((dec_in / 10) << 4) + (dec_in % 10)
int ds3231_address = 0x68; //ds3231 address, change if required.
byte mByte[0x13]; // create array for the register contents
String dOw; // holds the Day of the Week
void setup() {
Serial.begin(9600);
Wire.begin();
}
void loop() {
delay(2000);
// if serial input data availble, reset time
if(Serial.available() > 0){
String tempString = Serial.readString();
setDateTime(tempString);
}
// display register values in main loop
Wire.beginTransmission (ds3231_address);
Wire.write (0x00); // Set device to start read reg 0
Wire.endTransmission ();
// request 19 bytes from the DS3231 and release the I2C bus
Wire.requestFrom(ds3231_address, 0x13, true);
int idx = 0;
// read the bytes into an array
while(Wire.available()) {
byte input = Wire.read(); // read each byte from the register
mByte[idx] = input; // store each single byte in the array
idx++;
}
// get day of the week
switch (mByte[3]) {
case 0x0:
dOw = "Sunday";
break;
case 0x1:
dOw = "Monday";
break;
case 0x2:
dOw = "Tuesday";
break;
case 0x3:
dOw = "Wednesday";
break;
case 0x4:
dOw = "Thursday";
break;
case 0x5:
dOw = "Friday";
break;
case 0x6:
dOw = "Saturday";
break;
default:
// statements
break;
}
// print current values to serial output
Serial.print("Seconds = "); Serial.println(mByte[0], HEX);
Serial.print("Minutes = "); Serial.println(mByte[1], HEX);
Serial.print("Hours = "); Serial.println(mByte[2], HEX);
Serial.print("Day of Week = "); Serial.println(dOw);
Serial.print("Date = "); Serial.println(mByte[4], HEX);
Serial.print("Month = "); Serial.println(mByte[5], HEX);
Serial.print("Year = "); Serial.println(mByte[6], HEX);
Serial.print("On-board Chip Temperature ");Serial.print(" "); Serial.print(mByte[17], DEC); Serial.println("°C");
Serial.println();
}
void setDateTime(String dateTime){
// create empty array for datetime values
int dateTimeVals[7] ={};
// convert string to character array
int stringLength = dateTime.length();
char dateTimeArray[stringLength];
// convert string to character array
dateTime.toCharArray(dateTimeArray, stringLength + 1);
// char array index
int idx1 = 0;
// array index
int idx2 = 0;
while(idx2 != 7){
// process double digit input
if(isDigit(dateTimeArray[idx1]) && isDigit(dateTimeArray[idx1 + 1])){
int temp1 = int(dateTimeArray[idx1]);
temp1 = temp1 - 48;
int temp2 = int(dateTimeArray[idx1 + 1]);
temp2 = temp2 - 48;
dateTimeVals[idx2] = (temp1 * 10) + temp2;
idx1 += 3;
}
// process single digit input
else if(isDigit(dateTimeArray[idx1]) && !isDigit(dateTimeArray[idx1 +1])){
dateTimeVals[idx2] = int(dateTimeArray[idx1] - 48);
idx1 += 2;
}
// increment if input is not a digit
else{
idx1++;
}
// increment array index
idx2++;
}
// write values to the DS3231 registers
Wire.beginTransmission (ds3231_address);
// Set device to start read reg 0
Wire.write (0x00);
for (int idx = 0; idx < 7; idx++){
Wire.write (dec2bcd(dateTimeVals[idx]));
}
Wire.endTransmission ();
return;
}
Have fun dissecting this!
@pugwash nice.
Yeah, the DS3231 is one of the nice and easy i2c devices to play with and learn i2c protocol coding with. I had a pic based outdoors lighting controller I did back in 2005 or 2006. The board is probably in a box somewhere now.
Good coding,
Scott
This has whetted my appetite to start some bit bashing in the alarm registers!
@jscottbee Thanks. i have a problem using ds3231 module. i want it to trigger a relay for instance on monday January13, 2022 at 5.30am and put it off at 6.20pm. i modified a sketch from Eric Ayars library on github but im only able to get the hour functionality and nothing else. i cant program for years, months, days of week, minutes and seconds. kindly assist as i can provide you with my code
Since you acknowledge that your code is the problem... please provide it along with your questions... that may encourage people to chime in and help, because they know the problem.
Cheers.
@frogandtoad Thank you so much for the response. I will post the code in the next slide along with the library and sketch i modified to arrive at this code. Please understand that the lines i commented were originally for the first project i did using this library. The task was to put off a fridge at 9:pm and put it on at 7:am. it worked perfectly. And because it was aimed at repeating this operation every day, there was nothing to test for other parameters like minutes, day of week, month of year and even seconds. So i assumed the code was fine.
I then tried to adapt the same code for an irrigation system that turns on a dc pump on specific dates and times using a cropping calendar as a criteria. That was when i discovered that the code does not respond to the functions i mentioned; months, weeks, minutes and second.
/*
DS3231_test.pde
Eric Ayars
4/11
Test/demo of read routines for a DS3231 RTC.
Turn on the serial monitor after loading this to check if things are
working as they should.
*/
#include <DS3231.h>
#include <Wire.h>
#include <LiquidCrystal.h>
LiquidCrystal Lcd(10,9,5,4,3,2);
DS3231 clock;
bool century = false;
bool h12Flag;
bool pmFlag;
byte alarmDay, alarmHour, alarmMinute, alarmSecond, alarmBits;
bool alarmDy, alarmH12Flag, alarmPmFlag;
int relay1 =12;
int redled = 13;
int blueled = 11;
int greenled = 10;
void setup() {
// Start the I2C interface
Wire.begin();
pinMode(relay1, OUTPUT);
pinMode(redled, OUTPUT);
pinMode(greenled, OUTPUT);
pinMode(blueled, OUTPUT);
// Start the serial interface
Serial.begin(57600);
Lcd.begin(16,2);
Lcd.setCursor(0,0);
Lcd.print("Quickfix Eng ltd");
}
void loop() {
// send what's going on to the serial monitor.
// Start with the year
Serial.print("2");
if (century) { // Won't need this for 89 years.
Serial.print("1");
} else {
Serial.print("0");
}
Serial.print(clock.getYear(), DEC);
Serial.print(' ');
// then the month
Serial.print(clock.getMonth(century), DEC);
Serial.print(" ");
// then the date
Serial.print(clock.getDate(), DEC);
Serial.print(" ");
// and the day of the week
Serial.print(clock.getDoW(), DEC);
Serial.print(" ");
// Finally the hour, minute, and second
Serial.print(clock.getHour(h12Flag, pmFlag), DEC);
Serial.print(" ");
Serial.print(clock.getMinute(), DEC);
Serial.print(" ");
Serial.print(clock.getSecond(), DEC);
// Add AM/PM indicator
if (h12Flag) {
if (pmFlag) {
Serial.print(" PM ");
} else {
Serial.print(" AM ");
}
} else {
Serial.print(" 24h ");
}
for (clock.getYear()==21; clock.getYear()<=50; clock.getYear()==clock.getYear()+1){ //for all years before 2050
/* for(clock.getMonth(century)==1; clock.getMonth(century)<=12; clock.getMonth(century)== clock.getMonth(century)+1){ // for all 12 months
for(clock.getDoW()==1; clock.getDoW()<=7; clock.getDoW()== clock.getDoW()+1){ */ // for all days in a week
if(clock.getMonth(century)==9 || clock.getMonth(century)==10 || clock.getMonth(century)==11 || clock.getMonth(century)==12){
if(clock.getDoW()=="7"){
if(clock.getHour(h12Flag,pmFlag) == 01){
// if((clock.getMinute(), DEC)== 45){
digitalWrite(relay1, HIGH);
digitalWrite(redled, LOW);
digitalWrite(greenled, HIGH);
Lcd.setCursor(0,1);
Lcd.print(" ");
Lcd.setCursor(0,1);
Lcd.print("WATERING");
}
}
}
}
if(clock.getMonth(century)==9 || clock.getMonth(century)==10 || clock.getMonth(century)==11 || clock.getMonth(century)==12){
if(clock.getDoW()=="7"){
if(clock.getHour(h12Flag,pmFlag) == 02){
// if((clock.getMinute(), DEC)== 47){
digitalWrite(relay1, LOW);
digitalWrite(redled, HIGH);
digitalWrite(greenled, LOW);
Lcd.setCursor(0,1);
Lcd.print(" ");
Lcd.setCursor(0,1);
Lcd.print("NOT WATERING");
}
}
}
}
/*if (clock.getHour(h12Flag,pmFlag) == 22 | ){
digitalWrite(relay1, HIGH);
digitalWrite(redled, HIGH);
digitalWrite(greenled, LOW);
Lcd.setCursor(0,1);
Lcd.print(" ");
Lcd.setCursor(0,1);
Lcd.print("FRIDGE OFF TIME");
}*/
/* if (clock.getHour(h12Flag,pmFlag) == 7 ||clock.getHour(h12Flag,pmFlag)==8 || clock.getHour(h12Flag,pmFlag)==9 || clock.getHour(h12Flag,pmFlag)==10 || clock.getHour(h12Flag,pmFlag)== 11 ||clock.getHour(h12Flag,pmFlag)== 12 || clock.getHour(h12Flag,pmFlag)== 13 || clock.getHour(h12Flag,pmFlag)== 14 || clock.getHour(h12Flag,pmFlag)== 15 || clock.getHour(h12Flag,pmFlag)==16 || clock.getHour(h12Flag,pmFlag)== 17 || clock.getHour(h12Flag,pmFlag)== 18 || clock.getHour(h12Flag,pmFlag)== 19 || clock.getHour(h12Flag,pmFlag)== 20){
digitalWrite(relay1, LOW);
digitalWrite(redled, LOW);
digitalWrite(greenled, HIGH);
Lcd.setCursor(0,1);
Lcd.print(" ");
Lcd.setCursor(0,1);
Lcd.print("FRIDGE ON TIME");
}*/
// if (clock.getHour(h12Flag,pmFlag) >= 21 ||clock.getHour(h12Flag,pmFlag)<=7){
//digitalWrite(redled, HIGH);
//digitalWrite(greenled, LOW);
// digitalWrite(blueled, LOW);
// }
//if (clock.getHour(h12Flag,pmFlag) >= 7 && clock.getHour(h12Flag,pmFlag)<=17){
// digitalWrite(redled, LOW);
// digitalWrite(greenled, HIGH);
// digitalWrite(blueled, LOW);
// }
// if (clock.getHour(h12Flag,pmFlag) >= 17 && clock.getHour(h12Flag,pmFlag)<=21){
// digitalWrite(redled, LOW);
// digitalWrite(greenled, LOW);
// digitalWrite(blueled, HIGH);
The library used was by Eric Ayars. it has examples for set time, test time, echo time, and oscillator test.
i will upload the different codes for these tasks here