clock with daytime chime / British summertime correction and new year chime

I would figure that the DS3231 is more than accurate enough for a tower clock.

In my apartment is a DS3231-based clock. I set it only once or twice a month, and then only by maybe 1 or 2 seconds each time (I know, I am anal about my clocks).
As long as your chimes are within 1 minute of the correct time, I doubt that too many people would care about the difference. Especially if it’s on an island.
To be honest, though, I don’t really know how good those DS3231s are with extreme temperature changes. Mine is kept quite cozy in my apartment. Will your DS3231 be exposed to very high and very low temperatures? There is temperature compensation built in, but I have no idea how well it works in real life. Probably more than good enough for “island time”.

As for a setting procedure: that makes things a bit more complicated. But if I were you, I wouldn’t overthink it. I would just use two buttons: a “plus” button and a “minus” button. Have “plus” move the time forward 1 minute (or maybe 15 seconds, if you’re anal like me). Have “minus” move the time back by the same amount.

As for debugging: your most important tools are your ears and your wristwatch. Besides those, the LCD can be used to display the time that your system “thinks” it is (extremely useful for debugging; absolutely essential for time setting).

What does your code look like now?

@jurs: You don't need "silent strikes". If the clock is not supposed to strike, then just set the number of strikes to 0.

@piccy: If you want to manually turn off striking, the simplest and surest way is to disconnect the speaker.

odometer: @jurs: You don't need "silent strikes". If the clock is not supposed to strike, then just set the number of strikes to 0.

Hehe, you are right.

But the user wanted a button to switch striking on/off by pressing a button.

At 12 o'clock the duration of 12 strikes is 44 seconds. First strike at 12:00:00, 12th strike at 12:00:44.

With the programming logic I provide, the user can switch his button any time he wants to silent or loud. Even in between the single clock strikes, if he wants.

About your suggestion simply setting the time with two buttons:

odometer: As for a setting procedure: that makes things a bit more complicated. But if I were you, I wouldn't overthink it. I would just use two buttons: a "plus" button and a "minus" button. Have "plus" move the time forward 1 minute (or maybe 15 seconds, if you're anal like me). Have "minus" move the time back by the same amount.

But this setting logic may become a nightmare, if the mains power fails and the backup battery is empty, and the time needs to be set from 01.01.2000 to 10.11.2015 several years into the future.

But perhaps this can be improved, by a "press and hold" logic for the +/- buttons. I'd think about that: - if button is short keypress: adjust time by 15 seconds +/- - if button is "press and hold" for more than 1 second, there will be an automatic accelleration in time setting: The longer the button is pressed, the faster the time will be forward/backward running.

Perhaps in a way, that if the button is pressed for more than 30 seconds, the increase is 1 year per second, so that is becomes possible to do a time setting from year 2000 (after backup battery change) to year 2015 or 2020 in a reasonable amount of time with just a '+' and a '-' button.

P.S: I think the current code is in the file attachment to reply #8, with DEBUG set to 0, to make the SoftwareSerial work with the audio player module.

jurs: About your suggestion simply setting the time with two buttons: But this setting logic may become a nightmare, if the mains power fails and the backup battery is empty, and the time needs to be set from 01.01.2000 to 10.11.2015 several years into the future.

But perhaps this can be improved, by a "press and hold" logic for the +/- buttons. I'd think about that: - if button is short keypress: adjust time by 15 seconds +/- - if button is "press and hold" for more than 1 second, there will be an automatic accelleration in time setting: The longer the button is pressed, the faster the time will be forward/backward running.

Yes, I was thinking about doing it that way, more or less. Of course, the seconds would have to carry into the minutes, etc., etc. In order to figure out the best way to do this, I will need to see what the OP's code looks like now.

I've programmed clocks before, and here are some things I've found out:

The easiest way to move the time back 1 minute is, you don't. Instead, you move the date back 1 day, and the time forward 23 hours and 59 minutes, and then do the carries.

When you set the date on the DS3231, you should remember to set the correct day of the week. That way, when you go to read the date, you will be able to recognize bad dates at least 6 times out of 7.

jurs: You have the audio device and can do "audio debugging", I don't have it.

Or you could blink an LED.

jurs: But the user wanted a button to switch striking on/off by pressing a button.

At 12 o'clock the duration of 12 strikes is 44 seconds. First strike at 12:00:00, 12th strike at 12:00:44.

With the programming logic I provide, the user can switch his button any time he wants to silent or loud. Even in between the single clock strikes, if he wants.

As for how to do it: you just answered your own question. Don't count strokes, count seconds. Although there's not much point in incompletely striking an hour.

Hi Jurs, odometer, stowite,

apologies for delay in replying , i have been up at the clock tower today looking at the clock that is in there , it was installed 23 years ago , i think it is a synchronous motor that is fitted , i also found a sticker of the supplier on it, a google check has shown they still exist and i am going to call them in the morning , i may be lucky and it is one with a sync wire fitted.

Regarding your posts replies are below

@Jurs I think that is the basic program then as you wanted it: - chiming at full hours, 4 seconds between single strikes - automatically summertime switching between UTC and BST time. - with exception: no chiming strikes during night hours - with exception: no chiming strikes when set to "silent" by button - with exception: 12 chiming strikes at midnight on new year - LCD display of time and bell icon

yes that is correct

@Jurs But as I understand, you would prefer, that date/time setting could be done with the device itself, no other device attached, right?

yes i would like it to be on the device setting , either by buttons or rotary encoder i dont mind if it took a reasonable amount of time to set , so either rotary or buttons whatever is easiest to be implemented.

@Jurs What do you think? Would it be possible to replace the button in your application with such a rotary encoder with button and then try to adapt my menu for date/time setting from the other thread for your application?

yes

@Jurs Create the full hardware now, prepared to be used for functions that are not available yet and need to be implemented later by programming a firmware update? But for now use the sketch that you have?

use the existing sketch as a firmware, only the button function of the encoder is used

Jurs, i am more than happy to use the software as it is now , with the addition of the rotary encoder (button use only at this time) I am concious of the input and effort you have put into this for me up to know , for which i am truly grateful, if you wish to work on it further it will totally be on your timescale with no feeling of pressure from me.

I will be spending the next couple of weeks monitoring the physical clock against this one to see how far out they may be and what correction will be needed .

@stowite Consider using MSF ( http://www.npl.co.uk/science-technology/time-frequency/products-and-services/time/msf-radio-time-signal ) to synchronize your DS3231. For my clock whenever the DS3231 is more than 2 seconds in error I update it with MSF time; this is fairly infrequent since the DS3231 is very accruate.

msf is not receivable reliably on the south west tip of Ireland so wasnt a reliable option. Nice thought though, i built a pic msf clock a 3 years ago when i was over in the uk

@odometer In my apartment is a DS3231-based clock. I set it only once or twice a month, and then only by maybe 1 or 2 seconds each time (I know, I am anal about my clocks). As long as your chimes are within 1 minute of the correct time, I doubt that too many people would care about the difference. Especially if it's on an island.

re apartment clock setting thats serious OCD lol , I agree with you re being within 1 minute of actual clock , so long as the minute hand is pretty close to the 12 o clock position ie minute either side i dont think folks will notice ( although there will always be one that does )

@odometer There is temperature compensation built in, but I have no idea how well it works in real life. Probably more than good enough for "island time".

where the clock is located the temp rarely drops below 4 degrees in winter , and a mild frost was last seen around five years ago, i suppose time will tell and i think it will be monitored by me for at least the next six months . The main aim of the project is to bring a piece of history back to life , the last time the bell rang was 1922.

piccy: msf is not receivable reliably on the south west tip of Ireland so wasnt a reliable option. Nice thought though, i built a pic msf clock a 3 years ago when i was over in the uk

I holidayed on the Dingle peninsula a few years back. Brilliant place - I wish I could live there. An alternative to MSF would be the time and date 198 KHz BBC long wave transmitter which has a better reception range than MSF. I'm currently studying the documentation ( http://downloads.bbc.co.uk/rd/pubs/reports/1984-19.pdf ) with the aim of creating a clock and a frequency standard synchronized to it. I have started the design of the frequency standard but I still have a long way to go before I can consider even starting the design of the clock ( I don't yet understand the modulation but am getting there).

@piccy:

What exactly does your code look like now? Please post it.

Personally, I think it would be much easier to implement time setting with buttons than with a rotary encoder. I would use two buttons: a "plus" button and a "minus" button. Together with the on/off button for the chimes, that would be three buttons total. The idea is to make the controls simple to build and simple to operate.

What kind of LCD display are you using? How many lines of how many characters?

odometer: @piccy:

What exactly does your code look like now? Please post it.

He uses the code that I posted. It is attached as a file attachment to reply #8 in this thread.

DEBUG option must be set to 0, otherwise SoftwareSerial cannot send the command to the audio device correctly because SoftwareSerial and Serial cannot work at the same time without SoftwareSerial garbling the characters it sends.

odometer: Personally, I think it would be much easier to implement time setting with buttons than with a rotary encoder. I would use two buttons: a "plus" button and a "minus" button. Together with the on/off button for the chimes, that would be three buttons total. The idea is to make the controls simple to build and simple to operate.

Yes, I think the same: Two buttons for setting date/time are much easier than a rotary encoder menu. I'll think a little bit over it and then post a suggestion that might work. :wink:

@odometer
What kind of LCD display are you using? How many lines of how many characters?

16x2 I2C

code attached kindly provided by JURS

sketch_nov07a.ino (8.92 KB)

Hi Jur,

poss bug ?

wasnt around during day yesterday while clock was running , it chimed at 21:00 last night (only one i was around for) this morning so far it hasnt chimed at 9 or 10 o clock ,not had chance to look at code will be out again until later

if you get chance could you have a look please

piccy: apologies for delay in replying , i have been up at the clock tower today looking at the clock that is in there , it was installed 23 years ago , i think it is a synchronous motor that is fitted , i also found a sticker of the supplier on it, a google check has shown they still exist and i am going to call them in the morning , i may be lucky and it is one with a sync wire fitted.

I think the accuracy of synchronous motor clocks heavily depends on the frequency of the AC mains power in your country.

In mainland Europe, the electricity grid is organized like that: The mains frequency of nominal 50 Hz can float in a range of 49.9 and 50.1 Hz actually. So clocks may win or lose time relatively fast, dependent on the frequency of mains power. Let's say a short time inaccuracy of one minute can occur within a single day. But on the long run, synchronous clocks will be nearly as accurate as atomic clocks. The mains and frequency in the electric grid is regulated in a way, so that all frequency plus/minus changes will be compensated to zero. Although synchronous clock may be inaccurate by 1 minute per day in short time, they are keeping time very accurate on the long run.

I don't know about frequency regulation in the electricity grid of your country.

piccy: yes i would like it to be on the device setting , either by buttons or rotary encoder i dont mind if it took a reasonable amount of time to set , so either rotary or buttons whatever is easiest to be implemented.

I have slept over it and maybe this is what I can do, without being too complicated: Use a rotary encoder, but NOT a full featured "menu".

All values to be edited are visible on the display at the same time. So I would suggest a setting logic which simply consists of the following functions: - press rotary button ==> select value - rotate rotary knob ==> change value

The sequence of selected values may be: - silent mode - seconds - minutes - hours - days - month - year - nothing

So if you want to change "silent state", you would: - press button once (select "silent mode") - rotate button to change value on/off

Or if you want to change "minutes", you would: - press button three times (select "minutes") - rotate button to change minutes value in the range 0..59

As a visible feedback about the selected value, the LCD offers a cursor to be activated: - lcd.Cursor() - lcd.noCursor() If any value is selected, a "underline cursor" would become visible below the selected value. Then you can rotate the knob and change the value. Any change will become effective immediately, so no fancy Save/Cancel options available.

A timeout may watch out for time of last button pressed or knob rotated, and after maybe 10 seconds without user action, the "selected value" becomes "nothing selected" and changing values by rotating the knob is automatically disabled again.

Possibly I'll try that settings logic with a rotary encoder.

piccy: poss bug ?

wasnt around during day yesterday while clock was running , it chimed at 21:00 last night (only one i was around for) this morning so far it hasnt chimed at 9 or 10 o clock ,not had chance to look at code will be out again until later

I don't know. I did only short tests using the code for a few minutes. Which symbol (if any) is displayed for the "silent" state then (nothing, full bell, outline bell)? Is the LCD displaying date and time correctly?

BTW: Which serial audio module are you using in your circuit?

piccy:
Hi Jur,

poss bug ?

wasnt around during day yesterday while clock was running , it chimed at 21:00 last night (only one i was around for) this morning so far it hasnt chimed at 9 or 10 o clock ,not had chance to look at code will be out again until later

if you get chance could you have a look please

What exactly are you running now?
Is the attachment in reply #30 exactly what you are running now? Did you do anything with DEBUG?
Try changing this

#define DEBUG 1

to this
#define DEBUG 0 
and see what happens.

jurs: All values to be edited are visible on the display at the same time. So I would suggest a setting logic which simply consists of the following functions: - press rotary button ==> select value - rotate rotary knob ==> change value

The sequence of selected values may be: - silent mode - seconds - minutes - hours - days - month - year - nothing

So if you want to change "silent state", you would: - press button once (select "silent mode") - rotate button to change value on/off

Or if you want to change "minutes", you would: - press button three times (select "minutes") - rotate button to change minutes value in the range 0..59

For obvious reasons, it might be a good idea to disable strike while in time-setting mode, as well.

HI Jurs , Odometer,

running the version as stated in your last post with debig set to 0 as it was affecting playing of mp3

have noticed that if i let the hour roll over ie 3.00 clock then it doesnt chime but if i then reboot the nano it instantly plays the chime , so i am guessing that a flag is being set incorrectly and resseting it makes it check again and with initialisation values it chimes but just the once , when it gets to 4.00 clock it doesnt chime again

the serial mp3 player is the calatex one manual attached

the idea of limited rotary encoder menu sounds good , i have ordered one from ebay today , will take about 4 days to arrive

Serial MP3 Player v1.0 Manual(1).pdf (548 KB)

piccy: have noticed that if i let the hour roll over ie 3.00 clock then it doesnt chime but if i then reboot the nano it instantly plays the chime , so i am guessing that a flag is being set incorrectly and resseting it makes it check again and with initialisation values it chimes but just the once , when it gets to 4.00 clock it doesnt chime again

Do you really mean 03:00 and 04:00? Both times would be during night hours and no sound should be played during the night, except at 00:00 on new year.

Sound should be played only if the bell is set to on and between 09:00 and 21:00 by day.

Do you possibly mean 15:00 and 16:00 (in the afternoon)?

piccy: the serial mp3 player is the calatex one manual attached

I will have a closer look at the manual and check the commands (as far as I can do it from the manual).

jurs:
Do you really mean 03:00 and 04:00? Both times would be during night hours and no sound should be played during the night, except at 00:00 on new year.

Sound should be played only if the bell is set to on and between 09:00 and 21:00 by day.

Do you possibly mean 15:00 and 16:00 (in the afternoon)?

I will have a closer look at the manual and check the commands (as far as I can do it from the manual).

I think you’re looking in the wrong place.

You have:

    if (minute==0 && oldMinute!=0) // minute just switched to a full hour
    {
#if (DEBUG==1) 
  Serial.print("New Hour: ");Serial.println(hour);
#endif 
      oldMinute=minute; // remember current minute
      if (hour>12)      // and set the number of strikes
        strike=hour-12; 
      else if (hour>0)
        strike=hour;
      else
        strike=12;
    }

The variable oldMinute occurs exactly three times in your version of this sketch: once when you declare it (you initialize it to 255), plus twice in this snippet. So oldMinute can only ever be 0 or 255.
And if I were you, I’d lose the DEBUG statements. They seem to be more of a hindrance than a help.

odometer: The variable oldMinute occurs exactly three times in your version of this sketch: once when you declare it (you initialize it to 255), plus twice in this snippet. So oldMinute can only ever be 0 or 255.

You are right, programming logic for full hour detection is wrong and needs to be reworked.

I'm currently working over it, also with the intention: - to provide immediate change of the bell icon in the LCD when the button is pressed - to provide a UTC or BST display (so the user can see which time is active) - to prepare the loop() function logic for rotary encoder time settings - to put the time functions on a seperate "tab" of the editor

jurs:
You are right, programming logic for full hour detection is wrong and needs to be reworked.

Nothing to it. Detect a changed hour rather than a changed minute.

For debugging purposes, substitute a piezo buzzer (if you have one) for the MP3 player.

To debug a striking clock, it might be necessary just to let it run for several hours and observe what happens. That’s what I ended up doing for one of my clocks.

And you don’t need to count strikes.

const int strikeLength = 4; // seconds per strike

int twelveHour = hour;
if (twelveHour > 12) twelveHour -= 12;
if (twelveHour == 0) twelveHour = 12;

if ((!silent) &&
   (((hour >= startStrikeTime) && (hour <= stopStrikeTime)) ||
    ((month==1) && (dayOfMonth==1) && (hour==0))) &&
     (minute == 0) &&
    ((second % strikeLength) == 0) &&
     (second < (twelveHour * strikeLength))) {
       //
       // if we're in here, it's time to sound the chime 
       //
     }