python3 でバイナリデータをシリアル通信で送受信する (mac で)

やること

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 のインストール

install.sh
$ pip install pyserial

受信

シリアルで 1 byte 受信して、10進数表記に変換して標準出力にコードは以下の通りです。

serial_read.py
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) を送信します。

serial_write.py
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 のチェックをしないと、たまに正常に送れないことがあるようです。

バイナリではなく、(英数の)文字列を送りたければ、下記でいけます。

serial_str_write.py
x = b'abcdef'
ser.write( x )

utf8 文字列を送る場合は encode する必要があります。

まとめ

C 言語や swift で書くよりは楽かなと思って調べてみましたが、通信する部分以外でやることが結構多くて、unpack とか encode あたりを調べるのに意外に苦労しました。

mml
LEDを光らせる屋内での軽作業に従事して早300年。LEDに関係しそうな技術には、だいたい何でも手を出します。
http://www.bbled.org
ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
ユーザーは見つかりませんでした