最終更新日:2023/2/13
WizFi360-EVB-PICOを入手しました、PicoWが入手困難だったので取り敢えずです。ただ、Wiznet製のWiFiモジュールに触れるいい機会でもありました。一緒にW5100S-EVB-Picoも入手出来たのですが、残念ながらこちらはNICがまともに動作せず、故障品として倉庫行きとなってしまいました。
Wiznetが提供するライブラリをArduinoIDEにインストールし、“WebServerLed”っているのをビルドして動作確認して見ました。
やはり、シリアルポートが認識されませんでしたので、初期化用のUF2ファイルをブートフォルダにインストールして、シリアルドライバが認識されたら、デバイスマネージャを開いて登録されたCOMポートに対し手動でドライバの更新を行いました。これでなんとかビルドしたバイナリオブジェクトを自動で転送できるようになりました。“WebServerLed”というサンプルはGETを使うようでちょっと戴けないのですが、動いて何よりでした。提供されているExampleを一つ一つ確認し、このボードの振る舞いを感じたいと思います。
このボードを使う上での注意点ですが、WIZNETのライブラリを使いWIFIモジュールを初期化する際に
SoftwareSerial Serial2(6, 7); // RX, TX WiFi.init(&Serial2);と云う点ですWizFi360との接続は6番pin(RX)7番pin(TX)のシリアル接続なのですがGPIO番号ではなく物理pin番号での設定のようです。統一性がないですね。
そしてビルドインLEDの接続先ですがGPIO25であることはメーカのサイトに情報がありました。
https://docs.wiznet.io/Product/Open-Source-Hardware/wizfi360-evb-picoまた、このサンプルを実行し、ブラウザからIPアドレスを叩いて表示した頁を見て【here】をクリックするのですが、反応は良くないです。
17:57:55.750 -> [WizFi360] Initialization successful - 1.1.1.7 17:57:55.750 -> Attempting to connect to WPA SSID: Kingsland 17:57:57.174 -> [WizFi360] Connected to Kingsland 17:57:57.174 -> You're connected to the network 17:57:58.190 -> SSID: Kingsland 17:57:58.190 -> IP Address: 192.168.0.142 17:57:58.190 -> 17:57:58.190 -> To see this page in action, open a browser to http://192.168.0.142 17:57:58.190 -> 17:57:58.190 -> [WizFi360] Server started on port 80 |
ソースを読めば判るのですが、
http://192.168.0.142/H
とアクセスすると、ビルトインLEDが緑点灯し、
http://192.168.0.142/L
とアクセスすると消灯します。
2023年2月9日: Stationモードは一般的ですので、APモード(アクセスポイントモード)は動くのか確認しました。
サンプルスケッチはちゃんと用意されており、早速ビルドしてみました。
18:14:04.379 -> [WizFi360] Initialization successful - 1.1.1.7 18:14:04.379 -> Attempting to start AP wiznet 18:14:05.599 -> [WizFi360] Access point started wiznet 18:14:05.599 -> Access point started 18:14:05.599 -> IP Address: 192.168.36.1 18:14:05.599 -> 18:14:05.599 -> To see this page in action, connect to wiznet and open a browser to http://192.168.36.1 18:14:05.599 -> 18:14:05.599 -> [WizFi360] Server started on port 80 18:14:05.599 -> Server started |
ソースコードに書かれているパスワード【0123456789】を入力したところ、接続出来ました。
IPアドレス(192.168.36.1)にブラウザからアクセスしてみました。大丈夫みたいです。※実際にはAI_0のポートが間違っていて数値は“0”のままでした。
と云う事で、もう少し凝ったHTMLを記述して挙動を確認したいと思います。
2023年2月10日: WizFi360 example: WebServerAP をレタッチしています。レタッチしたいこととして、
とりあえずのスケッチを示しておきます。
/* * 2023年2月10日 T.Wanibe * WizFi360のサンプルスケッチWebServerAPを最低限のレタッチで動作確認しました。 * 実際に動かすとアナログ入力の値が0のままですし、余りに寂しいHTMLなのでちょっとレタッチしたいと思っています。 * * WizFi360 example: WebServerAP * * アナログ入力の値を表示するシンプルな Web サーバー * WizFi360 モジュールを使用して Web ページ経由でピン留めします。 * このスケッチは、アクセス ポイントを開始し、あなたの IP アドレスを出力します。 * WizFi360 モジュールをシリアル モニタに接続します。 そこから、開くことができます * そのアドレスを Web ブラウザーに入力して、Web ページを表示します。 * Web ページは 20 秒ごとに自動的に更新されます。 * * 最大1044480バイトのフラッシュメモリのうち、スケッチが62076バイト(5%)を使っています。 * 最大262144バイトのRAMのうち、グローバル変数が7872バイト(3%)を使っていて、ローカル変数で254272バイト使うことができます。 */ #include "arduino_secrets.h" #include "WizFi360.h" // setup according to the device you use #define WIZFI360_EVB_PICO // Emulate Serial1 on pins 6/7 if not present #ifndef HAVE_HWSERIAL1 #include "SoftwareSerial.h" #if defined(ARDUINO_MEGA_2560) SoftwareSerial Serial1(6, 7); // RX, TX #elif defined(WIZFI360_EVB_PICO) SoftwareSerial Serial2(6, 7); // RX, TX #endif #endif /* Baudrate */ #define SERIAL_BAUDRATE 115200 #if defined(ARDUINO_MEGA_2560) #define SERIAL1_BAUDRATE 115200 #elif defined(WIZFI360_EVB_PICO) #define SERIAL2_BAUDRATE 115200 #endif #define HTTPPort 80 /* Wi-Fi info */ char ssid[] = SECRET_APSSID; // your network SSID (name) char pass[] = SECRET_APPASS; // your network password int status = WL_IDLE_STATUS; // the Wifi radio's status int reqCount = 0; // number of requests received WiFiServer server(HTTPPort); RingBuffer buf(8); // リングバッファを使用して速度を上げ、メモリ割り当てを減らす //---------------- void sendHttpResponse(WiFiClient client) { client.print( "HTTP/1.1 200 OK\r\n" "Content-Type: text/html\r\n" "Connection: close\r\n" // the connection will be closed after completion of the response "Refresh: 20\r\n" // refresh the page automatically every 20 sec "\r\n"); client.print("<!DOCTYPE HTML>\r\n" "<html>\r\n" "<h1>Hello World!</h1>\r\n" "Requests received: "); client.print(++reqCount); client.print("<br>\r\n" "Analog input A0: "); client.print(analogRead(0)); client.print("<br>\r\n" "</html>\r\n"); } //---------------- void printWifiStatus() { // print your WiFi shield's IP address IPAddress ip = WiFi.localIP(); Serial.print("IP Address: ");Serial.println(ip); // print where to go in the browser Serial.println(); Serial.print("To see this page in action, connect to "); Serial.print(ssid); Serial.print(" and open a browser to http://"); Serial.println(ip); Serial.println(); } //---------------- void setup() { // initialize serial for debugging Serial.begin(SERIAL_BAUDRATE); // initialize serial for WizFi360 module #if defined(ARDUINO_MEGA_2560) Serial1.begin(SERIAL1_BAUDRATE); #elif defined(WIZFI360_EVB_PICO) Serial2.begin(SERIAL2_BAUDRATE); #endif // initialize WizFi360 module #if defined(ARDUINO_MEGA_2560) WiFi.init(&Serial1); #elif defined(WIZFI360_EVB_PICO) WiFi.init(&Serial2); #endif // check for the presence of the shield if (WiFi.status() == WL_NO_SHIELD) { Serial.println("WiFi shield not present"); while (true); // don't continue } Serial.print("Attempting to start AP ");Serial.println(ssid); // uncomment these two lines if you want to set the IP address of the AP //IPAddress localIp(192, 168, 111, 111); //WiFi.configAP(localIp); // start access point status = WiFi.beginAP(ssid, 10, pass, ENC_TYPE_WPA2_PSK); Serial.println("Access point started"); printWifiStatus(); // start the web server on port 80 server.begin(); Serial.println("Server started"); } //---------------- void loop() { WiFiClient client = server.available(); // listen for incoming clients if (client) { // if you get a client, Serial.println("New client"); // print a message out the serial port buf.init(); // initialize the circular buffer while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then buf.push(c); // push it to the ring buffer // you got two newline characters in a row // that's the end of the HTTP request, so send a response if (buf.endsWith("\r\n\r\n")) { sendHttpResponse(client); break; } } } // give the web browser time to receive the data delay(10); // close the connection client.stop(); Serial.println("Client disconnected"); } } |
このサンプルスケッチを見て思った点
- WizFi360とMega2560を組み合わせたモジュールがWiznetから提供されているのかと思ったのですが、ちょっと違っていました。
https://github.com/Wiznet/WizFi360_arduino_library#using_wizfi360_evb_shield_arduino_mega_2560
亀の子接続で使えないサンプルスケッチだったようです。- そのスケッチをレタッチして#ifdefでWizFi360-EVB-PICOと切り分けする仕組みを用意していたが、AI_0の扱いでPicoのPINアサインの扱いまでは対応していなかったようでうまく動かなかったようです。Arduino-PICO環境の場合AI_0はGP26が相当するようで、analogRead(26)とすれば動く様です。
- このスケッチではhtmlのmeta refreshによるリダイレクトで20秒毎の更新をしているのですが、この手法はGoogle等で非推奨となっているかと思います。
※2023年2月13日 MQTTのサンプルスケッチがあったので動作確認しました。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MQTT(Message Queuing Telemetry Transport)は、接続が不安定な状態でもTCP/IP通信できるように軽量なプロトコルとして設計された通信規格です。
HTTPと比較されることが多いです。IO制御なんかをHTTPで実現するArduinoサンプルスケッチがあるように見た目使いやすい仕組みなのですが、やりたいことに比較して余りにコストの掛かる仕組みだとのことです。その対策としてIBMがMQTTという仕組みを構築したとのことです。
Brokerと呼ばれるサーバを介した通信となります。ルータのような存在があれば、そこにBrokerを立てれば良いことになります。上記テスト環境において、サンプルスケッチをArduinoIDEでビルドしシリアル接続したWizFi360-EVV-PICOにバイナリオブジェクトを書き込んだ上で、
WizFi360-EVV-PICOは作業環境内のWIFIに接続します。そのとき取得したIPアドレスがシリアルコンソールに表示されているので、そのIPアドレスに対して、PCのコマンドプロンプトを開き、コマンドを叩くことでMQTTの確認をするというモノです。
手順については、https://wizfi.github.io/Document/docs/basic_guides/mqtt_client に記載があるので とりあえずそれに従って【感じをつかみ取る】ことが必要なのかと思います。予めPC側にmosquitto(モスキート)ツールをインストールしておく必要があるようです。Brokerソフトと云われるもので、Windows環境では一番ポピュラーのようです。
バイナリデータはhttps://mosquitto.org/files/binary/にあります。
PCにインストール後、PCを再起動して、コンソールを立上げ、パスをmosquittoのインストールパスに変更し、コマンドmosquitto -c mosquitto.conf -p 1883 -vを実行すると、mosquittoが動作中となります。“1883”はMQTT用のポート番号です。
あとはBrokerを介して複数のクライアント間でのメッセージ通信を実行することになります。
WizFi360-EVB-PICO側からBrokerにmessageを送るには、port1883に対して接続する必要があります。そのためその環境に於けるBrokerのIPアドレスを調査した上でWizFi360-EVV-PICO側スケッチをレタッチする必要があります。
※Brokerを起動したPCのIPアドレスをスケッチに含めないといけません。スケッチをレタッチ後にビルドし直し、WizFi360-EVB-PICOに書き込んでください。
WizFi360-EVB-PICOもMQTTクライアントですから、Brokerを介してメッセージの遣り取りが出来ます。
動作確認ですが、WizFi360-EVB-PICOを起動した後にシリアルモニタを開くと以下のようなmessageを得ました。brokerに接続出来ませんでした。
15:19:38.514 -> [WizFi360] Connected to Kingsland |
理由を検討しているのですが判りません。
if (client.connect("arduino", "public", "public")){
で失敗していることが明らかなのですが、サンプルスケッチに何もコメントがなく、パラメータをどう設定するのが正解なのか?
mosquitto.exe側の情報/設定が必要な気もしているのですが、現時点では検討がつかないです。記録としてスケッチを残します。
/* * 2023年2月13日 T.Wanibe * WizFi360 example: MqttClient * このスケッチは、WizFi360 モジュールを使用してブローカーに接続し、単純なパブリッシュとサブスクライブを実行します。 * MQTTは、TCP / IPプロトコルの上で使用するための軽量メッセージングプロトコルです。“小さなコードフットプリント” * が必要であるか、ネットワーク帯域幅が限られているリモートの場所との接続用に設計されています。 * これは、ほとんどすべてのネットワークオブジェクトを 外部、それはセンサーとして使用されます。 * */ #include "Arduino_secrets.h" #include "WizFi360.h" #include "WizFi360Mqtt.h" // setup according to the device you use #define WIZFI360_EVB_PICO // Emulate Serial1 on pins 6/7 if not present #ifndef HAVE_HWSERIAL1 #include "SoftwareSerial.h" #if defined(ARDUINO_MEGA_2560) SoftwareSerial Serial1(6, 7); // RX, TX #elif defined(WIZFI360_EVB_PICO) SoftwareSerial Serial2(6, 7); // RX, TX #endif #endif /* Baudrate */ #define SERIAL_BAUDRATE 115200 #if defined(ARDUINO_MEGA_2560) #define SERIAL1_BAUDRATE 115200 #elif defined(WIZFI360_EVB_PICO) #define SERIAL2_BAUDRATE 115200 #endif /* Wi-Fi info */ char ssid[] = SECRET_SSID; // your network SSID (name) char pass[] = SECRET_PASS; // your network password int status = WL_IDLE_STATUS; // the Wifi radio's status //注: ローカル ドメイン名 (OSX の "Computer.local" など) は、Arduino ではサポートされていません。 //IP アドレスを直接設定する必要があります。 char broker[] = SECRET_BROKERIP; unsigned long lastMillis = 0; // イーサネット クライアント オブジェクトを初期化する WiFiClient net; MQTTClient client; //---------------- void printWifiStatus() { // print the SSID of the network you're attached to Serial.print("SSID: "); Serial.println(WiFi.SSID()); // print your WiFi shield's IP address IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip); // print the received signal strength long rssi = WiFi.RSSI(); Serial.print("Signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm"); } //---------------- void messageReceived(String &topic, String &payload) { Serial.println(topic + " - " + payload.length() + "," + payload); //注: コールバックでクライアントを使用してパブリッシュ、サブスクライブ、またはサブスクライブ解除しないでください。 //確認の送受信中に他のものが到着したときにデッドロックが発生する可能性があるためです。 //代わりに、グローバル変数を変更するか、キューにプッシュして `client.loop()` を呼び出した後にループ内で処理します。 } //---------------- void setup() { // initialize serial for debugging Serial.begin(SERIAL_BAUDRATE); if(!Serial){delay(1000);} // initialize serial for WizFi360 module #if defined(ARDUINO_MEGA_2560) Serial1.begin(SERIAL1_BAUDRATE); #elif defined(WIZFI360_EVB_PICO) Serial2.begin(SERIAL2_BAUDRATE); #endif // initialize WizFi360 module #if defined(ARDUINO_MEGA_2560) WiFi.init(&Serial1); #elif defined(WIZFI360_EVB_PICO) WiFi.init(&Serial2); #endif // check for the presence of the shield if (WiFi.status() == WL_NO_SHIELD) { Serial.println("WiFi shield not present"); // don't continue while (true); } // attempt to connect to WiFi network while ( status != WL_CONNECTED) { Serial.print("Attempting to connect to WPA SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network status = WiFi.begin(ssid, pass); } // you're connected now, so print out the data Serial.println("You're connected to the network"); printWifiStatus(); Serial.println(); Serial.println("Starting connection to broker..."); client.begin(broker, net); //void begin(const char _hostname[], Client &_client) //if (client.connect("arduino", "sub_client", "pub_client")){ //bool connect(const char clientID[], const char username[], const char password[], bool skip = false); if (client.connect("roger","sub_client","pub_client")){ Serial.println("Connected to broker"); client.subscribe("/world"); client.onMessage(messageReceived); }else{ Serial.println("Can't Connected to broker"); } } //---------------- void loop() { client.loop(); // publish a message roughly every second. if (millis() - lastMillis > (1000 * 10)){ // 10 seconds lastMillis = millis(); client.publish("/hello", "world"); } } |
WizFi360とRP2040はソフトウエアシリアル接続のようです。ボーレート115200bpsでは十分な通信帯域を確保出来ないようで、Werserverで大きなデータを扱おうとするとフリーズしてしまいます。ちょっと使い物にならないです。
UDPでNTPによる時刻取得をする場合も、タイマ待ちはうまくゆかないです。有線なら1000msec待てば十分だったのに、WiFiでは応答が返るまでチェックしないとなかなかうまくゆきません。
Modbusを移植してみようと思いましたが、これはそれなりに大変ですね。
免責事項
本ソフトウエアは、あなたに対して何も保証しません。本ソフトウエアの関係者(他の利用者も含む)は、あなたに対して一切責任を負いません。
あなたが、本ソフトウエアを利用(コンパイル後の再利用など全てを含む)する場合は、自己責任で行う必要があります。本ソフトウエアの著作権はToolsBoxに帰属します。
本ソフトウエアをご利用の結果生じた損害について、ToolsBoxは一切責任を負いません。
ToolsBoxはコンテンツとして提供する全ての文章、画像等について、内容の合法性・正確性・安全性等、において最善の注意をし、作成していますが、保証するものではありません。
ToolsBoxはリンクをしている外部サイトについては、何ら保証しません。
ToolsBoxは事前の予告無く、本ソフトウエアの開発・提供を中止する可能性があります。
商標・登録商標
Microsoft、Windows、WindowsNTは米国Microsoft Corporationの米国およびその他の国における登録商標です。
Windows Vista、Windows XPは、米国Microsoft Corporation.の商品名称です。
LabVIEW、National Instruments、NI、ni.comはNational Instrumentsの登録商標です。
I2Cは、NXP Semiconductors社の登録商標です。
その他の企業名ならびに製品名は、それぞれの会社の商標もしくは登録商標です。
すべての商標および登録商標は、それぞれの所有者に帰属します。