Help with code, Hdd Pov Clock

Hi to everyone!
I'm building my own HDD POV CLOCK. Finally I have all the hardware up and running and it's time to code. Before codeing the clock I've started with something simpler like a circle splitted in 4. I almost got it, but my problem is that I can't get the circle to stay "static" it keeps spinning very slowly!! I posted a video to show it better.. Do you think it's a software problem or a hardware problem?

About the hardware:

  • Hdd running at 7220 rpm -> This is very stable, sometimes it goes to 7214 or 7223 but no beyond that
  • Magnet sticked to hard drive plate
  • Hall effect sensor through a schmitt trigger (40106) to interrupt 0 of Arduino
  • ULN2003 to turn on the leds

The video showing the bug:

And my code:

int leds=8; //Led strip on pin 8, connect to 12v from ATX trough ULN2003

unsigned long tiempoAnterior = 0;
unsigned long tiempoLeds = 0;
unsigned long tiempoVuelta=0;
volatile  unsigned long vueltas=0;
int ledState=LOW;

void setup()
{
  attachInterrupt(0, rpm_fun, FALLING); //interrupt 0 -> pin 2
}

void loop()
{
  unsigned long tiempoActual= micros();
  if(vueltas>=20)
  {
    tiempoVuelta = (tiempoActual-tiempoAnterior) / vueltas; //Each turn takes aproximately 8310 uS
    tiempoAnterior = tiempoActual;  
    vueltas=0;   
  }

  if(tiempoActual-tiempoLeds>= (tiempoVuelta/4)-4)           //tiempoVuelta/4 -> Split each revolution time into 4
  {                                                          //This (-4) factor is a correction factor showed in the video, best value I've found
    tiempoLeds=tiempoActual;   //Last time Leds blinked      //If I put (-0) the circle spins faster,
    ledState = !ledState;                                   //And if I put (-5) of below, the circle starts spinng the other way
    digitalWrite(leds, ledState);
  }
}

void rpm_fun()
{
  vueltas++;
}

Thanks to everyone!

I think it would work if you synchronized the LED loop with the interrupt. By re-starting the LED timer with each interrupt you should be able to keep the blinking locked to the position of the platter. Something like this:

int leds=8; //Led strip on pin 8, connect to 12v from ATX trough ULN2003

unsigned long tiempoAnterior = 0;
volatile unsigned long tiempoLeds = 0;
unsigned long tiempoVuelta=0;
volatile  unsigned long vueltas=0;
int ledState=LOW;

void setup()
{
  attachInterrupt(0, rpm_fun, FALLING); //interrupt 0 -> pin 2
}

void loop()
{
  unsigned long tiempoActual = micros();
  if(vueltas>=20)
  {
    tiempoVuelta = (tiempoActual-tiempoAnterior) / vueltas; //Each turn takes aproximately 8310 uS
    tiempoAnterior = tiempoActual;  
    vueltas=0;   
  }

  if(tiempoActual-tiempoLeds >= (tiempoVuelta/4))           //tiempoVuelta/4 -> Split each revolution time into 4
  {                                                     
    tiempoLeds=tiempoActual;   //Last time Leds blinked
    ledState = !ledState;
    digitalWrite(leds, ledState);
  }
}

void rpm_fun()
{
  vueltas++;
  tiempoLeds = micros();
}

Hi John! Thanks for your answer, and sorry for answering so late, I didn't see the notification... I realized that the problem was exactly what you're pointing. I could solve it making the loop() run only once with each interruption, kinda worked, but is not perfect, i'm still working on that :smiley:
I'm going to try aproching the problem the way you pruposed, I think is more efficient!

this is what I've so far - YouTube

Thanks!