Problemas al contar pulsos en un tiempo fijo

Hola a todos. Soy nuevo en este foro. Este es mi primer Post.
Estoy intentando contar las vueltas que da un molinete (de hélice) en un tiempo determinado ( 30 segundos). El molinete funciona como un interruptor, con una onda cuadrada, un tiempo en HIGH y un tiempo en LOW por vuelta. En un primer momento probé con la función "pulseIn" para medir el tiempo que dura el pulso y sumarlo, pero no funciona bien. Ahora estoy probando con la función "millis()", pero no consigo que la temporización coincida en realidad con el tiempo prefijado (30 segundos). No se exactamente que hago mal. He programado otras veces aunque no mucho en Arduino. Os pongo mi código:

const int molinete = 5;
int vueltas = 0;
int estadomolinete;
int ultimoEstadomolinete = 0;
float rps;
float velocidad;
float temp = 30000.0;
long cuentatiempo = 0;
unsigned long tiempo;
long tiempo2 = 0;
long tiempo3 = 0;

void setup()
{
pinMode(molinete, INPUT);
Serial.begin(9600);

}

void loop()
{
if (cuentatiempo < temp)
{

// Lee el estado del molinete
estadomolinete = digitalRead(molinete);
tiempo = millis();
// Compara el estado del molinete con el estado previo
if (estadomolinete != ultimoEstadomolinete)
{
// Si el estado ha cambiado incrementa el contador

vueltas++;
while (estadomolinete == HIGH)
{
tiempo2 = millis();
estadomolinete = digitalRead(molinete);

}

tiempo3 = tiempo2 - tiempo;
cuentatiempo = cuentatiempo + tiempo3;

Serial.print("vuelta:");
Serial.println(vueltas);

Serial.println("Tiempo2: ");
Serial.print(tiempo2);
Serial.print("Tiempo: ");
Serial.println(tiempo);
Serial.print("Cuentatiempo: ");
Serial.println(cuentatiempo);

}

ultimoEstadomolinete = estadomolinete;
}
else
{
rps = ((vueltas)/(temp/1000.0));
if (rps < 0.36)
{
velocidad = ((0.4050 * rps) + 0.032);
Serial.print("vuelta:");
Serial.println(vueltas);

Serial.print("Velocidad:");
Serial.println (velocidad);
delay(1000000);
}
else
{

velocidad = ((0.4850 * rps) - 0.003);
Serial.print("vuelta:");
Serial.println(vueltas);
Serial.print("RPS:");
Serial.println(rps);
Serial.print("Velocidad:");
Serial.println (velocidad);
delay (1000000);

}
}

}

El programa cuenta las vueltas pero la temporización no coincide con los 30 segundos. Al final se obtienen revoluciones por segundo que introducidos en la formula que trae el molinete nos debe de dar la velocidad en m/s.

Espero que me podais ayudar. Gracias

Podria ser un poco ma rapido usar interrupciones?
http://arduino.cc/es/Reference/AttachInterrupt#.UwxJX_l5OHY

const int  molinete = 2;    // Usar pin 2 o 3, o en mega 18,19,20 o 21
int vueltas = 0;
int estadomolinete;        
int ultimoEstadomolinete = 0;  
float rps;
float velocidad;
float temp = 30000.0;
long cuentatiempo = 0;
unsigned long tiempo;
long tiempo2 = 0;
long tiempo3 = 0;


void setup()
{
  pinMode(molinete, INPUT);
  Serial.begin(9600);
  attachInterrupt(0, Cambio_estado, RISING);
  cuentatiempo=millis()+temp;
}
void Cambio_estado()
{
  vueltas++;
}

void loop() 
{
   if (millis()>cuentatiempo)
   {
      Serial.print("vuelta:");
      Serial.println(vueltas);   
      vueltas=0;
      cuentatiempo=millis()+temp;      
    }
}

Ok. Muchas gracias por la información. Lo voy a probar con interrupciones. No obstante, el codigo que he publicado, aunque largo y mal estructurado, ¿estaría correcto para lo que necesito?. Lo digo porque al hacer las pruebas contar si cuenta las vueltas pero cuando se supone que ya han pasado los 30 segundos, con un cronometro exterior me salen unos 24 0 25. No se exactamente porqué. Perdon por mi ignorancia.

Saludos y garcias.

Creo que no estas controlando cuanto tiempo transcurre en la ejecución del programa, sino mas bien cuanto transcurre desde el digitalread hasta que cambia de estado.

usando tu codigo te diria algo asi:

const int  molinete = 5;
int vueltas = 0;
int estadomolinete;        
int ultimoEstadomolinete = 0;  
float rps;
float velocidad;
float temp = 30000.0;
long cuentatiempo = 0;
unsigned long tiempo;
long tiempo2 = 0;
long tiempo3 = 0;


unsigned long tiempoControl=30000;
unsigned long tiempoFin;

void setup()
{
  pinMode(molinete, INPUT);
  Serial.begin(9600);
  tiempoFin=tiempoControl+millis();      
}


void loop() 
{
   if (tiempoFin > millis())
   {  
      estadomolinete = digitalRead(molinete);                // Lee el estado del molinete
      if (estadomolinete != ultimoEstadomolinete)            // Si el estado ha cambiado incrementa el contador  
       {
         vueltas++;
       }
       ultimoEstadomolinete = estadomolinete;
       Serial.print("vuelta: ");
       Serial.print(vueltas);
       Serial.print("  Tiempo transcurrido: ");
       Serial.print(tiempoControl-tiempoFin-millis());
       Serial.print("  Tiempo restante: ");
       Serial.println(tiempoFin-millis());
   }
   else
   {
        rps = ((vueltas)/(temp/1000.0));
      if (rps < 0.36)
      {
         velocidad = ((0.4050 * rps) + 0.032);
                        Serial.print("vuelta:");
         Serial.println(vueltas);
            
         Serial.print("Velocidad:");
         Serial.println (velocidad);
         delay(1000000);
         tiempoFin=tiempoControl+millis(); 
      }
      else
      {
         
         velocidad = ((0.4850 * rps) - 0.003);
                        Serial.print("vuelta:");
         Serial.println(vueltas);
                        Serial.print("RPS:");
                        Serial.println(rps);
         Serial.print("Velocidad:");
         Serial.println (velocidad);
         delay (1000000);   
         tiempoFin=tiempoControl+millis(); 
         
      }
   }
   
}

Efectivamente. Tienes razón. Asi funciona perfectamente. He comprobado también el programa usando interrupciones y funciona a la perfeción, y es mucho mas corto y sencillo. Poco a poco voy aprendiendo algo. Mi programa, para el cálculo de velocidad en m/s de un molinete basado en la información del fabricante en RPS, gracias a tu ayuda, y por si ha alguien le es util, finalmente quedaría así:

const int molinete = 2; //Uso pin 2 por ser Arduino UNO o 18,19, 20 0 21 en MEGA
int vueltas = 0;
float rps;
float velocidad;
long temp = 30000; //30 s en milisegundos
long cuentatiempo = 0;
unsigned long tiempo;

void setup()
{
pinMode(molinete, INPUT);
Serial.begin(9600);
attachInterrupt(0, Cambio_estado, RISING); // Interrupción, función, modo, perfecto para encoder rotacional
cuentatiempo=millis()+temp; // le sumo el tiempo prefijado
}

void Cambio_estado()
{
vueltas++; // voy sumando las vueltas
Serial.print("vuelta:");
Serial.println(vueltas); //Imprime las vueltas que va dando
}

void loop()
{
if (millis()>cuentatiempo) //compruebo si ha transcurrido el tiempo prefijado
{

rps = ((vueltas)/(temp/1000.0)); //Revoluciones x S
if (rps < 0.36)
{
velocidad = ((0.4050 * rps) + 0.032); //Formula obtenida del fabricante para menos de 36 revoluciones x S
Serial.print("RPS:");
Serial.println(rps);

Serial.print("Velocidad:");
Serial.println (velocidad); // Velocidad en m/s

}
else
{

velocidad = ((0.4850 * rps) - 0.003); //Formula obtenida del fabricante para mayor o igual a 36 revoluciones x S

Serial.print("RPS:");
Serial.println(rps);
Serial.print("Velocidad:");
Serial.println (velocidad); //Velocidad en m/s

}
vueltas=0; //Contador a 0
cuentatiempo=millis()+temp; //Reinicio cuentatiempo
}

}

Muchas Gracias. Saludos.