🤖

W6300-EVB-PICO2でWifiClient-W6300.inoを動作する話

に公開

はじめに

ネットワーク接続を利用するプロジェクトを実行する場合、展示を想定して、有線でネットワークを作製するように心がけています。
RP2040やRP2350を使う場合、Ethernetチップを搭載したボードをWIZnetが作製しています。

https://wiznet.io/

このボードのAdruinoIDEでの利用方法が公開されています。

https://maker.wiznet.io/mason/projects/how-to-build-w6300-evb-pico-or-w6300-evb-pico2-on-arduino/

私の環境では、上手く動きませんでした。
そこで、公開されているArduino用スケッチを修正して、W6300チップを搭載するボードのW6300-EVB-PICO2をインターネットに接続しましたので、報告します。

W6300-EVB-PICO2

W6300を搭載したボードには、RP2040とRP2350を搭載したものがあります。
今回使用したボードの仕様は以下のホームページで公開されています。

https://docs.wiznet.io/Product/Chip/Ethernet/W6300/w6300-evb-pico2

主な特徴

  • Raspberry Pi Pico2クローン
  • Ethernet (W6300 Hardwired TCP/IP CHIP)
    W6300はQSPIで接続されており、最高90MBPSで通信可能なようです。

Arduinoのスケッチの修正箇所

W6300-EVB-PICO2の使用例がWIZnetから「WifiClient-W6300.ino」から公開されています。

https://maker.wiznet.io/mason/projects/how-to-build-w6300-evb-pico-or-w6300-evb-pico2-on-arduino/

公開情報に従って環境構築したのですが、私の環境ではインターネット接続ができませんでした。
Copilotを使って、公開されているスケッチを修正しました。

  1. W6300のCSピン指定をボード配線に合わせて修正

    • 変更前:Wiznet6300lwIP eth(1 /* chip select */);
    • 変更後:Wiznet6300lwIP eth(16);
      理由:W6300‑EVB‑Pico/Pico2はGPIO16がCSに固定配線です。1のままだとチップを認識できません。
  2. 標準SPIピン設定と SPI.begin() を削除

    • 変更前:SPI.setRX/CS/SCK/TX によるピン割り当てと標準SPI初期化
    • 変更後:削除
      理由:このボードではPIOベースのQSPIドライバがライブラリ側で固定ピン(CS=16, SCK=17, IO0..IO3=18..21)を使用します。標準SPI設定は不要かつ混乱の元。
  3. 起動メッセージの調整(任意)

    • 変更前:Starting Ethernet port
    • 変更後:Starting Ethernet (W6300 via QSPI)
      理由:環境を明示し、ログ解析しやすく。
  4. DHCP待ちにタイムアウトを追加

    • 変更前:while (!eth.connected()) { ... }(無限待ち)
    • 変更後:10秒タイムアウトを追加。タイムアウト時は警告を出しつつ続行。
      理由:ケーブル未接続やDHCP不調時にスケッチが止まらないように。
  5. 受信待ちでの切断検知とタイムアウト強化

    • 変更前:while (client.available() == 0) { if (millis()-timeout > 5000) { ... } }
    • 変更後:上記に加えて !client.connected() を検知して即終了。
      理由:QOTDサーバは送信後すぐ切断することがあり、その場合に無駄待ちしない。
  6. アクセス頻度制御のロジック見直し

    • 変更前:常に wait を真にし、以降5分待ち(失敗時も5分待つ場合あり)
    • 変更後:成功時のみ wait を真にし、2回目以降は5分間隔。失敗時は短めに再試行。
      理由:先方のサービスに負荷をかけない配慮を維持しつつ、失敗時のリカバリを早める。

動作の実際

シリアルモニタに出力されます。
名言を取ってきて表示するプログラムです。

Starting Ethernet (W6300 via QSPI)
  version = 0x61
  MAC RAW mode!
  .......
  Ethernet connected, IP: 192.168.8.215
  connecting to djxmmx.net:17
  sending data to server
  Server closed connection.
  connecting to djxmmx.net:17
  sending data to server
  Server closed connection.
  connecting to djxmmx.net:17
  sending data to server
  receiving from remote server
  "When a stupid man is doing something he is ashamed of, he always declares
   that it is his duty." George Bernard Shaw (1856-1950)
  closing connection
  connecting to djxmmx.net:17
  sending data to server
  receiving from remote server
  "We want a few mad people now. See where the sane ones have landed us!"
   George Bernard Shaw (1856-1950)
  closing connection

おわりに

W6300-EVB-PICOをインターネットに接続することができました。
ポイントは以下の点のようです。
「Wiznet6300lwIP eth(16);」でW6300の初期化を行います。

  • Wiznet6300lwIPオブジェクトをethという名前で作成しています。
  • 引数に 16 を渡すことで、「W6300チップのチップセレクト(CS)は GP16
    に接続されています」とライブラリに伝えています

おまけ

公開されているinoファイルに対するパッチです。
参考にしてください。

```diff
--- WiFiClient-W6300.ino	2025-12-13 11:35:00
+++ WiFiClient-W6300.ino	2025-12-13 11:36:00
@@ -1,56 +1,75 @@
 /*
- This sketch establishes a TCP connection to a "quote of the day" service.
- It sends a "hello" message, and then prints received data.
+  W6300-EVB-Pico (QSPI connection): Connect to QOTD (TCP/17) and read a line.
+  - W6300 QSPI pins are hard-wired on the board (GPIO16–21). No standard SPI pin setup is needed.
+  - Arduino-Pico lwIP_w6300 uses a PIO-based QSPI driver with fixed pins.
 */
-#include <W6300lwIP.h>
-const char* host = "djxmmx.net";
-const uint16_t port = 17;
-Wiznet6300lwIP eth(1 /* chip select */);
+#include <W6300lwIP.h>
+const char*   host = "djxmmx.net";
+const uint16_t port = 17;
+// W6300 driver (chip select is hard-wired to GPIO16 on the board)
+Wiznet6300lwIP eth(16);
 
 void setup() {
-  // Set up SPI pinout to match your HW
-  SPI.setRX(0);
-  SPI.setCS(1);
-  SPI.setSCK(2);
-  SPI.setTX(3);
   Serial.begin(115200);
-  delay(5000);
+  delay(1000);
   Serial.println();
-  Serial.println();
-  Serial.println("Starting Ethernet port");
+  Serial.println("Starting Ethernet (W6300 via QSPI)");
 
   // Start the Ethernet port
   if (!eth.begin()) {
     Serial.println("No wired Ethernet hardware detected. Check pinouts, wiring.");
     while (1) {
       delay(1000);
     }
   }
-  while (!eth.connected()) {
-    Serial.print(".");
-    delay(500);
-  }
-  Serial.println("");
-  Serial.println("Ethernet connected");
-  Serial.println("IP address: ");
-  Serial.println(eth.localIP());
+  // Wait for DHCP (10-second timeout)
+  unsigned long t0 = millis();
+  while (!eth.connected()) {
+    if (millis() - t0 > 10000) {
+      Serial.println("Ethernet DHCP timeout. Check cable/DHCP server.");
+      break;
+    }
+    Serial.print(".");
+    delay(500);
+  }
+  Serial.println();
+  Serial.print("Ethernet connected, IP: ");
+  Serial.println(eth.localIP());
 }
 
 void loop() {
-  static bool wait = false;
+  static bool wait = false;
+  bool success = false;
   Serial.print("connecting to ");
   Serial.print(host);
   Serial.print(':');
   Serial.println(port);
   // Use WiFiClient class to create TCP connections
   WiFiClient client;
   if (!client.connect(host, port)) {
     Serial.println("connection failed");
     delay(5000);
     return;
   }
   // This will send a string to the server
   Serial.println("sending data to server");
   if (client.connected()) {
     client.println("hello from RP2040");
   }
   // wait for data to be available
   unsigned long timeout = millis();
-  while (client.available() == 0) {
-    if (millis() - timeout > 5000) {
+  while (client.available() == 0) {
+    // disconnect detection
+    if (!client.connected()) {
+      Serial.println("Server closed connection.");
+      client.stop();
+      return;
+    }
+    // timeout after 5s
+    if (millis() - timeout > 5000) {
       Serial.println(">>> Client Timeout !");
       client.stop();
-      delay(60000);
+      if (wait) delay(60000);
       return;
     }
   }
   // Read all the lines of the reply from server and print them to Serial
   Serial.println("receiving from remote server");
   // not testing 'client.connected()' since we do not need to send data here
   while (client.available()) {
     char ch = static_cast<char>(client.read());
     Serial.print(ch);
   }
   // Close the connection
   Serial.println();
   Serial.println("closing connection");
   client.stop();
-  if (wait) {
-    delay(300000); // execute once every 5 minutes, don't flood remote service
-  }
-  wait = true;
+  // mark success
+  success = true;
+  // throttle: after the first successful run, access once every 5 minutes
+  if (success) {
+    if (wait) delay(300000);
+    wait = true;
+  } else {
+    delay(5000); // Short retry interval on failure
+  }
 }
```

Discussion