やること
mac と python3 で USB シリアルドライバなどを使ってシリアル(UART)通信します。
やりかた
pyserial を pip でインストールして import serial すればできます。python3 ではできないという記事が検索で沢山みつかりますが、2020/02/29 時点では python3 でもできました。
環境
- MacOS 10.15.3
- python3.7.4
- pip 19.2.3
手順
pyserial のインストール
$ pip install pyserial
受信
シリアルで 1 byte 受信して、10進数表記に変換して標準出力にコードは以下の通りです。
import serial
import struct
ser = serial.Serial(
port = "/dev/cu.usbserial-XXXXXXXX",
baudrate = 115200,
#parity = serial.PARITY_NONE,
#bytesize = serial.EIGHTBITS,
#stopbits = serial.STOPBITS_ONE,
#timeout = None,
#xonxoff = 0,
#rtscts = 0,
)
while True:
if ser.in_waiting > 0:
recv_data = ser.read(1)
print(type(recv_data))
a = struct.unpack_from("B",recv_data ,0)
print( a )
port の文字列は ls /dev/cu.*
として、usbserial-...
と出てくるデバイスの中から適切なものを選びます。コメントアウトされている部分は、デフォルトの設定のままなので、必要があればコメントアウトして適切なパラメータを設定します。
ser.in_waiting
を参照することで、シリアルバッファに受信データがあるか(バッファに含まれるバイト数)を調べることができます。
受信したデータは、バイナリデータであっても文字列扱いになります。受信したデータがバイナリの場合は、上のコードのようにstruct_unpack_from()
を使って数値に変換する必要があります。utf8 文字列の場合は decode する必要があります。いわゆる 7bit 文字列であれば、decode や unpack せずにそのまま文字列として扱えます。
送信
任意のバイト列 (buf) を送信します。
import serial
import struct
def send( buf ):
while True:
if ser.out_waiting == 0:
break
for b in buf:
a = struct.pack( "B", b )
ser.write(a)
ser.flush()
ser = serial.Serial(
port = "/dev/cu.usbserial-XXXXXXXX",
baudrate = 115200,
#parity = serial.PARITY_NONE,
#bytesize = serial.EIGHTBITS,
#stopbits = serial.STOPBITS_ONE,
#timeout = None,
#xonxoff = 0,
#rtscts = 0,
)
x = [ 0x01, 0xFF, 0x02, 0xFE, 0x03]
send( x )
自力で flush しないと、ある程度の送信データがバッファされるまで送ってくれないようです。ser.out_waiting
のチェックをしないと、たまに正常に送れないことがあるようです。
バイナリではなく、(英数の)文字列を送りたければ、下記でいけます。
x = b'abcdef'
ser.write( x )
utf8 文字列を送る場合は encode する必要があります。
まとめ
C 言語や swift で書くよりは楽かなと思って調べてみましたが、通信する部分以外でやることが結構多くて、unpack とか encode あたりを調べるのに意外に苦労しました。