问题
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.
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);
}
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
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.
Thank you for your help.
回答1:
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.
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
.
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]
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.
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}
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)
回答2:
Re,
In first I want to thank you for your answer and to make me discover Json. So I tried your last python code and modify my Arduino code like this :
int one=1;
int two=2;
int three = 3;
int four = 4;
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("{\"one\":\"" + String(one) +
"\", \"two\":\"" + String(two) +
"\", \"three\":\"" + String(three) +
"\", \"four\":\"" + String(four) +
"\"}");
}
In raspberry Py when i execute the code (without a while), the console return nothing. It seems that data send juste one character.
Thanks again
来源:https://stackoverflow.com/questions/40818169/send-multiple-values-to-raspberry-with-arduino-using-serial