04.ATOM Liteで降水確率のLED表示


04.ATOM Liteで降水確率のLED表示

降水確率をLEDの色表示します。Wi-Fi接続をして、気象庁の降水確率を06-12時 → 12-18時 → 18-24時で今日 → 明日 → 明後日の順にLEDで色表示します。10%ごとの降水確率の表示色は、抵抗のカラーコード表示色とし、100%は90%同じとしました。
0%→黒(消灯), 10%→茶, 20%→赤, 30%→橙, 40%→黄,
50%→緑, 60%→青, 70%→紫, 80%→灰, 90%→白, 100%→白
赤は降水確率20%

必要ハード

・ATOM Lite

ライブラリのインストール

Arduino-IDE > スケッチ > ライブラリをインクルード > ライブラリを管理... > "json" で検索

ArduinoJson by Benoit Blanchon 6.19.4 をインストール > 閉じる
(Arduino_JSON by Arduino 0.1.0ではありません)

ArduinoJsonの解説
https://arduinojson.org/v6/doc/

XMLファイル

降水確率は一定時間内(ここでは6H)に1mm以上の雨or雪の降る確率で、四捨五入して10%単位で表現しています。
気象庁の天気予報
 https://www.jma.go.jp/bosai/forecast/
の内容をXMLとJSONP形式で配信してくれているJapan Weather Forecast xml(日本お天気予報)
 https://www.drk7.jp/weather/
のサービスを利用します。
神奈川県の実際に使用するのはjsonファイル
https://www.drk7.jp/weather/json/14.js
ですが、ここでは見やすいXMLファイル
https://www.drk7.jp/weather/xml/14.xml
を参考にします。

・東部(横浜地方気象台)
今日から6日先までの7日間の天気・天気マーク(gif)・9-18時の日中の最高気温(℃)・0-9時の朝の最低気温(℃)・降水確率。今日と明日はさらに、詳細天気・波の高さ(m)も。

・西部(小田原観測所)
東部と同じ項目。ただし、明後日~6日先は横浜と同じデータです。

ある日の14.xmlを、一部見やすいように字下げ・改行・省略・注釈をつけると以下になります。

<weatherforecast>
  <title>weather forecast xml</title>
  <link>http://www.drk7.jp/weather/xml/14.xml</link>
  <description>気象庁の天気予報情報を XML で配信。1日1回 AM 6:00 ごろ更新。</description>
  <pubDate>Sat, 20 Aug 2022 06:00:01 +0900</pubDate>
  <author>気象庁</author>
  <managingEditor>drk7.jp</managingEditor>
  <pref id="神奈川県">
    <area id="東部"> ← 横浜
      <geo><long/><lat/></geo>
      <info date="2022/08/20"> ← 今日
        <weather>曇</weather> ← 天気
        <img>http://www.drk7.jp/MT/images/MTWeather/200.gif</img> ← 天気マーク
        <weather_detail>くもり 所により 夕方 から 雨</weather_detail> ← 詳細天気
        <wave>1メートル</wave> ← 波高
        <temperature unit="摂氏">
          <range centigrade="max">31</range> ← 最高温度
          <range centigrade="min">23</range> ← 最低温度
        </temperature>
        <rainfallchance unit="%">
          <period hour="00-06">10</period> ← 0-6時の降水確率
          <period hour="06-12">10</period>
          <period hour="12-18">20</period>
          <period hour="18-24">30</period>
        </rainfallchance>
      </info>

      <info date="2022/08/21"> ← 明日
        <weather>曇一時雨</weather>
        <img>http://www.drk7.jp/MT/images/MTWeather/202.gif</img>
        <weather_detail>くもり 明け方 から 朝 雨</weather_detail>
        <wave>1メートル</wave>
        <temperature unit="摂氏">
          <range centigrade="max">29</range>
          <range centigrade="min">24</range>
        </temperature>
        <rainfallchance unit="%">
          <period hour="00-06">60</period>
          <period hour="06-12">60</period>
          <period hour="12-18">20</period>
          <period hour="18-24">20</period>
        </rainfallchance>
      </info>

      <info date="2022/08/22"> ← 明後日
        <weather>曇時々晴</weather>
        <img>http://www.drk7.jp/MT/images/MTWeather/201.gif</img>
        <temperature unit="摂氏">
          <range centigrade="max">30</range>
          <range centigrade="min">24</range>
        </temperature>
        <rainfallchance unit="%">
          <period hour="00-06">30</period>
          <period hour="06-12">30</period>
          <period hour="12-18">30</period>
          <period hour="18-24">30</period>
        </rainfallchance>
      </info>

      <info date="2022/08/23"> ← 3日先
        <weather>晴時々曇</weather>
          ・・・ 略 ・・・
      </info>
      <info date="2022/08/24"> ← 4日先
        <weather>曇時々晴</weather>
          ・・・ 略 ・・・
      </info>
      <info date="2022/08/25"> ← 5日先
      <weather>曇一時雨</weather>
          ・・・ 略 ・・・
      </info>
      <info date="2022/08/26"> ← 6日先
        <weather>曇一時雨</weather>
          ・・・ 略 ・・・
      </info>
    </area>
    <area id="西部"> ← 小田原
      ・・・ 略 ・・・
    </area>
  </pref>
</weatherforecast>
その時の気象庁の表示
* 1時間に1mm以上の雨が降ると、普通に傘が必要です。降水確率30%以上は外出時傘を持った方が良いらしいです。

解説

気象庁 神奈川県の天気予報
https://www.jma.go.jp/bosai/forecast/#area_type=offices&area_code=140000

表示内容

色表示は、0-6時の降水確率表示は省略し、
1.今日の06-12時の降水確率
2.今日の12-18時
3.今日の18-24時
4.明日の06-12時
5.明日の12-18時
6.明日の18-24時
7.明後日(7-9は同じ値です)
8.明後日
9.明後日
の順です。

日付

今日は1回、明日は2回、明後日は3回、確率表示の前に短く白色が点灯します。

色表示

降水確率と変更した表示色
00%→黒 0x000000 or 消灯
10%→茶 0x100000 暗い赤800000では赤いので
20%→赤 0xFF0000
30%→橙 0xFF610F 橙EF810Fでは黄色っぽいので
40%→黄 0xFFFF00
50%→緑 0x008000
60%→青 0x0000FF
70%→紫 0x400080 紫800080では赤っぽいので
80%→灰 0x0F0F0F 暗い白808080では明るいので
90%&100%→白 0xFFFFFF

注意

drk7.jpでは、朝6時頃にデータを更新しているので、深夜1時に見ると今日の降水確率は、明日の降水確率表示の部分です。
また、気象庁は毎日5時、11時、17時、天気が急変したときには随時修正して発表しているので、朝6時以降に更新された場合は、気象庁のデータと異なる場合があります。

スケッチ

**********の2件は、接続Wi-FiのSSIDとパスワードです。

// ATOM Liteで今日と明日と明後日の06-12,12-18,18-24時の降水確率9件を色表示
// 気象庁の天気予報をJson型式に変換してくれるdrk7.jpを利用 (drk7.jpの更新は毎朝6時頃)
// 変換サイト https://www.drk7.jp/weather/
// 気象庁の天気予報(横浜市) https://www.jma.go.jp/bosai/forecast/#area_type=class20s&area_code=1410000
#include <WiFi.h>        // wifi使用
#include <HTTPClient.h>  // HTTPClientを使用
#include <ArduinoJson.h> // json使用
#include <M5Atom.h>      // Atom使用
const char* ssid     = "**********";  // wifiのSSID
const char* password = "**********";  // そのパスワード
const char* endpoint = "https://www.drk7.jp/weather/json/14.js";//神奈川県
const char* region   = "東部";                  // 横浜地方気象台
// 関東1都6県は
// 東京都→"・・・/13.js", 東京地方(東京), 伊豆諸島北部, 伊豆諸島南部, 小笠原諸島
//神奈川県→"・・・/14.js",東部(横浜), 西部(小田原)
// 埼玉県→"・・・/11.js", 北部(熊谷), 南部(さいたま), 秩父地方
// 千葉県→"・・・/12.js", 北東部(銚子), 北西部(千葉), 南部(館山)
// 茨城県→"・・・/08.js", 北部(水戸), 南部(土浦)
// 栃木県→"・・・/09.js", 北部(大田原), 南部(宇都宮)
// 群馬県→"・・・/10.js", 北部(みなかみ), 南部(前橋)
DynamicJsonDocument weatherInfo(20000);   //

String createJson(String jsonString) {    // JSONPをJSONにする関数
  jsonString.replace("drk7jpweather.callback(", "");       //
  return jsonString.substring(0, jsonString.length() - 2); //
}

DynamicJsonDocument getJson() {           //
  DynamicJsonDocument doc(20000);         //
  if ((WiFi.status() == WL_CONNECTED)) {  // wifiが接続されていたら
    HTTPClient http;                      // 定義
    http.begin(endpoint);                 //
    int httpCode = http.GET();            // 登録URLに、GETリクエスト送信
    if (httpCode > 0) {                   // HTTPのリターンコードにエラーがなければ
      String jsonString = createJson(http.getString());//jsonオブジェクト作成関数
      deserializeJson(doc, jsonString); //JSON文字列をCFML(構造体や配列など)に変換
    } else {
      Serial.println("HTTP要求エラー");   // シリアルモニタに表示
    }
    http.end();                         // リソースを解放
  }
  return doc;                           //
}

void lighting(String rain) {               // LED1回点灯関数
  int intrain = rain.toInt();              // 文字を数値に変換
  switch (intrain) {
    case 0:
      M5.dis.drawpix(0, 0x000000); break;  // 黒
    case 10:
      M5.dis.drawpix(0, 0x100000); break;  // 茶(暗い赤)800000では赤い
    case 20:
      M5.dis.drawpix(0, 0xFF0000); break;  // 赤
    case 30:
      M5.dis.drawpix(0, 0xFF610F); break;  // 橙EF810Fでは黄色っぽい
    case 40:
      M5.dis.drawpix(0, 0xFFFF00); break;  // 黄
    case 50:
      M5.dis.drawpix(0, 0x008000); break;  // 緑
    case 60:
      M5.dis.drawpix(0, 0x0000FF); break;  // 青
    case 70:
      M5.dis.drawpix(0, 0x400080); break;  // 紫800080では赤紫っぽい
    case 80:
      M5.dis.drawpix(0, 0x0F0F0F); break;  // 灰(暗い白)808080では明るい
    default:
      M5.dis.drawpix(0, 0xFFFFFF); break;  // 白
  }
  delay(1000);                             // 1秒点灯
  M5.dis.drawpix(0, 0x000000);             // 黒
  delay(200);                              // 0.2秒消灯
}

void drawWeather(String infoWeather) {  // 1日分のデータ表示関数
  DynamicJsonDocument doc(20000);       //
  deserializeJson(doc, infoWeather);    //
  String docdate = doc["date"];         // 予報年月日
  Serial.print("(");  Serial.print(docdate); //シリアルモニタに表示
  Serial.print("):");                   // シリアルモニタに表示
  String weather = doc["weather"];      // 天気予報
  Serial.println(weather);              // シリアルモニタに表示
  String weatherdetail = doc["weather_detail"]; // 詳しい天気予報
  if (weatherdetail != "null") {        // 明後日以外の時
    Serial.println(weatherdetail);      // シリアルモニタに表示
  }
  String docwave = doc["wave"];         // 波の高さ
  if (docwave != "null") {              // 明後日以外の時
    Serial.print("波:");
    Serial.println(docwave);            // シリアルモニタに表示
  }
  String maxTmp = doc["temperature"]["range"][0]["content"];
  //                      温度          範囲   最高    値
  String minTmp = doc["temperature"]["range"][1]["content"];
  //                      温度         範囲    最低    値
  String rain0006 = doc["rainfallchance"]["period"][0]["content"];
  //                         降水確率          期間  00-06   値
  String rain0612 = doc["rainfallchance"]["period"][1]["content"]; // 06-12
  String rain1218 = doc["rainfallchance"]["period"][2]["content"]; // 12-18
  String rain1824 = doc["rainfallchance"]["period"][3]["content"]; // 18-24
  Serial.print(maxTmp); Serial.print("℃max, ");  // 最高気温を表示
  Serial.print(minTmp); Serial.println("℃min");  // 最低気温を表示
  Serial.printf("降水確率(0-6:%3s%%,)6-12:%3s%%, 12-18:%3s%%, 18-24:%3s%%\n",
                rain0006, rain0612, rain1218, rain1824);  // 降水確率
  lighting(rain0612);                      // 06-12時の降水確率を色で点灯
  lighting(rain1218);                      // 12-18時の降水確率を色で点灯
  lighting(rain1824);                      // 18-24時の降水確率を色で点灯
  Serial.println();                        // 改行
}

void setup() {
  M5.begin(true, false, true);  //(LCD,PowerEnable=true,Serial)
  delay(50);                               // 50mS待つ
  Serial.begin(115200);                    // Upload Speed=15200にする
  WiFi.begin(ssid, password);              // Wi-Fi設定を初期化
  Serial.println("");                      // 改行
  Serial.println("Wi-Fiに接続中です。");     // シリアルモニタに表示
  while (WiFi.status() != WL_CONNECTED) {  // 接続状態が接続完でない時
    delay(500);                            // 0.5S待つ
    Serial.print(".");                     // シリアルモニタに表示
    Serial.print(WiFi.status());           // Wi-Fiの状態数表示
    // 0:WL_IDLE_STATUS     WiFi.begin()が呼び出され
    //                      下記3か4になるまでの一時的状態
    // 1:WL_NO_SSID_AVAIL   使用可能なSSIDがない
    // 2:WL_SCAN_COMPLETED  スキャンネットワークが完了
    // 3:WL_CONNECTED       WiFiに接続が確立
    // 4:WL_CONNECT_FAILED  すべての試行で接続失敗
    // 5:WL_CONNECTION_LOST 接続が失われた
    // 6:WL_DISCONNECTED    ネットワークから切断
    // 255:WL_NO_SHIELD     WiFiシールドが存在しない
  }                                        // 接続完の時
  Serial.println("");                      // シリアルモニタで改行
  Serial.println("Wi-Fiに接続しました。");    // シリアルモニタに表示
  Serial.print("IPアドレス:");              // シリアルモニタに表示
  Serial.println(WiFi.localIP());          // WiFiのIPアドレスを表示
  weatherInfo = getJson();                 // 関数実行
  WiFi.disconnect(true);                   // Wi-Fi機能のみがoff
}

void loop() {
  String day0 = weatherInfo["pref"]["area"][region]["info"][0];
  //                          県     東部    領域     情報   今日
  String day1 = weatherInfo["pref"]["area"][region]["info"][1]; // 明日
  String day2 = weatherInfo["pref"]["area"][region]["info"][2]; // 明後日
  M5.dis.drawpix(0, 0xFFFFFF); delay(100);   // 白0.1秒点灯
  M5.dis.drawpix(0, 0x000000); delay(200);   // 黒0.2秒消灯
  delay(700);                                // 0.7秒待つ
  Serial.print("今日"); drawWeather(day0);    // データ表示関数 今日
  delay(500);                                // 0.7秒待つ
  for (int i = 0; i <= 2; i++) {             // 2回
    M5.dis.drawpix(0, 0xFFFFFF); delay(100); // 白0.1秒点灯
    M5.dis.drawpix(0, 0x000000); delay(200); // 黒0.2秒消灯
  }
  delay(700);                                // 0.7秒待つ
  Serial.print("明日"); drawWeather(day1);    // データ表示関数 明日
  delay(500);                                // 0.5秒待つ
  for (int i = 0; i <= 3; i++) {             // 3回
    M5.dis.drawpix(0, 0xFFFFFF); delay(100); // 0.1秒点灯
    M5.dis.drawpix(0, 0x000000); delay(200); // 黒0.2秒消灯
  }
  delay(700);                                // 0.7秒待つ
  Serial.print("明後日"); drawWeather(day2);  // データ表示関数 明後日
  delay(3000);                               // 3秒待つ

  /*LED 色test
    M5.dis.drawpix(0, 0x000000);  // 黒
    delay(2000);
    M5.dis.drawpix(0, 0x100000);  // 茶(暗い赤)800000では赤い
    delay(2000);
    M5.dis.drawpix(0, 0xFF0000);  // 赤
    delay(2000);
    M5.dis.drawpix(0, 0xFF610F);  // 橙EF810Fでは黄色っぽい
    delay(2000);
    M5.dis.drawpix(0, 0xFFFF00);  // 黄
    delay(2000);
    M5.dis.drawpix(0, 0x008000);  // 緑
    delay(2000);
    M5.dis.drawpix(0, 0x0000FF);  // 青
    delay(2000);
    M5.dis.drawpix(0, 0x400080);  // 紫800080では赤紫っぽい
    delay(2000);
    M5.dis.drawpix(0, 0x0F0F0F);  // 灰(暗い白)808080では明るい
    delay(2000);
    M5.dis.drawpix(0, 0xFFFFFF);  // 白
    delay(2000);
  */
}
* フラッシュメモリ(1.3Mbyte)を、スケッチが65%使用。RAM(327kbyte)は、グローバル変数が12%使用、ローカル変数で286kbyte使用可能。(1000byte=1kbyteで計算)