Re: note

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

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

f:id:hik0leaf:20190615125456j:plain

WIZnetのW5500を使ってArduinoUDP通信を行ってみます。

1. 準備

W5500を入手します。日本国内で格安で扱っているところはあまりなさそうだったのでAliexpressで注文しました。1個$3.82。送料無料でも送ってくれますが、トラッキングができないのと配送期間も長くなる傾向があるので、商品価格よりも高くなりますが、$3~$5支払ってトラッキングと配送期間を短縮できるようにしました。 (今回は注文から12日程度で到着)

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モジュールのピン配置

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

3. コード

以下のコードをArduinoに書き込みます。Arduinoの標準サンプルコードの[ファイル] > [スケッチ例] > [Ethernet] > [UDPSendReceiveString]を参考にしています。

ArduinoEthernetライブラリの詳細はこちらから確認することができます。

Arduino - Ethernet

#include <Ethernet.h>
#include <EthernetUdp.h>

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

unsigned int localPort = 1337;

char packetBuffer[UDP_TX_PACKET_MAX_SIZE];
char ReplyBuffer[] = "acknowledged";

EthernetUDP Udp;

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

  // 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());
  
  Udp.begin(localPort);
}

void loop() {
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i=0; i < 4; i++) {
      Serial.print(remote[i], DEC);
      if (i < 3) {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    Serial.print("Contents: ");
    Serial.println(packetBuffer);

    // send a reply to the IP address and port that sent us the packet we received
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(ReplyBuffer);
    Udp.endPacket();
  }
  delay(10);
}

MACアドレスIPアドレスは環境に合わせて変更してください。

4. 実行

シリアルモニタでログを確認します。通信相手はNode.jsを使うと簡単に用意することができます。正常に動作していれば、ログに受信したメッセージと相手先に"acknowledged"を送信していることが確認できます。

5. 参考リンク

http://nopnop2002.webcrow.jp/Arduino_Networking/Network-2.html