芝刈りーー今年第8回目

先週の今日,8回目の芝刈りをしました。本当は,今日,9回目の芝刈りをしようと思いましたが,雨がちら
ちらしているので,断念。二日ほど雨が降りそうで,火曜になりそうです。ちょっと,伸びすぎるかな。
芝刈りの前や,最中に適宜草取りをしています。カタバミは,大分少なくなってきましたが,名前の分からな
い草が,はびこるようになってます。

カタバミのように爆発的に増えることはないようですが,芝刈りをしてしまうと,芝と見分けが付きにくくな
ります。種が飛んでくるのか,結構生えてます。
芝は,芝刈り後が,かなり,はっきりするようになりました。

IOT再びーESP32編(8)ーESP32へ移植完了ーA0221AT(防水超音波センサー)+SSD1306OLE

あれこれ手こずりましたが,ESP32への移植完了しました。おまけに,手元にあったSSD1306OLEを
ディスプレイにくわえました。当初,BLEも加えようかと思いましたが,BLEをいれるとメモリーが足りな
なるので断念。ESP32への接続は次のようにしました。

 SSD1306OLE  SCL→→→→GPIO22
         SDA→→→→GPIO21
 A0221AT    RX(コネクター3)→→→→GPIO17
         TX(コネクター4)→→→→GPIO16
 LED       赤(WIFY接続 OFF)→→→→GPIO2
         緑(WIFY接続 ON)→→→→GPIO4

ESP32をブレッドボードで使うに当たって,通常の使い方では,端子が使えなくなってしまうので,秋月電子
から購入したブレッドボード BB-01P を二つ組み合わせて使ってます。
OLEは,I2Cのものですが,表示をいれると,通信に時間がかかるのか,WEB に反映されるのに,タイムラ
グがあるようです。実際の運用には,外した方がいいかもですね。

下記が今回使ったスケッチです,といっても,諸兄のものをちょっと改変しただけす。また,WEB用のhtml
ファイルは,ESP32編(3) のものを使ってます。本当は,WEB に距離を反映させたかったのですが,
javascript が手強くて,そのままにしてあります。

// 必要なライブラリのインクルード
#include <wifi.h> 
#include <spi.hamp>
#include <webserver.h>
#include <spiffs.h>
#include <adafruit_gfx.h>
#include <adafruit_ssd1306.h>


byte hdr, data_h, data_l, chksum;
String inputString = "";
float distance=0;
float new_distance=0;
float val=0.00f;

// ピンの定義
#define wifyOn 4 // wify 接続OK
#define wifyOff 2 // wify 未接続

//OLE
#define OLED_RESET     -1 
#define SCREEN_ADDRESS 0x3C //< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// WiFi接続情報(固定IP)
const char* ssid = "*************";
const char* password = "**********";
const IPAddress ip(192, 168, 2, 30);
const IPAddress gateway(192, 168, 2, 2);
const IPAddress subnet(255, 255, 255, 0);
const IPAddress dns1(192, 168, 2, 2);


// WebServerオブジェクトの初期化
WebServer server(80);

// セットアップ関数
void setup() {

  Serial.begin(115200); // シリアル通信の開始
  Serial2.begin(9600,SERIAL_8N1,16,17);

//OLE開始
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }

  display.display();
  delay(2000); // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();

 //OLE初期設定
  display.setTextSize(2);             // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.print(F("wify-set"));
  display.display(); 

  pinMode(wifyOn, OUTPUT);
  pinMode(wifyOff, OUTPUT);

  digitalWrite(wifyOn, LOW);
  digitalWrite(wifyOff, HIGH);
  
   // SPIFFSの初期化
  if(!SPIFFS.begin(true)){
    Serial.println("SPIFFSのマウントに失敗しました");
    return;
  }

  // WiFi接続
  if (!WiFi.config(ip,gateway,subnet,dns1)){
      Serial.println("Failed to configure!");
  }
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
  }

  digitalWrite(wifyOn, HIGH);
  digitalWrite(wifyOff, LOW);

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // Webサーバーのルート設定
  server.on("/", HTTP_GET, []() {
    server.send(200, "text/html", SPIFFS.open("/index.html", "r").readString());
  });

  // '/distance'で距離を返す設定
  server.on("/distance", HTTP_GET, []() {
    server.send(200, "text/plain", String(measureDistance()));
  });

  server.begin(); // サーバーの開始
}

// メインループ
void loop() {
  server.handleClient(); // クライアントのリクエストを処理
}

// 距離測定関数
float measureDistance() {
  char m[50];
   Serial2.write("S");
  if (Serial2.available())
  {
    hdr = (byte)Serial2.read();
    if (hdr == 255){
      data_h = (byte)Serial2.read();
      data_l = (byte)Serial2.read();
      chksum = (byte)Serial2.read();

      if (chksum == ((hdr + data_h + data_l)&0x00FF)){
        distance = data_h * 256 + data_l;

        //if(distance!=new_distance){
          display.clearDisplay();
          new_distance=distance;
          dtostrf(new_distance, 6, 1, m);
          Serial.print(m);
          Serial.println(" mm");
          display.setCursor(0, 0);
          display.println("distance= ");
          display.print(m);
          display.println(" mm");
          display.display(); 
         // delay(100);
          //return new_distance;
        //}      
      }
    }
  }
   delay(100); 
  return distance;
 
}

IOT再びーーーESP32編(7)ーーーESP32への移植-A0221AT

A0221ATのセンサーを ESP32 用に移植していました。何度書き換えても,思ったようにうごきませんでし
た。でもある HP の記載を見て,スケッチを変更したらやっと動きました。
いろんな方の HP で,シリアル通信(UART)にデフォルトで使えるピンの説明がありその通りにしていた
のですが,動きませんでした。「デフォルト」ということで,何もしなくてもいいのかと思っていました。
ある方のHPのように

 Serial2.begin(9600);→→→→→→Serial2.begin(9600,SERIAL_8N1,16,17);

のように,使うピンを明示してやっと動作しました。

不要な部分を取り除いて,esp32に移植しとりあえず動くようにしたスケッチです。

 

byte hdr, data_h, data_l, chksum;
unsigned int distance;

void setup() {
  // initialize both serial ports:
  Serial.begin(9600);
  Serial2.begin(9600,SERIAL_8N1,16,17);
}

void loop() {
 Serial2.write("1");
  if (Serial2.available())
  {
    hdr = (byte)Serial2.read();
    if (hdr == 255){
      data_h = (byte)Serial2.read();
      data_l = (byte)Serial2.read();
      chksum = (byte)Serial2.read();

      if (chksum == ((hdr + data_h + data_l)&0x00FF)){
        distance = data_h * 256 + data_l;
        Serial.print(distance, DEC);
        Serial.println(" mm");
      }
    }
  }
  delay(100); 
}

はっきりしませんが,メジャーで,だいたいの距離をとりながら,測定させています。手で持っているので,
数字が安定しませんが,ほぼほぼ正確な距離をだしています。
始め,
センサーが天井をむいていたので,2000とかの数字ですが,
なおしてから10cm-20cm-30cmと10cm刻みでうごかしています。

IOT再びーーーESP32編(6)ーーー部品調達(防水 超音波センサー)-A0221AT

〇zonより,

超音波距離センサー、UART 制御距離検出器 3 ~ 450cm 低電力設計距離センサー、
IP67 防水設計 DC 3.3V ~ 5V ロボット用超音波距離検出器

を購入しました。たまたま,データシートをみつけ,GitHubにもサンプルのスケッチがのっていたので大丈夫
だろうと思っての購入でした。
取り合えず,arduino UNO で動かしてから,esp32に移植しようかと思いましたが,初期段階で,はまり
ました。何回やっても,シリアルポートが二つ開けないのです。結局勘違いでした。

    Srial.available()

の関数ですが,ポートが有効かどうかの判断の関数かと思いましたが,書き込みがあったかどうかの判定の
関数でした。どうりで,ポートが有効にならないはずです。

おまけに,届いた品物は,A0221AT というものですが,この型番のものは,測定を開始するのに,RX ピ
ンを一時ハイにしてやらないとだめなようで,GitHub のスケッチには,この部分が抜けていて,うごきませ
んでしたが,試しに,

  ss.write(“s”);(”S”を書き込みましたが,なんでもいみたいです)

を書き込んでやると無事うごきはじめました。

ちなみに,この防水センサーには,入出力の違いで,いくつか種類があるようで,UART 出力のものもに二種
類あるようでした。多分〇zonのものは,オートではないものなのかな,と思いました。
アリエクスプレスでは,きちんと,選択できるようになってます。

下記が,arduino UNO のスケッチで,loop(){ の次に,ss.write(“s”);を加筆してます。

/**
 * 
 * Author: Ritesh Talreja, Made in China, Warehouse: Shenzhen, Guangdong.
 * 
 * Components: Arduino UNO, DYPA02YYUM  v1.0
 * 
 * Arduino UNO +5V    --> DYPA02YYUM Pin 1 Red
 * Arduino UNO GND    --> DYPA02YYUM Pin 2 Black
 * Arduino UNO Pin 11 --> DYPA02YYUM Pin 3 or Floating
 * Arduino UNO Pin 10 --> DYPA02YYUM Pin 4
 * 
 * Since Arduino UNO does not have 2 hardware serial ports.
 * We are using 1 software serial port connected to the sensor.
 * All data from software serial port is copied onto hardware serial port to view in "Arduino IDE Serial Monitor".
 */

#include <SoftwareSerial.h>

SoftwareSerial ss (10, 11);   // RX, TX

byte hdr, data_h, data_l, chksum;
unsigned int distance;

void setup()
{
  Serial.begin(9600);
  while (!Serial);

  ss.begin(9600);
}

void loop()
{
  ss.write("s");
  if (ss.available())
  {
    hdr = (byte)ss.read();
    if (hdr == 255)
    {
      data_h = (byte)ss.read();
      data_l = (byte)ss.read();
      chksum = (byte)ss.read();

      if (chksum == ((hdr + data_h + data_l)&0x00FF))
      {
        Serial.print(hdr);
        Serial.print(",");
        Serial.print(data_h);
        Serial.print(",");
        Serial.print(data_l);
        Serial.print(",");
        Serial.print(chksum);
        
        Serial.print("=");
      
        Serial.print(hdr, HEX);
        Serial.print(",");
        Serial.print(data_h, HEX);
        Serial.print(",");
        Serial.print(data_l, HEX);
        Serial.print(",");
        Serial.print(chksum, HEX);
        Serial.print(" => ");
  
        distance = data_h * 256 + data_l;
        Serial.print(distance, HEX);
        Serial.print("=");
        Serial.print(distance, DEC);
        Serial.println(" mm");
      }
    }
  }
  delay(100);
}

写真が動かしたときの距離の様子です。結構正確に測定できてるようです。

久しぶりに UNO 引っ張りだしてきましたが,無事うごきました。

次は,esp32への移植ですが,レベルシフターをかまさないとでめでしょうかね。

「らくらく液体肥料素プレイヤーAQUA+」の改造

過日,「らくらく液体肥料素プレイヤーAQUA+」を〇zonより購入。

早速,肥料をまくべく,調合していざ使用となりましたが,テスト段階で,水漏れがひどくて,一時断念。
初回の使用でこれでから,欠陥かなと思いました。返品もかんがえましたが,パッケージ等,処分してあり
ますので,断念。
早速,分解してみて,原因を確認。すぐに判明しました。調合ユニットとON/OFFユニットは,Oリング二つで
接合してあり,ON/OFFユニットで,OFFにすると,ON/OFFユニットが調合ユニットの流入口に栓をする形で
流量をストップしますんが,このとき,調合ユニットが押されて,Oリングが見えるようになってしまい,
ここから水漏れするようです。動かないようにすればいいのですが,接合部分をホットボンドでつけたり,
接着剤で付けたりして使用してみましたが,だめでした。
写真のように,黄色矢印二つのユニットが,赤矢印の部分で,差し込んである構造です。

あれこれ考えましたが,手元にあった太めの熱収縮チューブで覆ってみました。ビンゴでした。
うまく,接合したようで,これで,一時的には水漏れがなくなりました。もちろん,欠陥品ですので,メーカ
ーには即クレームの書き込みをしました。便利なだけに残念ですON/OFFを使うと水漏れ再開します。

===その後===
何度かメーカーとやりとりをしました。
結局,代替え品を送ってもらえるということで,
本日,代替え品がとどきました。
メーカーの対応はすこぶるいいかと思います。
結局はメーカーというより担当者でしょうか。

IOT再びーーーESP32編(5)ーーー部品調達

アリエクスプレスから,部品の調達です。〇Zonでは,かなりするのに,ありでは,格安です。でも,届く
のが1ヶ月後ぐらいです。

注文時は,送料込みで,252円でしたが,今日みたら,657円になってました。まとめて買えばよかった。
ちなみに〇ZONでは,700円から2500円ぐらいと幅があります。

IOT再びーーーESP32編(4)

苦労しましたが,思った動作をさせることができました。
ESP32編(3)の諸兄の,超音波センサーで距離を測る関数を,書き換えました。

// 距離測定関数
float measureDistance() {
 digitalWrite(trigPin, LOW);
 delayMicroseconds(2);
 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10);
 digitalWrite(trigPin, LOW);
 long duration = pulseIn(echoPin, HIGH);
 float distance = (duration * 0.0343) / 2;*/
 return distance;
}

この関数を

float measureDistance() {
 while (Serial.available()) {
   char inChar = (char)Serial.read();
   inputString += inChar;
   if (inChar == '\n') {
     distance=inputString.toFloat();
     inputString="";
     return distance;
   }
 }
 return distance;
}

のように変更して,動かしてみました。本来,センサーが受け持つ部分を,シリアルコンソールからの手動入
力に変えての動作確認です。
動画の右側のシリアルコンソールから,2→→4→→6→→8→→10 と入力を繰り返してます。入力に応じて,
iphoneのドーナツグラフが変化してくれます。
これで,第一段階の難関がクリアーです。

投稿日: 2024年7月3日 IOT再びーーーESP32編(3)ーSPIFFS不可

前掲の諸兄のスケッチ眺めてみましたが,ハンドラーの部分の記述と,html の javascript の部分がいま
いちわかりません。youtbe をあれこれ検索していましたら,別の諸兄の記事がめにとまりました。この諸兄の
スケッチなら,私用に改変できそうです。諸兄は,超音波を使ってますが,超音波だと,タンクに穴を開ける
必要がある気がしますので,超音波は使わないで当初の予定のように水位センサーを使ってやります。
ひとまず,諸兄のプログラムのオリジナルをインストールしてみます。

 

ところが,ところが,インストールに必要な,プラグインをIDEに取り込めません。一日,あれこれやりまし
たがやっとできました。
原因は,arduino IDE のバージョンで,使っていたV2.**ではだめで,v1.**で,やっとできました。
これが,分かるのに丸一日,インストールしていたarduino IDE 関係のフォルダーも全削除して,何回か
インストール,つかれました。
おかげで,やっと,下記の諸兄のスケッチをesp32に書き込み,テストできました。

// 必要なライブラリのインクルード
#include <WiFi.h>
#include <WebServer.h>
#include <SPIFFS.h>

// ピンの定義
#define trigPin 5 // 超音波センサのトリガーピン
#define echoPin 18 // 超音波センサのエコーピン

// WiFi接続情報
const char* ssid = "Your SSID";
const char* password = "Your Password";

// WebServerオブジェクトの初期化
WebServer server(80);

// セットアップ関数
void setup() {
  Serial.begin(115200); // シリアル通信の開始
  pinMode(trigPin, OUTPUT); // トリガーピンを出力として設定
  pinMode(echoPin, INPUT); // エコーピンを入力として設定

  // SPIFFSの初期化
  if(!SPIFFS.begin(true)){
    Serial.println("SPIFFSのマウントに失敗しました");
    return;
  }

  // WiFi接続
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected");
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  // Webサーバーのルート設定
  server.on("/", HTTP_GET, []() {
    server.send(200, "text/html", SPIFFS.open("/index.html", "r").readString());
  });

  // '/distance'で距離を返す設定
  server.on("/distance", HTTP_GET, []() {
    server.send(200, "text/plain", String(measureDistance()));
  });

  server.begin(); // サーバーの開始
}

// メインループ
void loop() {
  server.handleClient(); // クライアントのリクエストを処理
}

// 距離測定関数
float measureDistance() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  long duration = pulseIn(echoPin, HIGH);
  float distance = (duration * 0.0343) / 2;
  return distance;
}

 

スケッチは簡単ですが,HP掲載用のhtmlとjavascritpがやっかいのようですが,これもあまり手を加えずに済みそうです。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>水位計</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://code.highcharts.com/highcharts.js"></script>
    <script src="https://code.highcharts.com/highcharts-more.js"></script>
    <script src="https://code.highcharts.com/modules/solid-gauge.js"></script>
    <style>
        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            font-family: Arial, sans-serif;
            font-size: 20px;
        }
        #container {
            width: 90%;
            height: 50%;
        }
        .settings {
            display: flex;
            justify-content: center;
            align-items: center;
            margin-bottom: 20px;
        }
        .settings > div {
            margin: 0 10px;
        }
        .alert {
            display: none;
            color: red;
            text-align: center;
            position: absolute;
            width: 100%;
            bottom: 10%;
        }
        #title {
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 50px;
        }
    </style>
</head>
<body>
    <div id="title">Water Level monitoring</div>
    <div class="settings">
        
        <div>
            <label for="minDistance">0% Distance (cm): </label>
            <input type="number" id="minDistance" value="2">
        </div>
        <div>
            <label for="maxDistance">100% Distance (cm): </label>
            <input type="number" id="maxDistance" value="15">
        </div>
    </div>
    <div id="container"></div>
    <div id="alert" class="alert">Alert: The value is below 20%</div>

    
    <script>
        var minDistance = parseFloat(document.getElementById('minDistance').value);
        var maxDistance = parseFloat(document.getElementById('maxDistance').value);

        document.getElementById('minDistance').addEventListener('change', function() {
            minDistance = parseFloat(this.value);
            updateChart();
        });

        document.getElementById('maxDistance').addEventListener('change', function() {
            maxDistance = parseFloat(this.value);
            updateChart();
        });


        // Highchartsのゲージオプション設定
        var gaugeOptions = {
            chart: {
                type: 'solidgauge',
            },
            title: null,
            pane: {
                startAngle: -120,
                endAngle: 120,
                background: {
                    backgroundColor: '#EEE',
                    innerRadius: '60%',
                    outerRadius: '100%',
                    shape: 'arc'
                }
            },
            tooltip: {
                enabled: false
            },
            yAxis: {
                stops: [
                    [0.1, '#DF5353'], // 高い値で青系
                    [0.5, '#DDDF0D'], // 中間値で黄色
                    [0.9, '#55BF3B']  // 低い値で赤系
                ],
                lineWidth: 0,
                minorTickInterval: null,
                tickAmount: 2,
                min: 0,
                max: 100,
                title: null,
                labels: {
                    y: 16
                }
            },
            credits: {
                enabled: false
            },
            series: [{
                name: 'Distance',
                data: [100], // 初期値
                dataLabels: {
                    format: '<div style="text-align:center"><span style="font-size:30px">{y}%</span></div>'
                }
            }]
        };

        // Highchartsのゲージを作成
        var chart = Highcharts.chart('container', Highcharts.merge(gaugeOptions, {
            series: [{
                data: [100] // シリーズにも初期値をセット
            }]
        }));

        // ゲージの値を更新する関数
        function updateGauge(value) {
            // minDistanceとmaxDistanceを使用して値を計算
            var newVal = ((maxDistance - value) / (maxDistance - minDistance)) * 100;
            
            // newValが0未満の場合は0に、100を超える場合は100に制限する
            newVal = Math.max(0, Math.min(newVal, 100));    
            newVal = Math.round(newVal); // 小数点以下を四捨五入して整数に
            chart.series[0].points[0].update(newVal);

            // 値が20以下の場合、アラートを表示
            if (newVal <= 20) {
                document.getElementById('alert').style.display = 'block';
            } else {
                document.getElementById('alert').style.display = 'none';
            }
        }

        // ESP32からデータを取得してゲージを更新する
        // HTML内のJavaScriptの一部
        // HTML内のJavaScriptの一部
        setInterval(function () {
            fetch('/distance')
                .then(response => response.text())
                .then(distance => {
                var dist = parseFloat(distance);
                updateGauge(dist); // ゲージを更新する関数に距離データを渡す
                })
                .catch(function (error) {
                console.error('Error fetching distance:', error);
                });
        }, 1000); // 1秒ごとに更新
    </script>
</body>
</html>

この諸兄のいいところは,スケッチにhtmlの部分を含めるのではなく,htmlは別途esp32にアップロードでき
るところでしょうか。そのため,デバックのために,htmlを抜き出す必要もなく,htmlをそのままデバックで
きます。

IOT再びーーーESP32編(2)

前回,とりあえず,諸兄のスケッチ動かしみました。
このスケッチのhtml部分を書き換え,下記ようにして,スケッチの方で,それぞれのLの帯を順次消していけ
ば,目的を達成できるかなと考えました。

ただ,これでは,問題があるようで,サーバー側で,新しい情報をクライアントの方に送っても,クライア
ント側で更新を行わないと,画面が新しくならないみたいなので,このままでは,つかえないかなとおもい
ました。

いろいろあさってると,「非同期処理」が必要だとのHPを見つけました。これを改変すれば,目的が達成でき
そうな気がしてきました。
このHPのスケッチをDLして,自分の環境に合わせて,動かしてみました。温度センサーは以前買った,
Sensor Kit for Aruduinoというセット

に入ってた物をつかいました。
写真の下にあるのが,写真のものを動かしている諸兄のHPにあった,スケッチです。
もっともここよりも諸兄のHPに全文がのっていますので,そちらからDLした方がいいでし
ょうか。


/*
 * File:      WiFiMeasureAsync.ino
 * Function:  計測デバイスを非同期Webサーバーにして、クライアント画面に計測値を更新表示
 *            させる。
 * Date:      2020/02/12
 * Author:    M.Ono
 * 
 * Hardware   MCU:  ESP32 (DOIT ESP32 DEVKIT V1 Board)
 *            ブレッドボードに上記開発ボードと温湿度センサー、プッシュボタン、LEDを配線
 *            温湿度センサーはDHT11 
 *            ※今回はプッシュボタンとLEDは使用しない。
 */
 
#include <arduino.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <DHT.h>                    // DHTセンサー用


/* Function Prototype */
String getTemperature();
String getHumidity();
String processor(const String&);
void doInitialize();
void connectToWifi();

// ルーター接続情報
#define WIFI_SSID "aterm-e4b126-g"
#define WIFI_PASSWORD "3d259dac2f80e"

/* 基本属性定義  */
#define SPI_SPEED   115200          // SPI通信速度
#define DHTTYPE     DHT11           // DHTセンサーの型式

// Webサーバーオブジェクト
#define HTTP_PORT 80
AsyncWebServer server(HTTP_PORT);

/* DHTセンサー*/
const int DHTPin = 14;                  // DHTセンサーの接続ピン
DHT   dht(DHTPin, DHTTYPE);             // DHTクラスの生成(初期化?)

/* HTMLページ */
const char* strHtml = R"rawliteral(
 <!DOCTYPE HTML>
 <html>
 <head>
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1">
 <style>
html { font-family: Helvetica; display: inline-block; margin: 0px auto;text-align: center;}
h1 {font-size:28px;}
body {text-align: center;}
table { border-collapse: collapse; margin-left:auto; margin-right:auto;}
th { padding: 12px; background-color: #0000cd; color: white; border: solid 2px #c0c0c0;}
tr { border: solid 2px #c0c0c0; padding: 12px;}
td { border: solid 2px #c0c0c0; padding: 12px;}
.value { color:blue; font-weight: bold; padding: 1px;}
 </style>
 </head>
 <body>
 <h1>Asynchronous Server </h1>
 <p style='color:brown; font-weight: bold'>計測値は 10 秒ごとに自動更新されます! </p>
 <p> <table>
 <tr> <th>ELEMENT </th> <th>VALUE </th> </tr>
 <tr> <td>Temperature </td> <td> <span id="temperature" class="value">%TEMPERATURE%
 </span> <tr> <td>Humidity </td> <td> <span id="humidity" class="value">%HUMIDITY% </span>
 </td> </tr>
 </table> </p>
 </body>
 <script>
var getTemperature = function () {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("temperature").innerHTML = this.responseText;
}
};
xhr.open("GET", "/temperature", true);
xhr.send(null);
}
var getHumidity = function () {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("humidity").innerHTML = this.responseText;
}
};
xhr.open("GET", "/humidity", true);
xhr.send(null);
}
setInterval(getTemperature, 10000);
setInterval(getHumidity, 10000);
 </script>
 </html>)rawliteral";

/*****************************************************************************
 *                          Predetermined Sequence                           *
 *****************************************************************************/
void setup(){
    doInitialize();             // 初期化処理をして
    connectToWifi();            // Wi-Fiルーターに接続する

    // GETリクエストに対するハンドラーを登録して
    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send_P(200, "text/html", strHtml, editPlaceHolder);
    });
    server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send_P(200, "text/plain", getTemperature().c_str());
    });
    server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
        request->send_P(200, "text/plain", getHumidity().c_str());
    });
    // サーバーを開始する
    server.begin();
}
 
void loop(){
}

/* 計測処理ロジック */
String getTemperature() {
    float t = dht.readTemperature();
    if (isnan(t)) {    
        Serial.println("Failed to get temperature!");
        return "--";
    }
    else {
        Serial.println(t);
        return String(t) + " ℃";
    }
}

String getHumidity() {
    float h = dht.readHumidity();
    if (isnan(h)) {
        Serial.println("Failed to get humidity!");
        return "--";
    }
    else {
        Serial.println(h);
        return String(h) + " %";
    }
}

/* プレースホルダー処理 */
String editPlaceHolder(const String& var){
    if(var == "TEMPERATURE"){
        return getTemperature();
    }
    else if(var == "HUMIDITY"){
        return getHumidity();
    }
    return "??";
}

/* 初期化処理 */
void doInitialize() {
    Serial.begin(SPI_SPEED);
    dht.begin();                       // DHTセンサーを起動
}

/****************************< Connect functions >****************************/
/* Wi-Fiルーターに接続する */
void connectToWifi() {
    Serial.print("Connecting to Wi-Fi ");
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println("");
    // モニターにローカル IPアドレスを表示する
    Serial.println("WiFi connected.");
    Serial.print("  *IP address: ");
    Serial.println(WiFi.localIP());
    server.begin();
}

  }
}

IOT再びーーーESP32編

何年か前に,raspberry Pi を使って,スマホから,LED の制御を実験しました。

このと時は,raspberry Pi のプログラムが良く分からないところもあったので,結構手間がかかりました。
あることがやりたくで,再びIOTに挑戦することにしました。

手始めに,ESP32を使って,wify経由でのLチカです。

諸兄のスケッチをESP32に書き込み,ESP32にLEDをつけると,それほど手間がかからずにできます。
arduino・IDEのシリアル通信の画面に表示される,IPアドレスを,スマホのブラウザに打ち込むと,動画の
制御画面に入れます。
ブレッドボードには,ジャンパー線が多数見られますが,これは,前回までの作業の名残で,片付けていま
せん。


反応が鈍いようですが,多分,ルーターのためだと思います。
この,動画のスケッチをいじって,あれこれやる予定です。

/*********
  Rui Santos
  Complete project details at https://randomnerdtutorials.com  
*********/
// Load Wi-Fi library
#include <WiFi.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// Auxiliar variables to store the current output state
String output26State = "off";
String output27State = "off";
// Assign output variables to GPIO pins
const int output26 = 26;
const int output27 = 27;
// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0; 
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
void setup() {
  Serial.begin(115200);
  // Initialize the output variables as outputs
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output26, LOW);
  digitalWrite(output27, LOW);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}
void loop(){
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    currentTime = millis();
    previousTime = currentTime;
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected() && currentTime - previousTime <= timeoutTime) {  // loop while the client's connected
      currentTime = millis();
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();
            
            // turns the GPIOs on and off
            if (header.indexOf("GET /26/on") >= 0) {
              Serial.println("GPIO 26 on");
              output26State = "on";
              digitalWrite(output26, HIGH);
            } else if (header.indexOf("GET /26/off") >= 0) {
              Serial.println("GPIO 26 off");
              output26State = "off";
              digitalWrite(output26, LOW);
            } else if (header.indexOf("GET /27/on") >= 0) {
              Serial.println("GPIO 27 on");
              output27State = "on";
              digitalWrite(output27, HIGH);
            } else if (header.indexOf("GET /27/off") >= 0) {
              Serial.println("GPIO 27 off");
              output27State = "off";
              digitalWrite(output27, LOW);
            }
            
            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons 
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #4CAF50; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #555555;}</style></head>");
            
            // Web Page Heading
            client.println("<body><h1>ESP32 Web Server</h1>");
            
            // Display current state, and ON/OFF buttons for GPIO 26  
            client.println("<p>GPIO 26 - State " + output26State + "</p>");
            // If the output26State is off, it displays the ON button       
            if (output26State=="off") {
              client.println("<p><a href=\"/26/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/26/off\"><button class=\"button button2\">OFF</button></a></p>");
            } 
               
            // Display current state, and ON/OFF buttons for GPIO 27  
            client.println("<p>GPIO 27 - State " + output27State + "</p>");
            // If the output27State is off, it displays the ON button       
            if (output27State=="off") {
              client.println("<p><a href=\"/27/on\"><button class=\"button\">ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/27/off\"><button class=\"button button2\">OFF</button></a></p>");
            }
            client.println("</body></html>");
            
            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

このスケッチを改変するにあたって,これまた,丁寧に解説なさってる諸兄がいらっしゃいました。
おかげで,スケッチの構造がやっとおぼろげながら分かってきました。