Skip to main content
 首页 » 编程设计

python之使用串行向带有 Arduino 的 Raspberry 发送多个值

2024年08月21日32sxdcgaq8080

我有一个关于 Arduino 和 Raspberry Pi 之间串行通信的问题。事实上,我想使用 Arduino 将 2 个变量发送到 Raspberry Pi,并以不同的方式使用它们。

这是我的 Arduino 草图:

int one = 1; 
int two = 2; 
 
void setup()  
{ 
 
     Serial.begin(9600); 
} 
 
void loop()  
{ 
   Serial.print(one); 
   Serial.print(two); 
   delay(3000); 

这是我的 Raspberry python 脚本:

import serial 
import time 
 
ser = serial.Serial('/dev/ttyACM0', 9600) 
time.sleep(4) 
 
while True: 
    data=ser.read() 
    print data 

问题是 python 代码中的“数据”采用 Arduino 发送的两个值(因为 Arduino loop() 中有两个打印)。但我想用两个不同的变量接收 Raspberry Pi 中的数据(之后记录它们)。我尝试了很多技术以两种不同的方式接收这些数据,但它不起作用。

感谢您的帮助。

请您参考如下方法:

Arduino 的 Serial.print以 ASCII 格式发送数据。 因此,您从 Arduino 发出的命令实际上发送了字符串 12。 Python 无法看到第一个值在哪里结束以及第二个值在哪里开始。

一种解决方案是使用 Serial.println而不是 Serial.print。 这将在每次调用后添加一个回车符和一个换行符。 所以字符串将变为 1\r\n2\r\n。

然后在 Python 端,您可以使用 split 方法。 IPython 中的示例:

In [1]: recv = "1\r\n2\r\n" 
 
In [2]: recv.split() 
Out[2]: ['1', '2'] 

然后您可以轻松地将这些值转换为整数。

In [3]: [int(j) for j in recv.split()] 
Out[3]: [1, 2] 

注意:Python 有可能得到不完整的信息!因此,您可能会在第一次阅读时收到字符串 1,而在第二次阅读时收到 2!因此,您可能需要考虑格式化您的数据,以便您知道您收到了完整的消息。

实现此目的的一种选择是将您的数据格式化为 JSON。在您的示例中,这将是 {"one": 1, "two": 2}。在这个简单的例子中,您可以检查是否收到了完整的消息,因为它以 { 开头并以 } 结尾。但您也可以使用 Python 的内置 JSON 解析器。

In [4]: data = {'one': 1, 'two': 2} 
 
In [5]: import json 
 
In [6]: json.dumps(data) 
Out[6]: '{"two": 2, "one": 1}' 
 
In [7]: recv2 = json.dumps(data) 
 
In [8]: json.loads(recv2) 
Out[8]: {'one': 1, 'two': 2} 

使用 JSON 解析器有一个优势,因为它会在您尝试解析不完整的消息时引发异常:

In [10]: recv2 
Out[10]: '{"two": 2, "one": 1}' 
 
In [11]: recv3 = '{"two": 2, "on' 
 
In [12]: json.loads(recv3) 
--------------------------------------------------------------------------- 
JSONDecodeError                           Traceback (most recent call last) 
<ipython-input-12-c1774b41dafa> in <module>() 
----> 1 json.loads(recv3) 
 
/usr/local/lib/python3.5/json/__init__.py in loads(s, encoding, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw) 
    317             parse_int is None and parse_float is None and 
    318             parse_constant is None and object_pairs_hook is None and not kw): 
--> 319         return _default_decoder.decode(s) 
    320     if cls is None: 
    321         cls = JSONDecoder 
 
/usr/local/lib/python3.5/json/decoder.py in decode(self, s, _w) 
    337  
    338         """ 
--> 339         obj, end = self.raw_decode(s, idx=_w(s, 0).end()) 
    340         end = _w(s, end).end() 
    341         if end != len(s): 
 
/usr/local/lib/python3.5/json/decoder.py in raw_decode(self, s, idx) 
    353         """ 
    354         try: 
--> 355             obj, end = self.scan_once(s, idx) 
    356         except StopIteration as err: 
    357             raise JSONDecodeError("Expecting value", s, err.value) from None 
 
JSONDecodeError: Unterminated string starting at: line 1 column 12 (char 11) 

正确的处理方式是不断从串口读取数据,并追加到字符串中,直到解析数据没有失败为止;

import serial 
import json 
import time 
 
ser = serial.Serial('/dev/ttyACM0', 9600) 
 
buffer = '' 
while True: 
    buffer += ser.read() 
    try: 
        data = json.loads(buffer) 
        print(data) 
        buffer = '' 
    except json.JSONDecodeError: 
        time.sleep(1)