ワンコインでiot入門 第二章
TRANSCRIPT
ワンコインでIoT入門2章: Arduino nano clone + 格安Ether ENC28J60の人柱とMQTT
makoto
今回のゴール
Arduinonano
SPI
コンセプト - 格安Ethernet モジュール”ENC28J60”(266円)の人柱 - MQTTの基本的なPub/Subまでの確認ゴール Arduino nano クローンにENC28J60を接続、DHCPでアドレスを取得してMQTT通信ができることを確認
ENC28J60 eth MQTT Broker
(Linux)MQTT PublishMQTT SubscribeMQTT Publish
必要なハードウエア
パソコン:
とりあえずOSXを例に。Wind/LinuxでもIDEが動けば何でもOK
半田セット:
2000円ぐらいの安い物でOK
必要なハードウエアITEM 最安値 価格備考 備考
Arduino nano clone 179円 前回購入 マイコン本体。前回使ったものを利用
USB cable(mini) 100円 前回購入 前回使ったものを利用
LANケーブル 0円 エンジニアなら余るほど持ってるはず
ジャンパーコード各3種類×40本
239円 aliexpress 最安値 オスメス、メスメス、オスメス全種類。どうせ今後使うので3種類全部準備
ENC28J60 266円 aliexpress 最安値 イーサネットモジュール
3.3v 電源 70円 3.3vの外部電源が必要なことが判明種類手配中
ワンコインを超えてる気もするが、とりあえず気にしない
対象者
対象とする者
PCのネットワークの設定には全く困らない程度のTCP/IP知識
MAC/Linuxのコマンドラインの扱いには慣れている
数百円程度の投資ができる
対象としない者
ニーモニック原理主義者
ブルジョアArduino派(Genuino101とか)
トレードオフ・スライダー
低コスト
技術の新しさ
技術の美しさ
技術の簡単さ
重視軽視
電波法順守
なぜArduino uno + ENC28J60なのか=安いから ArduinoのEthernet実装の選択肢
今回の構成 Ethernet Shield
実装例 Arduino nano クローン(139円〜)+ENC28J60 (266円〜)
正規版Arduino UNO (3000円ぐらい)+ Ethernet Shield(3000円ぐらい)クローンArduino UNO (270円ぐらい)+ Ethernet Shield(551円ぐらい)
利点 安い、小さい世界的には情報量が多い
半田いらず情報量が多い
欠点 ピンの半田付け必須 大きい
酔っぱらって触って壊してもいいやと思える程度にお手軽(酒の肴に最適)ワンコインにこだわらなかったらEthernet Shield クローンもアリ
ArduinoとENC28J60との通信:SPI Arduinoと周辺機器とのデジタル通信インターフェースの例
SPI I2C UART
トポロジー
概要 SCLK: クロックSOMI: 周辺機器からArduinoへの通信SIMO: Arduinoから周辺機器への通信SS: 通信する周辺機器を選択
SCL: クロックSDAI:データ送受信
TX: データ送信RX:データ受信
特徴 バイナリー通信Pros:全二重、通信速度が早いCons,:結線が多い
バイナリー通信周辺機器のアドレスで対象を選択Pros:結線数が少ないCons;半二重通信、遅め
テキスト通信の利用も多いPros:全二重そこそこ早いCons: 通信速度は両端で手動設定
実装例 TFT液晶、イーサネット等の高速通信
デジタルセンサー、LCD液晶など Arduinoへのスケッチ書き込みATコマンドやGPSのNMEA、,Log出力等のテキスト通信
Arduino 周辺機器
周辺機器
SCLKSOMISIMOSS1SS2 Arduino 周辺機器
周辺機器
SDA
SCL Arduino 周辺機器
TX
RX
RX
TX
バス型 バス型 P2P型
なぜMQTTなのか1. 理由(棒読み)
HTTP MQTT
トポロジー
通信 1:1のRequest-Responseが基本。擬似的なPush型通信実現のため、頻繁にRequestが発生、トラフィック増加
Push型通信をサポートSub/Pub型のため、容易に1:Nを実現
データ量 扱うデータが小さいのでプロトコルヘッダーの割合が相対的に大きい
IoTに最適化されているため小さい
なんとなくまわりで流行ってて楽しそうだから
HTTPServer
Client A
Client B
Response
Request
Response
RequestClient A MQTT
Broker
Client B
Client C
Request/Response型 Sub/Pub型
2. 理由(本音)
Ether
Ubuntu 14.04
MQTT Subscriber
MQTT Publisher
MQTT Broker
今回実装する概要1: ArduinoでPublishテスト
Arduino nano clone
MQTT Subscriber
MQTT Publisher
ENC28J60
IP network
1. “output”購読
2. “output”に”Ready”を発行
3. “Ready”受信
シリアルモニタ(UART)へログを出力
1. テスト用MQTTクライアントが topic”output”をsubscribe2. Arduino起動後、Topic”output”へ”Ready”という文字列をpublish3. テスト用MQTTクライアントが ”Ready”という文字列を受信(*) 一連の開析のため、テキストログをシリアル通信( UART)へ出力
Ether
Ubuntu 14.04
MQTT Subscriber
MQTT Publisher
MQTT Broker
今回実装する概要2:ArduinoでSubscribeテスト
Arduino nano clone
MQTT Subscriber
MQTT Publisher
ENC28J60
IP network
1. “input”購読
2. inputに“ping”発行
シリアルモニタ(UART)へログを出力
1. Arduinoがtopic”intput”をsubscribe2. テストクライアントがTopic”input”へ”ping”という文字列をpublish3. Arduinoが”ping”という文字列を受信(*) 一連の開析のため、テキストログをシリアル通信( UART)へ出力
3. “Ping”受信
Server側準備
❖ 環境
➢ OS: Ubuntu 14.04➢ MQTT: Mosquitto ubuntuデフォルトのパッケージは古いのでNG。PPAで最新
版をインストール
$sudo apt-get install software-properties-common$sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa$sudo apt-get update$sudo apt-get install mosquitto$sudo service mosquitto start$sudo apt-get install mosquitto-clients
Server側接続テストサーバ上にターミナルを2つ立ち上げ、topic”output”経由で文字列”test”が送受信される事
を確認
$mosquitto_sub -d -t "output" -h localhostClient mosqsub/2308-ip-172-31- sending CONNECTClient mosqsub/2308-ip-172-31- received CONNACKClient mosqsub/2308-ip-172-31- sending SUBSCRIBE
(Mid: 1, Topic: output, QoS: 0)Client mosqsub/2308-ip-172-31- received SUBACKSubscribed (mid: 1): 0
Client mosqsub/2311-ip-172-31- received PUBLISH (d0, q0, r0, m0, 'output', ... (4 bytes))test
$mosquitto_pub -t "output" -h localhost -m "test"
MQTT Publish
Termina1: Subscriber 側 Termina2: Publisher 側
Arduino物理的準備(PINハンダ付け)❖ 簡単なハンダ付け作業必須
➢ 道具は2000円のセットで OK。失敗したとき用に吸い取り線だけはあった方がいい
➢ やってみると思ったより簡単。そう簡単に壊れないし壊れたところで数百円。 Go ahead
ピンをハンダ付け
❖ まずは動画でイメージトレーニング
➢ https://www.youtube.com/watch?v=37mW1i_oEpA
RJ45
USB
Arduino物理的準D12 D11 D10
5V GNDD13
SO
SCK
GNDVCC
CS
SI 動かない
3.3v
SI
原因と対策● 原因
ENC28J60への電流が予想以上に大きく、実測で140mA,Google先生に聞くと最大で250mAらしい。Arduinoが供給可能な電流を大きく上回り、3.3v電圧が下降し、ENC28J60に必要な電圧(3.0-3.6v)を下回る
● 対策1. regulator付きの3.3v外部電源が必要。(70円のをポチったけど今手元にない)2. 今すぐ動かしてみたいので色々やってみた○ アルカリ電池×2(3.2v)を外部電源に利用
■ 失敗:電圧が2.7vぐらいまで下降。3本だと逆に電圧高すぎ○ ニッケル充電電池×3(1.2v×3=3.6v)を外部電源に利用
■ 成功:電圧の降下ほとんど無く、実測値で3.7v○ USBからの5v電圧を10オームぐらいの抵抗で分圧
■ 成功:とりあえずは動いた○ Arduinoの3.3vピンではなく5vピンで給電
■ 成功:適度に電圧が下降し動いた。真似するなら壊す覚悟を
とりあえず今回はこれで
RJ45
USB
Arduino物理的準(3.3v外部電源)D12 D11 D10
5V GNDD13
SO
SCK
GNDVCC
SI
3.3v
SI
3.3V
GND
CS
GND外部電源
乱暴に言えば「3.3v」が電
池でいうプラスでGNDがマ
イナス
本来5vのArduinoと3.3vの周辺機器は給電だけでなくデータ線も直接接続できず、レベル変換が必要ですが
28J60のデータ線は5vに耐えられる(5v tolerant)なのでOK
Arduino物理的準備(暫定構成)
充電式ニッケル単三電池×3=3.6v
開発環境(ソフトウエア)以下二つのライブラリをダウンロードして取り込む
UIPEthernetENC28J60用のTCP/IPスタックhttps://github.com/ntruchsess/arduino_uip/archive/master.zipPubSubClientArduinoのMQTTクライアントhttps://github.com/knolleary/pubsubclient/archive/master.zip
#include <UIPEthernet.h>#include <PubSubClient.h>
byte mac[] = {0x00,0x01,0x02,0x03,0x04,0x05};byte server[] = { 192,168,1,1 };
EthernetClient ethClient;void callback(char* topic, byte* payload, unsigned int length);PubSubClient client(server, 1883, callback, ethClient);
void setup(){ Ethernet.begin(mac); Serial.begin(9600); Serial.print("IP Address : "); Serial.print(Ethernet.localIP()); Serial.print("/"); Serial.println(Ethernet.subnetMask()); if (client.connect("arduinoClient")) { Serial.println("MQTT PubSub Ready"); client.publish("output","ready"); client.subscribe("input"); }else{ Serial.println("MQTT PubSub failer"); }}
void loop(){ client.loop();}
void callback(char* topic, byte* payload, unsigned int length) { byte* pl = (byte*)malloc(length); memcpy(pl,payload,length); if (memcmp(pl, "ping",4)==0) { Serial.println("Payload=ping"); client.publish("output","ok"); } free(pl);}
開発環境(サンプルスケッチ)
「カンマ」区切りのMQTT brokerのIPアドレス
MACアドレス手書きっすか!!
書き込み:シンボリックリンクを作成
❖ OSXではArduino nanoのUARTのデバイス名に空白文字が含まれ、IDEで正常に扱えないのでシンボリックリンクを作成
-rw- 1 root wheel 18, 93 4 24 14:23 cu.wch ch341 USB=$ sudo ln -s "/dev/cu.wch ch341 USB=>RS232 fd120" /dev/cu.wchPassword:$ ls -al /dev/cu.*crw-rw-rw- 1 root wheel 18, 3 4 3 15:24 /dev/cu.Bluetooth-Modemcrw-rw-rw- 1 root wheel 18, 1 4 3 15:24 /dev/cu.Bluetooth-PDA-Synclrwxr-xr-x 1 root wheel 0 4 24 14:20 /dev/cu.wch -> /dev/cu.wch ch341 USB=>RS232 fd120crw-rw-rw- 1 root wheel 18, 97 4 24 14:46 /dev/cu.wch ch341 USB=>RS232 fd120 ダメなデバイス名
書き込み:書き込み実効
1. シリアルポートに作成したシンボリックリンクを選択、マイコンボード、プロセッサが正しく設定されていることを確認
2. シリアルモニタを起動3. 書き込む
1
3
成功
2
シリアルモニタ
Publishのテスト
$mosquitto_sub -d -t "output" -h localhostClient mosqsub/2308-ip-172-31- sending CONNECTClient mosqsub/2308-ip-172-31- received CONNACKClient mosqsub/2308-ip-172-31- sending SUBSCRIBE
(Mid: 1, Topic: output, QoS: 0)Client mosqsub/2308-ip-172-31- received SUBACKSubscribed (mid: 1): 0
Client mosqsub/2311-ip-172-31- received PUBLISH (d0, q0, r0, m0, 'output', ... (4 bytes))Ready
1.ubuntuで”output”をサブスクライブ
4.文字列”Ready”を受信
2.Arduinoのリセットボタンで再起動
IP Address : 172.16.81.52/255.255.192.0MQTT PubSub Ready
3.シリアルモニタでDHCOで取得したIPアドレス、MQTT接続を確認
Subscribeのテスト1.ubuntuから”output”へ文字列”ping”をpublish
IP Address : 172.16.81.52/255.255.192.0MQTT PubSub ReadyPayload=ping
$mosquitto_pub -t "output" -h localhost -m "ping"
2.受信した事をシリアルモニタで確認
まとめENC28J60を使ってMQTTのクライアントの基本的な動作を確認。ATMegaベースのArduinoはIPベースのGateway母艦としては少々役不足かも
想定外だったこと1、 消費電力が予想以上に高い
ENC28J60の固有ではなくEthernet自体の消費電力がArduinoの周辺機器としては高い。私が無知でした。Google先生がarduinoからの3.3v給電で動かしている回路図を紹介してくるのだけどホントだろうか
2、まさかのMACアドレス手書き
3、TCP/IPスタックの消費メモリが大きすぎるたったこれだけの実装で74%(1.5kB)のSRAMを消費(75%を超えるとアラート)これもENC28J60固有の問題ではない(TLSで暗号化とかはまず無理)
次回:WiFiか可視光、赤外線
センサーを何か一つ接続するとして、通信は以下2案で検討中
案1 WiFi ESP wroom 2(ESP8266の電波法OKバージョン)を使ったWiFi シンプル版は扱いにくいしくUSB Uart付きのやつは高い 案2 赤外線/可視光通信: WiFiは結局高いので赤外線通信か可視光
APPENDIX: Arduino uno clone編
PC(USB) ←
結線図
RJ45SO
SCK
GNDVCC
SI
CS
13 12 11 10
GND3.3v
USB
→ Hub/Switch
結論:unoなら外部電源も半田も不要(の場合もある)
手順1. マイコンボードとして”Arduino/Genuino Uno”を選択2. あとはnanoと同じMQTT用のスケッチを同じ手順で書き込む原因unoもnanoも同じようなレギュレータ。でもunoの3.3vはレギュレータ直なのであとはレギュレータ次第(クローンなので何が実装されるか不明、とりあえず私の持ってるuno/nanoは全部AMS1117だった)追加コスト324円(Arduino uno と古い形状のUSBケーブルセット
Arduino uno clone
uno(上)とnano(下)
uno と ENC28J60