うちIoT

Atmospheric Tide (大気潮汐)とな。

きっかけ

ログ取りの基本、気温、湿度、大気圧をずいぶん前から手を変え品を変えて測定している。これまでに、不快指数に応じて表示LCDのバックグラウンドの色が変わるようにしたり、指数がある値を超えるとGoogle Homeが教えてくれるようにしたりして遊んできた(うるさすぎてやめた)。

記録するのは、ログ好きだからそれ自体に喜びを感じてしまうのと(月刊ログの発刊を心待ちにしている<-ググらないでね。そんなものないので)、記録から何かのパターンを探したいというのが目的で、とくに突然雨が降るときの予兆を見つけたいと長らく思っている。雨の前に風の向きが反転したり、気温が急激に変わることがちょくちょくあるので、(あと、雨のにおいが先にしてくることもあるが、これはどう拾えばいいのでしょうか)そういう変化のパターンを見つけて検出できるようにして、雨がどっしゃーと来る前に、「窓閉めたほうがいいですよ」とGoogle Homeに言わせたりしたい。

パターンは目で見つけたい。そのためには測定値をグラフにしてみるのが一番。測定は随時(毎分)行っているので、いつでも見えるようになっているほうがいい。ということで、googleのChartsを使ってこのwebに埋め込む、をやろうと思ったのですが、それより先にAdafruit IO上でサクッとグラフにして、しばらく眺めてみることにしました。

気温や湿度の変化をみると、いつごろクーラーをつけたか、いつ頃起きだしたか、いつ頃Youtube見ながらやせただの、燃焼だのいいながら運動したか、などを読み取ることができ、それなりに面白いのですが、それよりも、気圧の変化にきれいな日周期パターンがでたのでそれを紹介します。

測定機材

材料

  • Adafruit HUZZAH32 – ESP32 Feather Board (PRODUCT ID: 3405)
  • Adafruit 0.96″ 160×80 Color TFT Display (PRODUCT ID: 3533)
  • Adafruit BME280 I2C or SPI Temperature Humidity Pressure Sensor (PRODUCT ID: 2652)
  • LED (red, yellow, green, blue)
  • 330 ohm resistor
  • breadboard
  • jumper wire
  • Adafruit IOアカウント(制限はありますが無料で利用できます)

接続図

TFT displayへの接続がちょっとややこしく、これ描くの大変。

説明図

実物はこんな見た目です。USBケーブルからの電源で動いています。

このバージョンではGoogle Homeさんには何も知らせていない。

観察される気圧のパターン

BME280からの測定値は、ネットワークを旅してAdafruit IOのページでグラフになります。温度と湿度は8時間分、気圧(右上)は7日分を表示しています。なんだか、気圧に似た形が続いていますね。

Adafruit IOのDashboard

12AMから12AMまでの一日分に枠を当てはめてみると、

一日のリズムにあっているようだ。d6のスパイクはノイズです。無視してください。

一日の区切りにパターンがそろうのがわかります。一日分をとってみると、どれも次の形をしています。

高から始まって、低、高、低、最後に高、で一日が終わる。

なんだこりゃ?一日に2周サイクルが回っているようだ。一日2周といえば、潮の満ち引き?でもこれ気圧ですし。そんなの聞いたことないぜ、と思って少し検索してみると、なぬ!

Atmospheric tide 大気潮汐

普通に出てくるし。そっくりなグラフもここに。なんでこんなにはっきりしていて、よく知られていることをまるで知らないでいたのでしょうか。こりゃまだまだそういうことがありそうで楽しみですな。

コード:実際にやってみる人に

Mainのコード(BME280-station3-AdafruitIO.ino)ともにconfig.hが必要です。詳しいことはAdafruitのページを参照してください。長いので、スクロールが大変ですが、実際に動いているコードを載せます。

こういうコードはたいてい0から書き上げる必要はなく、ライブラリについてくるexampleコードを書き換えればできあがります。今回は、Adafruit IO Arduinoについてきた、arduino_22_environmental_monitorをもとにして書き換えています。

ライブラリについてくるexample codeを利用してほしいものを作る。

BME280-station3-AdafruitIO.ino

// examplesにある、adafruitio_22_environmental_monitorを改変
// BME280-station3-AdafruitIO.ino

// Adafruit IO Environmental Data Logger 
// Tutorial Link: https://learn.adafruit.com/adafruit-io-air-quality-monitor
//
// Adafruit invests time and resources providing this open source code.
// Please support Adafruit and open source hardware by purchasing
// products from Adafruit!
//
// Written by Brent Rubell for Adafruit Industries
// Copyright (c) 2018 Adafruit Industries
// Licensed under the MIT license.
//
// All text above must be included in any redistribution.

/********** Adafruit IO Configuration **********/

// edit the config.h tab and enter your Adafruit IO credentials
// and any additional configuration needed for WiFi, cellular,
// or ethernet clients.
#include "config.h"

/*********** Sensor Configuration **********/
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

// BME280 Sensor Definitions
#define SEALEVELPRESSURE_HPA (1013.25)

// Instanciate the sensor
Adafruit_BME280 bme; // I2C

// Something mine =============== mine
// vars
int ticket = 1;
float temp;
float humidity;
float pressure;
float d_idx;
float y_threshold = 83.0;
float r_threshold = 83.5;
// 160x80 TFT, ST7735 =============== preps
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>
// Feather Huzzah32
#define TFT_CS         14
#define TFT_RST        15
#define TFT_DC         32
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
// LEDs =============== preps
const int greenLED = 12;
const int yellowLED = 27;
const int redLED = 33;

const int blueLED = 21;

/********** Example **********/
// Report interval control with millis
unsigned long startMillis;
unsigned long currentMillis;
unsigned long saveInterval = 60000; //ms

// set up the feeds for the BME280
AdafruitIO_Feed *temperatureFeed = io.feed("Temp-BME280");
AdafruitIO_Feed *humidityFeed = io.feed("RH-BME280");
AdafruitIO_Feed *diFeed = io.feed("DI-BME280");
AdafruitIO_Feed *pressureFeed = io.feed("hP-BME280");


void setup() {
  // LED
  pinMode(greenLED, OUTPUT);
  pinMode(yellowLED, OUTPUT);
  pinMode(redLED, OUTPUT);
  pinMode(blueLED, OUTPUT);

  // start the serial connection
  Serial.begin(9600);
  // wait for serial monitor to open
  while (!Serial);
  Serial.println("Adafruit IO Environmental Logger");

  // set up BME280
  setupBME280();

  // TFT, ST7735
  // OR use this initializer (uncomment) if using a 0.96" 160x80 TFT:
  tft.initR(INITR_MINI160x80);  // Init ST7735S mini display
  // black screen
  tft.fillScreen(ST77XX_BLACK);
  delay(1000);
  // set top comes to the top
  tft.setRotation(3);

  // Use OLED display
  OLEDSetupDone();
  delay(1000); // 1 sec

  // connect to io.adafruit.com
  Serial.print("Connecting to Adafruit IO");
  io.connect();

  // wait for a connection
  while (io.status() < AIO_CONNECTED)
  {
    Serial.print(".");
    delay(500);
  }

  // we are connected
  Serial.println();
  Serial.println(io.statusText());

  // Use OLED display
  AfIOReady();
  delay(3000);

  // black screen
  tft.fillScreen(ST77XX_BLACK);

  // take start millis
  startMillis = millis();
}


void loop() {
  // io.run(); is required for all sketches.
  // it should always be present at the top of your loop
  // function. it keeps the client connected to
  // io.adafruit.com, and processes any incoming data.
  io.run();

  // take current millis
  currentMillis = millis();

  Serial.println("Taking Sensor Reads...");

  // read BME data
  temp = bme.readTemperature();
  humidity = bme.readHumidity();
  pressure = bme.readPressure() / 100.0F;
  // calculate discomfort index
  d_idx = 0.81*temp+0.01*humidity*(0.99*temp-14.3)+46.3;
  // display it
  displayReads(temp, humidity, pressure, d_idx);

  Serial.print("Temp: ");
  Serial.print(temp);
  Serial.print(" RH: ");
  Serial.print(humidity);
  Serial.print(" hPa: ");
  Serial.print(pressure);
  Serial.print(" idx: ");
  Serial.print(d_idx);
  Serial.println();

  if (currentMillis - startMillis >= saveInterval) {
    // send data to Adafruit IO feeds
    temperatureFeed->save(temp);
    humidityFeed->save(humidity);
    pressureFeed->save(pressure);
    diFeed->save(d_idx);
    startMillis = currentMillis;
    Serial.println("Data sent to Adafruit IO!!!");
    digitalWrite(blueLED, HIGH);
  }
  
  // LED control
  if (d_idx >=r_threshold) {
    Serial.println("### Hits red threshold --- (1)");
    blink_red();
    if (ticket == 1) {
      // reset ticket
      ticket = 0;
    }
  } else if (d_idx >=y_threshold) {
    blink_yellow();
  } else {
    on_green();
    ticket = 1;
  }

  digitalWrite(blueLED, LOW);

  delay(100);
}


// functions ===============
void OLEDSetupDone() {
  tft.setCursor(0, 0);
  tft.setTextColor(ST77XX_CYAN);
  tft.setTextSize(2);
  tft.println("OLED ready.");
}

void AfIOReady() {
  tft.setCursor(0, 33);
  tft.setTextColor(ST77XX_CYAN);
  tft.setTextSize(2);
  tft.println("Af. IO ready.");
}

void displayReads(float t, float rh, float p, float idx) {
  // erase all
  tft.fillScreen(ST77XX_BLACK);
  delay(100);
  // display!
  tft.setCursor(0, 0);
  tft.setTextSize(2);
  tft.setTextColor(ST77XX_WHITE);
  //tft.setTextSize(2);
  tft.print("Temp: ");
  tft.print(t);
  tft.println("*C");

  tft.print(" RH%: ");
  tft.print(rh);
  tft.println("%");

  tft.print(" hPa: ");
  tft.println(p);

  // the index
  if (idx >=r_threshold) {
    tft.setTextColor(ST77XX_RED);
  } else if (idx >=y_threshold) {
    tft.setTextColor(ST77XX_YELLOW);
  } else {
    tft.setTextColor(ST77XX_GREEN);
  }
  tft.setCursor(0, 56);
  tft.print("index: ");
  tft.println(idx);
}

void on_green() {
  // just turn on the green and wait 10 seconds
  digitalWrite(greenLED, HIGH);
  delay(10000);
  digitalWrite(greenLED, LOW);  
}

void blink_yellow() {
  // about 10 sec
  int i = 0;
  while (i < 5) {
    digitalWrite(yellowLED, HIGH);
    delay(1000);
    digitalWrite(yellowLED, LOW);
    delay(1000);
    i ++;
  }
}

void blink_red() {
  // about 10 sec
  int i = 0;
  while (i < 10) {
    digitalWrite(redLED, HIGH);
    delay(500);
    digitalWrite(redLED, LOW);
    delay(500);
    i ++;
  }
}

// Set up the BME280 sensor
void setupBME280() {
  bool status;
  status = bme.begin();
  if (!status)
  {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
  Serial.println("BME Sensor is set up!");
}

config.h

Adafruit IO Configと、WIFIのところのみ変更が必要です。

/********** Adafruit IO Config **********/
// visit io.adafruit.com if you need to create an account,
// or if you need your Adafruit IO key.
#define IO_USERNAME "ご自分のものをここに"
#define IO_KEY "ご自分のものをここに"

/********** WIFI **********/
// the AdafruitIO_WiFi client will work with the following boards:
//   - HUZZAH ESP8266 Breakout -> https://www.adafruit.com/products/2471
//   - Feather HUZZAH ESP8266 -> https://www.adafruit.com/products/2821
//   - Feather HUZZAH ESP32 -> https://www.adafruit.com/product/3405
//   - Feather M0 WiFi -> https://www.adafruit.com/products/3010
//   - Feather WICED -> https://www.adafruit.com/products/3056
//   - Adafruit PyPortal -> https://www.adafruit.com/product/4116
//   - Adafruit Metro M4 Express AirLift Lite ->
//   https://www.adafruit.com/product/4000
//   - Adafruit AirLift Breakout -> https://www.adafruit.com/product/4201
//   - Adafruit AirLift Shield -> https://www.adafruit.com/product/4285
//   - Adafruit AirLift FeatherWing -> https://www.adafruit.com/product/4264

#define WIFI_SSID "ご自分のものをここに"
#define WIFI_PASS "ご自分のものをここに"
ABOUT ME
misson
ものづくりが趣味。頭の中でモヤモヤと渦巻くガスを形として沈殿させるのが趣味。座右の銘その2は:未来は今の積分値


follow us in feedly

COMMENT

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