I was intrigued by a recent thread about the Elegoo RTC wherein the loop was controlled by the condition of the seconds
void loop ()
{
read RTC;
if (second != prevSecond())
{
DO STUFF;
}
}
This seems just as good as using the square wave output from a DS3231, is easier to understand, and involves less code. This might particularly apply if you were also displaying the time but, to get that count you might need only to read the seconds forego all the rest - which is pretty frugal.
It's not really code. I just want the seconds from the DS3231
void GetClock(){
Wire.beginTransmission(DS1307_ADDRESS);
byte zero = 0x00;
Wire.write(zero);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 1);// seconds, and only seconds
second = bcdToDec(Wire.read());
}
something like that, and it comes along the I2C bus. And, just in case,
byte bcdToDec(byte val) {
// Convert binary coded decimal to normal decimal numbers
return ( (val/16*10) + (val%16) );
}
I guess I shouldn't have put it in code space in the first place...
You could take it further, and publish a full prints once a second sketch, or take it the other direction a bit and add that it is pseudocode…
But the idea is a good one, and is at least one wire easier than using the square wave output, and frees that up when using it at its higher frequency output is oart of the plan.
A similar idea can be used with millis(), either directly for one loop per millisecond
void loop()
{
unsigned long now;
static unsigned long lastTime = millis();
now = millis();
if (now == lastTime) return;
// below here once per millisecond
}
or, of course, waiting for a number of them to go by.
void loop()
{
unsigned long now;
static unsigned long lastTime = millis();
now = millis();
// stuff here runs at whatever the loop can achieve
// and this
if (now - lastTime < INTERVAL) return;
lastTime = now;
// means stuff below here runs every INTERVAL
}
In my play, these patterns usually find themselves in functions that are designed to handle their own scheduling. A function can run on a schedule, but is called frequently in case it wants to run differently from time to time. A made-up example would be blinking ten times at 10 Hz every 10 seconds. Or a state machine that sometimes needs to pause. Called very frequently, usually doing nothing.
I generally use the Time library when checking for a change in seconds, because I don't want to saturate the I2C bus by continuously reading the time from the RTC. The Time library runs a software clock based on millis(), syncing with the RTC at a specified interval (default is 300 seconds).
You can do the same type loop with a clock run off the square wave output of the RTC by driving the clock off an interrupt from the 1Hz square wave. That eliminates almost all I2C communications with the RTC.
The RTC is normally used by connecting an ISR in your code to the INT/SQW pin. Every RTC library has examples. The code in both cases is similar. The advantage of the ISR approach is that the MCU or MPU can be asleep in between RTC interrupts.
The code you were looking at was written by someone who does not understand how an RTC works.
The I2C lines have pullup resistors. So if you are repeatedly getting the current time from the RTC just to find when it changes, the power consumption may be significant for a battery-powered circuit. Also, there have been rumors that some RTCs don't keep time quite as well if they are constantly communicating over I2C. I think this is really not a good idea. You can use a square wave output interrupt, or just poll that pin, or use millis().
Yes, I guess it's the same approach, and avoids doing nasty things on the I2C bus. For what I'm working on now, I am coming to the conclusion that I don't actually need an RTC, I just need the pulse.