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

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

问题描述

我对Arduino和Raspberry Pi之间的串行通信有疑问.事实是我想使用Arduino将2个变量发送到Raspberry Pi,并以不同的方式使用它们.

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

}

这是我的Raspberry 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}.在这种简单的计算中,您可以检查您是否已收到完整的消息,因为该消息以{开头,以}结尾.但是您也可以使用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的Raspberry的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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