ESP32でLEDの色を天気に合わせて変えてみた

ESP32でOpenWeatherMapから天気を取得→LEDの色を天気に合わせて変えてみた

こんにちは!
今回はタイトルの通り、OpenWeatherMapという天気予報APIサービスから天気を取得して、その天気によってLEDの色を変えていきます

起きたてで寝ぼけている中いちいちスマホで天気調べてられないですもんね!
LEDが青くなってれば「雨だ!」と一発で分かるので便利じゃありませんか?

上記は曇りの時の状態。今回はこんな工作をしていきます!

完成プログラムは記事の最後にあります。「とにかく動く塊のコードを知りたい!」という方は一番下までどうぞ!

必要な前提知識

本記事は以下の2記事の工作を合わせたものです。分からない点があれば以下の記事に目を通してください。

環境

回路


RGBLEDの設定

まずはRGBLEDの設定。RGBLEDの詳細は前提知識の項目からご覧ください

今回の注意点はLEDを接続するピンです。以前の記事とは繋がっているピンが異なります

ESP32のledc関数は、PWMが使用可能なAのついたポートにのみ適用可能です。上記画像でいうA0-A19までですね。
今回はA15,A16,A17(IO12,IO14,IO27)にRGBを割り当てます。

回路をセットしたら、RGBLEDを駆動する以下の関数と設定を用意します。

void RGBLED_setup(){
  //ledpin
  const int ledR = A17; //IO27
  const int ledG = A15; //IO12
  const int ledB = A16; //IO14
  //R
  ledcSetup(0, 12800, 8);  // ledRをチャネル0へ接続
  ledcAttachPin(ledR, 0);  
  ledcSetup(1, 12800, 8);  // ledGをチャネル1へ接続
  ledcAttachPin(ledG, 1);  
  ledcSetup(2, 12800, 8);  // ledBをチャネル2へ接続
  ledcAttachPin(ledB, 2);
}
void RGB(int R,int G,int B,int delay_time){
  ledcWrite(0,R);
  ledcWrite(1,G);
  ledcWrite(2,B);
  delay(delay_time);
}

RGBLEDのどのピンにR,G,Bが割り当ててあるかは製品により異なります。ご自身のピン配置を確認して適宜設定を変更しましょう。

ledcは一度設定すれば変更するまで常に出力してくれるので、1色であれば
RGB(255,0,0,0); //赤単色で点灯のようにdelayが0msでも作動します。順次点灯させたい場合にdelayの値を設定しましょう

温度に合わせて色を変えてみる

以下ではRGB関数を使って、それぞれの天気に合わせた色を作りました。

上記デモのコードはこちら

//ledpin
const int ledR = A17; //IO27
const int ledG = A15; //IO12
const int ledB = A16; //IO14

void RGB(int R,int G,int B,int delay_time){
  ledcWrite(0,R);
  ledcWrite(1,G);
  ledcWrite(2,B);
  delay(delay_time);
}

void setup() {
  //R
  ledcSetup(0, 12800, 8);
  // ledRをチャネル0へ接続
  ledcAttachPin(ledR, 0);
  //G
  ledcSetup(1, 12800, 8);
  // ledGをチャネル1へ接続
  ledcAttachPin(ledG, 1);
  //B
  ledcSetup(2, 12800, 8);
  // ledBをチャネル2へ接続
  ledcAttachPin(ledB, 2);
}

void loop(){
  RGB(100,200,0,2000); //Orange
  RGB(20,70,30,2000); //Darker white
  RGB(0,0,200,2000);  //Blue
  RGB(50,200,200,2000); //Bright white
  RGB(70,250,0,2000); //Yellow
  RGB(0,10,20,2000); //Darker Blue
  RGB(0,0,0,4000);
}

天気情報によって色を変える

天気情報をweatherに入れ、その中身の文字列を以下のように比較して色を変えます。

//天気によりLEDの色を変更
if(!strcmp(weather,"Clear")){
  RGB(100,200,0,1); //オレンジ
}else if(!strcmp(weather,"Clouds")){
  RGB(20,70,30,2000); //暗い白
}else if(!strcmp(weather,"Rain")){
  RGB(0,0,200,2000);  //青
}else if(!strcmp(weather,"Snow")){
  RGB(50,200,200,2000); //明るい白
}else if(!strcmp(weather,"Thunderstorm")){
  RGB(70,250,0,2000); //黄色
}else if(!strcmp(weather,"Drizzle")){
  RGB(0,10,20,2000);  //暗い青
}

重要なのはstrcmp関数。引数の2つの文字列を比較して、全く同じであれば0を出力します。if分のTrueに引っかからせるために!で反転してあげましょう

天気の種類はOpenWeatherMapで確認できます。上記のほかにも沢山の状態があるので、それぞれに色や機能を割り当てると面白いかもです!

プログラム(ほぼコピペで動く)

上記のコードをESP32で天気APIから天気情報を取得し、OLEDディスプレイに表示させてみたと組み合わせてLEDと連動させるのが以下の完成プログラムです。

API keyの取得はESP32でAPIを使って現在の天気を取得してみたを参考にしてください。

#include <Wire.h>
#include "SSD1306.h" 
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <stdio.h>

const char* ssid = "SSID";
const char* password =  "PASSWORD";
String WiFiMessage = "Connecting...";
const String endpoint = "http://api.openweathermap.org/data/2.5/weather?q=tokyo,jp&APPID=";
const String key = "YOURAPIKEY";

SSD1306  display(0x3c, 21, 22);
void RGBLED_setup(){
  //ledpin
  const int ledR = A17; //IO27
  const int ledG = A15; //IO12
  const int ledB = A16; //IO14
  //R
  ledcSetup(0, 12800, 8);
  // ledRをチャネル0へ接続
  ledcAttachPin(ledR, 0);
  //G
  ledcSetup(1, 12800, 8);
  // ledGをチャネル1へ接続
  ledcAttachPin(ledG, 1);
  //B
  ledcSetup(2, 12800, 8);
  // ledBをチャネル2へ接続
  ledcAttachPin(ledB, 2);
}
void RGB(int R,int G,int B,int delay_time){
  ledcWrite(0,R);
  ledcWrite(1,G);
  ledcWrite(2,B);
  delay(delay_time);
}
void setup() {
  Serial.begin(115200);
  pinMode(21, INPUT_PULLUP); //デファルトのSDAピン21 のプルアップの指定
  pinMode(22, INPUT_PULLUP); //デファルトのSDAピン22 のプルアップの指定
  display.init();//SSD1306を初期化

  RGBLED_setup();

  //LCDにWiFi接続中の情報を表示
  display.clear();
  display.setFont(ArialMT_Plain_16);
  display.drawString(20, 20, WiFiMessage);
  display.display();
  delay(2000);
  //WiFi接続
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
}

void loop() {
  if ((WiFi.status() == WL_CONNECTED)) {
 
    HTTPClient http;
 
    http.begin(endpoint + key); //URLを指定
    int httpCode = http.GET();  //GETリクエストを送信
 
    if (httpCode > 0) { //返答がある場合
 
        String payload = http.getString();  //返答(JSON形式)を取得
        Serial.println(httpCode);
        Serial.println(payload);

        //jsonオブジェクトの作成
        DynamicJsonBuffer jsonBuffer;
        String json = payload;
        JsonObject& weatherdata = jsonBuffer.parseObject(json);

        //パースが成功したかどうかを確認
        if(!weatherdata.success()){
          Serial.println("parseObject() failed");
        }

        //各データを抜き出し
        const char* weather = weatherdata["weather"][0]["main"].as<char*>();
        const double temp = weatherdata["main"]["temp"].as<double>();

        //LCDに表示
        display.clear();//画面を消去
        //天気を表示
        display.setFont(ArialMT_Plain_16);
        display.drawString(0, 0, weather);
        //気温を表示
        display.setFont(ArialMT_Plain_24);
        String temp_str = String(temp-273.15) + "°C";
        display.drawString(20,20,temp_str);
        display.display();

        //天気によりLEDの色を変更
        if(!strcmp(weather,"Clear")){
          RGB(100,200,0,1); //オレンジ
        }else if(!strcmp(weather,"Clouds")){
          RGB(20,70,30,2000); //暗い白
        }else if(!strcmp(weather,"Rain")){
          RGB(0,0,200,2000);  //青
        }else if(!strcmp(weather,"Snow")){
          RGB(50,200,200,2000); //明るい白
        }else if(!strcmp(weather,"Thunderstorm")){
          RGB(70,250,0,2000); //黄色
        }else if(!strcmp(weather,"Drizzle")){
          RGB(0,10,20,2000);  //暗い青
        }
      }
 
    else {
      Serial.println("Error on HTTP request");
    }
 
    http.end(); //Free the resources
  }
 
  delay(30000);   //30秒おきに更新
 
  }

まとめ・発展

今回は天気と連動したLEDシステムを作りました。
利用したAPIは現在の天気を返してくれるものですが、数時間後の予報や明日の天気を出してくれるものもOpenWeatherMapが提供してくれています。これを使って、寝る前に明日の天気を色で表示してくれたら準備が捗りそうですね!

ぜひ応用して、できたらtwitterで教えてくれると嬉しいです!
ご覧くださりありがとうございましたm(__)m

コメントする

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です