ArduinoとPCとの情報のやりとりはシリアル通信でする。このサイトを参考にした。
深層学習(DNN)にはシリアル通信は必須なので、やり方とデモもかねて動かしたコードをまとめていく。
目次
1.Arduino Unoのシリアル通信の設定
2.Arduino UnoからPCへのデータ送信
3.PCからArduino Unoへのデータ送信
1.Arduinoのシリアル通信の設定
Arduino for Macを起動して、[ツール]-[シリアルボード~]で表示されてるパスを取得して確認。# シリアル通信できるか確認 $ sudo pip install pyserial $ python3 >>>import serial >>>ser = serial.Serial("/dev/cu.usbmodem14301") >>>print(ser) Serial<id=0x106a8f710, open=True>(port='/dev/cu.usbmodem14301', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=None, xonxoff=False, rtscts=False, dsrdtr=False) >>>ser.close() >>>exit()
シリアル通信ができてる。
2.Arduino UnoからPCへのデータ送信
0~9までの数字を一秒おきに送信
Arduinoから1秒毎にカウントされる値がPCに送られる。
通信中はArduinoのTXと書かれた通信用LEDが一秒毎に点滅する。
serial_send.ino
void setup() { int signal_speed = 9600; Serial.begin(signal_speed); } void loop() { static int count=0; Serial.print(count); count ++; if(count == 10) count = 0; delay(1000); }
serial_receive1.py
# -*- coding: utf-8 -*- import serial import time wait_second = 5.0 total_number = 10 ser = serial.Serial("/dev/cu.usbmodem14301", timeout=0.5) time.sleep(wait_second) for i in range(total_number): line = ser.read() print(line) ser.close()
# 実行 $ python3 serial_receive1.py >>> b'0' b'1' b'2' ~ b'5'
1~10までを読みこんで表示
ser.read()関数で一文字ごとに読み込んで表示。
serial_receive2.py
# -*- coding: utf-8 -*- import serial import time wait_second = 5.0 total_number = 10 with serial.Serial("/dev/cu.usbmodem14301") as ser: time.sleep(wait_second) for i in range(total_number): line = ser.read() print(line)
# 実行 $ python3 serial_receive2.py >>> b'0' b'1' b'2' ~ b'8' b'9'
# ファルダ構造 $ tree Serial_receive >>> Serial_receive ├── serial_send │ └── serial_send.ino ├── serial_receive1.py └── serial_receive2.py
データロガー
データロガーは「Arduinoで計測したデータをPCに送って、PCでそのデータを保存する」こと。
試しに一秒おきに
0, 0, 0.00 1, 1, 2.00
と0, 1, 2, 3と増えるデータをArduinoからPCに送信して、テキストファイル(data.txt)に保存してみる。
serial_datalogger.ino
void setup() { int signal_speed = 9600; Serial.begin(signal_speed); } void loop() { static int count=0; Serial.print(count); Serial.print(','); Serial.print(count); Serial.print(','); Serial.println(count*2.0); count ++; if(count == 10) count = 0; delay(1000); }
serial_datalogger.py
# -*- coding: utf-8 -*- import serial import time wait_second = 12.0 with serial.Serial('/dev/cu.usbmodem14301', timeout=0.5) as ser: time.sleep(wait_second) with open('data.txt', 'w') as f: for i in range(10): line = ser.readline() line = line.rstrip().decode('utf-8') print(line) f.write((line)+'\n')
# 実行 $ python3 serial_datalogger.py >>> 0,0,0.00 1,1,2.00 2,2,4.00 ~ 8,8,16.00 9,9,18.00
データがうまく保存できないならtime.sleep()の時間を増やすのがコツ
# ファルダ構造
$ tree Serial_datalogger
Serial_datalogger
├── data.txt
├── serial_datalogger
│ └── serial_datalogger.ino
└── serial_datalogger.py
3.PCからArduino Unoへのデータ送信
今度は逆にPCからArduinoへ文字や数値を送信する。これを使えばDNNで得た学習モデルを使って、Arduinoを含めたラズパイとかの電子工作を動かせる。
バイト文字の送信
void setup() { int signal_speed = 9600; Serial.begin(signal_speed); pinMode(LED_BUILTIN, OUTPUT); } void loop() { if(Serial.available()>0){ char c = Serial.read(); if(c=='a') digitalWrite(LED_BUILTIN,HIGH); else if(c=='b') digitalWrite(LED_BUILTIN,LOW); } }
# -*- coding: utf-8 -*- import serial import time with serial.Serial('/dev/cu.usbmodem14301') as ser: time.sleep(5.0) for i in range(5): ser.write(b'a') time.sleep(1.0) ser.write(b'b') time.sleep(1.0)
受信した変数が’a’なら確認用LEDを点灯、’b’なら確認用LED消灯。
‘a’を送信し、1秒待ち、’b’を送信して1秒待つを5回繰り返す。
Arduinoの確認用LEDが5回点滅する。
数値の送信
0~255の数値を送ってLEDの明るさを変化させる(もっと大きい数値(500とか1500)も送信可能)。
デジタル9番ピンを使ってLEDの明るさを変える。
serial_receive_value.ino
int pin_number = 9; void setup() { int signal_speed = 9600; Serial.begin(signal_speed); pinMode(pin_number, OUTPUT); } void loop() { if(Serial.available()>0){ long int v = Serial.parseInt(); analogWrite(pin_number, v); } }
Serial.available()関数は浮動小数点値を受け取る。
・LEDがだんだん明るくなる=>消える
を5回繰り返す(0~255までの値を送る)。
serial_receive_value.py
# -*- coding: utf-8 -*- import serial import time wait_second = 0.01 with serial.Serial('/dev/cu.usbmodem14301') as ser: time.sleep(5.0) for i in range(5): for j in range(255): ser.write((str(j)+'\n').encode('utf-8')) time.sleep(wait_second) # 0.01秒待つ
# 実行
$ python3 serial_send_value.py
$ tree serial_receive_value
>>>
serial_receive_value
├── serial_receive_value.ino
└── serial_receive_value.py
これでArduinoを使って深層学習ができる。
速度とかとはultra96v2と比較して劣るものの、Arduino Unoは動かすのはかなり簡単だった。