Estoy usando un Arduino para lecturas de sensores 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 configuran 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 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 radica el problema, ya que estoy muy seguro de que mi código es perfecto. Incluso convertí las lecturas a una cadena antes de enviarlas y, sin embargo, siguen apareciendo las lecturas constantes y los dígitos puestos a cero. Agregué un entero de contador que se envió correctamente sin problemas.
¿Alguien ha probado esto antes? ¿Alguna idea sobre cómo resolver esto?
Código de frambuesa Pi:
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);
}
}
El arduino no es adecuado para hacer matemáticas de punto flotante, ni es particularmente adecuado para manipular cadenas.
Sería mejor enviar el valor leído desde la entrada analógica directamente al código python en el Pi y hacer la manipulación matemática y de cadenas en Python.
En el lado de arduino solo 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
Encontré una manera de enviar la información correctamente usando Serial.write()
, pero aparentemente funciona byte por byte. Por lo tanto, tendré que escribir más código para traducir todos y cada uno de los bytes.
Sin embargo, estoy seguro de que hay una manera mejor y más fácil.
Si sospecha de la biblioteca PySerial, debo decir que me sorprendería mucho si el problema está ahí.
He usado PySerial bastante extensamente, tanto para datos binarios como ascii sin problemas (aunque no en una Raspberry Pi).
Una cosa que se me ocurre es que es posible que el puerto se abra de 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á enviando un código de control ASCII, que PySerial está interpretando correctamente, y la terminal Arduino no.
Si es posible, pruebe con un terminal serial adicional y vea si está de acuerdo con uno u otro.
Honestamente, esto realmente huele como un problema de RAM para mí. Está utilizando muchas funciones de C++ (std::string), que consumen mucha memoria 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? ¡La precisión del ADC es de 12 bits! Un simple viejo float
es de 32 bits en el arduino.
También está seguro de que su código es "impecable", lo que me huele a inexperiencia (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 doble a cadena (¡que encontraste en Internet!), Me hace sospechar más del código arduino.
Publique toda su fuente de arduino, no solo un fragmento también.
Otra cosa que puede intentar es simplemente almacenar e imprimir algunos de sus 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.
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()
si planea leer datos en serie de una antena RF APC220 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 prueba-error.
Alejandro
ahmed farid
chris stratton
Alejandro
ahmed farid
ahmed farid
chris stratton
Alejandro
ahmed farid
void setup() { ... Serial.begin(19200); ... }
connor lobo
ahmed farid
connor lobo
chris stratton