web-dev-qa-db-fra.com

La réception en série d’Arduino à Raspberry Pi avec PySerial s’arrête après un certain temps

Je travaille sur un projet dans lequel je dois recevoir 25 données de caractères à la fois pour pouvoir les traiter dans Raspberry Pi. Voici l'exemple de code qui génère certaines données que je souhaite recevoir d'Arduino:

char i =0;
char  a =0;
char b=0;


void setup(){

 Serial.begin(9600);
 for(i=0;i<25;i++){

    Serial.print('l');}
    Serial.print('\n');
    delay(2000);
}


void loop(){

 for(i=0;i<25;i++){
     for(a=0;a<i;a++){
      if((a==9)||(a==19)||(a==24))
          Serial.print('l');
      else
          Serial.print('d');   
     }
     for(b=0;b<25-i;b++){
          Serial.print('l');
     }


     delay(2000);
  }
}

Il envoie une ligne comme celle-ci 'llllddddllldddd ...' Cette ligne a une longueur de 25 caractères. Maintenant, je veux recevoir ceci avec Raspberry Pi. Voici le code que j'essaye de travailler:

ser = serial.Serial('/dev/AMA0',9600,timeout=1)
ser.open()

try:
   serial_data = ser.readline()
   print serial_data
except serial.serialutil.SerialException:
   pass

Ce code reçoit les données très correctement pendant environ 5 secondes, puis cesse soudainement de recevoir.

De plus, lorsque j'essaye ce qui suit, je n'obtiens aucune sortie ni d'erreur d'entrée/sortie 

serial_data = ser.readline()
print serial_data

EDIT1: D'accord, j'ai commenté l'exception à présent. Cela donne l'erreur suivante:

 raise SerialException('device reporst rediness to read but returned no data (device disconnected?)')
serial.serialutil.SerialException: device reports readiness to read but returned no data (device disconnected?)

Quelle est la bonne façon de recevoir des données de 25 caractères d’arduino à framboise via PySerial? Toute aide sera grandement appréciée.

9
mozcelikors

J'ai eu le même problème et me cassais la tête pendant un bon moment, essayez ceci

Courir

ps -ef | grep tty

Si la sortie ressemble à quelque chose

root      2522     1  0 06:08 ?        00:00:00 /sbin/getty -L ttyAMA0 115200 vt100

Ensuite, vous devez empêcher getty d'essayer d'envoyer des données à ce port.

Pour utiliser le port série de Raspberry Pi, nous devons désactiver getty (le programme qui affiche l’écran de connexion) en recherchant cette ligne dans le fichier/etc/inittab.

T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

Et commentez en ajoutant # devant

#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100)

Pour empêcher le Raspberry Pi d’envoyer des données aux ports série lors de son démarrage, accédez au fichier /boot/cmdline.txt, recherchez la ligne et supprimez-la.

console=ttyAMA0,115200 kgdboc=ttyAMA0,115200

Redémarrez le Raspberry Pi

Crédit lorsque le crédit est dû: http://blog.oscarliang.net/raspberry-pi-and-arduino-connected-serial-gpio/ m'a aidé à comprendre comment diable getty

12
user2387729

J'ai eu du mal à lire cela lors de la lecture de données gps dans Raspberry Pi. La sortie s'arrêterait au bout de 10 secondes environ et ferait rapport 

 device reports readiness to read but returned no data (device disconnected?)

Les solutions données dans presque tous les forums concernent Raspberry Pi 2 avec Wheezy. J'ai finalement réussi à obtenir un streaming continu dans mon Raspberry Pi3 avec Jessie en procédant comme suit:

  1. définissez enable_uart=1 et ajoutez dtoverlay=pi3-disable-bt dans /boot/config.txt. puis redémarrez
  2. Je devais changer mon/boot/cmdline.txt en 

    dwc_otg.lpm_enable=0 console=tty1 console=serial0,9600 root=/dev/mmcblk0p7 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait

    puis redémarrez

  3. arrêtez getty: Sudo systemctl stop [email protected]

    désactiver: Sudo systemctl stop [email protected]

Vous devez faire attention avec /boot/cmdline.txt. Toute erreur dans le fichier peut empêcher votre Raspberry Pi de démarrer. Il est préférable de garder une sauvegarde du fichier avant de le modifier. Définissez également correctement le débit en bauds. Dans mon cas, c'était 9600. J'espère que ça aide!

2
Chandan Purohit

J'avais l'habitude de recevoir cela souvent, puis un ami m'a dit de demander à l'arduino des données à partir de python.

Description ci-dessous


pensez à ce que l'arduino n'envoie des données que lorsque votre programme python vous le demande:

Prompt.py

#!/usr/bin/python
import serial, time
ser = serial.Serial('/dev/ttyACM0',  115200, timeout = 0.1)

#if you only want to send data to arduino (i.e. a signal to move a servo)
def send( theinput ):
  ser.write( theinput )
  while True:
    try:
      time.sleep(0.01)
      break
    except:
      pass
  time.sleep(0.1)

#if you would like to tell the arduino that you would like to receive data from the arduino
def send_and_receive( theinput ):
  ser.write( theinput )
  while True:
    try:
      time.sleep(0.01)
      state = ser.readline()
      print state
      return state
    except:
      pass
  time.sleep(0.1)

f = open('dataFile.txt','a')

while 1 :
    arduino_sensor = send_and_receive('1')
    f.write(arduino_sensor)
    f.close()
    f = open('dataFile.txt','a')

Prompt.ino

void setup () {   pinMode(13, OUTPUT);   Serial.begin(115200); } 
    void loop() {

  if (Serial.available())    {

     ch = Serial.read();

     if ( ch == '1' ) { 
       Serial.println(analogRead(A0)); // if '1' is received, then send back analog read A0
     } 
     else if (ch == '2') {    
       digitalWrite(13,HIGH); // if '2' is received, turn on the led attached to 13
     } 
     else if (ch == '3') {
       digitalWrite(13,LOW); // if '3' is received then turn off the led attached 13
     } else {
       delay(10);
     }
   }    
}

De plus, j'ai créé un dépôt github qui contient quelques exemples supplémentaires pour la communication python-arduino: 

https://github.com/gskielian/Arduino-DataLogging/blob/master/PySerial/README.md

1
gskielian

Au cours de votre fonction loop dans votre code Arduino, vous ne mettez jamais fin à un caractère newline \n; il ne s'agit que d'un problème avec ser.readline() car il lit jusqu'au caractère \n.

Pendant votre fonction setup, vous envoyez correctement un caractère \n qui pourrait expliquer la valeur initiale envoyée, mais pas les données.

peut-être en modifiant votre code Arduino comme ceci:

void loop(){
    for(i=0;i<25;i++){
        for(a=0;a<i;a++){
            if((a==9)||(a==19)||(a==24)) {
              Serial.print('l');
            } else {
                Serial.print('d');   
            }
        } /*end for loop a*/
        for(b=0;b<25-i;b++){
            Serial.print('l');
        } /*end for loop b*/

        Serial.print('\n'); // CODE EDITED HERE
        delay(2000);
    }    
}

Et votre code python comme si ...

ser = None
try:
    ser = serial.Serial('/dev/AMA0',9600,timeout=3)
    ser.open()

    while True:
        try:
            serial_data = ser.readline()
            print serial_data
        except:
            pass
except:
    pass    
finally:
    if ser:
        ser.close()
0
Farmer Joe