Stepper motor off sync

I'm using this stepper motor and trying to simply get it to rotate once every minute. It does fairly well, but after a while it gets a little too fast. After only a few rotations actually. This stepper has 64 steps and is geared down to 1/64 so it should have 4096 steps. And even when testing to make sure that it makes that number of steps every rotation, it is still off sync. I've also tested to make sure it is not the timer accuracy. I'm also certain that this isn't too fast for the motor, I've had it going much faster before.

long count = 0;
int lastStep = 0;
int curStep = 0;
void setup(){
    pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(10, OUTPUT);
 Serial.begin(9600);
 Serial.println("0");
}


void loop(){
  delay(1);
  curStep = (long) 7 - map(millis()%60000,0,59999,0,4095)%8;
  if(millis()%60000==0){Serial.println(millis()/60000); Serial.println(count); count=0;}//report minutes and step count, reset step count
  
  if(lastStep != curStep){lastStep=curStep; count++;}//count if step changes

   switch(curStep){
  case 0:

digitalWrite(10,HIGH);
digitalWrite(11,LOW);
digitalWrite(12,LOW);
digitalWrite(13,LOW);

      break; 

  case 1:

digitalWrite(10,HIGH);
digitalWrite(11,HIGH);
digitalWrite(12,LOW);
digitalWrite(13,LOW);

      break; 

  case 2:

digitalWrite(10,LOW);
digitalWrite(11,HIGH);
digitalWrite(12,LOW);
digitalWrite(13,LOW);

      break; 

  case 3:

digitalWrite(10,LOW);
digitalWrite(11,HIGH);
digitalWrite(12,HIGH);
digitalWrite(13,LOW);

      break; 

  case 4:

digitalWrite(10,LOW);
digitalWrite(11,LOW);
digitalWrite(12,HIGH);
digitalWrite(13,LOW);

      break; 

  case 5:

digitalWrite(10,LOW);
digitalWrite(11,LOW);
digitalWrite(12,HIGH);
digitalWrite(13,HIGH);

      break; 

  case 6:

digitalWrite(10,LOW);
digitalWrite(11,LOW);
digitalWrite(12,LOW);
digitalWrite(13,HIGH);

      break; 

  case 7:

digitalWrite(10,HIGH);
digitalWrite(11,LOW);
digitalWrite(12,LOW);
digitalWrite(13,HIGH);

      break; 



  }
}

This is my code. Am I doing anything obviously wrong or is there anything I can troubleshoot? Thanks.

Yes the whole code looks wacky. There is no need to contillully write to the motors, only write when something changes.
Work with relitave time from the millis() not absoloute time.
Use the blink without delay method to do this.

The other thing is that there're not an interger number of milliseconds in the step interval you need so you will have to be a bit more clever than this.

It's an unusual approach to solving the problem, but it should be workable until millis() wraps round after 50 days. Try changing it to:

curStep = (long) 7 - map(millis()%60000,0,60000,0,4096)%8;

Otherwise you are quite likely to miss the curstep == 7 step when millis()%60000 wraps round to zero.

The beginning of your loop before switch could just be:
curStep++; delay(2);

Check out my code it's easy to try:
http://arduino.cc/forum/index.php/topic,89159.0.html

trying to simply get it to rotate once every minute. It does fairly well, but after a while it gets a little too fast. After only a few rotations actually. This stepper has 64 steps and is geared down to 1/64 so it should have 4096 steps.

So you want to have 4096 steps in 60 seconds.
That is 68.26666. steps per second.
That is a step every 14.6484375143 milli seconds
So getting your step value directly from the millis() timer is not going to work.
You need to work out a fractional division, that is one where you divide by one value for n1 times and divide by another value for n2 times. In that way you average the stepping rate you want but it jitters a bit.

I keep coming up with 14.6484375143 milliseconds, not microseconds. Wouldnt it require more than 1000 steps/second before it got into the micros?

Yes sorry, I have corrected this.

Couldn't I achieve that by rounding instead of using using int?

I'll have to try this stuff tomorrow

Any sort of rounding introduces an error, it is this error you want to eliminate to keep your motor in step.
Another way to go about it is to have an error accumulator variable and have a leap step when it overflows into a complete step out.

Use delayMicroseconds() or micros() instead of millis() than the error is 100ppm.
1 line of code.

I have done something similar in my code with a leap step when you want to turn 1.81 degrees repetitively.
Assuming 1.80 is your step size for example.
Only a few lines of code.

http://arduino.cc/forum/index.php/topic,89159.0.html

Grumpy_Mike:
Any sort of rounding introduces an error, it is this error you want to eliminate to keep your motor in step.
Another way to go about it is to have an error accumulator variable and have a leap step when it overflows into a complete step out.

But I'm working absolutely. So that little error shouldn't need to be accounted for, it's irrelevant because the previous number isn't used. I've even tested this, I had it counting 0-7, and tell me whenever a number gets skipped and none ever did.

Is your speed critical? The time between steps? That's the error he's referring to when you use millis().

I didn't read through the whole sketch but that part with the map function immediately set alarm bells ringing.

If you want something to happen at a fixed interval of the order of a few milliseconds, I would just use the timing technique demonstrated in the 'blink without delay' sample sketch but based on micros rather than millis, to detect when the interval has elapsed.

There are two issues which I think would be significant.

Your timer comparison needs to deal with timer overflow. This is easily done if you code it like this:

if((micros() - lastMicros) > intervalMicros)
{
...

If you want to keep the average frequency accurate (to the extent possible with an uncalibrated clock) then you also need to update the timer based on when your timer became due rather than when you detected it. In other words:

if((micros() - lastMicros) > intervalMicros)
{
    lastMicros += intervalMicros;
...