I'm working on a project were I'm making a word clock, much like this one:
The code that I'm currently using is provided by this site:
I've wired everything up, and it all seems to work fine, but the one thing that got me to stagnate is the DS3231 RTC module I'm using;
When I reset the power, the time also resets, which is not what I intend it to do. The whole point for the RTC module is to keep accurate time and also to keep track of the time even without powering the arduino, by using a cell battery.
The arduino seems to change the time completly fine without the DS 3231 module wired up as well, I get the feeling that this might be a coding issue, but I can be wrong.
All the other problems I've had, I've managed to figure out by myself and by researching on the web except this one. Any tips would be greatly appreciated as I'm making this for a christmas present and want to reach the finish line before it's too late
This is my very first time coding an arduino, I have little to no experience other than what I've learned from this project.
The code I used is the second one on that site, pardon me for not pointing that out earlier. The diagram I've been using is attached to this post. Note; I'm using the whole Arduino for my project instead of a standalone ATmega.
When resetting the Arduino it resets to "TWENTY" "MINUTES" "TO" "HTEN"
I just measured VBAT with reference to GND and i got 3V. There is no powersignal when the battery is plugged, (power saving?) only when i have the arduino powered the powersignal is lid.
The code you refer to does not use a DS3231 in any way shape or form. With that code, if a reset occurs it looks as though you have to reset the clock manually using the minute (pin 2) and/or hour (pin 3) buttons.
Please post the exact code you are using. Please place your code within code tags. The code tags are found at the second icon from the right on the top of the reply box.
#include <Wire.h>
#include "RTClib.h"
// Display output pin assignments
#define MTEN Display1=Display1 | (1<<0)
#define HALF Display1=Display1 | (1<<1)
#define QUARTER Display1=Display1 | (1<<2)
#define TWENTY Display1=Display1 | (1<<3)
#define MFIVE Display1=Display1 | (1<<4)
#define MINUTES Display1=Display1 | (1<<5)
#define PAST Display1=Display1 | (1<<6)
#define UNUSED1 Display1=Display1 | (1<<7)
#define TO Display2=Display2 | (1<<0)
#define ONE Display2=Display2 | (1<<1)
#define TWO Display2=Display2 | (1<<2)
#define THREE Display2=Display2 | (1<<3)
#define FOUR Display2=Display2 | (1<<4)
#define HFIVE Display2=Display2 | (1<<5)
#define SIX Display2=Display2 | (1<<6)
#define UNUSED2 Display2=Display2 | (1<<7)
#define SEVEN Display3=Display3 | (1<<0)
#define EIGHT Display3=Display3 | (1<<1)
#define NINE Display3=Display3 | (1<<2)
#define HTEN Display3=Display3 | (1<<3)
#define ELEVEN Display3=Display3 | (1<<4)
#define TWELVE Display3=Display3 | (1<<5)
#define OCLOCK Display3=Display3 | (1<<6)
#define UNUSED3 Display3=Display3 | (1<<7)
int hour=9, minute=30, second=00;
static unsigned long msTick =0; // the number of Millisecond Ticks since we last
// incremented the second counter
int count;
char Display1=0, Display2=0, Display3=0;
// hardware constants
int LEDClockPin=6;
int LEDDataPin=7;
int LEDStrobePin=8;
int MinuteButtonPin=2;
int HourButtonPin=3;
int PWMPin = 9;
void setup()
{
// initialise the hardware
// initialize the appropriate pins as outputs:
pinMode(LEDClockPin, OUTPUT);
pinMode(LEDDataPin, OUTPUT);
pinMode(LEDStrobePin, OUTPUT);
//pinMode(BrightnessPin, INPUT);
pinMode(MinuteButtonPin, INPUT);
pinMode(HourButtonPin, INPUT);
pinMode(PWMPin, OUTPUT);
Serial.begin(19200);
msTick=millis(); // Initialise the msTick counter
displaytime(); // display the current time
}
void ledsoff(void) {
Display1=0;
Display2=0;
Display3=0;
}
void WriteLEDs(void) {
// Now we write the actual values to the hardware
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display3);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display2);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display1);
digitalWrite(LEDStrobePin,HIGH);
delay(2);
digitalWrite(LEDStrobePin,LOW);
}
void displaytime(void){
// start by clearing the display to a known state
ledsoff();
Serial.print("It is ");
// now we display the appropriate minute counter
if ((minute>4) && (minute<10)) {
MFIVE;
MINUTES;
Serial.print("Five Minutes ");
}
if ((minute>9) && (minute<15)) {
MTEN;
MINUTES;
Serial.print("Ten Minutes ");
}
if ((minute>14) && (minute<20)) {
QUARTER;
Serial.print("Quarter ");
}
if ((minute>19) && (minute<25)) {
TWENTY;
MINUTES;
Serial.print("Twenty Minutes ");
}
if ((minute>24) && (minute<30)) {
TWENTY;
MFIVE;
MINUTES;
Serial.print("Twenty Five Minutes ");
}
if ((minute>29) && (minute<35)) {
HALF;
Serial.print("Half ");
}
if ((minute>34) && (minute<40)) {
TWENTY;
MFIVE;
MINUTES;
Serial.print("Twenty Five Minutes ");
}
if ((minute>39) && (minute<45)) {
TWENTY;
MINUTES;
Serial.print("Twenty Minutes ");
}
if ((minute>44) && (minute<50)) {
QUARTER;
Serial.print("Quarter ");
}
if ((minute>49) && (minute<55)) {
MTEN;
MINUTES;
Serial.print("Ten Minutes ");
}
if (minute>54) {
MFIVE;
MINUTES;
Serial.print("Five Minutes ");
}
if ((minute <5))
{
switch (hour) {
case 1:
ONE;
Serial.print("One ");
break;
case 2:
TWO;
Serial.print("Two ");
break;
case 3:
THREE;
Serial.print("Three ");
break;
case 4:
FOUR;
Serial.print("Four ");
break;
case 5:
HFIVE;
Serial.print("Five ");
break;
case 6:
SIX;
Serial.print("Six ");
break;
case 7:
SEVEN;
Serial.print("Seven ");
break;
case 8:
EIGHT;
Serial.print("Eight ");
break;
case 9:
NINE;
Serial.print("Nine ");
break;
case 10:
HTEN;
Serial.print("Ten ");
break;
case 11:
ELEVEN;
Serial.print("Eleven ");
break;
case 12:
TWELVE;
Serial.print("Twelve ");
break;
}
OCLOCK;
Serial.println("O'Clock");
}
else
if ((minute < 35) && (minute >4))
{
PAST;
Serial.print("Past ");
switch (hour) {
case 1:
ONE;
Serial.println("One ");
break;
case 2:
TWO;
Serial.println("Two ");
break;
case 3:
THREE;
Serial.println("Three ");
break;
case 4:
FOUR;
Serial.println("Four ");
break;
case 5:
HFIVE;
Serial.println("Five ");
break;
case 6:
SIX;
Serial.println("Six ");
break;
case 7:
SEVEN;
Serial.println("Seven ");
break;
case 8:
EIGHT;
Serial.println("Eight ");
break;
case 9:
NINE;
Serial.println("Nine ");
break;
case 10:
HTEN;
Serial.println("Ten ");
break;
case 11:
ELEVEN;
Serial.println("Eleven ");
break;
case 12:
TWELVE;
Serial.println("Twelve ");
break;
}
}
else
{
// if we are greater than 34 minutes past the hour then display
// the next hour, as we will be displaying a 'to' sign
TO;
Serial.print("To ");
switch (hour) {
case 1:
TWO;
Serial.println("Two ");
break;
case 2:
THREE;
Serial.println("Three ");
break;
case 3:
FOUR;
Serial.println("Four ");
break;
case 4:
HFIVE;
Serial.println("Five ");
break;
case 5:
SIX;
Serial.println("Six ");
break;
case 6:
SEVEN;
Serial.println("Seven ");
break;
case 7:
EIGHT;
Serial.println("Eight ");
break;
case 8:
NINE;
Serial.println("Nine ");
break;
case 9:
HTEN;
Serial.println("Ten ");
break;
case 10:
ELEVEN;
Serial.println("Eleven ");
break;
case 11:
TWELVE;
Serial.println("Twelve ");
break;
case 12:
ONE;
Serial.println("One ");
break;
}
}
WriteLEDs();
}
void incrementtime(void){
// increment the time counters keeping care to rollover as required
second=0;
if (++minute >= 60) {
minute=0;
if (++hour == 13) {
hour=1;
}
}
// debug outputs
Serial.println();
Serial.print(hour);
Serial.print(",");
Serial.print(minute);
Serial.print(",");
Serial.println(second);
}
void loop(void)
{
/*analogWrite(PWMPin, analogRead(0)/4); //enable dimming via potentiometer or photoresistor*/
analogWrite(PWMPin, 255); //manually set brightness level
// heart of the timer - keep looking at the millisecond timer on the Arduino
// and increment the seconds counter every 1000 ms
if ( millis() - msTick >999) {
msTick=millis();
second++;
// Flash the onboard Pin13 Led so we know something is hapening!
digitalWrite(13,HIGH);
delay(100);
digitalWrite(13,LOW);
}
//test to see if we need to increment the time counters
if (second==60)
{
incrementtime();
displaytime();
}
// test to see if the Minute Button is being held down
// for time setting
if ( (digitalRead(MinuteButtonPin) ==1 ) && second!=1)
// the Minute Button is down and it has been more
// than one second since we last looked
{
minute=(((minute/5)*5) +5);
second=0;
incrementtime();
second++; // Increment the second counter to ensure that the name
// flash doesnt happen when setting time
displaytime();
}
// test to see if the Hour Button is being held down
// for time setting
if ((digitalRead(HourButtonPin)==1 ) && second!=1)
{
minute = (minute/5)*5; //round minute down to previous 5 min interval
if (++hour == 13) {
hour=1;
}
incrementtime();
second++; // Increment the second counter to ensure that the name
// flash doesnt happen when setting time
displaytime();
}
}
Just checking. Have you, since recieving your RTC, actually set the time on it? Although I don't have the same RTC. The one I have will not run until you've successfully set the time on it at least once.
I have not set the time for my RTC. Does that mean that i have to find a code for my specific RTC, set the time, and afterwards reupload the code shown above again? Might be alot of stupid questions, still trying to wrap my head around all of this
The code does not use the RTC at all. The time at reset is set by this statement
int hour=9, minute=30, second=00;
The program then uses the Arduino's millisecond timer to keep time.
You will need to add to your program to read the RTC time at startup and use those values. And you will need to handle setting the RTC time, maybe with a separate sketch as you say. I think the first of the two programs you linked to originally may have some pointers.
Your hardware diagram does not show the RTC. How have you connected it?
OK before attempting the fancy stuff. Try loading this sketch and running it. Go into Serial monitor. Make sure you set the baud rate to 57600 (bottom right hand corner) and see what it produces.
Dert, I browsed your code and I do not see any interaction with the RTC. You need to do a little more than just include the rtc lib. You need to actually read it on setup()...
KenTF:
OK before attempting the fancy stuff. Try loading this sketch and running it. Go into Serial monitor. Make sure you set the baud rate to 57600 (bottom right hand corner) and see what it produces.
#include <Wire.h>
#include <RTClib.h>
RTC_DS1307 RTC;
void setup () {
Serial.begin(57600);
Wire.begin();
RTC.begin();
RTC.adjust(DateTime(DATE, TIME));
if (! RTC.isrunning())
Serial.println("RTC is NOT running!");
}
Just tried this and it worked like a charm. From what I understood from RobvdVeer I need to include this in the setup. I am not quite sure how to make that happen, I'll have to do some research.
Hackscribble:
The code does not use the RTC at all. The time at reset is set by this statement
int hour=9, minute=30, second=00;
The program then uses the Arduino's millisecond timer to keep time.
You will need to add to your program to read the RTC time at startup and use those values. And you will need to handle setting the RTC time, maybe with a separate sketch as you say. I think the first of the two programs you linked to originally may have some pointers.
Your hardware diagram does not show the RTC. How have you connected it?
Just noticed the read from RTC at startup from the first code, thank you for pointing that out!
I'll play around with that to see if I can incorporate it to my current code.
In the loop, you will need to use this call, and use the returns of now.hour, now.minute, and now.second to replace all the times you derive from the Arduino's millis timer.
Dert:
Just tried this and it worked like a charm. From what I understood from RobvdVeer I need to include this in the setup. I am not quite sure how to make that happen, I'll have to do some research.
OK well that line RTC.adjust(DateTime(DATE, TIME)); has now set your real time clock to the time on your computer. It should be the last time you need it (for a while at least)
But at least now we know that your RTC is wired correctly and is working. So bear with me I'll see if we can't integrate the vital parts into your original sketch.
Well this should be getting close. A lot of the original code is now redundant (so has been remarked out). But the issue of updating the time still needs to be sorted.
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 RTC;
// Display output pin assignments
#define MTEN Display1=Display1 | (1<<0)
#define HALF Display1=Display1 | (1<<1)
#define QUARTER Display1=Display1 | (1<<2)
#define TWENTY Display1=Display1 | (1<<3)
#define MFIVE Display1=Display1 | (1<<4)
#define MINUTES Display1=Display1 | (1<<5)
#define PAST Display1=Display1 | (1<<6)
#define UNUSED1 Display1=Display1 | (1<<7)
#define TO Display2=Display2 | (1<<0)
#define ONE Display2=Display2 | (1<<1)
#define TWO Display2=Display2 | (1<<2)
#define THREE Display2=Display2 | (1<<3)
#define FOUR Display2=Display2 | (1<<4)
#define HFIVE Display2=Display2 | (1<<5)
#define SIX Display2=Display2 | (1<<6)
#define UNUSED2 Display2=Display2 | (1<<7)
#define SEVEN Display3=Display3 | (1<<0)
#define EIGHT Display3=Display3 | (1<<1)
#define NINE Display3=Display3 | (1<<2)
#define HTEN Display3=Display3 | (1<<3)
#define ELEVEN Display3=Display3 | (1<<4)
#define TWELVE Display3=Display3 | (1<<5)
#define OCLOCK Display3=Display3 | (1<<6)
#define UNUSED3 Display3=Display3 | (1<<7)
static unsigned long msTick =0; // the number of Millisecond Ticks since we last
// incremented the second counter
int count;
char Display1=0, Display2=0, Display3=0;
// hardware constants
int LEDClockPin=6;
int LEDDataPin=7;
int LEDStrobePin=8;
int MinuteButtonPin=2;
int HourButtonPin=3;
int PWMPin = 9;
void setup()
{
// initialise the hardware
// initialize the appropriate pins as outputs:
pinMode(LEDClockPin, OUTPUT);
pinMode(LEDDataPin, OUTPUT);
pinMode(LEDStrobePin, OUTPUT);
//pinMode(BrightnessPin, INPUT);
pinMode(MinuteButtonPin, INPUT);
pinMode(HourButtonPin, INPUT);
pinMode(PWMPin, OUTPUT);
Serial.begin(19200);
msTick=millis(); // Initialise the msTick counter
Wire.begin();
RTC.begin();
//RTC.adjust(DateTime(__DATE__, __TIME__));
if (! RTC.isrunning())
Serial.println("RTC is NOT running!");
displaytime(); // display the current time
}
void ledsoff(void) {
Display1=0;
Display2=0;
Display3=0;
}
void WriteLEDs(void) {
// Now we write the actual values to the hardware
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display3);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display2);
shiftOut(LEDDataPin, LEDClockPin, MSBFIRST, Display1);
digitalWrite(LEDStrobePin,HIGH);
delay(2);
digitalWrite(LEDStrobePin,LOW);
}
void displaytime(void)
{
byte hour,minute, second;
DateTime now = RTC.now();
hour=now.hour();
minute=now.minute();
second=now.second();
// start by clearing the display to a known state
ledsoff();
Serial.print("It is ");
// now we display the appropriate minute counter
if ((minute>4) && (minute<10)) {
MFIVE;
MINUTES;
Serial.print("Five Minutes ");
}
if ((minute>9) && (minute<15)) {
MTEN;
MINUTES;
Serial.print("Ten Minutes ");
}
if ((minute>14) && (minute<20)) {
QUARTER;
Serial.print("Quarter ");
}
if ((minute>19) && (minute<25)) {
TWENTY;
MINUTES;
Serial.print("Twenty Minutes ");
}
if ((minute>24) && (minute<30)) {
TWENTY;
MFIVE;
MINUTES;
Serial.print("Twenty Five Minutes ");
}
if ((minute>29) && (minute<35)) {
HALF;
Serial.print("Half ");
}
if ((minute>34) && (minute<40)) {
TWENTY;
MFIVE;
MINUTES;
Serial.print("Twenty Five Minutes ");
}
if ((minute>39) && (minute<45)) {
TWENTY;
MINUTES;
Serial.print("Twenty Minutes ");
}
if ((minute>44) && (minute<50)) {
QUARTER;
Serial.print("Quarter ");
}
if ((minute>49) && (minute<55)) {
MTEN;
MINUTES;
Serial.print("Ten Minutes ");
}
if (minute>54) {
MFIVE;
MINUTES;
Serial.print("Five Minutes ");
}
if ((minute <5))
{
switch (hour) {
case 1:
ONE;
Serial.print("One ");
break;
case 2:
TWO;
Serial.print("Two ");
break;
case 3:
THREE;
Serial.print("Three ");
break;
case 4:
FOUR;
Serial.print("Four ");
break;
case 5:
HFIVE;
Serial.print("Five ");
break;
case 6:
SIX;
Serial.print("Six ");
break;
case 7:
SEVEN;
Serial.print("Seven ");
break;
case 8:
EIGHT;
Serial.print("Eight ");
break;
case 9:
NINE;
Serial.print("Nine ");
break;
case 10:
HTEN;
Serial.print("Ten ");
break;
case 11:
ELEVEN;
Serial.print("Eleven ");
break;
case 12:
TWELVE;
Serial.print("Twelve ");
break;
}
OCLOCK;
Serial.println("O'Clock");
}
else
if ((minute < 35) && (minute >4))
{
PAST;
Serial.print("Past ");
switch (hour) {
case 1:
ONE;
Serial.println("One ");
break;
case 2:
TWO;
Serial.println("Two ");
break;
case 3:
THREE;
Serial.println("Three ");
break;
case 4:
FOUR;
Serial.println("Four ");
break;
case 5:
HFIVE;
Serial.println("Five ");
break;
case 6:
SIX;
Serial.println("Six ");
break;
case 7:
SEVEN;
Serial.println("Seven ");
break;
case 8:
EIGHT;
Serial.println("Eight ");
break;
case 9:
NINE;
Serial.println("Nine ");
break;
case 10:
HTEN;
Serial.println("Ten ");
break;
case 11:
ELEVEN;
Serial.println("Eleven ");
break;
case 12:
TWELVE;
Serial.println("Twelve ");
break;
}
}
else
{
// if we are greater than 34 minutes past the hour then display
// the next hour, as we will be displaying a 'to' sign
TO;
Serial.print("To ");
switch (hour) {
case 1:
TWO;
Serial.println("Two ");
break;
case 2:
THREE;
Serial.println("Three ");
break;
case 3:
FOUR;
Serial.println("Four ");
break;
case 4:
HFIVE;
Serial.println("Five ");
break;
case 5:
SIX;
Serial.println("Six ");
break;
case 6:
SEVEN;
Serial.println("Seven ");
break;
case 7:
EIGHT;
Serial.println("Eight ");
break;
case 8:
NINE;
Serial.println("Nine ");
break;
case 9:
HTEN;
Serial.println("Ten ");
break;
case 10:
ELEVEN;
Serial.println("Eleven ");
break;
case 11:
TWELVE;
Serial.println("Twelve ");
break;
case 12:
ONE;
Serial.println("One ");
break;
}
}
WriteLEDs();
}
/*This function is now redundant
//we're now using REAL time not artificially updating it
void incrementtime(void){
// increment the time counters keeping care to rollover as required
second=0;
if (++minute >= 60) {
minute=0;
if (++hour == 13) {
hour=1;
}
}
// debug outputs
Serial.println();
Serial.print(hour);
Serial.print(",");
Serial.print(minute);
Serial.print(",");
Serial.println(second);
}
*/
byte lastSec=0;
void loop(void)
{
/*analogWrite(PWMPin, analogRead(0)/4); //enable dimming via potentiometer or photoresistor*/
analogWrite(PWMPin, 255); //manually set brightness level
//test to see if we need to increment the time counters
DateTime now = RTC.now();
if(lastSec!=now.second())
{
displaytime();
lastSec=now.second();
}
//this is the end of the active section of the loop function
//the remaining part is all to do with changing the setting of the time
//It needs updating to deal with the RTC
/*
// test to see if the Minute Button is being held down
// for time setting
if ( (digitalRead(MinuteButtonPin) ==1 ) && second!=1)
// the Minute Button is down and it has been more
// than one second since we last looked
{
minute=(((minute/5)*5) +5);
second=0;
incrementtime();
second++; // Increment the second counter to ensure that the name
// flash doesnt happen when setting time
displaytime();
}
// test to see if the Hour Button is being held down
// for time setting
if ((digitalRead(HourButtonPin)==1 ) && second!=1)
{
minute = (minute/5)*5; //round minute down to previous 5 min interval
if (++hour == 13) {
hour=1;
}
incrementtime();
second++; // Increment the second counter to ensure that the name
// flash doesnt happen when setting time
displaytime();
}
*/
}
KenTF:
Well this should be getting close. A lot of the original code is now redundant (so has been remarked out). But the issue of updating the time still needs to be sorted.
Just woke up to see this post. I uploaded the code and it's working perfectly! I did some testing around and it seems to keek time, even when there is a power reset! Words cannot describe how grateful I am just right now, This issue has been bothering me for weeks now. I'm heding to work now, and wont't be back for around 11 hours.
You mentioned something about an issue of updating the time, but from what i've testet so far it all seems to work just as intended. I might have misunderstood something here, any way you could elaborate?
Again many thanks for this, you guys have been amazing. I'm learing so much now!
// Init the DS3231 using the hardware interface
DS3231 rtc(SDA, SCL);
void setup()
{
// Setup Serial connection
Serial.begin(57600);
// Uncomment the next line if you are using an Arduino Leonardo
//while (!Serial) {}
// Initialize the rtc object
rtc.begin();
// The following lines can be uncommented to set the date and time
rtc.setDOW(6); // Set Day-of-Week to SUNDAY
rtc.setTime(19, 26, 30); // Set the time to 12:00:00 (24hr format)
rtc.setDate(21, 5, 2016); // Set the date to January 1st, 2014
}
williamdv:
bud why is the time getting back to 19:26:30 h and 21-5-2016
Maybe because you set it to that value on each reset?
rtc.setDOW(6); // Set Day-of-Week to SUNDAY
rtc.setTime(19, 26, 30); // Set the time to 12:00:00 (24hr format)
rtc.setDate(21, 5, 2016); // Set the date to January 1st, 2014