概要
個人的に組み込み開発ではデバッグが難しいと感じており,ほとんどの場合シリアル通信を行うことでPCに何らかのデータを送って確認する.しかし,シリアル通信自身がおかしい場合,プログラムのどのパスを通ったのか,などはLEDを光らせて確認するしか無い.加えて,Arduino IDEにはシリアル通信を使ってデータの受信と表示,データ送信をできるツールが付属しているが,データ送信は文字として送られてしまうため,生データを送ることが難しい(できない?).
そこで,今後のために,Pythonでシリアル通信を実行し,加えてLEDを使って正しくシリアル通信ができることを確認してみる.
Arduino Unoのプログラム
Arduino Unoで以下のプログラムを実行する.
#include "serial.h"
int putc(unsigned char c) {
if (c == '\n') {
serial_send_byte('\r');
}
return serial_send_byte(c);
}
unsigned char getc() {
return serial_recv_byte();
}
void setout();
void turnon();
void turnoff();
int main(void) {
serial_init();
setout(); // シリアルの初期化
putc('D'); // 1文字出力
char c = getc(); // 1文字入力を待つ
turnon(); // LEDを点灯
putc(++c); // 受信した文字をインクリメントし,シリアルで出力
putc('E'); // 1文字出力
c = getc(); // 1文字入力を待つ
turnoff(); // LEDを消灯
putc(++c); // 受信した文字をインクリメントし,シリアルで出力
putc(++c); // 受信した文字をインクリメントし,シリアルで出力
while(1){}
コメントにあるように,Arduinoでは1文字出力し,その後,受信->送信を2回繰り返して処理を終了する.そして,1回目の受信でLEDを点灯,2回めの受信でLEDを消灯する.よって,仮に送受信できない場合でも,LEDの点灯/消灯でどこまでプログラムが実行されたかわかる.
Pythonでのシリアル通信
Pythonでシリアル通信を実行するために,pyserial
をpipでインストールする
pip3 install pyserial
そして,Arduinoのプログラムに合わせてデータを送受信する.
import serial
import time
ser = serial.Serial('/dev/cu.usbmodem142101', 9600, timeout = 1)
while True:
data: bytes = ser.read();
if len(data) > 0:
break
int_data = int.from_bytes(data, 'big')
print(data)
print("data1 = {}".format(int_data)) # Dを読む
time.sleep(0.5)
ser.write(bytes([65])) # aを書く
time.sleep(0.5)
data: bytes = ser.read() # bを読む
int_data = int.from_bytes(data, 'big')
print(data)
print(len(data))
print("data2 = {}".format(int_data))
time.sleep(0.5)
data: bytes = ser.read() # Eを読む
print(data)
time.sleep(0.5)
ser.write(bytes([67])) # cを書く
time.sleep(0.5)
data: bytes = ser.read() # d
print(data)
特に解説は必要ないと思うが,シリアル通信は遅いので,送受信の間に0.5秒のsleepを入れている.これを入れないと,実行が早すぎて見えない.
この実装は,以下のコマンドで試すことができる.
>git clone https://github.com/hiro4669/iosv.git
>cd iosv
>cd serial_py
>make
>make write
>python3 test.py