Arduinoの覚書

自分の備忘録です。Arduino以外もあります。

ATOM Lite 4.降水確率のLED表示


降水確率をLED表示します。Wi-Fi接続をして、気象庁の降水確率を06-12時 → 12-18時 → 18-24時で今日 → 明日 → 明後日の順にLEDで色表示します。降水確率は、40~100%→青色、30%→白色、20%→黄色、10%→赤色、0%→緑色です。

必要なもの

  • ATOM Lite
  • USB電源
  • USBケーブル

説明

Wi-Fiは、2.4GHzのb(11Mbps),g(54Mbps),n(300Mbps)のみ接続可能です。(ATOM Lite仕様より)
スケッチ内に接続Wi-FiSSIDとパスワードを記入しておきます。

降水確率は一定時間内(ここでは6H)に1mm以上の雨or雪の降る確率で、四捨五入して10%単位で表現しています。気象庁の天気予報
 https://www.jma.go.jp/jp/yoho/320.html (横浜地方気象台)
を使用します。実際は、気象庁の天気予報情報をXMLで配信とJSONP形式で配信してくれているdrk7.jp
 https://www.drk7.jp/weather/
のサービスを利用します。

XMLファイルで、ある日ある場所の1日分(実際は7日分)を抜出し、字下げをすると以下が得られます。


<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>Thu, 26 Nov 2020 06:00:03 +0900</pubDate>
  <author>気象庁</author>
  <managingEditor>drk7.jp</managingEditor>
  <pref id="神奈川県">
    <area id="東部">
      <geo>
        <long>139.5479</long>
        <lat>35.5142</lat>
      </geo>
      <info date="2020/11/26">
        <weather>くもり時々晴れ</weather>
        <img>http://www.drk7.jp/MT/images/MTWeather/201.gif</img>
        <weather_detail>北の風 日中 東の風 くもり 朝 から 昼過ぎ 晴れ 所により 夜遅く 雨</weather_detail>
        <wave>波 1メートル</wave>
        <temperature unit="摂氏">
          <range centigrade="max">17</range>
          <range centigrade="min">10</range>
        </temperature>
        <rainfallchance unit="%">
          <period hour="00-06">0</period>
          <period hour="06-12">10</period>
          <period hour="12-18">10</period>
          <period hour="18-24">30</period>
        </rainfallchance>
      </info>
    </area>
  </pref>
</weatherforecast>

 * 1時間に1mm以上の雨が降ると、普通に傘が必要です。降水確率30%以上は外出時傘を持った方が良いらしい。

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

Arduino IDE > スケッチ > ライブラリをインクルード > ライブラリを管理にて
ArduinoJson by Benoit Blanchon 6.17.0を検索してインストール > 閉じる
(Arduino_JSON by Arduino 0.1.0ではない)

動作

検証と書込みに1分半程度かかります。 書き込み終了後にUSBケーブルをPCからUSB電池に切り替えても同じ動作をします。表示は、今日の06-12時の降水確率、12-18時、18-24時、明日の06-12時、12-18時、18-24時、明後日の06-12時、12-18時、18-24時の順です。40%以上が青色、10%ずつ下がって白黄赤、0%が緑です。シリアルモニタにはそれ以外に詳しいデータも表示されます。

注意 朝6時頃にデータを更新しているので、深夜1時に今日のLED表示を見ると、実際は昨日の降水確率です。

スケッチ


// ATOM Liteで降水確率色表示
// 接続できるWi-Fiは2.4GHzのb(11Mbps),g(54Mbps),n(300Mbps)のみ
// 気象庁の天気予報をJson型式に変換してくれるdrk7.jpを利用
// drk7.jpの更新は毎朝6時頃
// 今日と明日と明後日の06-12,12-18,18-24時の降水確率9件を色表示
// LEDの色は、緑(0%), 赤(10%), 黄(20%), 白(30%), 青(40~100%)とする
// 起動時に1回点灯
// 気象庁の天気予報 https://www.jma.go.jp/jp/yoho/320.html
// 変換サイト https://www.drk7.jp/weather/
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "M5Atom.h"
const char* ssid     = "xxxxxxxxxxxxxxx";  // SSID 文字列ポインタ
const char* password = "xxxxxxxx";         // PW
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)) {  // 
    HTTPClient http;                      // 
    http.begin(endpoint);                 // 
    int httpCode = http.GET();            // 
    if (httpCode > 0) {                   // 
      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();     // 文字を数値に変換
    Serial.println(intrain);        // シリアルモニタに表示
    if (intrain >= 40){             // 降水確率40~100%時
      M5.dis.drawpix(0, 0x0000ff);  // 青点灯
    } else if (intrain >= 30) {     // 30%時
      M5.dis.drawpix(0, 0xffffff);  // 白点灯
    } else if (intrain >= 20) {     // 20%時
      M5.dis.drawpix(0, 0xffff00);  // 黄点灯
    } else if (intrain >= 10) {     // 10%時
      M5.dis.drawpix(0, 0x00ff00);  // 赤点灯
    }else {                         // 0%時
      M5.dis.drawpix(0, 0x800000);  // 緑点灯
    }
  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"];  // 詳しい天気予報
  Serial.println(weatherdetail);     // シリアルモニタに表示
  String docwave = doc["wave"];      // 波の高さ
  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("気温(℃):"); Serial.print(maxTmp); // 最高気温を表示
  Serial.print("max,");                        // シリアルモニタに表示
  Serial.print(minTmp); Serial.println("min"); // 最低気温を表示
  Serial.printf("降水確率±3H:3時%3s,9時%3s,15時%3s,21時%3s", rain0006, rain0612, rain1218, rain1824);//降水確率
  Serial.println("%");                       // シリアルモニタに表示
  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
  String day0 = weatherInfo["pref"]["area"][region]["info"][0];
  //                          県     東部    領域     情報   今日
  String day1 = weatherInfo["pref"]["area"][region]["info"][1];  // 明日
  String day2 = weatherInfo["pref"]["area"][region]["info"][2];  // 明後日
  Serial.print("今日");   drawWeather(day0); // 今日のデータ表示関数
  delay(500);  // 0.5秒待つ
  Serial.print("明日");   drawWeather(day1); // 明日のデータ表示関数
  delay(500);  // 0.5秒待つ
  Serial.print("明後日"); drawWeather(day2); // 明後日のデータ表示関数
}

void loop() {
}




以上