Acelerómetro de muestreo Arduino

Tengo un acelerómetro analógico que quiero muestrear a 100 HZ, también quiero trazar los datos con el tiempo de cada muestra para tener aceleración con el tiempo. Para llevar la cuenta del tiempo, iba a usar millis(). Para muestrear a 100 HZ puedo usar un temporizador, pero AnalogRead() tiene una sobrecarga y me preguntaba cómo muestrear a 100 HZ corrigiendo la sobrecarga de AnalogRead().

También el envío de datos en serie tiene una sobrecarga, no estoy seguro de cómo compensar esto, quiero obtener una aceleración en el tiempo que sea al menos algo precisa si es posible. No tengo el dinero en este momento para un chip RTC

Tenga en cuenta que la demora es determinista : el temporizador ocurre cada 10 milisegundos y sus datos aparecen en el puerto serie un tiempo después, pero el tiempo transcurrido es el mismo cada vez. Tenga en cuenta que también se necesitan menos de 10 ms para enviar cada lectura en serie, lo que puede ser el principal factor limitante.

Respuestas (3)

Puede enviar transmitir aproximadamente 11 bytes por milisegundo a 115200 baudios. Entonces, siempre que restrinja su salida a 10 caracteres y una nueva línea por muestra, debería estar bien.

La matemática detrás de eso es 115200 baudios significa 115200 tiempos de bit/segundo, y hay 10 tiempos de bit por byte transmitido en el UART (bit de inicio, 8 bits de datos y bit de parada). Entonces 115200/10 = 11520 bytes/segundo = 11.520 bytes/milisegundo (y redondeo hacia abajo).

En resumen, el muestreo de 100 Hz debería ser fácil.

El enfoque canónico de la temporización de intervalos se demuestra en el ejemplo de BlinkWithoutDelay Arduino. Consolidado se ve así:

long previousMillis = 0;
long interval = 10; // interval in milliseconds (10ms => 100Hz)

void setup() {
   // whatever
   Serial.begin(115200);
   Serial.println("Hello World");
}

void loop(){
   unsigned long currentMillis = millis();
   if(currentMillis - previousMillis > interval) {
      previousMillis = currentMillis;

      // do your task
      Serial.println(analogRead(0));
   }
}
¡Se ve muy bien, gracias! Quiero trazar la aceleración a lo largo del tiempo, pero ¿debería usar startTime o sumar todos los intervalos millis() en el ciclo como el tiempo total para que la aceleración se trace?
Cada vez que se llama a AnalogRead() a 100 HZ, mi tiempo total sería 1/100 HZ = 10 mS, por lo que estaría haciendo tiempo = tiempo + 10 mS, y trazaría la variable de tiempo con los datos. o lo sincronizaría con el tiempo = tiempo + (currentMillis - Previousmillis)
@ zacharoni16 correcto, simplemente implicaría el tiempo en su análisis externo como intervalos de 10 ms desde algún tiempo de inicio t0. No es necesario generar o almacenar una variable de tiempo.

from Arduino: millis() - Devuelve el número de milisegundos desde que la placa Arduino comenzó a ejecutar el programa actual. Este número se desbordará (volverá a cero), después de aproximadamente 50 días.

es una representación convertida del contador del programa, que continúa ejecutándose, independientemente. No debe confundirse con delay() y delayMicroseconds(), que son básicamente nop calculados por separado. Usarlos entre muestras tendría retrasos y sesgos crecientes.

entonces usando

if ((millis() - lastTime) > _Delay) {
  lastTime = millis();
  blah... 
}

no se desviaría. Del mismo modo, existe la biblioteca http://playground.arduino.cc/Code/SimpleTimer que hará lo mismo. pero en un formato de biblioteca y servicio más típico, que yo uso.

Donde ambos tendrán algo de fluctuación, no sesgada, de otras interrupciones y otras cosas que suceden. Dicho esto, usar la interrupción Timer1 para generar los 100 Hz debería reducir la fluctuación lo mejor posible. Como ejemplo http://www.pjrc.com/teensy/td_libs_TimerOne.html

La función millis() no sería una representación convertida del contador del programa. En cambio, es un contador que sigue contando a una velocidad de 1 ms mientras el programa sigue funcionando. El contador de programa en la mayoría de los programas como este está saltando por todas partes y luego eventualmente regresa para repetir su patrón de salto por todas partes. El contador de programa de la MCU no es un conteo lineal constante de larga duración, a menos que alguien haya creado un programa casi inútil compuesto por una memoria llena de NOP e incluso entonces la ejecución lineal solo duraría unos pocos milisegundos antes de que la secuencia NOP terminara y colapsara.
¡Gracias! ¿A qué hora estaría trazando? ¿Tomaría el contador de millis() en ejecución como el tiempo para trazar o debería sumar todos los tiempos de las muestras y ese es el tiempo exacto para enviar a trazar en el gráfico con valores de aceleración?
Podría estar convencido de que lo que se quería decir en esta respuesta era "contador de ciclos" en lugar de "contador de programas" si los AVR tuvieran tal cosa :-) pero el comentario de @MichaelKaras es pedagógicamente preciso
El millis() es acumulativo, por lo que es necesario sumarlos. Sólo hay que estar atento a un vuelco.

El tiempo de lectura analógica es del orden de decenas de microsegundos con la mayoría de las configuraciones de selección de reloj, nada de qué preocuparse. La serie es similar a lo que dijo vicatu: 11 bytes en un milisegundo. Tiene diez milisegundos para hacer todo su trabajo y los retrasos no deberían sumar más de un milisegundo, no debería ser un problema. Simplemente implemente la verificación de tiempo como lo mostró en su publicación y debería estar bien.