Re: note

技術的な知見やポエムなど役に立たない情報を書き連ねる場所

W5500を使ってArduinoでMQTT通信する

f:id:hik0leaf:20190616104524j:plain

WIZnetのW5500を使ってArduinoでMQTT通信を行ってみます。

1. 準備

Aliexpress等でW5500を購入します。

1 個 USR ES1 W5500 チップ新 spi 蘭イーサネット変換 TCPIP Mod - Aliexpress.com | Alibaba グループ上の 電子部品&用品 からの 集積回路 の中

f:id:hik0leaf:20190615222738j:plain
とってもコンパクト

ArduinoはUNO R3を使います。

2. 接続

ArduinoとはSPIで通信を行うため、W5500を以下のように接続します。IOレベルは3.3Vですが5VトレラントでもあるのでArduinoへ直結することができます。その他の注意点としてはW5500の消費電流が大きいため3.3Vの供給をArduinoから行わずに外部から加えるようにしています。

W5500 | WIZnet Co., Ltd.

f:id:hik0leaf:20190616105511j:plain
接続図

Arduino W5500
D10 (SS) CS
D11 (MOSI) MOSI
D12 (MISO) MISO
D13 (SCK) SCLK
GND GND

データシートを見ると100M Trasmittingのときに132mA消費すると書いてあるので、外部電源は200mA以上供給できるものを用意すると良いでしょう。

products:w5500:datasheet [Document Wiki]

f:id:hik0leaf:20190615134207j:plain
W5500の消費電流 (データシートから抜粋)

f:id:hik0leaf:20190615134554j:plain
W5500モジュールのピン配置

【注意】ブレッドボードで接続する場合はワイヤーをなるべく短くしてください。ワイヤーが長いと通信が不安定になります。

3. ライブラリのインストール

W5500を使用する場合はENC28J60とは異なり、標準のEthernetライブラリでモジュールを制御することができるため、MQTT部分を処理するPubSubClientのみをインストールします。

github.com

ライブラリはArduino IDEのライブラリマネージャから名前で検索してインストールすることができます。

f:id:hik0leaf:20190615212349j:plain

4. コード

以下のコードをArduinoに書き込みます。

#include <Ethernet.h>
#include <PubSubClient.h>

byte mac[] = { 0x70, 0x69, 0x69, 0x2D, 0x30, 0x31 };
byte server[] = { 10, 0, 1, 5 };

void callback(char* topic, byte* payload, unsigned int length) {
  payload[length] = '\0';
  String msg = String((char*) payload);
  Serial.println(msg);
}


EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);


void reconnect() {
  while (!client.connected()) {
    Serial.println("Attempting MQTT connection...");
    
    if (client.connect("myClient")) {
      Serial.println("MQTT PubSub Ready");
      client.publish("output", "ready");
      client.subscribe("input");
      Serial.println("subscribe input");
    } else {
      Serial.println("MQTT PubSub failer");
      Serial.println("try again in 2 seconds");
      delay(2000);
    }
  }  
}


void setup() {
  Serial.begin(9600);
  Serial.println("starting...");
  
  Ethernet.init(10);// CS pin 10
  Ethernet.begin(mac);

  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  Serial.print("IP: ");
  Serial.println(Ethernet.localIP());
  
  delay(1500);
}


void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}

PubSubClientにはAPIドキュメントも用意されています。

Arduino Client for MQTT

MACアドレスやserverアドレスは環境に合わせて変更してください。 serverアドレスはMQTT Brokerのアドレスで、動作確認するためにはMQTT Brokerが必要になります。MQTT BrokerはRaspberry Pimosqittoをインストールして構築するのが一番簡単でおすすめです。

5. 実行

MQTT Brokerが動作していることが確認できたら、Arduinoに繋がっているシリアルモニタでログを確認します。正常に動作していれば以下のようになります。

f:id:hik0leaf:20190616110611j:plain

mosquittoをインストールすると、Brokerの他にPubSubクライアントもインストールされるのでPublish(Pub)用とSubscribe(Sub)用のターミナルを立ち上げて動作を確認してみます。

f:id:hik0leaf:20190615214945j:plain
Subscribe画面

トピックはoutputをSubscribeしておきます。Arduinoが立ち上がるとreadyが送られてくるのを確認できます。見逃してしまったらArduinoをリセットするともう一度送られてきます。

f:id:hik0leaf:20190615214907j:plain
Publish画面

inputトピックに対してメッセージ(payload)を送るとArduinoのシリアルモニタで受信を確認することができます。

6. まとめ

W5500やENC28J60を使うことで非力なマイコンでもTCPUDP通信できることをこのブログで紹介してきました。最近ではWi-Fiを搭載したESP8266やESP32の登場により、単体で気軽にIoT機器を作ることができるようになりましたが、人が多い場所や電波干渉が顕著な環境では有線による安定動作が望まれる場面もあるかと思います。

マイコンで通信を行うときはコストや用途、使用環境などを考慮して有線や無線、プロトコルを選択できるようになると良いでしょう。