digital clock generated from the 50Hz mains

Hello,

I am new to Arduino and not a genius in programming neither. I have a project on making a digital clock using Arduino ATmega328 which counts the mains 50Hz pulses and displays the time on an LCD. what will be the best way to start off the programming?

Would really appreciate your response.
:slight_smile:

counts the mains 50Hz pulses

Well, first, you've got to turn a sine wave into pulses.
Something like a comparator after the transformer, then trigger an interrupt (or simply poll) on the edges?

Yeh, the mains supply is stepped down using a transformer and then rectified+smoothed to power the Arduino board. but i think, I have to use a photocoupler to isolate the circuit so that the Arduino can use just the mains to generate the clock.

Just wandering how to go about writing the sketch for the Arduino to do this?

Count 'n' pulses, increment the seconds counter.
If seconds == 60, increment the minutes counter,
If minutes == 60, increment the hours counter.

And so on

Thanks. any ideas on how to trigger an interrupt at the edges? sorry I am abit new to C programming.

At 50Hz, you probably don't need an interrupt.
However, if you do:
http://www.arduino.cc/en/Reference/AttachInterrupt

seems good. Would try it out but not sure yet if i will need an interrupt.I think the starting point will be how to programme the Arduino to extract the pulses from the mains.

any suggestions?

External interrupts would be a good method to count mains pulses. If you have access to the secondary side of your transformer - you can connect any of its two legs to either digital pin 2 or 3 through a large resistor (30k - 100k). The external interrupt will then be called once per mains cycle allowing you to increment a count.

Voltage on the secondary side of your transformer will exceed the maximum/minimum allowed voltage for your Arduino pin, but the ATmega has protective diodes clamped to GND and Vcc that protects against under/over voltage. As long as you limit the current through these diodes (the large resistor will do this) - you will be ok.

I wouldn't rely on those protective diodes even with a large resistor. It's just asking for trouble. External diodes are more robust. And it depends on the power supply design - a wall wart should be ok, but a switching-type is a whole different beast.

My personal preference is to use a optocouple, but you could get by without it if you use some external diodes. Say one diode to protect against reverse polarity, and one 5V zener to clamp the maximum voltage, and a good sized resistor to limit current.

You'd create a simple function that updates the global variables:

// globals
volatile int pulses;
volatile int seconds;
// etc.

void pulse_count() {
       pulses++;
       if (pulses >= 50) {
            pulses = 0;  // reset
            seconds++;
       }

      // etc

}

Don't do anything in the interrupt function except update these variables. You want interrupt functions to be short & simple and to finish quickly. Put your LCD display handling in the normal "loop()" function.

The "volatile" designation is important! When the compiler analyzes your program it won't know that you're "pulse_count" function is actually being called and will think that the variables don't get changed. It would normally "optimize" your program in such a way that the loop function may miss the updates. "Volatile" tells the compiler that these variables get changed outside of the normal program flow and not to optimize them.

Then in your setup function you would attach the function to an interrupt:

void setup() {

   // setup stuff...

   attachInterrupt(0, pulse_count, RISING);
}

You will have to change the "0" to the interrupt that you are using. See the reference pages to attachInterrupt to determine which digital input pin corresponds to what interrupt number.

The "RISING", should cause the interrupt to trigger just after the sine wave crosses zero on the positive half of the cycle.

thanks guys,

Finished my power supply+Zero crossing circuit today.The next stage is now to programme the Arduino board to read the input(50hz pulse) and generate time with it.

I need help with knowing how to start writing the sketch for this project as I would be adding a LM35series temp sensor and an LDR function to it as well. I would like some advices.

Thanks :slight_smile:

Hi guys, this is how far I have got with my coding for counting the pulses and incrementing the seconds+ minutes+ hours.but dont think its working as I expected when viewed through the serial monitor.

code;

int pulsePin = 3;
//int ledPin = 13;

unsigned long counter = 0;
unsigned long duration = 0;
unsigned long timeout = 1000000; // in microseconds

volatile int pulses;
volatile int seconds;
volatile int minutes;
volatile int hours;

void pulse_count() {
pulses++;
if (pulses = 50) {
pulses = 0; // reset
seconds ++;
}

// move forward one minute every 60 seconds

if (seconds >= 60) {
minutes++;
seconds = 0; // reset seconds to zero
Serial.println("minutes");
}

// move forward one hour every 60 minutes

if (minutes >= 60) {
hours++;
minutes = 0; //resets minutes to zero
}

if (hours >=24) {
hours = 0;
minutes = 0; // resets minutes to zero
}

}

void setup() {
pinMode(pulsePin, INPUT);
// enable the 20K pull-up resistor to steer
// the input pin to a HIGH reading.
digitalWrite(pulsePin, HIGH);
Serial.begin(9600);
attachInterrupt (1, pulse_count, RISING);
Serial.println("here we go");
}

void loop() {
duration = pulseIn(pulsePin, HIGH, timeout);
if (duration == 0) {
Serial.print("Pulse started before the timeout.");
Serial.println("");
} else {
counter++;
Serial.print(counter);
Serial.print(", ");
Serial.print(duration);
Serial.println(", ");
Serial.print(seconds);
Serial.println(", ");
Serial.print(minutes);
Serial.println(", ");
Serial.print(hours);
Serial.println(", ");
}
}

Any one find any problem, pls point out to me. :slight_smile:

but dont think its working as I expected when viewed through the serial monitor.

No fair hogging the serial monitor! Let us see it, too.

Seriously, what isn't working as expected? Does the interrupt fire when expected? Is the time-keeping based on the interrupts not working, even though the interrupt fires on time?

Any clue as to where the problem lies will make it easier to find...

One comment, though.

volatile int pulses;
volatile int seconds;
volatile int minutes;
volatile int hours;

It would be better to explicitly initialize these.

change
if (pulses = 50) {
to
if (pulses == 50) {

also I suggest you don't try to do serial input or output in an interrupt handler.

From here...
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1261124850/all

Data that cannot be accessed atomically and is shared with an ISR needs to be protected by disabling interrupts during the access

Because the values never exceed 255, the protection isn't necessary. But, it would be a good idea to make pulses, seconds, minutes, and hours all byte and include a comment that the protection has been deliberately left out.

Thanks mem, I have added that change i.e. (if (pulses == 50) {

Coding badly, that was a nice explanation for interrupts, really good.

Paul, when you said I should explicitly initialise the;

volatile int pulses;
volatile int seconds;
volatile int minutes;
volatile int hours;

do you mean remove the volatile part, i.e just int pulses, int seconds etc ?
The seconds increase in two's and the minutes seem to be fine and the hours too.

anyway to fix all these?

I think mem pointed out the main problem with your code (if(pulses = 15) should be if(pulses == 15)). What I meant for you to do is this:

volatile int pulses[glow] = 0[/glow];
volatile int seconds[glow] = 0[/glow];
volatile int minutes[glow] = 0[/glow];
volatile int hours[glow] = 0[/glow];

Cheers Paul, that worked fine. the clock now counts the hours, minutes and seconds.

I am just wandering how I will set the time, what would I had to the code and I guess I will need some push buttons for that, do I?

If you want to set the time to an arbitrary time, push buttons would be one way to do it. A button to enter set mode, one to choose what to set (hours, minutes, or seconds), and up/down buttons would be good.

hey guys, been away for a bit. I have now added a piezzo buzzer for the alarm function, but using the example playMelody (http://www.arduino.cc/en/Tutorial/PlayMelody) I couldnt figure out how to get it to loop more than once when I used it with my code.

anyone has an idea how?

also I am looking into running the clock after switching off the mains supply (i.e. no more 50Hz input into the arduino) through a lithium battery pack but am not sure of how the time could be kept accurate since I want it to be possible for the clock to run using the battery when the mains is uplugged.

any help will do

thanks :slight_smile:

Your "clock" is an AC line. Replacing that with a DC line that never goes negative will make for some vvvvvvveeeeeerrrrrrrryyyyyy seconds.

I think it's time for you to invest in an RTC.