Estoy usando un Arduino Uno para enviar información de tiempo y voltaje a través del puerto serie a Python para trazar. Sin embargo, los intervalos de tiempo entre marcas de tiempo sucesivas parecen estar aumentando con el tiempo, lo que afecta mi trazado. Esto es especialmente cierto cuando la velocidad en baudios se establece en 9600, donde mis diferencias de tiempo iniciales pueden ser 1320 y aumenta a 16400 después de un período de tiempo relativamente corto. Cuando esta tasa se pone al máximo de 115200 bps, el cambio es más lento y menos notable, de alrededor de 1340 a 1500, incluso después de un envío relativamente largo. Todos los tiempos se dan en microsegundos.
Me gustaría saber si puedo reducir o eliminar este efecto, y si no entiendo por qué existe. He leído cosas sobre las interrupciones y los retrasos que causan esto, pero no aprecio completamente la complejidad de la electrónica en cuestión y me gustaría saber:
- ¿Puedo obtener mayor precisión en el tiempo?
- ¿Qué causa este cambio en el tiempo?
Esto es lo que tengo actualmente:
#include <eHealth.h>
extern volatile unsigned long timer0_overflow_count;
float fanalog0;
int analog0;
unsigned long time;
byte serialByte;
void setup() {
Serial.begin(9600);
}
void loop() {
while (Serial.available()>0){
serialByte=Serial.read();
if (serialByte=='S'){
while(1){
fanalog0=eHealth.getECG();
// Use the timer0 => 1 tick every 4 us
time=(timer0_overflow_count << 8) + TCNT0;
// Microseconds conversion.
time=(time*4);
//Print in a file for simulation
//Serial.print(time);
//Serial.print(" ");
Serial.print(fanalog0,5);
Serial.print("\n");
if (Serial.available()>0){
serialByte=Serial.read();
if (serialByte=='F') break;
}
}
}
}
}
fuente
eHealth.getECG()
hacer? ¿Esa llamada siempre dura la misma cantidad de tiempo?Respuestas:
Use un temporizador e ISR (rutina de servicio de interrupción) para hacer que la sincronización sea más precisa.
Eche un vistazo a mi prueba de concepto de interrupción temporizada de 1 ms . La idea es tener un 'latido' de 1 ms razonablemente preciso en el sistema que pueda usarse para desencadenar otros eventos. En el PoC se usa para parpadear un LED a ½ Hz, pero al tener acceso a las nuevas variables
millisecondCounter
y lesecondCounter
permite activar eventos en el bucle principal en momentos arbitrarios (pero sincronizados con precisión).fuente
loop()
), un ISR modifica este valor. Puede suceder queloop()
lea un valor incorrecto (en medio de una modificación por el ISR). He publicado un comentario en tu blog al respecto.loop()
: mi muestra acaba de obtener el valor de milisegundos, lo compara con el valor de lectura anterior y si la diferencia> 0 (que no sea restablecer el contador a 0), muestra un mensaje.Se me ocurren algunas cosas que pueden afectar la "consistencia" de los tiempos de escritura en serie:
Esto puede ser lo más obvio en lo que pensar, pero de hecho cuanto más imprima, más se necesitará para manejarlo.
Solución: imprima el formato de la cadena en una cadena de longitud conocida.
en Unix puede acceder al puerto serie utilizando una forma con o sin búfer. Usar el modo almacenado durante mucho tiempo puede hacerlo un poco más lento a medida que se llena el búfer, por lo general sucede cuando los datos ingresan más rápido de lo que lo está leyendo ...
Solución: utilice la línea serie sin búfer ( por ejemplo : en Darwin / OSX es en
/dev/cu.usbmodemXXX
lugar de/dev/tty.usbmodemXXX
)parece que está usando una interrupción TC, y los AVR tienen prioridades en la forma en que se manejan las interrupciones, no sé el orden de prioridad para el Atmega328, y no es una de las características más documentadas, así que no sé qué tan seguro es TC0 frente a la interrupción UART.
Solución: busque más en la documentación / hoja de datos sobre las prioridades de interrupción y cambie el temporizador si es necesario; y / o hacer una prueba sin tener el otro temporizador funcionando.
algunos controladores necesitan promediar o realizar algunas operaciones sobre los valores anteriores, por lo que cuantos más valores mida, más tiempo será el búfer y más tardará en calcular el valor, hasta que haya alcanzado el tamaño máximo del búfer.
Solución: mire el código fuente de la biblioteca que está utilizando y, bien, optimícelo, elimine el cálculo si hay uno o tenga en cuenta ese aumento del tiempo de procesamiento.
pero si realmente desea optimizar la salida en serie del arduino, debe evitar usar el arduino de arriba ... Pero es mucho menos elegante y cómodo de usar.
Estoy bastante seguro de que faltan otros puntos, pero eso es lo primero que verificaría antes de seguir investigando.
HTH
fuente
Su código incluye la duración de la salida en mediciones posteriores. Por lo tanto, dependiendo de la longitud de la salida, medirá diferentes tiempos. Esto se puede solucionar formateando a salida de longitud fija.
El siguiente problema es que la ONU tiene una base de tiempo muy pobre. Eche un vistazo aquí para ver una comparación de los diferentes tipos de Arduino y la referencia de tiempo DCF77
Conclusión: si necesita una sincronización precisa, obtenga un Arduino con cristal o elija un RTC. Puedo recomendar altamente los RTC DS3231 / DS3232 ya que estos generalmente alcanzan una precisión de 2 ppm de fábrica.
fuente