【シリアル通信〜基礎編】USBを繋いでArduino Unoとラズパイ間で簡単なシリアル通信を行ってみる


2021/06/11
蛸壺の中の工作室|USBを繋いでArduino Unoとラズパイ間で簡単なシリアル通信を行ってみる

ラズパイとArduinoをシリアル通信させるときにもっとも手っ取り早く使えるようにする方法は
USB接続です。

今回はラズパイをホストとして、USB接続させたAruduinoとサクッと通信させる方法を解説します。


事前準備〜Arduino Unoをラズパイに認識させる

まず以下のような構成を考えてみます。

合同会社タコスキングダム|蛸壺の中の工作室

構成もなにもただUSB接続しただけですが、ラズパイとArduinoのUSBポートの規格上、使用するUSBケーブルはTypeA-Bの異型コネクタ変換を使うことになります。

ラズパイ側のUSBポートは通常4つ程度ありますが、どこのポートに指してもらっても動作します。

これだけで準備はOKです。

ラズパイ側に電源を投入すると、Arduino側にもUSBから電源が供給されて便利です。

またラズパイ側からUSB接続されたペリフェラルへ電源供給しながら使うことを考えると、5V3Aを供給するケーブルもあったほうが良いかも知れません。

5V3Aになると専用のACDCアダプターを購入することになりますが、色々とコンパチで使えるようにUSBを含め変換プラグが付属するタイプのものがおすすめです。

まずはラズパイ側でログインしターミナルからデバイス一覧を見てArduinoを認識しているか確認してみます。

            $ ls -l /dev/ | grep tty
#...中略
crw-rw---- 1 root dialout 166,   0  6月 10 18:17 ttyACM0
crw-rw---- 1 root dialout 204,  64  6月 10 18:17 ttyAMA0
crw-rw---- 1 root dialout   4,  64  6月 10 18:17 ttyS0
#...
        
ここでいうttyACM0が現在接続中のArduino Unoになります。

ちなみにラズパイの仕組みからいうとシリアル通信用のUARTデバイスは2つ(ラズパイ4からは6つ)あり、ここでは
ttyAMA0ttyS0がそれに割り当てられています。

シリアルデバイスも見てみると、

            $ ls -l /dev/ | grep serial
drwxr-xr-x 4 root root          80  6月 10 18:17 serial
lrwxrwxrwx 1 root root           7  6月 10 18:17 serial0 -> ttyAMA0
lrwxrwxrwx 1 root root           5  6月 10 18:17 serial1 -> ttyS0
        
Arduino Unoを接続することで現れるserialという名前のデバイスが増えています。

これでラズパイとArduino間のシリアル通信が可能になっていることが分かります。


ラズパイから送信した信号でArduinoを操作する

ここからは簡単な実装例を見ていきます。

まずはじめにラズパイからArduinoへ信号を送り、その信号を読み取った値からArduinoのビルドインLEDを点灯消灯させてみましょう。

Arduino側の実装

以下のコードで、ビルドインLEDが0を受け取った時に消灯、1を受け取った時に点灯するだけのプログラムを別のPCからArduino IDEから書き込んでおきます。

            #define LED_PIN 13
int flg=0;

void setup() {
    pinMode(LED_PIN, OUTPUT);
    Serial.begin(9600);
}

void loop() {
    if (Serial.available() > 0) {
        flg = Serial.read();
        Serial.println(flg);
        if (flg == 49) {
            digitalWrite(LED_PIN, HIGH);
        } else if (flg == 48) {
            digitalWrite(LED_PIN, LOW);
        }
    }
}
        


ラズパイからの送信

では先程プログラムを書き込んだArduino UnoをラズパイにUSB接続させます。

シェルコマンドによるシリアル通信からの送信は以下のようにします。

            $ echo -n '1' > /dev/ttyACM0
        
これでArduinoが無事点灯すればいいのですが、そのままechoだと通信が上手くいかない場合があります。

そんなときはsttyコマンドで設定を確認します。

            $ stty -F /dev/ttyACM0
#👇出力
speed 9600 baud; line = 0;
-brkint -imaxbel
        
まぁボーレート位しか設定が無かったですが、これでは動かなそう...。

これはシリアル通信の設定というかArduino側の通信方式の問題で、
こちら|Bash to send command to Arduinoでも書いてあるようにシリアル通信で利用されるDTRの信号をホスト側からArduinoへ送らないといけないようです。

フォーラムに書かれているDTRを無効にする対処法はいくらかあるようですが、手っ取り早く初期化に以下の方法をとります。

            $ stty -F /dev/ttyACM0 -hupcl
        
ただし、この-hupclは通信のプロセス最後にリセットを繰り返す最終手段的なものらしいので、実用性はなくなります。

これで晴れて通信がArduinoとの通信が確立し、

            #👇点灯
$ echo 1 > /dev/ttyACM0
#👇消灯
$ echo 0 > /dev/ttyACM0
        
が使えるようになります。

余談〜ハード的にDTR無効化を試す

こちら紹介されているように、ちょうどいい感じの抵抗かコンデンサが手元にある方はより確実にDTR無効化ができます。

以下の写真のように5V電源-RST間に仕込むだけで済みます。

合同会社タコスキングダム|蛸壺の中の工作室

ですが抵抗でやる場合には
110〜124[Ω]の間に取らないといけないという選択幅の狭さがあり、コンデンサのほうがまだ無難かも知れません。

写真は0.1μFのセラミックコンデンサを挿入しました。

コンデンサの場合には
RST-GND間に挟むのが正しいと書いてあります。

後で気づきましたが上の写真は誤ってセラコンを5V-RST間に差し込んでしまった時の写真ですが、たまたまなのかこれでも動作しておりました。

試される場合には自己責任において、お試しください。

なお、ArduinoIDEでプログラムを書き込む際には、挿しっぱなしだと書き込みに支障が出ますので、抜いておかないといけません。


Arduinoから送信された信号をラズパイで受け取る

次にArduinoから定期発信した信号をラズパイで受ける方も試します。

Arduino側から信号を送信

今回のケースは以下のコードをまずArduinoに書き込みます。

            #define LED_PIN 13

void setup(){
    Serial.begin(9600);
    pinMode(LED_PIN, OUTPUT);
}

void loop(){
    Serial.println("LED ON");
    digitalWrite(LED_PIN, HIGH);
    delay(1000);

    Serial.println("LED OFF");
    digitalWrite(LED_PIN, LOW);
    delay(1000);
}
        
ビルドインLEDが1秒間隔で点灯・消灯を繰り返すたびにメッセージをラズパイ側に送り出します。

ラズパイ側のモニタリング

ラズパイ側で送信を受け取るためには、screenコマンドを使うのが手っ取り早いです。

以下のようにコンソールからscreenプロセスを呼び出します。

            $ sudo screen /dev/ttyACM0 9600
LED ON
LED OFF
LED ON
LED OFF
LED ON
LED OFF
LED ON
LED OFF
LED ON
LED OFF
LED ON
#...略
        
Arduino側からラズパイで信号を受け取る際には、DTRを考慮せずとも読み取れていると思います。


まとめ

今回はUSB接続を利用したArduino Unoとラズパイ間のシリアル通信のやり方をまとめてみました。

USB接続のシリアル通信がもっとも簡単で確実な方法でしたが、もっと汎用性の高いGPIOピンによるシリアル通信の方法も後日まとめていきたいと思います。GPIOピンでのシリアル通信にも興味がございましたら、また当ブログを覗いてみてください。


参考サイト

Raspberry Pi と Arduino をUSBシリアル通信(第一弾)

screenを使ったserial接続と終了の方法メモ