使用PySerial从Arduino接收数据到树莓派,在一段时间后停止接收

10

我正在进行一个项目,需要每次接收一些25个字符的数据,以便在树莓派上处理。这里是产生我想要从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);
  }
}

它发送这样的一行:'llllddddllldddd...' 这行的长度为25个字符。现在,我希望使用树莓派接收它。以下是我正在尝试使用的代码:

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

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

这段代码在最开始的5秒内能够正确地接收到数据,但随后突然停止了接收。

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

serial_data = ser.readline()
print serial_data

编辑1: 好的,我现在已经注释掉了异常处理。它会给出以下错误:

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

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

12

我曾经遇到过同样的问题,苦思冥想了好一段时间,试试这个方法

运行

ps -ef | grep tty
如果输出看起来像任何东西
root      2522     1  0 06:08 ?        00:00:00 /sbin/getty -L ttyAMA0 115200 vt100

然后,您需要禁用getty尝试向该端口发送数据。

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

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

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

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

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

console=ttyAMA0,115200 kgdboc=ttyAMA0,115200

重新启动树莓派

功劳归功于:http://blog.oscarliang.net/raspberry-pi-and-arduino-connected-serial-gpio/ 帮助我找出如何禁用getty。


如果你禁用了getty,而getty又显示了登录界面,那么你该如何登录到树莓派呢? - Cerin

2

当我在树莓派中读取GPS数据时,我遇到了这个问题。输出会在大约10秒后停止并报告错误。

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

几乎所有论坛中提供的解决方案都是针对装有 wheezy 的树莓派 2。以下是我通过以下步骤最终设法让我的树莓派3上装有jessie实现连续gps流:
  1. 在 /boot/config.txt 中设置 enable_uart=1 并添加 dtoverlay=pi3-disable-bt,然后重新启动
  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. 停止 getty: sudo systemctl stop serial-getty@ttyAMA0.service

    要禁用: sudo systemctl stop serial-getty@ttyAMA0.service

需要小心 /boot/cmdline.txt 文件。文件中任何错误可能导致您的树莓派无法启动。最好在编辑之前备份该文件。还要正确设置波特率。在我的情况下,波特率为9600。希望这能帮到您!

1

我曾经遇到过这个问题,后来一个朋友告诉我可以通过Python向Arduino请求数据。

以下为描述


考虑让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);
     }
   }    
}

此外,我创建了一个 Github 存储库,其中包含一些有关 Python-Arduino 通信的进一步示例:

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


0

在您的Arduino代码的loop函数中,您从未结束换行符\n。这只是ser.readline()的问题,因为它读取直到一个\n字符。

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

也许修改您的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);
    }    
}

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

实际上我之前用过那个。树莓派方面没有任何变化。奇怪的是,我在5秒钟内完全按照自己的意愿接收到数据。然后,即使我确保Arduino继续发送,数据突然停止被接收。 - mozcelikors
@mozcelikors 也许你可以将 timeout 增加到大于 2,因为你的 Arduino 被延迟了这么久?另外,在你的 python 代码中的 except 中增加一个打印语句或其他调试方式可能也是值得的,也许串口最终会出现异常。我最近做的一个 Arduino 项目就遇到了这个问题。 - Farmer Joe
@mozcelikors =( ... 我很感兴趣...等我回家后我会拿出我的Arduino板子。 - Farmer Joe
好的,我现在已经注释掉了异常。它会报以下错误:raise SerialException('device reporst rediness to read but returned no data (device disconnected?)') serial.serialutil.SerialException: device reporst rediness to read but returned no data (device disconnected?) - mozcelikors
@mozcelikors,你尝试过在你的Arduino代码中降低“delay”吗? - Farmer Joe

-1
尝试使用sudo rasbpi-config命令,选择接口选项,在第一条消息(“内核登录”)中选择“否”,在第二条消息(“串行通信开启”)中选择“是”。我发现如果第一条消息打开,会出现错误。选择“否”可以解决这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接