2016-11-26 66 views
1

我有一個關於Arduino和Raspberry Pi之間的串行通信的問題。事實是,我想用Arduino將2個變量發送到Raspberry Pi,並以不同的方式使用它們。使用串行向Arduino發送多個值到樹莓

這裏我草圖的Arduino:

int one = 1; 
int two = 2; 

void setup() 
{ 

    Serial.begin(9600); 
} 

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

}

這裏我的覆盆子Python腳本:

import serial 
import time 

ser = serial.Serial('/dev/ttyACM0', 9600) 
time.sleep(4) 

while True: 
    data=ser.read() 
    print data 

的問題是,在Python代碼 '數據' 需要兩個值由Arduino發送(因爲在Arduino循環()中有兩個打印)。但是我想用兩個不同的變量接收Raspberry Pi中的數據(以便記錄它們)。我嘗試了許多技術來以兩種不同的方式接收這些數據,但它不起作用。

謝謝你的幫助。

回答

2

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

重,

在首先我要感謝你的回答,並讓我發現JSON。 所以,我想你最後的Python代碼和修改我的Arduino這樣的代碼:

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) + 
    "\"}"); 
} 

在樹莓PY當我執行代碼(無時),控制檯任何回報。看來,數據發送正確的一個字符。

再次感謝

+0

請不要發佈其他問題的答案。改爲編輯你的問題。另外,JSON中的數字不需要引號。 –