He estado usando el Arduino para registrar algunos datos. En mi boceto Arduino también utilicé la millis()
función para poder hacer un seguimiento del tiempo en el que se toma cada valor que estoy midiendo. Sin embargo, noté que el momento no es correcto. Por ejemplo, 30 segundos en la vida real solo salen como 10 segundos (ejemplo inventado).
¿Estoy en lo cierto al decir que la función de retraso de Arduino afecta el tiempo que se usa millis()
? En otras palabras, supongamos que tengo un retraso de 50 ms, ¿eso significa que la millis()
función también se detiene durante esa duración y luego continúa y así sucesivamente durante la conexión? Noté esto cuando intenté trazar algunos datos y encontrar que la frecuencia de los picos en mis datos era demasiado frecuente dado el tiempo que había pasado. Entonces, quiero saber si ese es el motivo de esta falta de coincidencia de tiempo y, de ser así, ¿cómo puedo solucionar esto para poder mantener el tiempo en que ocurre cada muestra?
Para dar un poco de contexto aquí está mi boceto:
#include <eHealth.h>
unsigned long time;
// The setup routine runs once when you press reset:
void setup() {
Serial.begin(9600);
}
// The loop routine runs over and over again forever:
void loop() {
float ECG = eHealth.getECG();
time = millis();
Serial.print(time);
Serial.print(" ");
Serial.print(ECG, 5);
Serial.println("");
delay(50);
}
fuente
millis()
es impulsado por interrupción, por lodelay()
que no debería afectarlo.Respuestas:
millis()
es impulsado por interrupción, por lodelay()
que no lo afectará, al menos no en una placa basada en ATmega.Eso no quiere decir que
millis()
sea totalmente exacto tampoco. Cada tic del temporizador no es exactamente 1 ms, pero es 1.024 ms. Este error se acumula gradualmente hasta que se realiza una corrección. Esto se puede ver en la implementación del controlador de interrupción TIMER0_OVF (desbordamiento del temporizador 0).Otra fuente de inexactitud es el oscilador / cristal en sí, que no es exactamente 16MHz. Sin embargo, está bastante cerca, y siempre que la temperatura no cambie demasiado, es relativamente estable.
Lo anterior significa que puede estar alrededor de 1 ms cuando lo usa
millis()
. Esto no suena como tu problema.Otro problema potencial sería lo que
getECG()
está haciendo: puede ser muy lento.analogRead()
es lento, pero no tan lento como para impactar un ciclo como este.Otro problema que he visto que la gente tiene es cuando cambian la velocidad del reloj, pero no cambian correctamente boards.txt. Esto significa que las constantes utilizadas en la
millis()
implementación son incorrectas y los tiempos son incorrectos.Si realmente desea leer valores cada 50 ms, una forma mucho mejor de implementar esto es hacer lo siguiente
Realmente necesitaríamos ver las marcas de tiempo que está recibiendo. Si en realidad ve 30 años que se muestran como 10, entonces hay algo más en el trabajo.
fuente
Si las interrupciones se desactivan por una fracción considerable de la
eHealth.getECG()
duración de la llamada,millis()
el recuento podría retrasarse. De lo contrario,millis()
debería devolver un tiempo mucho más preciso que los errores 3x que describió.Dijiste que tu señal muestreada parece tener una frecuencia más alta de lo que esperabas, lo que podría suceder si tu frecuencia de muestreo es más baja de lo que esperabas. ¿Está asumiendo una frecuencia de muestreo de 20Hz? Su ciclo podría demorar un poco más de 50 ms, lo que vería en los tiempos impresos, pero aún así deberían seguir la hora del reloj. Si no tuvo en cuenta eso, pero asumió 50 ms / muestra, vería una aparente aceleración de los datos.
Si este no es el problema, el siguiente paso sería alternar una salida mientras está dentro
loop()
y medir la frecuencia de la onda cuadrada resultante con un medidor de frecuencia (algunos DVM económicos pueden hacer esto) o un 'alcance'. Haz lo mismo con un vacíoloop()
. El primer experimento será su frecuencia o intervalo de muestreo real; el segundo le dirá simillis()
(es decir, la frecuencia del temporizador 0) es lo que esperaba.fuente
Igual que aquí. Puedo agregar que si las interrupciones están desactivadas, el tiempo medido es "en tiempo real". De todos modos, no entiendo por qué este retraso, porque si el bucle tarda demasiado, de todos modos, el millis () debería devolver valores en tiempo real (solo con más distancia entre cada valor)
fuente