All Articles

お天気ランプを作りました【Arduino, Processing】

先日、光でお天気を表現するランプを作ったので、その作品の紹介と技術的なメモをします。

コード全文は下にあります。

作ったもの

作品の名前はお天気ランプです。

DSC 1529 1024x576

毎日、インターネットからお天気情報を取得して、それを光の色で表現します。

晴だったら赤、雨だったら青、曇りだったら緑といった感じです。

写真を撮った時は晴時々曇だったので、晴の赤と曇りの緑が混ざった色に光っています。

玄関のライトをこれにしておけば、今日傘がいるかどうかくらいは直感的に分かるので便利かと思います。

技術的メモ

コードはProcessingで書いて実行しています。Arduinoにはシリアル通信でLEDの光り方の信号を送っています。

ArduinoとProcessingの連携方法はこちらにあります。

ArduinoとProcessingでIoTクッションを作りました

今回、初の試みとしてインターネットからProcessingでお天気情報を取得してみました。

情報が少なくて大変だったので、それをメインに以下に書きます。

お天気情報はLivedoorWeather Hacksから取得しています。json形式で毎日、基本的なお天気情報を配信しています。無料かつコール制限がないため一番使いやすいかと思い、採用しました。これの利用は非営利に限るみたいです。

http://weather.livedoor.com/weather_hacks/webservice

先ほどjson形式で配布されいていると書きましが、これが使えるとデータの処理において非常に便利みたいです。

jsonの定義はこのようにされています。

JSONとはJavaScript Object Notationの略で、XMLなどと同様のテキストベースのデータフォーマットです。(https://thinkit.co.jp/article/70/1)

情報群を綺麗にインデントして整理するためのフォーマットです。書いてあること自体はプログラムでもなんでもなく、ただメモ帳に書いてあるテキストの様なものです。

これはjson形式で取得したお天気データの一部です。(こちらより引用)

54b428bdddae12585a804b9b018a89b5

こんな感じで”forecasts”の中に”telop”等が入っていることが分かります。ちなみに引用元サイトを見てもらえれば分かりますが、サイトを開いただけでは綺麗にフォーマットされていないので、「JSONきれい〜JSON整形ツール〜」を使いました。

実際のProcessingでのjson形式のデータの取得方法はこんな感じです。

[highlight_java]String baseURL = “http://weather.livedoor.com/forecast/webservice/json/v1?city=”;
String city = “都市の割り当てられた番号 ex)神奈川県→140010”;
JSONArray forecasts;
String telop;
String title;[/highlight_java]

これらを宣言します。

[highlight_java]JSONObject w = loadJSONObject(baseURL + city);
title = w.getString(“title”);
forecasts = w.getJSONArray(“forecasts”);

JSONObject f = forecasts.getJSONObject(0);
telop = f.getString(“telop”);[/highlight_java]

次にこれらを実行します。

階層がより深いもの(telop)を取得する時は.getJSONArray()や.getJSONObject()を使って、階層を掘っています。

String型で文字列を取得する時は、.getString(“”)を使います。

今回は取得した文字列を比較することで、色の変化の条件分岐しました。

毎回、Javaを使うときに忘れてしまうので自戒を込めて…

Javaで、参照型のString変数を「==」で比較できない!「.equals(“”)」を使う!!

→参考

取得した文字情報をProcessingで扱うときにひとつ注意があります。

おそらく文字コードの違いでconsole上では文字化けします。文字として結果を見たい時は、Processingのwindow内で描画すると読むことができます。

おわりに

今回で、json形式で格納されている情報を処理できるようになりました。これにより、より多くの情報を活用できそうです。

今回作った作品は、有線通信をします。今後、無線通信ができるようになればより綺麗に作品として完成させられると思います。

次回以降はESPと呼ばれるモジュールを使っての無線接続形式の作品を作りたいと思います。あと、できればGASと連携させてよりスタンドアローン感のあるものにしたいです。

以下は参考サイトです。

shangtian’s blog

いつも隣にITのお仕事

qiita

最後に今回の作品のコード全文です。

[highlight_java]import cc.arduino.*;
import org.firmata.*;
import cc.arduino.*; //ArduinoLibrary
import processing.serial.*;

String arduinoPort = “/dev/cu.usbserial-“;
Arduino arduino;

String baseURL = “http://weather.livedoor.com/forecast/webservice/json/v1?city=”;
String city = “140010”;
JSONArray forecasts;
String telop;
String title;

//時間管理
float playTime;
float elapsedTime = 0;

int brightness = 10; // how bright the LED is
int fadeAmount = 7; // how many points to fade the LED by

int redLED = 9;
int blueLED = 10;
int greenLED = 11;

void setup(){
//Arduinoイニシャライズ
arduino = new Arduino(this, arduinoPort, 57600);

//ピンの要素取得
arduino.pinMode(redLED, Arduino.OUTPUT);
size(200, 200);

getInfo();
}

void draw(){

//ウインドウ表示
background(255);
fill(0);

if(elapsedTime > 86400000){
getInfo();

}

elapsedTime = millis() – playTime;
//情報表示
text(title, 10, 35);
text(telop, 10, 55);

if(telop.contains(“晴”)){
//赤色がひかる
beautifulLighting(redLED);
}

if(telop.contains(“雨”)){
//青が光る
beautifulLighting(blueLED);
}

if(telop.contains(“曇”)){
//緑が光る
beautifulLighting(greenLED);
}

println(“elapsedTime: “+elapsedTime);
// println(“telop: “+telop);
// 86400000

}

//お天気データをゲットする
void getInfo(){

JSONObject w = loadJSONObject(baseURL + city);
title = w.getString(“title”);
forecasts = w.getJSONArray(“forecasts”);

JSONObject f = forecasts.getJSONObject(0);
telop = f.getString(“telop”);

playTime = millis();

}

//美しく(フェードしながら)光る
void beautifulLighting(int light){
arduino.analogWrite(light, brightness);

// change the brightness for next time through the loop:
brightness = brightness + fadeAmount;

// reverse the direction of the fading at the ends of the fade:
if (brightness <= 10 || brightness >= 255) {
fadeAmount = -fadeAmount;
}
// wait for 30 milliseconds to see the dimming effect
delay(30);
}[/highlight_java]