ここでRaspberryとArduinoの間にシリアル通信させるにはどんなことを実現するには踏まえるの手順を書きます。まず簡単でシリアル通信はどんなものなの?を紹介し、次はSoftwareとHardwareの構成を説明します。
シリアル通信とは?
簡単にデータを送信するの方法一つで、データ1Bit1Bitで相手に送ります。それを成立するには以下のパラメータが定義する必要があります。
- 通信速度
- Stop Bit・Start Bit
- Parity Bit
- 送りのデータの長さ
- Port 名
UART protocol
そしてRaspberryを使ってシリアル通信するってことはUARTプロトコルです。 UART=“Universal Asynchronous Reception and Transmission”。詳しくはGoogleで。
Hardware構成
RaspberryPi3をそのままUSBをArduino unoのUSB Portさして通信します。
Arduino uno
Arduino unoはUSB Cable・RX/TX PinsどっちらでもOkですが(同時に使わないでください。)注意するのは毎回プログラムUploadするたびにRapbserryからUSBケーブルを抜いてPCにさしておかないとだめです。
Raspberry Pi
今回使ってるPi3はPort4つあるので好きなほうにさしてください。Portことに違うデバイス名がついてますので後ほど確認の方法を説明します。もちろんGPIOs (RX0/TX0)を使っても構いません。
Software
ハードウェアの構成決まったら次はSoftwareのSetupになります。Pi3をshhかScreenとKeyboardかVNC Viewerかでつながってください
Arduino unoを検出する
ArduinoをUSB経由でPiとつながることになりと、/dev/ttyACM0が見えるはずです。(たまに違う名前もあるが)
一番簡単な方法はArduinoと接続してる状態で以下のコマンドを入れます:
ls /dev/tty*
そしていまのPortですべてリストされ、次はArduinoを抜いて先のコマンドもう一度実行すればどっちがArduinoが簡単に見つかると思います。
シリアル通信実行権限を許可
そしていまのUserがPort開けるようにします。そうしないと、Userこれを実行する権限たりませんよってエラーが出てくる可能性があります。
$ sudo adduser your_username dialout
そしてRebootします。
Python Serial libraryインストール
今回シリアル通信するためのライブラリです。
python3 -m pip install pyserial
実装1
簡単なプログラムから始めましょう。まずはArduinoから単方向をPiへ送ります。
Arduino uno
- 通信速度(baud rate)を9600にします。
- Hello i am Arduino!をPi3に送ります。
- printlnは文字列の最後に‘\n’を插入してくれます。
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("Hello i am Arduino!");
delay(500);
}
Raspberry
- serial.Serial()を使って初期化します。
- Serialの名前は/dev/ttyACM0を指定します。
- 通信速度(baud rate)を9600にします。(Arduinoと合わせてください)
- 1=1s、Timeout時間です。この1sというのはSerialからデータを読みますが、もしデータずっとこないならプログラムが止まってしまってなにできなくなってしまいます。
- ser.flush()はいまのInput・OutputのBufferデータを捨てる。いらないデータ・残りデータが影響されないために。
- そして無限Loopに入り、ser.in_waitingは0より大きならデータが受けましたよ~の意味。
- ser.readlineで1行を読み、utf-8でdecodeする。もちろんAsciiなども指定できます。
- .rstrip()は‘\n’ 、‘\r’を削除することできます。
#!/usr/bin/env python3
import serial
if __name__ == '__main__':
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
ser.flush()
while True:
if ser.in_waiting > 0:
line = ser.readline().decode('utf-8').rstrip()
print(line)
結果
Hello i am Arduino!
Hello i am Arduino!
Hello i am Arduino!
実装2
今度はArduinoとRaspberryをデータ交換して形でやります。つまり双方向ですね。
- 今度はArduino側でSerial.available()を使ってデータもらったかどうかをCheckします。もしデータ受信したらReceive Bufferにはそのデータのバイト数が格納されます。
- Serial.readStringUntil()で‘\n’までを読みます。先のPython側にあるreadline()と似てます。読み終わるとArduinoの文字列に変換します。
- もらったデータをPrintし、ちょっと追加して返しします。
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
String data = Serial.readStringUntil('\n');
Serial.print("You sent me: ");
Serial.println(data);
}
}
Raspberry
- write()を使ってデータをArduinoへ書き込みます。文字列送る前にbが入れるのは文字列をBytesに変換し、Serial上ではBytesしか送れませんので。
- Arduino側が\nをみてデータ受信終わったかどうかを見てるので、Python側最後にも\nを入れます。
- そしてArduino側の返事待ち。
- 最後は1秒をDelayします。
#!/usr/bin/env python3
import serial
import time
if __name__ == '__main__':
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)
ser.flush()
while True:
ser.write(b"Hello from Raspberry Pi!\n")
line = ser.readline().decode('utf-8').rstrip()
print(line)
time.sleep(1)
結果
You sent me: Hello from Raspberry Pi!
You sent me: Hello from Raspberry Pi!
You sent me: Hello from Raspberry Pi!
はーい、お疲れ様です。