シリアル通信
PythonとArduinoを連携して、シリアル通信で値を送り合う。
Windows環境を想定している。Macだともうちょっと簡単。
Pythonと連携するとこんなことができる!
- Arduinoで集めたデータをグラフにして分析
- Arduinoから集めたデータをもとにWebと連携、ブラウザの自動操作
- ネットから情報を取得してArduinoの動作を変える
Anacondaのインストール
WindowsでPythonを使うために、Anacondaというツールで環境を構築する。
https://www.javadrive.jp/python/install/index5.html
Pyserialのインストール
Anaconda Promptを開き、以下のように入力する。
pip install pyserial
これでPythonでシリアル通信が使えるようになった。
コマンドラインでUNIXと同じようにPythonを実行できる。
python3
ではなくpython
で実行する。
python ファイル名.py
Windowsでls
に相当するコマンドはdir
。cd
は同じように動作する。
ArduinoからPythonに値を送る
Arduino IDEを開き、以下のプログラムを実行する。
これは、制作した基盤の可変抵抗を回すとアナログ入力の値が変わるプログラム。
int analogInputPin = 5;
/** 初期設定の関数 一度だけ実行される */
void setup() {
Serial.begin(9600);
}
/** 定期的に実行される関数 頻度はdelay関数で調整 */
void loop(){
int val = analogRead(analogInputPin);
Serial.println(val); // PCに結果を送信
delay(200);
}
シリアルモニタを見て、可変抵抗を回すと値が変わることを確認する
また、シリアルポートが何番かを確認しておく。
次に、Pythonのファイルを作成する。
参考: https://haizairenmei.com/2019/11/13/pyserial-arduino/
import serial
ser = serial.Serial('COM6', 9600) # ここのポート番号を変更
ser.readline()
while True:
val_arduino = ser.readline()
val_decoded = int(repr(val_arduino.decode())[1:-5])
print(val_decoded)
ser.close()
このプログラムを実行すると、Arduinoのシリアルモニタと同じように数字が表示される。
PythonからArduinoに値を送る
intの値は、文字列として1桁ずつ送ることができる。
int led1 = 6;
int led2 = 5;
int led3 = 3;
int input = -1;
int add = 0;
int val = 0;
void setup() {
Serial.begin(9600);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
}
void loop() {
input = Serial.read();
if(input!=-1){
switch(input){
case '0':
add = 0 + add*10;
break;
case '1':
add = 1 + add*10;
break;
case '2':
add = 2 + add*10;
break;
case '3':
add = 3 + add*10;
break;
case '4':
add = 4 + add*10;
break;
case '5':
add = 5 + add*10;
break;
case '6':
add = 6 + add*10;
break;
case '7':
add = 7 + add*10;
break;
case '8':
add = 8 + add*10;
break;
case '9':
add = 9 + add*10;
break;
case 'a':
val = add;
add = 0;
break;
default:
break;
}
}
// ここまでで、valが送られた
// valが30以上のとき、右のLEDをHIGH
if(val >= 30){
digitalWrite(led1, HIGH);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
}
// valが20-29のとき、真ん中のLEDをHIGH
else if(val >= 20){
digitalWrite(led1, LOW);
digitalWrite(led2, HIGH);
digitalWrite(led3, LOW);
}
// valが1-19のとき、左のLEDをHIGH
else if(val > 0){
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(led3, HIGH);
}
}
import serial
import time
ser =serial.Serial("COM3", 9600) # ここのポート番号を変更
time.sleep(2)
val = 100 # ここの値を変更すると、Arduinoの挙動が変わる
a = str(val) + 'a'
ser.write(bytes(a,'utf-8'))
ser.close()
応用: APIの活用
Pythonで気象庁から明日の最高気温を取得し、それによって点灯するLEDを変える。
https://news.mynavi.jp/article/zeropython-75/
ネット上には、APIといって色々な情報がプログラミングしやすい形式でダウンロードできる仕組みがある。
今回は気象庁のAPIを利用する。JSONという形式で天気予報がダウンロードできる。
JSONはPythonでリストのように利用できる。
まずはURLにアクセスし、中身を見てみるとよい。
明日の最高気温が30度以上か、20度以上か、それ以外かによってArduino基盤の点灯するLEDを変える。
Arduinoのプログラムはそのまま
import serial
import time
import urllib.request as req
import json
# JSONをダウンロード
url = 'https://www.jma.go.jp/bosai/forecast/data/forecast/010000.json'
filename = 'tenki.json'
req.urlretrieve(url, filename)
with open('tenki.json', 'r', encoding="UTF-8") as f:
data = json.load(f)
nagoya_data = data[11]
nagoya_tomorrow_temps = nagoya_data["srf"]["timeSeries"][2]["areas"]["temps"]
print(nagoya_tomorrow_temps) # 明日の名古屋の[最低気温, 最高気温]
ser =serial.Serial("COM3", 9600)
time.sleep(2)
val = nagoya_tomorrow_temps[1] # 明日の名古屋の最高気温
a = val + 'a'
ser.write(bytes(a,'utf-8'))
ser.close()
Pythonでは、ブラウザの自動操作ができる。
ブラウザの自動操作
IFTTTを使うことで、LINEなどと連携できる。
LINE, メールとの連携