LoginSignup
12
17

More than 5 years have passed since last update.

pythonでTWE-Liteのシリアルを受け取る

Last updated at Posted at 2016-02-13

安価で低消費電力の無線マイコン、TWE-LiteのシリアルデータをRaspberry Pi上のpythonで受け取るメモ。

構成

  | TWE-Lite | - | raspberry Pi |

まず、Raspberry Piのシリアルを使えるようにする。
この辺を見るといいです。
http://qiita.com/ryugyoku/items/bf5fd10512c84a55d030

テスト

TWE-LiteのTX,RDをRaspberry Piのシリアルポートに接続します。
試しにminicomで読み込んでみましょう。


$ sudo minicom -b 115200 -o -D /dev/ttyAMA0

minicomはsudo apt-get install minicomでインストールできます。

-Dオプションがターミナルの場所。
USBシリアル変換を使用している場合はここを/dev/ttyUSB0とかに変えればいいです。


minicom へようこそ 2.7

オプション: I18n
コンパイルされた日時は:  Jan 12 2014, 05:42:53.
ポート /dev/ttyAMA0, 01:54:51

CTRL-A Z を押すと、説明画面になります。

:0F8115015481012CFB00A387000BB0150101FFFFFFFFFF66
:0F8115015181012CFB00A389000BB0150101FFFFFFFFFF67
:0F8115015481012CFB00A38B000BAC150101FFFFFFFFFF66
:0F8115015181012CFB00A38D000BAC150101FFFFFFFFFF67
:0F8115015481012CFB00A38F000BB0150101FFFFFFFFFF5E
:0F8115014E81012CFB00A393000BAC150101FFFFFFFFFF64

このような物が出たら接続は正常です。
Ctrl+A,Qで終了。

こいつをPythonで受け取ってパースしましょう

シリアル受け取り

シリアルの取得はpyserialを使用します。


$ pip3 install pyserial


Python 3.4.2 (default, Oct 19 2014, 13:31:11)
[GCC 4.9.1] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import serial
>>> ser = serial.Serial('/dev/ttyAMA0',115200)
>>> ser.readline()
b':0F8115014E81012CFB00A437000BAC150101FFFFFFFFFFBF'
>>> ser.close()
<bound method Serial.close of Serial<id=0xb68fd550, open=True>(port='/dev/ttyAMA0', baudrate=115200, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False)>
>>>

チェックサム計算

公式によると、コードの最後の1バイトがチェックサムとなっています。
計算方法は、先頭行から1バイトずつ加算していき、和の下位1バイトの補数がチェックサムとなっています。
つまり、':0F8115014E81012CFB00A437000BAC150101FFFFFFFFFFBF'の場合のチェックサムは最後のBFで、
0x0f+0x81+....0xff+0xff = 0x941 これの下1バイトの0x41 + 0xBF = 0xa00となります。

ということは、最初の":"を除く全桁を1バイトずつ加算した総和の下1バイトはかならず0になるということです。

python的な計算をすると、


Python 3.5.2 (default, Jun 28 2016, 08:46:01) 
[GCC 6.1.1 20160602] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> string = ':0F8115014E81012CFB00A437000BAC150101FFFFFFFFFFBF'
>>> string = string[1:] #冒頭の:を除く
>>> lst = [ int(string[i:i+2], 16) for i in range(0, len(string), 2) ] #二桁ずつ切り取って16進数として数値化
>>> s = sum(lst) #総和を取る
>>> hex(s & 0b1111)
'0x0'
>>>

0になりましたね。話のわかるやつだ

パース

データフォーマットはマニュアルを参照。

# coding: utf-8
#!/usr/bin/env python3

def parse(string):
    if string[-2:] == b"\r\n"  : string = string[:-2]
    if string[0]   == ord(':') : string = string[1:]
    lst = [ int(string[i:i+2], 16) for i in range(0, len(string), 2) ]
    if sum(lst) & 0xff == 0:
        return lst

    return False

if __name__ == '__main__':
    import serial
    s = serial.Serial('/dev/ttyAMA0',115200)

    l = s.readline()
    lst = parse(l)

    print (lst)

    SOURCE_DEVIDE = lst[0]
    COMMAND = lst[1]
    PACKET = lst[2]
    PROTOCOL = lst[3]
    LQI = (7 * lst[4] - 1970 ) / 20
    SN = lst[5] << 24 | lst[6] << 16 | lst[7] << 8 | lst[8]
    DESTINATION_ID = lst[9]
    TIMESTAMP = lst[10] << 8 | lst[11]
    RELATED = True if lst[15] % 1 else False
    VOLTAGE = lst[13] << 8 | lst[14]
    NONE = 0
    DIN = lst[16]
    DCHANGE = lst[17]
    ACOMP = lst[22]
    AD1 = (lst[18] * 4 + ACOMP) * 4
    AD2 = (lst[19] * 4 + ACOMP) * 4
    AD3 = (lst[20] * 4 + ACOMP) * 4
    AD4 = (lst[21] * 4 + ACOMP) * 4
    SUM = lst[-1]

    D1 = True if lst[16] & 0b0001 else False
    D2 = True if lst[16] & 0b0010 else False
    D3 = True if lst[16] & 0b0100 else False
    D4 = True if lst[16] & 0b1000 else False

あとはご自由に。

ライブラリですが、今見たら酷い出来だったのでそのうち改造します

12
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
17