LoginSignup
4
5

More than 3 years have passed since last update.

WEMOS の ESP32 で クラウドの気象データを表示

Last updated at Posted at 2018-10-07

WiFiにつながる安いESP32のボードで、クラウドに接続して、今の気象データを表示するIoTをしてみました。

IMG_20181008_072437.jpg

ESP32 WEMOS Lolin32

今回 WEMOS LOLIN32というESP32ボードを使いました。

(2020/02/06) WEMOS LOLIN32ボードの紹介は別ページに分離しました。
「WEMOS LOLIN32 の調査」
https://qiita.com/nanbuwks/items/111ee8cd69f3390d866f

まずは、動作確認まで終わらせておきます。

OLEDをつけます。

手元にSPIのOLEDがあったので、つなげてみました。

接続は
GND --  GND
VDD --  5V
SCK --  14
SDA -- 13
RES -- 4
DC -- 21
CS -- 16

IMG_20181001_022515.jpg

ライブラリとして、

  • Adafruit_GFX.h
  • Adafruit_SSD1306.h

を使っています。

ライブラリをインストールすると出てくる、SSD1306_128x64_SPI を使い、

// using software SPI
#define OLED_MOSI  13
#define OLED_DC    21
#define OLED_CS    16
#define OLED_CLK   14
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

だけ書き換えています。

Wi-Fiにつなぐ

「スケッチの例」の「WiFi」「WiFiClientBasic」で動きました。
ssid と passwd 、を書き換えるだけで Wi-Fiに接続しました。(接続後の!client.connect(host, port)))はうまく動かないみたい)

お天気情報を取得する

openweathermap.org

image

からTokyoの天気を取得しました。

サインアップし、APIキーを取得します。

APIを使って、


http://api.openweathermap.org/data/2.5/weather?APPID=eac・・・(APIキー)・・・2e2&id=1850147&units=metric

id=1850147 は東京のコードです。都市の指定は、Tokyoとかの指定でもいいですがコードで指定するほうが無難ぽいです。
http://bulk.openweathermap.org/sample/ の city.list.json.gz に都市のリストがあります。

units=metric とすると温度が摂氏で得られます。

取得したJSONは以下のようになっていました。


{"coord":{"lon":139.69,"lat":35.69} 
  ,"weather":[
   {"id":701,"main":"Mist","description":"mist","icon":"50n"}   
  ,{"id":721,"main":"Haze","description":"haze","icon":"50n"}
  ,{"id":520,"main":"Rain","description":"light intensity shower rain","icon":"09n"}
  ],"base":"stations"
  ,"main":{"temp":25.08,"pressure":980,"humidity":83,"temp_min":24,"temp_max":26},"visibility":3500     
  ,"clouds":{"all":75},"dt":1538331240
  ,"wind":{"speed":9.8,"deg":210,"gust":24.7}
  ,"sys":{"type":1,"id":7615,"message":0.0068,"country":"JP","sunrise":1538253334,"sunset":1538295968}
  ,"id":1850147,"name":"Tokyo","cod":200   
  }";

ArduinoJsonを使い、以下のようにパースしています。

  #include <ArduinoJson.h>
   ・・・
  Serial.println(json);  # "json"にデータが入っている
  JsonObject& root = jsonBuffer.parseObject(json);
  if (!root.success()) {
    Serial.println("parseObject() failed");
  }
  const char* weather = root["weather"][0]["main"];
  const char* description = root["weather"][0]["description"];
  long pressure = root["main"]["pressure"];
  double temp = root["main"]["temp"];

["weather"][0]だけ取得していますが、先ほど示したように複数の値がやってくることがあります。とりあえずは一番最初のものだけを取得するようにしています。

お天気情報を表示する

1分ごとにフェッチして、表示するようにしてみました。

IMG_20181008_072501.jpg

簡単に、まとめたプログラムコードが以下です。


#include <ArduinoJson.h>

// 接続先のSSIDとパスワード
const char ssid[] = "hogehoge";
const char passwd[] = "hagehage";

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <HTTPClient.h>
#include <WiFi.h> // This liblaly cause error "min". Replace to "_min".

// using software SPI
#define OLED_MOSI  13
#define OLED_DC    21
#define OLED_CS    16
#define OLED_CLK   14
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

String accessHttpAPI(char host[]) {
  HTTPClient http;
  http.begin(host);
  int httpCode = http.GET();
  String result = "";
  if (httpCode < 0) {
    result = http.errorToString(httpCode);
  } else if (http.getSize() < 0) {
    result =  "size is invalid";
  } else {
    result = http.getString();
  }
  http.end();
  return result;
}

void setup()   {                
  Serial.begin(115200);
  WiFi.begin(ssid, passwd);
  Serial.print("WiFi connecting...");
    while(WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(100);
    }
    Serial.print(" connected. ");
    Serial.println(WiFi.localIP());
  display.begin(SSD1306_SWITCHCAPVCC);
  display.display();
  delay(2000);
  display.clearDisplay();
}

void loop() {
  StaticJsonBuffer<1500> jsonBuffer;
  String json = accessHttpAPI("http://api.openweathermap.org/data/2.5/weather?APPID=eac・・・(APIキー)・・・2e&id=1850147&units=metric");
  Serial.println(json);
  JsonObject& root = jsonBuffer.parseObject(json);
  if (!root.success()) {
    Serial.println("parseObject() failed");
  }
  const char* weather = root["weather"][0]["main"];
  const char* description = root["weather"][0]["description"];
  long pressure = root["main"]["pressure"];
  double temp = root["main"]["temp"];
  Serial.println(weather);
  Serial.println(description);
  Serial.println(pressure);
  Serial.println(temp);

  display.setTextSize(3);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println(weather);
  display.setTextColor(BLACK, WHITE); // 'inverted' text
  display.setTextSize(1);
  display.println(description);
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.print(pressure); display.println("hPa");
  display.print("temp:");display.print(temp);
  display.display();
  delay(60000);
  display.clearDisplay(); 
}
4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5