見出し画像

Wifiモジュールを使って天気予報ランプを作ってみた話 その2

こんにちは!

今回は前回に引き続き、自作した天気予報ランプについて書いていきます。システムの全体像やサーバーサイドのプログラムについては前回書いたので、今回はハードウェア側の電子回路設計やマイコンのプログラムについて解説していきます。

前回の記事はこちら↓


RBG LED

今回のシステムでは、天気の予報と降水確率をもとに、ランプを特定の色に光らせる必要があるので、RGB LEDを用います。最近流行りのゲーミングPCなどでよく使われているのと原理的には同じものですね。今回の場合、例えば「晴れ」のときは黄色に光らせるとか、降水確率が高くなるとより強い青を光らせるとか、そういった用途に使います。

今回実際に用いた製品がこちら。PL9823-F5という型番のRGB LEDで一個あたり40円という安価なやつですね。中にマイコンが仕込まれていて、適切な信号を送り込んでやることで特定の色に光らせられるという仕組みのようです。

色の制御などは、Arduino用のadafruit_neopixelというライブラリを使って行うことができます。↓のサイト様なんかも参考にしつつ、コードは組んでいった感じですね。この手の機器は必ずしも公式ドキュメントがわかりやすく整備されているわけではないので、こういった先人の知恵は非常に頼りになります(そして、やっている内容が非常に興味深いw)。

こちらのRGB LEDを、以前紹介したesp8266というWifiモジュール付きのマイコンに接続します。Wifiモジュールと組み合わせることにより、サーバーから無線で色情報を取得し、実際にRGB LEDを特定の色に光らせるというシステムが組めるというわけです。


電子回路設計

今回の電子回路は以下のような形です。

画像1

左の方の部分が5Vの入力電圧をesp8266の入力用に3.3Vに変換するレギュレータ部分、真ん中がメイン基盤となるesp8266本体、そして右側が今回利用したRGB LEDという構成です。esp8266の配線関係がちょっとややこしいですが、LED周りの配線はかなりシンプルですね。電源とグラウンドと入力信号のみという非常にわかりやすい構成です。

実際に作った基盤はこんな感じ。

画像2

画像3

相変わらず配線・はんだ付けのクオリティは。。。な感じですw

また、今回の実装では電源供給は100均で買ったUSBケーブルを途中で切って自作しています。当初は電池での駆動も考えたのですが、消費電力が想像よりも多くてあまり長時間使えそうになかったので諦めました。USB経由だと、コンセントから気軽に5VDCが取れるので、まあこれはこれで良いかなと。どうせ室内で使うものですしね。

あと、今回は特にケース等は作成していません。深い理由があるわけではないのですが、単純につくるのがちょっとめんどくさくなってしまっただけですw こういうときは3Dプリンターがちょっと欲しくなってしまいますねw まあ、気が向いたら作ってみたいとは思います!

ちなみに最終形はこんな感じ。

画像4

右のランプが天気予報、左のランプが降水確率を示しています。細かい色の設定は前回のphpのコードを読んでいただければいいと思いますが、天気については主に「晴れ」だと黄色、「くもり」だと灰色、「雨」だと青に光ります。また、降水確率は基本青で、降水確率によって青の明るさがましていくような感じです。


esp8266プログラムコード

そして、マイコン側のプログラムコードはこちら。先に紹介したqiitaの記事のコードを結構な部分参考にしています。

#include <Adafruit_NeoPixel.h>
#include <ESP8266WiFi.h>
#include <string.h>
#define LEDPIN 14
#define NUMLED 2

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMLED, LEDPIN, NEO_RGB + NEO_KHZ800);
const char* ssid     = "{ssid}";
const char* password = "{password}";
const char* host = "192.168.179.11";
const long interval = 3600*1000*24;
long lasttime;
int flug = 0;

typedef struct {
 int r;
 int g;
 int b;
} RGB;

RGB rgb_hex2dec(String hexstr){
 RGB rgb;
 long val = strtol(&hexstr[1], NULL, 16);
 rgb.r = (int) (val >> 16 & 0xff);
 rgb.g = (int) (val >> 8 & 0xff);
 rgb.b = (int) (val & 0xff);
 return rgb;
}

void setLED(RGB rgb1, RGB rgb2) {
 strip.setPixelColor(0, strip.Color(rgb1.r, rgb1.g, rgb1.b));
 strip.setPixelColor(1, strip.Color(rgb2.r, rgb2.g, rgb2.b));
 strip.show();
}

void setup() {
 // Setting LED
 strip.begin();
 strip.setBrightness(10);
 setLED(rgb_hex2dec("#000000"), rgb_hex2dec("#000000"));
 
 // Setting Wifi
 Serial.begin(9600);
 delay(1000);
 
 // We start by connecting to a WiFi network
 Serial.println("");
 Serial.print("Connecting to ");
 Serial.println(ssid);
 WiFi.begin(ssid, password);
 
 while (WiFi.status() != WL_CONNECTED) {
   delay(500);
   Serial.print(".");
 }
 
 Serial.println("");
 Serial.println("Connected");
 lasttime = millis() - interval;
 
 delay(1000);
}

void loop() {

 long starttime = millis();
 if (starttime-lasttime > interval){
 
   while(flug==0){
     Serial.print("connecting to ");
     Serial.println(host);
     
     // Use WiFiClient class to create TCP connections
     WiFiClient client;
     const int httpPort = 80;
     if (!client.connect(host, httpPort)) {
       Serial.println("connection failed");
       return;
     }
     
     String url = "/tenki_php/index.php";
     Serial.print("Requesting URL: ");
     Serial.println(url);

     // This will send the request to the server
     client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                  "Host: " + host + "\r\n" +
                  "Connection: close\r\n\r\n");
     delay(60000);
     
     char buf[512];
     String rain;
     String weather;
     
     while(client.available()){
       String line = client.readString();
       Serial.print(line);
       line.toCharArray(buf,512);
       if(strstr(buf,"data") != NULL){
         rain = strtok(buf,",");
         rain = strtok(NULL,",");
         rain = strtok(NULL,",");
         weather = strtok(NULL,",");
       }
     }

     if(rain == "" & weather == ""){
       flug = 0;
       delay(10000);
     } else {
       Serial.print("rain:");
       Serial.println(rain);
       Serial.print("weather:");
       Serial.println(weather);
       RGB rain_RGB = rgb_hex2dec(rain);
       RGB weather_RGB = rgb_hex2dec(weather);
       setLED(rain_RGB,weather_RGB);
       flug = 1;
     }
   }
 lasttime = starttime;
 }
}

やや長めなコードですが、やっている事自体は比較的単純です。一定周期でサーバーにあるphpプログラムにアクセスして天気情報と降水確率を表示する色情報(RGBコード)取得して、それをRGB LEDに送り込むという感じ。

一応、データ取得周期は24時間としていますが、基板側のリセットスイッチを押せばいつでもデータを取得できるので、だいたい朝起きたら、トイレに行く途中にあるこのボタンを押すみたいな運用になっていますねw 基板側の時間精度がそこまで良いわけではないので、完全に自動化するのではなく、手動が入るような運用でも特に問題ないかなと。



まとめと感想

前回から今回にかけて、天気予報をお知らせするランプの自作について書いて来ました。意外とシンプルに実装できたなというのが正直な感想で、どちらかというと実装自体というよりもどういう構成にするかを考えるのに時間がかかった印象です。

前に作った自作コントローラーはなかなか使いみちがなくて持て余しているのが現状ですがw、こちらの天気予報ランプは日常的に使えて非常に良いです!僕はここ数年は全くテレビをつけておらず、天気予報にはかなり鈍感になっていたので、こういう形で認識できる方法を用意できたのは大きいですね。地味ながらも結構役に立ってくれている感じです。

こんな感じで、自作したものというのはなかなか愛着もわくので、これからも色々と作っていきたいところですね!

それでは、また!

この記事が気に入ったらサポートをしてみませんか?