9
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Posted at

やること

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 あたりを調べるのに意外に苦労しました。

9
12
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
9
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?