time error in controlling a clock

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

(code tags added by moderator)

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;
[color=red]int blinkDelay = 939; [/color]
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);
}

Is the ATTiny2313 using a crystal, resonator, or the internal oscillator?

crystal 8mhz

You are calling delay() - this cannot work, since the rest of the code also takes time,
a variable and unknown amount of time.

The way to schedule accurate regular events is this:

unsigned long time = 0L ;
#define SECOND 1000

void loop ()
{
  if (millis () - time >= SECOND)
  {
    time += SECOND ;
    do_stuff () ; // this is called accurately every second without drift
  }
}

but the delay is also used for stepping the motor. do i need to change that also?

No, the step_delay constant should probably be OK. Use the example from MarkT to decide WHEN to command a step. If the step takes a variable amount of time, due to interrupts or other things happening, then it doesn't affect the accuracy of the clock. The next second will still occur at the right time.

You may also have mechanical trouble. Is the clock hand balanced? It may run fast when the weight of the hand is pulling the motor forwards and skipping steps.

no, the clock is 3d printed and very light so there is no unbalanced force on the motor.
i will try the markT example…

thanks

also in the markT example wont the variable time keep getting larger and larger?. sorry for my noobness. !!

DSC_0213.jpg

Think of it as the difference between a wall clock and a stopwatch - comparing
a calculated time against millis() is like using the wall clock,
calling delay() is starting and stopping a stop watch, it has no global reference.