Welcome! Log In Create A New Profile

Advanced

help needed timing a clock

Posted by ekaggrat 
help needed timing a clock
March 23, 2015 11:47PM
hi,

I have designed and 3d printed a clock thingiverse
i am controlling the clock using a arduino sketch running on a attiny2313. the stepper motor i am using is a 12v 1:12 ratio stepper. the total number of steps per revolution are 288.

the problem i am facing is that i am unable to get the time right. i have got the steps per revolution of the minute ring bang on . but some how the motor gains 10 -11 minutes every 24 hours.

i have used a lot of the code from the stepper motor library. i am not using the stepper motor library as the code gets larger than what can fit into the 2k attiny space.

any help is appreciated



int number_of_steps = 288;
int motor_pin_1 = 9;
int motor_pin_2 = 10;
int motor_pin_3 = 11;
int motor_pin_4 = 12;
int ledpin = 13;
int delayTime = 4;
int buttonPin = 4;
int buttonState = 0;
int enablepin = 8;
int whatspeed = 40;
int last_step_time =0;
int step_number = 0;
int blinkDelay = 939;
int step_delay = 60L * 1000L / number_of_steps / whatspeed;
int step_direction = 0;
void setup() {


pinMode(motor_pin_1, OUTPUT);
pinMode(motor_pin_2, OUTPUT);
pinMode(motor_pin_3, OUTPUT);
pinMode(motor_pin_4, OUTPUT);
pinMode(buttonPin,INPUT);
pinMode(ledpin, OUTPUT);
pinMode(enablepin,OUTPUT);

}

void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState ==HIGH){
enablemotor();
movestep(20);
digitalWrite(ledpin,HIGH);
}
else{
digitalWrite(ledpin,LOW);

for (int xx = 0; xx<59;xx ++){

enablemotor();
movestep(42);
//delay(100);
motoroff();
blinkk();
}
enablemotor();
movestep(89);//85;

motoroff();
blinkk();
//delay(3000);
}
}



void enablemotor(){
digitalWrite(enablepin,HIGH);
}


void movestep(int steps_to_move){
int steps_left = abs(steps_to_move);

if (steps_to_move > 0) {
step_direction = 1;
}
if (steps_to_move < 0) {
step_direction = 0;
}


while(steps_left > 0) {
// if (millis() - last_step_time >= step_delay ) {
//last_step_time = millis();
if ( step_direction == 1 ){
step_number++;
delay(step_delay);
if (step_number == number_of_steps) {
step_number = 0;
}
}
else {
if (step_number ==0){
step_number = number_of_steps;
}
step_number--;
}
steps_left--;


stepmotor(step_number % 4);


//}
}
}





void stepmotor(int thisStep){

switch (thisStep) {
case 0: // 1010
digitalWrite(motor_pin_1, HIGH);
digitalWrite(motor_pin_2, LOW);
digitalWrite(motor_pin_3, HIGH);
digitalWrite(motor_pin_4, LOW);
break;
case 1: // 0110
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, HIGH);
digitalWrite(motor_pin_3, HIGH);
digitalWrite(motor_pin_4, LOW);
break;
case 2: //0101
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, HIGH);
digitalWrite(motor_pin_3, LOW);
digitalWrite(motor_pin_4, HIGH);
break;
case 3: //1001
digitalWrite(motor_pin_1, HIGH);
digitalWrite(motor_pin_2, LOW);
digitalWrite(motor_pin_3, LOW);
digitalWrite(motor_pin_4, HIGH);
break;
}

}

void blinkk(){
for (int i = 0 ; i<30;i++){
buttonState = digitalRead(buttonPin);
if (buttonState ==HIGH){
break;
}
else{
digitalWrite(ledpin, HIGH); // set the LED on
delay(blinkDelay); // 968 // wait for a second
digitalWrite(ledpin, LOW); // set the LED off
delay(blinkDelay); //968
}
}
}

void motoroff(){
digitalWrite(enablepin,LOW);
digitalWrite(motor_pin_1, LOW);
digitalWrite(motor_pin_2, LOW);
digitalWrite(motor_pin_3, LOW);
digitalWrite(motor_pin_4, LOW);
}
Re: help needed timing a clock
March 24, 2015 09:31AM
A clock is only as accurate as the reference. Are you using a crystal to drive the clock in the uC? Or an internal oscillator? Or is it tied to the power line for reference?

If the uC clock is off, the errors will accumulate and your clock won't keep correct time. If the uC clock frequency drifts with temperature changes you won't be able to keep accurate time.

The power line 50 or 60 Hz is VERY accurate and can be used as a reference for clocks to keep accurate time, but you have to plug into the wall outlet. If you're trying to remain battery powered you need to use a stable reference.
Re: help needed timing a clock
March 24, 2015 08:17PM
the board uses a crystal at 8mhz so i dont think that is causing a error. I think something is off in the code.

gitbub board files

thanks
Re: help needed timing a clock
May 05, 2015 07:02PM
I would write to console, (using serial) the outputted time for testing.
Update the positions according to the cycle time (If you understand how do that) or setup a interrupt timer.
Make your code modular/easy to read.


Sudo code.

secondsIntrupt()
{
increaseSeconds()
tick = 0
}


increaseSeconds()
{
if(seconds ==61)
{
seconds =0;
}

moveSecondsServo()
if( ++seconds == 60)
{
increaseMinutes()
}
}

ect
Re: help needed timing a clock
May 05, 2015 08:18PM
I assume that "delay(blinkDelay); // 968 // wait for a second" does not in fact wait for one second; my guess is that it actually waits for 939ms. But then there's another similar line, which means that the blinkk() function may take either a few microseconds or nearly a minute, depending on the state of pin 4. All the stepper delays would add on to that and it would take a bit under 2 seconds to move the hand by 288 steps.

The statement "int step_delay = 60L * 1000L / number_of_steps / whatspeed" uses integer division, which is always a dangerous thing. I figure that it works out to 60000/288/40 = 5, whereas what you want is 5.208333. So your timing will be off by about 4.16% which will means you clock would gain about an hour a day.

But it looks like you lose 89-42 = 47ms per minute = 0.708%, which would offset some of that gain.

But your whole approach is fraught with error... you really don't know how long each code statement will take to execute, so there will always be some inaccuracy in your clock. As someone else said, you really need an interrupt timer to do this.

And really, you're asking this question in the wrong place... it really belongs in some kind of Arduino programming forum.
Re: help needed timing a clock
May 05, 2015 10:02PM
@frankvdh

thanks for looking into the code. Since this post i have improved the code a lot and now get a accuracy of +- 2 minutes per day. The main source of error was the motor ( it had a weird gear ratio ) . I got a new motor of the same size from a different manufacture. Yes i know delay is also a source of error .( ia ma noob in terms of code ) yes i posted it on arduino forum and got people to help me out.. and everybody is a noob at some point and being rude doesnt help.... i will get it to be more accurate using interrupt once i understand to use them in this situation..

thanks anyways
Re: help needed timing a clock
May 06, 2015 05:01PM
Yah interrupts are a little more advanced but ardunio makes stuff super easy to code. Don't need a degree in computer engineering to code a mirco-controller.

Shoot me a PM if you need help setting up a interrupt.
Re: help needed timing a clock
October 03, 2015 03:12AM
There are two parts that can dift, the mechanical part and the clock. I'd use an external 32768 hz clock crystal, these tend to drift less than a 8mhz crystal, usually a couple of minutes per year instead of days. Some mcu's have a second crystal option. Or you could use a clock/calandar chip that uses i2c to control it. It usually includes interrupt services and triggers that can be set and a 50 hz line. You could program the avr to sleep, wake up on the 50 hz pulses, count the 50 pulses and move the clock pointers every second. I'd also include an optical detector at 12 o'clock to find out it's still in the correct position. You can make it self calibrating by pulsing the stepper until it hits 12 o'clock just before it's 12 o'clock, start moving one second after 12.00. It will realign itself every 12 hours.
Sorry, only registered users may post in this forum.

Click here to login