ラズパイpicoWを使ってリニアアンプ用操作パネルを製作し、WiFi経由でUDP通信により遠隔操作できるようしました。ここまでできると、もう一つ欲が出てきて、Webサーバー機能を付加することを検討しています。
Web上にある色んな記事を参考にして試行錯誤していましたが、これで行けそうだというシンプルな例を作ることができました。開発環境はArduino IDE 1.8です。巻末にソースコードを示しますが、既にコア0でUDPサーバーが動作しているので、SSIDやIPアドレスの設定、Web.begin処理などは重複するためCore1では省略しています。
Web上にある色んな記事を参考にして試行錯誤していましたが、これで行けそうだというシンプルな例を作ることができました。開発環境はArduino IDE 1.8です。巻末にソースコードを示しますが、既にコア0でUDPサーバーが動作しているので、SSIDやIPアドレスの設定、Web.begin処理などは重複するためCore1では省略しています。

ブラウザでボタンを操作して、ラズパイpicoWのデジタル出力をON/OFFできて、かつ1秒周期でラズパイpicoWの状態を更新します。ラズパイpicoW内蔵のLEDを使用しており、ブラウザからLEDの状態が色で確認でき、ボタンを押せばLEDの状態が反転するというものです。
最初は、この記事を参考にして実験していました。最後に、<meta http-equiv="refresh" content="1">というオマジナイを加えて1秒毎に更新されるようにしたころ、ボタンを押さないのにトグル動作するようになってしまいました。原因は、ボタンはtype="button"で、aタグが付けてあり、ボタンが押されると/Temperatureにジャンプするという構造にあると考えられます。
そこで、ボタンのタイプがsubmitの例を探していると、この記事を見つけました。
最初は、この記事を参考にして実験していました。最後に、<meta http-equiv="refresh" content="1">というオマジナイを加えて1秒毎に更新されるようにしたころ、ボタンを押さないのにトグル動作するようになってしまいました。原因は、ボタンはtype="button"で、aタグが付けてあり、ボタンが押されると/Temperatureにジャンプするという構造にあると考えられます。
そこで、ボタンのタイプがsubmitの例を探していると、この記事を見つけました。
この例ではボタンがON用とOFF用に分かれていて、かつLEDの状態が分からないので、格好悪いのでトグル動作するように改良しました。併せて、1秒毎に更新するようにしました。
最終的なサンプルプログラムのソースコードを以下に示します。
最終的なサンプルプログラムのソースコードを以下に示します。
bool core1_separate_stack = true;というのは、コア1用のスタックを別途8kB設けるというオマジナイです。String page;は、グローバル変数として宣言し、何度もヒープの割り当てを受けないようにし、setup1()の中で、page.reserve(1000);と宣言しています。これらの工夫をする前は、30分位動作させるとスタックしていましたので、効果があったようです。しかし、やはり3時間位動作させるとハングアップしてしまいました。pingにも応答しなくなりました。原因は今のところ不明です。
#include <WiFi.h>
#include <WebServer.h>
WebServer server(80);
bool core1_separate_stack = true;
String page;
String getPage(){
char msgBuf[16];
int iSS = millis() / 1000;
int iMM = iSS / 60;
int iHH = iMM / 60;
page = "<!DOCTYPE HTML>";
page += "<html>";
page += "<head>";
page += "<meta charset=\"utf-8\">";
page += "<meta http-equiv=\"refresh\" content=\"1\">";
page += "<title>button example</title>";
page += "<style>";
page += ".green{background-color: green; color: white}";
page += ".white{background-color: white; color: black}";
page += "</style>";
page += "</head>";
page += "<body style='background-color:powderblue;'>";
page += "<h2 style='color:red'>button toggle example</h2>";
page += "<br>";
page += "<br>";
page += "<FORM action=\"/\" method=\"post\">";
if(digitalRead(LED_BUILTIN) == HIGH){
page += "<button type=\"submit\" name=\"btnLED\" id=\"btnLED\" value=\"LED_OFF\" class=\"green\">LED</button>";
}else{
page += "<button type=\"submit\" name=\"btnLED\" id=\"btnLED\" value=\"LED_ON\" class=\"white\">LED</button>";
}
page += "</form>";
page += "<br>";
page +="<div><p>Uptime: ";
sprintf(msgBuf, "%02d:%02d:%02d", iHH, iMM%60, iSS%60);
String strMsg = String(msgBuf);
page += strMsg;
page +="</p></div>";
page += "<br>";
page += "</body></html>";
return page;
}
void handleNotFound(){
server.send(200, "text/html", getPage());
}
void handleSubmit(){
if (server.hasArg("btnLED")){
String btnValue = server.arg("btnLED");
Serial.print("received value is: ");
Serial.println(btnValue);
if(btnValue == "LED_ON"){
digitalWrite(LED_BUILTIN, HIGH);
}else{
digitalWrite(LED_BUILTIN, LOW);
}
}
server.send(200, "text/html", getPage());
}
void handleRoot(){
if (server.args()){
handleSubmit();
}else{
server.send(200, "text/html", getPage());
}
}
void setup1(){
delay(1000);
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN,LOW);
page.reserve(1000);
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
server.on("/", handleRoot);
server.onNotFound(handleNotFound);
server.begin();
delay(500);
digitalWrite(LED_BUILTIN,LOW);
}
void loop1(){
server.handleClient();
delay(100);
}
#include <WebServer.h>
WebServer server(80);
bool core1_separate_stack = true;
String page;
String getPage(){
char msgBuf[16];
int iSS = millis() / 1000;
int iMM = iSS / 60;
int iHH = iMM / 60;
page = "<!DOCTYPE HTML>";
page += "<html>";
page += "<head>";
page += "<meta charset=\"utf-8\">";
page += "<meta http-equiv=\"refresh\" content=\"1\">";
page += "<title>button example</title>";
page += "<style>";
page += ".green{background-color: green; color: white}";
page += ".white{background-color: white; color: black}";
page += "</style>";
page += "</head>";
page += "<body style='background-color:powderblue;'>";
page += "<h2 style='color:red'>button toggle example</h2>";
page += "<br>";
page += "<br>";
page += "<FORM action=\"/\" method=\"post\">";
if(digitalRead(LED_BUILTIN) == HIGH){
page += "<button type=\"submit\" name=\"btnLED\" id=\"btnLED\" value=\"LED_OFF\" class=\"green\">LED</button>";
}else{
page += "<button type=\"submit\" name=\"btnLED\" id=\"btnLED\" value=\"LED_ON\" class=\"white\">LED</button>";
}
page += "</form>";
page += "<br>";
page +="<div><p>Uptime: ";
sprintf(msgBuf, "%02d:%02d:%02d", iHH, iMM%60, iSS%60);
String strMsg = String(msgBuf);
page += strMsg;
page +="</p></div>";
page += "<br>";
page += "</body></html>";
return page;
}
void handleNotFound(){
server.send(200, "text/html", getPage());
}
void handleSubmit(){
if (server.hasArg("btnLED")){
String btnValue = server.arg("btnLED");
Serial.print("received value is: ");
Serial.println(btnValue);
if(btnValue == "LED_ON"){
digitalWrite(LED_BUILTIN, HIGH);
}else{
digitalWrite(LED_BUILTIN, LOW);
}
}
server.send(200, "text/html", getPage());
}
void handleRoot(){
if (server.args()){
handleSubmit();
}else{
server.send(200, "text/html", getPage());
}
}
void setup1(){
delay(1000);
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN,LOW);
page.reserve(1000);
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
server.on("/", handleRoot);
server.onNotFound(handleNotFound);
server.begin();
delay(500);
digitalWrite(LED_BUILTIN,LOW);
}
void loop1(){
server.handleClient();
delay(100);
}
WiFiWebServerというライブラリも存在するようなので、それも試してみました。先頭の3行を次のように入れ替えるとコンパイルできて、正常に起動しました。しかし、残念ながら、WebServerの場合と同様に3時間程でハングアップしました。1秒毎にアップデートしているのが原因だと思われます。長時間連続運転するような場合には困りものですが、EMEのように2時間程度の運用なら使い方によっては問題ないかもしれません。所詮趣味なので、これ以上は深入りしないことにします。
#define ARDUINO_RASPBERRY_PI_PICO_W
#include "defines.h"
WiFiWebServer server(80);
#include "defines.h"
WiFiWebServer server(80);