Python serial entre Arduino y Raspberry Pi: los datos se modifican al recibir

4

Estoy usando un Arduino para las lecturas del sensor y las envío a una Raspberry Pi a través de USB, usando PySerial para la recepción de datos.

Funciona muy bien, excepto por el hecho de que los datos recibidos se modifican de manera incómoda (y se establecen como constantes). Por ejemplo, estoy leyendo voltajes y calculando corrientes. Los resultados en la serie Arduino son los siguientes:

Volt   Current
4.93   0.38
4.92   0.37
4.92   0.37
4.92   0.36
...    ...

Sin embargo, en la Raspberry Pi, se lee constantemente de la siguiente manera (observe cómo los dígitos se cambian a cero):

  Volt   Current
    4.99   0.30
    4.99   0.30
    4.99   0.30
    4.99   0.30
    ...    ...

He intentado varias vueltas, pero sin suerte. No estoy seguro de dónde está el problema, ya que estoy muy seguro de que mi código es perfecto. Incluso convertí las lecturas en cadenas antes de enviarlas y, sin embargo, siguen apareciendo lecturas constantes y dígitos en cero. Agregué un entero de contador que se envió correctamente sin problemas.

¿Alguien ha intentado esto antes? ¿Alguna idea sobre cómo resolver esto?

Código Pi de frambuesa:

from time import gmtime, strftime
import time
import serial
import struct
ser = serial.Serial('/dev/ttyACM1', 19200)
f = open('results.txt','w')

while 1:
        temp=strftime("%Y-%m-%d %H:%M:%S", gmtime())+'\t'+ser.readline()
        print(temp)
        f.write(temp)
        f.close()
        f = open('results.txt','a')
        time.sleep(5)

Código Arduino:

...

  double volt = 5.0*(analogRead(A0))/1023.0;

  double current = 5.18 - temp;   //Resistance ~= 1 Ohm if you are wondering

  buffer += d2s(volt,2)+'\t'+d2s(current,2)+'\t'+ d2s(count,0) +'\t' + d2s(minCount,0);

  Serial.println(buffer);

...

//I got this from the web

String d2s(double input,int decimalPlaces){

  String string;

  if(decimalPlaces!=0){
    string = String((int)(input*pow(10,decimalPlaces)));

       if(abs(input)<1){
          if(input>0)
              string = "0"+string;
          else if(input<0)
              string = string.substring(0,1)+"0"+string.substring(1);
  }

  return string.substring(0,string.length()-
decimalPlaces)+"."+string.substring(string.length()-decimalPlaces);
}

   else {
     return String((int)input);

}
}
    
pregunta Ahmed Farid

5 respuestas

1

El arduino no está bien adaptado para hacer matemáticas de coma flotante, ni está especialmente adaptado para hacer manipulación de cadenas.

Sería mejor si enviaras el valor leído desde la entrada analógica directamente al código de Python en la Pi y realices la manipulación de las cadenas y las matemáticas en Python.

En el lado arduino, haz algo como esto:

int value;

value = analogRead(A0); // reads a 12bit integer value from the Analog input
Serial.println(value);  // converts the integer to a string and sends it over the serial port

Luego en el lado Pi:

str = ser.readline()  # read a string from the serial port

value = float(str)    # convert a string to a floating point number

volt = 5.0 * value / 1023.0  # compute the voltage
    
respondido por el jwygralak67
1

Si sospechas de la biblioteca de PySerial, debo decir que me sorprendería mucho si el problema está allí.

He usado PySerial bastante extensivamente, tanto para datos binarios como ascii sin problemas (aunque no en una Raspberry Pi).

Una cosa en la que puedo pensar es que es posible que el puerto se abra en un modo extraño. Intente especificar manualmente el modo de paridad y bits de parada:

ser = serial.Serial('/dev/ttyACM1', baudrate=119200, bytesize=8, parity='N', stopbits=1)

La otra cosa en la que puedo pensar es que de alguna manera estás enviando un código de control ASCII, que PySerial está interpretando correctamente, y el terminal Arduino no lo está. Si es posible, intente un terminal serial adicional y vea si está de acuerdo con uno u otro.

Honestamente, esto realmente me huele como un problema de RAM. Estás usando muchas funciones de C ++ (std :: string), que están muy hambrientas de RAM. Realmente deberías pensar en el arduino como un dispositivo C, y evitar las abstracciones de C ++, si es posible.

Además, ¿por qué diablos estás usando double s? Las precisiones ADC son de 12 bits! Un float simple tiene 32 bits en el arduino.

También confía en que su código sea "impecable", lo que me parece una falta de experiencia (el único código perfecto es el código que no existe). Junto con ese truco (muy descuidado) de una función de conversión de doble a cadena (¡que encontraste en Internet!), Me hace sospechar más el código arduino.

Por favor, publique su entero fuente de arduino, no solo un fragmento, también.

Otra cosa que debes probar es simplemente almacenar e imprimir algunos de tus resultados como cadenas puras:

Serial.println("4.93   0.38")
Serial.println("4.92   0.37")
Serial.println("4.92   0.37")
Serial.println("4.92   0.36")

Si eso falla, es probable que sea un problema en PySerial. Si no es así, es el código arduino.

    
respondido por el Connor Wolf
0

Encontré una forma de enviar la información correctamente usando Serial.write() , pero aparentemente funciona byte por byte. Por lo tanto, tendré que escribir un código más para traducir todos y cada uno de los bytes.

Estoy seguro de que hay una manera mejor y más fácil.

    
respondido por el Ahmed Farid
0

En realidad, pyserial lee datos de Arduino como bytes, por ejemplo, b234\r\n Por lo tanto, debe eliminar esos valores innecesarios antes de poder usarlos:

 valuebtw0to1023= serialObj.readline().strip('\r\n').strip()
    
respondido por el jona frank
0

si planea leer datos en serie desde una antena APC220 RF con python, deberá agregar la línea:

ser = serial.Serial('/dev/ttyACM1', 19200)
ser.setRTS(0) #  <------------------- this line solve the problem

Lo encontré después de un día entero de error de prueba.

    
respondido por el Marcelo

Lea otras preguntas en las etiquetas