INDEX
はじめに
ArduinoとRaspberry PiでUSBケーブルを介した通信を行いたかったのでテストしたときのメモ。
このプログラムは、両方のデバイスがUSBデバイスがシリアルポートであることが条件です。
通信形式は、テキスト、またはバイナリのシリアルデータとなります。
構成
- Arduino UNO Rev.4
- Arduino IDE 2.3.6
- Raspberry Pi 3
- Raspberry Pi OS with desktop 64-bit(Release date: May 13th 2025)
- Python 3.11.2
Raspberry PiのOS
下記からダウンロードし、Rufusで書き込みます。

Raspberry Pi OS downloads ??? Raspberry Pi
Raspberry Pi OS (previously called Raspbian) is our official, supported operating system.
Rufusは下記からダウンロードします。
Rufus - 起動可能なUSBドライブを簡単に作成できます
Rufus: Create bootable USB drives the easy way
Pythonの hid モジュールのインストール
HIDデバイスと簡易に通信できます。
sudo apt install libhidapi-dev libusb-1.0-0-dev build-essential python3-dev
Arduino UNO Rev.4の送信プログラム
「while (!Serial);」があるため、シリアル通信が有効にならないとプログラムが進みません。
そのため、プログラムを書き込んだら、以下を行います。
・Arduino IDEのシリアルモニターを開いてプログラムを進ませる。
・シリアル通信の重複を避けるため、Arduino IDEを終了する。
数字を送るプログラムです。
#include <FspTimer.h>
FspTimer timer;
// サンプリングレート (Hz)
// 1Hzの場合、1秒ごとに1回実行する。
const float sampleRate = 1.0;
int cnt = 0;
void timerCallback(timer_callback_args_t *) {
// シリアル通信を使ったデータの送信
Serial.print("Count: ");
Serial.println(cnt);
cnt++;
}
void setup() {
// シリアル通信の設定
Serial.begin(115200);
while (!Serial);
uint8_t timer_type;
// 未使用のタイマーのチャネルと種別を取得する
int8_t timer_ch = FspTimer::get_available_timer(timer_type);
if (timer_ch >= 0) {
// タイマーのパラメータを設定する
// TIMER_MODE_PERIODIC: 周期タイマーを指定
// timer_type: GitHubのFspTimer.cppを見るとGPT_TIMER(32ビット幅のカウンタ)の優先度が高く、AGT_TIMER(8ビットまたは16ビット幅のカウンタ)は低い
// sampleRate: タイマー割込みの間隔(Hz) 割り込みごとにデータ1個を出力するので、サイン波の周波数と同義
// timerCallback: タイマー割り込み発生時に呼ばれるコールバック関数
//
// FspTimer.cpp
// https://github.com/arduino/ArduinoCore-renesas/blob/main/cores/arduino/FspTimer.cpp
if (timer.begin(TIMER_MODE_PERIODIC, timer_type, timer_ch, sampleRate, 0.0f, timerCallback, nullptr)) {
// タイマオーバーフロー割込みを有効にする
timer.setup_overflow_irq();
// タイマーのチャネルを有効にする
timer.open();
// タイマーを開始する
timer.start();
}
}
}
void loop() {
// メインループでは何もしない - タイマー割り込みで処理
}
ArduinoとRaspberry PiをUSBケーブルで接続したときのdmesgのメッセージ
Raspberry Piでは、以下のように認識されました。
・Arduinoのベンダー番号:2341
・プロダクト番号:0069
・シリアルポート:ttyACM0
[10066.910281] hwmon hwmon1: Undervoltage detected! [10067.098257] usb 1-1.4: new full-speed USB device number 14 using dwc_otg [10067.190494] usb 1-1.4: New USB device found, idVendor=2341, idProduct=0069, bcdDevice= 1.00 [10067.190543] usb 1-1.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [10067.190562] usb 1-1.4: Product: UNO R4 Minima [10067.190575] usb 1-1.4: Manufacturer: Arduino [10067.190589] usb 1-1.4: SerialNumber: 370E1F0759333032D98433324B572E63 [10067.293035] cdc_acm 1-1.4:1.0: ttyACM0: USB ACM device [10067.293484] usbcore: registered new interface driver cdc_acm [10067.293520] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters [10072.958271] hwmon hwmon1: Voltage normalised
Raspberry Piの受信プログラム
今回は受信のみなので、送信部はコメントしています。
受信した数字をコンソールに表示します。
input_port変数には、ArduinoとUSBケーブルで接続後にdmesgコマンドで確認したポート名「ttyACM0」を指定します。
import serial
import time
# USBポート(受信)
input_port = '/dev/ttyACM0'
# USB機器2台(送信)
#output_ports = ['/dev/ttyUSB1', '/dev/ttyUSB2']
#baudrate = 9600
# 初期化
try:
ser_in = serial.Serial(input_port, baudrate, timeout=1)
#ser_outs = [serial.Serial(p, baudrate, timeout=1) for p in output_ports]
except serial.SerialException as e:
print(f"シリアルポートの初期化に失敗: {e}")
exit(1)
print("USBデータミラーリング開始")
try:
while True:
if ser_in.in_waiting:
data = ser_in.readline()
print(f"[受信]: {data.decode(errors='ignore').strip()}")
'''
for out in ser_outs:
try:
out.write(data)
except serial.SerialException as e:
print(f"[送信エラー]: {e}")
'''
time.sleep(0.01)
except KeyboardInterrupt:
print("\n終了")
finally:
ser_in.close()
for out in ser_outs:
out.close()


Comments