Python 使用 PySerial 从 Arduino 到 Raspberry Pi 的串行接收在一段时间后停止

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20107700/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 19:33:13  来源:igfitidea点击:

Serial Receiving from Arduino to Raspberry Pi with PySerial stops after a while

pythonserial-portarduinoraspberry-pipyserial

提问by mozcelikors

I'm working on a project in which I have to receive some 25 character data at a time in order to process it in Raspberry Pi. Here is the example code that generates some data I want to receive from Arduino:

我正在做一个项目,我必须一次接收大约 25 个字符的数据才能在 Raspberry Pi 中处理它。这是生成我想从 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);
  }
}

It sends a line like this 'llllddddllldddd...' This line is 25 characters length. Now, I want to receive this with Raspberry Pi. Here is the code I'm trying to work:

它发送这样的一行'lllldddddllldddd...' 该行长度为 25 个字符。现在,我想用 Raspberry Pi 接收这个。这是我正在尝试工作的代码:

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

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

This code receives data very correctly for like 5 seconds, and then suddenly stops receiving.

此代码非常正确地接收数据大约 5 秒钟,然后突然停止接收。

Moreover, when I try the following, I get no output, or Input/output errors.

此外,当我尝试以下操作时,没有输出或输入/输出错误。

serial_data = ser.readline()
print serial_data

EDIT1:Okay, I commented the exception now. It gives the following error:

EDIT1:好的,我现在评论了异常。它给出了以下错误:

 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?)

What is the correct way to receive a 25 character data from arduino into raspberry via PySerial? Any help will be greately appreciated.

通过 PySerial 从 arduino 接收 25 个字符的数据到 raspberry 的正确方法是什么?任何帮助将不胜感激。

回答by Farmer Joe

During your loopfunction in your Arduinocode you never end an newline char \n, this is only a problem with ser.readline()because it reads until a \ncharacter.

在代码中的loop函数期间,您Arduino永远不会结束换行符 char \n,这只是一个问题,ser.readline()因为它会读取到一个\n字符。

During your setupfunction you correctly send a \ncharacter which could explain the intial value being sent, but not the data.

在您的setup函数中,您正确发送了一个\n字符,该字符可以解释正在发送的初始值,但不能解释数据。

perhaps modifying your Arduino code like this:

也许像这样修改你的 Arduino 代码:

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);
    }    
}

And your python code like so...

而你的python代码就像这样......

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()

回答by gskielian

I used to get this a lot, and then a friend told me to prompt the arduino for data from python.

以前经常弄这个,后来朋友叫我提示arduino从python中输入数据。

Description below

说明如下



consider having the arduino only send data when prompted by your python program:

考虑让 arduino 仅在您的 python 程序提示时发送数据:

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);
     }
   }    
}

Also, I made a github repository that has some further examples for python-arduino communication:

此外,我制作了一个 github 存储库,其中包含一些用于 python-arduino 通信的更多示例:

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

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

回答by user2387729

I had the same problem and was breaking my head for a good time, try this

我遇到了同样的问题,并且很长时间都让我头疼,试试这个

Run

ps -ef | grep tty

If the output looks anything like

如果输出看起来像

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

Then you need to disable getty from trying to send data to that port

然后您需要禁止 getty 尝试将数据发送到该端口

In order to use the Raspberry Pi's serial port, we need to disable getty (the program that displays login screen) by find this line in file /etc/inittab

为了使用树莓派的串口,我们需要通过在文件 /etc/inittab 中找到这一行来禁用 getty(显示登录屏幕的程序)

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

And comment it out by adding # in front of it

并通过在它前面添加 # 来注释掉

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

To prevents the Raspberry Pi from sending out data to the serial ports when it boots, go to file /boot/cmdline.txt and find the line and remove it

为了防止 Raspberry Pi 在启动时向串口发送数据,请转到文件 /boot/cmdline.txt 并找到该行并将其删除

console=ttyAMA0,115200 kgdboc=ttyAMA0,115200

Reboot the Raspberry Pi

重启树莓派

Credit where credit is due: http://blog.oscarliang.net/raspberry-pi-and-arduino-connected-serial-gpio/helped me figure out how to diable getty

信用到期的信用:http: //blog.oscarliang.net/raspberry-pi-and-arduino-connected-serial-gpio/帮助我弄清楚如何禁用getty

回答by Chandan Purohit

I had to struggle with this when reading gps data in raspberry pi. The output would stop after about 10seconds and report

在树莓派中读取 GPS 数据时,我不得不为此而苦苦挣扎。输出将在大约 10 秒后停止并报告

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

The solutions given in almost all forums are for raspberry pi 2 with wheezy. I finally managed to get continuous gps streaming in my raspberry pi3 with jessie by doing the following:

几乎所有论坛中给出的解决方案都是针对 raspberry pi 2 with wheezy。通过执行以下操作,我终于设法通过 jessie 在我的 raspberry pi3 中获得连续的 GPS 流:

  1. set enable_uart=1and add dtoverlay=pi3-disable-btin /boot/config.txt. then reboot
  2. I had to change my /boot/cmdline.txt to

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

    then reboot

  3. stop getty: sudo systemctl stop [email protected]

    to disable: sudo systemctl stop [email protected]

  1. 设置enable_uart=1并添加dtoverlay=pi3-disable-bt到 /boot/config.txt。然后重启
  2. 我不得不将我的 /boot/cmdline.txt 更改为

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

    然后重启

  3. 停止盖蒂: sudo systemctl stop [email protected]

    禁用: sudo systemctl stop [email protected]

You need to be careful with the /boot/cmdline.txt. Any mistake in the file may make your raspberry pi to not boot. It is better keep a backup of the file before editing. Also set the baud rate properly. In my case, it was 9600. Hope this helps!

你需要小心 /boot/cmdline.txt。文件中的任何错误都可能使您的树莓派无法启动。最好在编辑之前保留文件的备份。还要正确设置波特率。就我而言,它是 9600。希望这会有所帮助!

回答by nate c

Try sudo rasbpi-config, choose interface option, say 'no' to first message ("kernel login"), 'yes' to second message ("serial communication on"). I found if the first message is on it throws errors. Saying 'no' fixes it.

尝试sudo rasbpi-config,选择接口选项,对第一条消息说“不”(“内核登录”),对第二条消息说“是”(“串行通信开启”)。我发现第一条消息是否会引发错误。说“不”可以解决问题。