I would like to have an output that turns on once every minute for half a second using an RTC module for accuracy. This is for a clock project.
Is this feasible? Can someone please share some example code.
I would like to have an output that turns on once every minute for half a second using an RTC module for accuracy. This is for a clock project.
Is this feasible? Can someone please share some example code.
You should define what you mean by "Super Accurate".
... Can someone please share some example code.
The sharing starts with you! This forum is about learning and teaching how to make Arduino projects. So show whatever it is you have done, then folks will step forward and help you with it!
Start by reading the post called “How to use this forum ...”
Agree with the above, but to help out - typically the longer duration events are derived from common clock reference - e.g. using the millis() counter, or a hardware timer used to accumulate enough ‘ticks’ in your ‘minute’ or other duration.
pert:
You should define what you mean by "Super Accurate".
I think he just means the level of accuracy that an RTC module provides.
...R
Most RTC modules have a square wave output that can be programmed to be frequencies of, for example, 32.768kHz, 8.192kHz, 4.096kHz and 1Hz.
It would be easy to use a 1 Hz squarewave, and count 60 pulses.
As it is a square wave, the pulse width is already the 0.5 seconds mentioned.
On some modules, such as this DS3231 module, that output can even be programmed to be an alarm/interrupt every 60 seconds.
Yes , the DS3231 is the one to go for and is very accurate , I be a block that gas run for a couple of years and I’ve not had to adjust it yet . The DS1307 is poor by comparision .
There are libraries for both of there’s RTC , the 1307 commands and libraries work with the 3231 and the examples will get you started
You could of course look at synchronising with some external clock reference over the Internet .
I don't have any experience with RTC modules but, in view of the OP's stated requirement
on once every minute for half a second
can't you just use the time from the RTC in much the same way that you use millis()?
...R
I think I can just use the RTC oscillator output and feed it to an input, divide it and get 1 min output.
Oliver-B:
I think I can just use the RTC oscillator output and feed it to an input, divide it and get 1 min output.
As mentioned the RTC has a 1Hz - one pulse per second - output that is automatically on when the chip is running. It doesn't even need to be set to get that. And it's super accurate - over a year, it'll be a few seconds off at most.
If your sketch is doing other stuff, feed the pulses to an interrupt pin, that will make sure pulses aren't skipped while something else is happening. So look up interrupts in the Arduino Reference.
I always assumed the purpose of an RTC module was to tell you the time. Counting pulses seems like barking when you already have a dog.
...R
Oliver-B:
I would like to have an output that turns on once every minute for half a second using an RTC module for accuracy. This is for a clock project.Is this feasible? Can someone please share some example code.
This is my "standard" RTC test sketch. Once every half-second or so, it reads the time from the RTC and displays it on the Serial monitor.
Now all you have to do is figure out what to do when ss
(the seconds) reaches zero.
#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("");
}
...seems like barking when you already have a dog.
Love it!
ChrisTenone:
If your sketch is doing other stuff, feed the pulses to an interrupt pin, that will make sure pulses aren't skipped while something else is happening. So look up interrupts in the Arduino Reference.
If you want to go that route you can make it even less demanding on the hardware: connect the pulse output to one of the counter pins (T2 for the 8-bit timer2) and a timer interrupt at 60 to set the output high.
At that point set an interrupt for the other edge of the counter (a pin change interrupt will do fine) which comes half a second later, where the output is set low again and the timer count restarted.
Not sure if it's the most appropriate solution to the problem but it's going to be fun implementing it, and you can after that pretty much do anything with the rest of the code and it will just work, with less than a microsecond delay from the pulse signal.
Sounds like an excellent plan. I may try implementing this myself, as I need to learn much more about avr timers.