Python | シリアル通信(RS-232C)

Python

Pythonでシリアル通信(RS-232C)を行う方法を説明する。

基本的な使用方法

1. ライブラリ

serialというライブラリを使用する。

import serial
from serial.tools import list_ports

2. COMポートの検出

comports()でPCに搭載されているCOMポートを検出しリストで返ってくる。

self.ports = list_ports.comports()

例)PCにCOMポート1、3、5が搭載されていた場合

self.portsに[1, 3, 5]というリストが代入される。

3. COMポートを設定

  1. 使いたいポート番号を指定する。
  2. serial.Seiralのインスタンスを設定する。
  3. ボーレート、パリティ、バイトサイズ、ストップビット、タイムアウトを必要な値に設定する。

一例を示す。

self.use_port = str(COMポート番号)
self.ser = serial.Serial(self.use_port)
self.ser.baudrate = 115200
self.ser.parity = serial.PARITY_NONE
self.ser.bytesize = serial.EIGHTBITS
self.ser.stopbits = serial.STOPBITS_ONE
self.ser.timeout = 1 #sec

4. 送信

送りたい文字列をwrite()に記述する。

self.ser.write(bytes(送りたい文字列, 'UTF-8'))

例1)「cd /mnt」を送信して改行(正規表現で「\n」)したい場合や、Ctrl + C( 正規表現で「\x03」)でブレークし改行(正規表現で「\n」)したい場合は以下のようになる。

self.ser.write(bytes('cd /mnt\n', 'UTF-8'))
self.ser.write(bytes('\x03\n', 'UTF-8'))

5. 受信

readline()で受信する。

recv_data = self.ser.readline()

6. COMポートを切断

close()でCOMポートを切断する。

self.ser.close()

具体例

このようなアプリを作成する。

  • COMポートを検出する。
  • 検出したCOMポートをコンボボックスに表示する。
  • connectボタンをクリックすると接続する。
  • データを送信する。
  • データを受信する。
  • 切断する。

メインの動作はこんな感じに実装してみる。

    def main(self):
        self.set_serial_port()
        self.send_serial_data('うんこ出た?')
        if self.read_serial_data() == '出たよ':
            print('良かったね')
        else:
            print('残念だったね')
        self.close_serial_ports()

コード全文

  1. serialをimportする。
  2. COMポートを検出する。
  3. 検出したCOMポートをコンボボックスに追加する。
  4. COMポートを設定する。
  5. データを送信する。
  6. データを受信する。
  7. COMポートを切断する。
#!/usr/bin/env python3

import os
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton,\
                            QComboBox, QGridLayout
from PyQt6 import QtGui ,QtCore
import serial                                                       # 1
from serial.tools import list_ports                                 # 1


class GuiWindow(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent)
        self.set_variables()
        self.build_ui()
        self.connect_signal_slot()

    def set_variables(self):
        self.combobox = QComboBox()
        self.button = QPushButton('connect')
        self.detect_serial_ports()                                  # 2
        for i in range(len(self.ports)):                            # 3
            self.combobox.addItem(str(self.ports[i]).split(' ')[0])

    def build_ui(self):
        self.grid = QGridLayout()
        self.grid.addWidget(self.combobox, 0, 0)
        self.grid.addWidget(self.button, 0, 1)
        self.setLayout(self.grid)

    def connect_signal_slot(self):
        self.button.clicked.connect(self.main)

    def main(self):
        self.set_serial_port()                                      # 4
        self.send_serial_data('うんこ出た?')                          # 5
        if self.read_serial_data() == '出たよ':                      # 6
            print('良かったね')
        else:
            print('残念だったね')
        self.close_serial_ports()                                   # 7

    # serial
    def detect_serial_ports(self):                                  # 2
        self.ports = list_ports.comports()

    def set_serial_port(self):                                      # 4
        self.use_port = str(self.combobox.currentText())
        self.ser = serial.Serial(self.use_port)
        self.ser.baudrate = 115200
        self.ser.parity = serial.PARITY_NONE
        self.ser.bytesize = serial.EIGHTBITS
        self.ser.stopbits = serial.STOPBITS_ONE
        self.ser.timeout = 1 #sec

    def send_serial_data(self, cmd):                                # 5
        data = cmd + "\n"
        self.ser.write(bytes(data, 'UTF-8'))

    def read_serial_data(self):                                     # 6
        recv_data = self.ser.readline()
        recv_data = recv_data.decode('utf-8').split('<0x1b>')
        recv_data = [s.replace('\r\n', '') for s in recv_data]
        return recv_data

    def close_serial_ports(self):                                   # 7
        self.ser.close()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = GuiWindow()
    window.move(0,0)
    window.show()
    sys.exit(app.exec())

まとめ

Pythonでシリアル通信(RS-232C)を行う方法を説明した。

コメント