使用串行向 Arduino 发送多个值 [英] Send multiple values to Raspberry with Arduino using serial

查看:127
本文介绍了使用串行向 Arduino 发送多个值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have got a question about serial communication between Arduino and Raspberry Pi. The fact is I want to send 2 variables to Raspberry Pi with Arduino and use them in different ways.

这是我的 Arduino 草图:

Here my sketch for Arduino :

int one = 1;
int two = 2;

void setup() 
{

     Serial.begin(9600);
}

void loop() 
{
   Serial.print(one);
   Serial.print(two);
   delay(3000);

}

这里是我的树莓派 Python 脚本:

Here my python script for Raspberry:

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 中的数据(之后记录它们).我尝试了许多技术以两种不同的方式接收这些数据,但它不起作用.

The problem is that 'data' in the python code takes the two values send by Arduino (because of two print in the Arduino loop() ). But I want to receive the datas in Raspberry Pi with two different variables (to record them after). I try many technics to receive these datas in two different ways, but it not work.

感谢您的帮助.

推荐答案

Arduino 的 Serial.print 以 ASCII 格式发送数据.所以来自 Arduino 的命令实际上发送了字符串 12.Python 无法看到第一个值的结束位置和第二个值的开始位置.

Arduino's Serial.print sends data as ASCII. So your commands from the Arduino actually send the string 12. There is no way for Python do see where the first value ends and where the second one begins.

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

One solution is to use Serial.println instead of Serial.print. This will add a carriage return and a newline after each call. So the string will become 1\r\n2\r\n.

在 Python 端,您可以使用 split 方法.IPython 中的一个例子:

On the Python side you can then use the split method. An example in IPython:

In [1]: recv = "1\r\n2\r\n"

In [2]: recv.split()
Out[2]: ['1', '2']

然后您可以轻松地将值转换为整数.

And you can then easily convert the values to integers.

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

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

Note: it is possible for Python to get an incomplete message! So you just might receive the string 1 the first time you read and 2 during a second read! So you might want to consider formatting your data so you know you have received a complete message.

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

One option to do that is to format your data as JSON. In your example this would be {"one": 1, "two": 2}. In this simple calse you can check that you have received a complete message because it starts with a { and ends with a }. But you could also use Python's built-in JSON parser.

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 解析器有一个优势,因为当您尝试解析不完整的消息时,它会引发异常:

Using the JSON parser has an advantage because it raises an exception when you try to parse an incomplete message:

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)

正确的处理方法是继续从串口读取数据并附加到字符串中,直到解析数据没有失败;

The correct way to deal with this is to keep reading data from the serial port and appending it to a string until parsing the data doesn't fail;

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)

这篇关于使用串行向 Arduino 发送多个值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆