Datos perdidos al escribir en el puerto serial de Arduino. ¿Desbordamiento?

Tengo un Arduino conectado a una caja de linux (una Raspberry Pi). Estoy leyendo un pin analógico y lo escribo junto Serial.println()con el valor de millis()El puerto serie funciona a 9600 bps

Algo en las líneas de:

void Setup() {
Serial.begin(9600)
}
void loop() {
    Serial.print(analogRead(A0));
    Serial.print("\t");
    Serial.println(millis());
}

En el extremo receptor veo un flujo continuo de 5 o 6 segundos, luego un intervalo de 2 segundos sin datos, luego otros 5 o 6 segundos llenos de datos. No lo "visto" en vivo, pero estoy trazando el valor de millis () con una lectura de datos del puerto serie.

Creo que podría ser que los datos se pierdan en el búfer de escritura del arduino, o que otra cosa tome tiempo del procesador cada 5 o 6 segundos (hay un protector de ethernet sin usar adjunto) o tal vez el puerto serie escribe en ráfagas.

Cuando aumento la tasa de baudios a 115200, todavía obtengo intervalos de tiempo, pero parecen más aleatorios.

Actualizar:

El aumento de la tasa de baudios a 38400 eliminó las brechas en las muestras (brechas medidas en tiempo de arduino millis())

Otra cosa extraña fue:

En el extremo receptor, estaba haciendo cat /dev/ttyACM0y canalizándolo, a awklo que agregaba el reloj del sistema a cada línea recibida. Luego tracé el tiempo recibido frente al tiempo del sistema, y ​​no era una línea recta, sino una trama en forma de escalera. Se eliminó lo innecesario caty el tiempo volvió a la normalidad.

Resulta que cat /dev/ttyACM0 | awk {print}no es lo mismo que </dev/ttyACM0 awk {print}. Parece que el gato hace un almacenamiento en búfer extraño.

Ahora parece que el arduino lee todos los valores.

No estoy del todo seguro de lo que quieres decir con verlo en vivo y la trama. ¿El intervalo entre todas las líneas es más o menos el mismo o también hay espacios? ¿Qué herramienta / línea de comando del lado de Linux usa para leer los datos? ¿Puede dar un ejemplo de los datos impresos?
Primero, desconecte el escudo de ethernet. En segundo lugar, es posible que esté desbordando el búfer en serie. Ponga un sueño de 10 ms al final de su bucle. Luego cambie el valor del sueño, hacia arriba o hacia abajo, dependiendo de sus resultados.
Cambié la tasa de baudios a 38400 y los intervalos de tiempo parecen haber desaparecido.

Respuestas (2)

analogRead() devolverá valores de 2 a 3 dígitos, digamos 3. millis() crecerá rápidamente a valores de 4 y 5 caracteres, y con el tabulador y la nueva línea, se generan aproximadamente 10 caracteres en cada ejecución del ciclo.

A 9600 baudios, su puerto serie puede escribir un poco menos de 1000 caracteres/seg o un poco menos de 100 líneas de 10 caracteres/seg. Su bucle podría ejecutarse fácilmente más rápido que 100 veces/seg y, de ser así, el búfer de salida en serie sin duda se está desbordando. Debe retrasar 10 ms o más en el bucle para que el puerto serie se ponga al día. 115 K baudios es 12 veces más rápido, por lo que podría reducir el retraso (una vez que sepa cuánto necesita) por ese factor para la velocidad en baudios más alta.

9600 bps = 960 char/seg (no 96 como sugieres)
Mi error (pero, ¿qué es un cero entre amigos? <blush>) Gracias por la captura, editado para corregirlo.
Creo que las rutinas en serie deberían bloquearse, en lugar de desbordar el búfer, pero dada la basura de gran parte del resto de los componentes internos del código arduino, no me sorprendería.

Dos posibilidades como yo lo veo:

  1. Su programa es en realidad mucho más grande de lo que nos está mostrando y, de hecho, está experimentando algún tipo de desbordamiento de pila que resulta en reinicios aleatorios.

  2. Es mucho más probable que su "problema" esté en Rasp Pi y que el tráfico en serie entrante se almacene en búfer antes de enviarse a su (en la parte superior de la pila de aplicaciones), presumiblemente Python, aplicación

Si quiere asegurarse de que los bytes salgan del Arduino lo antes posible, llame a Serial.flush() al final de cada bucle (o después de cada Serial.print*)

El programa es un poco más largo que eso, pero no mucho, y no se reinicia ya que eso haría que millis() volviera a 0.