第二十項 ArduinoとLAN・Wi-Fi

電子工作創作表現(2019/11/29)

スライドPDF

Arduino同士やPCとの通信

  • Arduinoが基本的に扱えるのはシリアル通信のみ
     
  • インターネットやLANに接続する手段もある
Arduino単体でPCと通信する方法としては、USBを介したシリアル通信があります。手軽に実行できますがソフトウェアでやらなければいけない要素が多く、かなり取っつきづらいです。
一方で追加のパーツが必要になりますが、EthernetケーブルやWi-Fiを通してLANを使って通信する方法というのも実はあって、今回はそれらを紹介していきます。

LAN接続のメリット

  • LANハブが使えるので、デバイス間通信が楽
     
  • 距離の制約にも強い
     
  • プロトコルもOSCなどが使用可能
LANを使って接続をすれば、LANハブを使い複数のArduinoを制御したり、かなり離れた距離のデバイスを制御したりといったことが可能になります。またソフトウェア側もOSCなどを使えるので、MAX/MSPやTouchdesignerで定番の機能をそのまま使うことができます。

LANに接続する方法

  • Arduino Ethernetを使う(有線)
     
  • ArduinoにW5500 Ethernetモジュールを付ける(有線)
     
  • ESP-WROOMシリーズを使う(無線)
LANに接続する代表的な方法にこの3つがあります。一つずつ解説していきます。

Arduino Ethernetを使う

  • ArduinoにEthernetポートが付いたモデル
     
  • 今は純正の取り扱いが無い
まず一つ目はArduino Ethernetという特殊なArduinoを使う方法です。USBの他にEthernetポートが付いているので、有線LANに差してすぐ使うことができます。他にArduinoEthernetシールドという、従来のArduinoにシールドを差して使うモデルも過去あったのですが、現在純正品は販売されていません。その代わりKEYSTUDIOなど他で作られたクローン版があるので、そちらを使うことができます。

ArduinoにW5500モジュールを付ける

  • ひと手間増えるが、外せば普通のArduinoとしても使える
     
  • SPI通信で接続。Arduino Ethernetはこれが既に載っているモデル
もう一つは、Ethernet用のチップが別になっているW5500というモジュールをArduinoに付ける方法です。既にArduinoを持っている人は、こういったモジュールを接続することでも実現できます。Ethernet2というライブラリを使って、SPI通信でArduinoと接続することでLAN用のパケットをやり取りできるようになります。

ちなみに、Arduinoでよく使われるLAN用のチップにW5100とW5500があり、5100はEthernet.h、5500の方はEthernet2.hを使う必要があるので注意が必要です。

ESP-WROOMシリーズを使う

  • Arduino互換で動作するマイコン
     
  • 安くて小さい。
     
  • IOポートは少ないが、これ一個でWi-Fi接続が可能
そして最後が今日紹介するESP-WROOMシリーズで、有線ではなくWi-Fiを使って接続する方式です。Arduinoとは別の製品ですが、ArduinoIDEでプログラムを開発できるように設計されているので、ほぼArduinoと同じように扱うことができます。IOポートはやや少なめですが、単独でWi-Fiが扱えて値段も安いです。

ESP-WROOM-02

  • スタンダード品。もう少しグレードの高い32も流通
     

  • 秋月で単品が400円

  • おススメはスイッチサイエンスのモジュール品

今回持ってきたのはESP-WROOM-02というスタンダードなモデルです。もう少し機能が多く、Bluetooth機能もついた32というモデルもあります。02は秋月で単品だと400円という値段で売っていて、これはマイコン+Wi-Fi機能付きでかなり破格といえます。

ただし、単品のピンが2mmピッチと小さめで、ブレッドボードやユニバーサル基板に載せづらいです。USBピンもついてないので、最初は秋月やスイッチサイエンスのモジュール化されたモデルを購入するのがおススメです。

ESP-WROOM-32

  • 02はArduinoと比べるとピン数がかなり少なめ
     
  • BluetoothやSDカード読み取り機能など高機能
ちなみに、この02を高機能にしたESP32というチップもあり、そちらは少し高くてサイズが大きいけど高機能なモデルになっています。Arduinoと比較すると02の方は少しピンが少ない印象がありますが、32の方は20以上のIOピンが備わっているので、Arduinoの感覚で行っても全然足りなくなるということは無さそうです。

ESPを使えるように設定する

Arduino公式のマイコンではないので、ArduinoIDEに追加でICの情報を追加する必要があります。詳しくはスイッチサイエンス等のWebページに書いてあるので、ここを参照しながら追加するのが良いでしょう。

書き込んでみる

nodemcu

  • Arduinoと比べ少し時間がかかる
     
  • 書き込み方式はckではなくnodemcuがおススメ
ボード情報を書き込んだら、Uploadボタンを押せば通常のArduinoと同じように書き込むことができます。ESPは書き込みモードで立ち上げなくてはいけないckモードと、通常のArduinoと同じPCからリセットをかけるnodemcuモードがあって、ckはUploadを押した後手動でリセットボタンを押す必要があるので、ここの設定はnodemcuモードがおススメです。
void setup() {
  pinMode(16, OUTPUT);
  pinMode(4, OUTPUT);
}

void loop() {
  digitalWrite(16, HIGH);
  digitalWrite(4, LOW);
  delay(1000);

  digitalWrite(16, LOW);
  digitalWrite(4, HIGH);
  delay(1000);
}

Wi-Fiに接続して、OSCを受信する

  • taihideaki氏の「AdruinoOSC」
     
  • 一つのアドレスに対して実行する内容をラムダ式で記述
ESPシリーズは、ボード設定を入れた段階で基本的なArduino用のライブラリも一通り入っています。TCPやUDPなどの通信方式のサンプルは入ってますが、OSCの送受信をしようとするとまた別でライブラリが必要になります。

今回は「ArduinoOSC」というライブラリを使ってOSCの受信を試してみます。
#include "ArduinoOSC.h"
OscWiFi osc;

String ssid = "ssid";
String passwd = "pw";
IPAddress ip(10, 0, 0, 31);
IPAddress gateway(10, 0, 0, 1);
IPAddress subnet(255, 255, 255, 0);

void setup()
{
  pinMode(16, OUTPUT);
  pinMode(4, OUTPUT);

  WiFi.begin(ssid, passwd);
  WiFi.config(ip, gateway, subnet);

  Serial.begin(115200);
  Serial.println(WiFi.localIP());
  osc.begin(8888);

  osc.subscribe("/led1", [](OscMessage& m) //OSCを受信すると、カッコの中身が実行される
  {
    analogWrite(16, m.arg<int>(0));
  });

  osc.subscribe("/led2", [](OscMessage& m)
  {
    analogWrite(4, m.arg<int>(0));
  });
}

void loop()
{
    osc.parse(); // should be called
}

TDのouc out CHOPから送信

  • チャンネル名がアドレスになる
     
  • アドレスやポートの他”Data Format"をSampleに指定
touchdesignerからOSCを送信してみます。先ほどのソースコードで"/led1・/led2"というアドレスを受信するようにしたので”led1”というチャンネルをOSC outCHOPに入れて送信します。頭のスラッシュ記号は自動的に入れられるので、チャンネル名には含めません。

設定項目としては、アドレスやポートの他に”Data Format”という項目があり、そこをSampleにする必要があります。

ESPからOSCを送信する

  • osc.sendで1行で送ることができる
     
  • 複数の違うタイプの値も連続して入れられる
マイコン側から、OSCを送信することもできます。ArduinoOSCではosc.sendにアドレスとポート、値を入れれば送信が可能です。値の種類はbool, int, float, String等が使えます。loopを以下のように記述して、マイフレーム起動時間とランダムな数値を送ってみます。
void loop()
{
  delay(12);//マイコンのループは早いので、Delayを入れる
  osc.parse();
  osc.send("192.168.1.255", 9999, "/array", millis() / 1000.0f, float(random(100)));
}

TDから受信

今度はTDで受信をしてみます。osc inCHOPでは、ポート番号だけを指示すれば受信できるようになっています。
/arrayというアドレスで送った複数のデータは、array1, array2...という風にインデックスを付けた状態で受け取ることができます。CHOPでは文字列を受信できないので、文字列などをやり取りしたい場合はOSC in DATを使う必要があります。array1にはmillisで取得したArduino起動からの時間、array2ではrandomで生成した0~100のランダムな数値が入ってきています。