I was wondering whenever anyone has or could share simple code to set/retrieve time on a DS3231. Likewise for the temperature sensor on chip.
The reason I ask (I understand there are plenty of libraries available for this) is because i often have to port to different mcu's and it would be nice to have a single piece of code i could call as a function rather than having to hack a library it each time.
Also, I remember there was a very good I2C library for atmel MCU's written using port manipulation (rather than hardware I2C, with error detection/timeout and smaller footprint than the arduino built-in and able to run inside an IRS) which i cannot remember the name, sadly. Anyone with better memory than me that can give a hint here?
#include <Wire.h>
// variables for storing the time
// second minute hour weekday date month year
byte ss=0, mi=0, hh=0, wd=6, dd=1, mo=1, yy=0;
void setup()
{
Wire.begin();
Serial.begin(9600); // or whatever baud rate you wish to use
// clear /EOSC bit
// Sometimes necessary to ensure that the clock
// keeps running on just battery power. Once set,
// it shouldn't need to be reset but it's a good
// idea to make sure.
// Wire.beginTransmission(0x68); // address DS3231
// Wire.write(0x0E); // select register
// Wire.write(0b00011100); // write register bitmap, bit 7 is /EOSC
// Wire.endTransmission();
}
void loop()
{
// read the time from the RTC, if we can
boolean gotTheTime = grabTime();
if (gotTheTime) {
// if we are here, then the time has been successfully read
// and stored in global variables (ss, mi, hh, wd, dd, mo, yy)
Serial.print("Got the time: ");
printTime();
}
else {
// if we are here, then we tried to read the time but couldn't
Serial.println("Unable to read time from RTC");
}
delay(500);
}
boolean grabTime() {
// get time from the RTC and put it in global variables
// send request to receive data starting at register 0
Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
Wire.write((byte)0); // start at register 0
Wire.endTransmission();
Wire.requestFrom(0x68, 7); // request seven bytes (ss, mi, hh, wd, dd, mo, yy)
// check for a reply from the RTC, and use it if we can
if (Wire.available() >= 7) {
// if we're here, we got a reply and it is long enough
// so now we read the time
ss = bcd2bin(Wire.read()); // get seconds
mi = bcd2bin(Wire.read()); // get minutes
hh = bcd2bin(Wire.read()); // get hours
wd = bcd2bin(Wire.read()); // get day of week
dd = bcd2bin(Wire.read()); // get day of month
mo = bcd2bin(Wire.read()); // get month
yy = bcd2bin(Wire.read()); // get year (two digits)
// indicate that we successfully got the time
return true;
}
else {
// indicate that we were unable to read the time
return false;
}
}
byte bcd2bin(byte x) {
// converts from binary-coded decimal to a "regular" binary number
return ((((x >> 4) & 0xF) * 10) + (x & 0xF)) ;
}
void printTime() {
// just like it says on the tin
Serial.print ("\'");
if (yy<10) Serial.print("0"); Serial.print(yy,DEC); Serial.print("-");
if (mo<10) Serial.print("0"); Serial.print(mo,DEC); Serial.print("-");
if (dd<10) Serial.print("0"); Serial.print(dd,DEC); Serial.print("(");
switch (wd) {
case 1: Serial.print("Mon"); break;
case 2: Serial.print("Tue"); break;
case 3: Serial.print("Wed"); break;
case 4: Serial.print("Thu"); break;
case 5: Serial.print("Fri"); break;
case 6: Serial.print("Sat"); break;
case 7: Serial.print("Sun"); break;
default: Serial.print("Bad");
}
Serial.print(") ");
if (hh<10) Serial.print("0"); Serial.print(hh,DEC); Serial.print(":");
if (mi<10) Serial.print("0"); Serial.print(mi,DEC); Serial.print(":");
if (ss<10) Serial.print("0"); Serial.print(ss,DEC); Serial.println("");
}
Use of DS3231.h Library to measure temperature using intertanl sensor of DS3231RTC
#include <DS3231.h>
DS3231 clock; //pre-defined object created from DS3231 Class
float temp;
void setup()
{
Serial.begin(9600);
clock.begin(); //RTC Clock is intialized
}
void loop()
{
clock.forceConversion(); //start temperature conversion and wait until conversion is done
temp = clock.readTemperature(); //read raw data from temp sensor and use it to compute actual temp using library function.
Serial.print(temp, 2); //show temp on Serial Monitor
Serial.println(" deg-C");
delay(3000);
}
sterretje:
Just my opinion, but unless there is no hardware I2C, bit banging I2C isn't the way to go.
Spend the time on understanding what is needed for the different micros and write higher level functions for each.
The standard wire library does not not work inside an interrupt. A requirement of my code is to prioritize an interrupt on power down and save variables to an FRAM/EEPROM, just before the system runs out of power. I could write my own I2C library using the hardware, but a software one just makes it portable.
casemod:
The standard wire library does not not work inside an interrupt. A requirement of my code is to prioritize an interrupt on power down and save variables to an FRAM/EEPROM, just before the system runs out of power.
I suppose that in the power down ISR, you can individually disable all interrupts except the ones needed by I2C and next enable the global interrupt again.
You are going at this the wrong way. The only thing you do in the power down interrupt is set a flag (e.g. globally declared volatile char p_down) and in the loop() function, if that flag is set, do all the I2C you need to do.