見出し画像

M5Stack:自分用の気温ロガーが欲しかったので作ってみた!(その①)

M5Stackというおもちゃ(小型のコンピュータ)を入手したので、そちらでいろいろ作ってみるシリーズ(シリーズ化するの!?)その①です。

作りながらいろいろ試したことをだらだら書きますので、興味ない方はすっとばしてくださいませw

M5Stackについてはこちらの記事をどうぞー♪


前口上

さて、M5Stackを使ったでんきおもちゃ遊びですが、実はこれを使って作りたいものがあったのです。そう、気温ロガーです。

実はこう見えて(?)わたくし虚弱なところがありまして、ちょっとの温度差ですぐ風邪をひいちゃったりすることがあるのです。特に季節の代わり目とかには服装を気温に合わせて吟味しないとてきめんにやられてしまうのですね。(特に今年は某ウイルスさんのせいで、ここで風邪ひいちゃったらほんとにやばいかも!? って危機感もあります><)

そんな体質なクセに冬のキャンプとかやりたがるものですから、いつも外気温にはとっても気を付けて、あったかい服装で対応しているのです。んが……。

天気予報やネットの情報だとごくおおざっぱな気温しか出てこないので、手元に温度計が必須なのです。

身体の周りの温度がほしいのに、天気予報の気温って日照条件や風のぐあいで大きくかわっちゃうじゃないですか。もちろん室内の温度はネットの情報じゃわからないし。

それに、できれば「昨日のこの時間帯の気温はこのぐらいで、この服装で耐えられた」って情報があるとありがたいんですよね。それで今日の服装の検討ができるので。(それなのにWeb天気でよく見る気温グラフって今からの予測値ばっかりで過去の情報なかなかないんですよねー><)

なので、必要は発明のマザー牧場。自分でつくっちゃおう。ということで、今回M5Stackに白羽の矢を立てたのでありました。

何はともあれ気温センサー

M5Stackにした理由はいくつかありますけど、いろんなセンサーをくっつけるのが簡単! ということもあります。温度センサーで探してみたら

こんなのが見つかりました。なんかディスコン(在庫限り)みたいですねぇ。でも後継機種がきっとすぐでるんでしょう。とりあえずぽちり。

参考情報

だれかこれ使って温度計つくっていないかな? と情報収集。

↑つくりたいのをそのものつくってくれてた人いました。

よーし、これ真似してやってみよう! と、ENV UNITも届いたので(早っ!)早速作ってみます。

画像10

悪い例

以下、産まれて初めて見たものを親と思い込む(検索してトップに出てきた情報を使いたがる)悪い例(?)です。せっかく画面キャプチャしながらやってたので乗せちゃいますが、他人のミスなんて興味ないから正しいやり方が知りたいって方(当然ですね><)はここはすっとばしてスクロールしてくださいませ。

あ、もちろん、参考にしたサイトをDISってるわけでは決してありません。たんに違った情報を信じたアタシがお馬鹿なだけです、すいません><

さて、参考サイトに合わせてやってみましょう!

でもこれはM5StickCというやつ用。中のマイコンは同じらしい(違います)けどちょっと改造しないといけないかも?

画像9

※M5StickというのはM5Stackよりさらにちっちゃい棒みたいなやつです。これもいつか使いたいですねー♪

ライブラリをインストール

↑の参考サイトによると、この温度センサーを使うにはセンサー用のライブラリをインストールしないといけないようです。

画像1

素直に言われた通り入れます。インストール時に

画像3

こんなこと言われるけどもちろんInstall all。

で、参考サイトのプログラムソースをみてみると、最初に


1: #include  <M5StickC.h> // ----A

とあります、これ、M5StickC用だからですね。これをM5Stackに変えないときっとダメでしょう。

とりあえず安易にそこだけ書き換えてコンパイルしてみます。

画像2

やっぱ簡単にはいきませんでした><

DHT12.h が無いというエラーが出ます。ふんもー。さっき入れたのはBMP280用のライブラリだから、DHT12っての用はまた探さなきゃいけないのかー。

というわけでその名でライブラリを検索。

画像4

なにやらそれっぽいライブラリを見つけたのでこれもインストールしてみました。

そんでもダメ。

DHT12.h が無いとあいかわらずのエラーがでます。。

うーん、こまったなー。

諦める前にもう一度検索ワードを変えてGoogle先生の御宣託を仰ぎます。

すると……

正しい情報発見!

こんな素敵な動画を発見。(∩´∀`)∩☆ 

やりたいことほぼこれでいいじゃん!

この方の GitHubをみると、

Arduinoプロジェクト一式: https://github.com/nishizumi-lab/sample/tree/master/m5stack/bmp280/arduino/bmp280

画像5

あーるじゃーん! ありがたーい!!

その上サンプルソース (bmp280.ino)まで!!

というわけでGitHubからソースをゲット。そのまま実行してみます。

画像6

わーお☆

さっくり動きましたね~(∩´∀`)∩☆

ちょっと寄り道もありましたが、またほとんどキーボード使わずにプログラムできちゃったのでちょっと物足りない感じ(またか)w

というわけで、さらに(きっと寄り道しながら)理想に近づけていきましょう。

バッテリーチェック

M5Stackにした理由のもう一つに、バッテリーが内蔵されているということです。それなら自由に持ち歩いて温度チェックできますもんね。

でも心配なのはどのくらい電池が持つかということ。なので、バッテリーをチェックする機能を付けたいところ。

いろいろ検索して見つけた Moo Softさん

こちらの

画像11

を使わせてもらうことにしましょう。

なにやら説明を読んでいると、

を利用すると、SDカードにコンパイル済みのプログラムの実行ファイルを入れておくとランチャーで選んで実行できるようになるそう!

それはそれで便利そう。。だけれどもすでに脇道にそれているので今はちょっと我慢して、バッテリーのチェックだけできるようにしますw

とりあえずMooSoftさんのソースの中で LovyanLauncher 対応と書かれているところをコメントアウトします。

画像7

画像8

9行目と31行目~36行目をコメントにしておきます。

では実行!

画像12

わーお☆

これまたさっくり動きました!(∩´∀`)∩☆

いまはUSBをパソにつなぎっぱなしなのでそこから電気来てるでしょうからケーブルを引っこ抜いてみます。

うんうん、無事電池でも動作してるわね。

っと思った瞬間、10秒ぐらいで

画像13

75%に!!w

(25%単位でしかわからないそうですw)

まあちょっとこの状態でどのくらい持つかほおっておいてみましょう。

その間に、温度のログをSDカードに保存する方法を探します。

ロギング参考情報

さっくり見つかりましたw

こちらの方はボタン押したときに押したボタンと時間とを記録するプログラムつくられてますね。

ほうほう、ntpサーバーに接続して時間を取るのですか、ネットのつなぎ方もこれでわかりますね。参考になるなる!

ここらへんを合体させたらつくることできそうです!

内蔵電池はさすがに……

ほむほむ、さてさてプログラミング。と、思ってる間に先ほど試していた電池が切れました……。わずか20分程度の命の模様。

画像14

輝度をさげたらもうちょっと持ちそうですけど、内蔵電池だとあんまり実用性はなさそうですねぇ(´・ω・`)ショボーン

実用はモバイルバッテリーとかを使うかんじでしょうかねー…

脇道情報①:バッテリーモジュール

↑こんな素敵なモジュールもあるようです。ポチっちゃおうかしらん?w

脇道情報②:Deep Sleep処理情報

いちおう検索してみつけた情報。いまはそこまで難しいことしないので良いですが、将来的にはやってみるかも。とりあえずメモ。

レッツゴープログラミング!

と、ゆーわけで、

ここに、コレ

と、

画像15

コレと、

コレがあるじゃろ?

これをこうして……こうして……

画像16

こうじゃっ!

画像17

どーん♪

でーきたー☆(∩´∀`)∩☆

(ただ混ぜただけともいうw)

気温と湿度、気圧(ついでにバッテリー)をつぎつぎとファイルに保存しつづけるプログラムです。

画像18

保存した内容はこんなかんじになるので(日付、時間、気温、湿度、気圧、バッテリー)、Excelにでも食べさせてあげると簡単にグラフ化してくれるはずです。

M5Stackの画面にグラフ表示してあげてもよいかもですね~♪

と、いうわけで、本日はここまで!☆

とりあえず三体合体させただけなので大したことはしてませんが、ソース解説とすでに分かっているバグ情報は長くなるのでこの先のオマケエリアにいれておきます。興味があるかただけどうぞーん♪

オマケエリア

ソース

〈env_log.ino〉

#include <M5Stack.h>
#include "DHT12.h"
#include <Wire.h> //The DHT12 uses I2C comunication.
#include "Adafruit_Sensor.h"
#include <Adafruit_BMP280.h>
#include <WiFi.h>
#include <time.h>


// ファイル保存するかどうか。ファイルに保存するならここを true にする
#define FILEWRITE false

// 保存するファイル名
const char* fname = "/env_log.csv";

// ループのウェイト、何秒待つかをミリ秒で指定
const long DELAY = 10000;    // ミリ秒

// WiFiの設定 (XXXのところを自分のWiFiの設定に)
char ssid[] = "XXXXXXXXXXXXXX";
char pass[] = "XXXXXXXXXXXXXX";

// === グローバル変数、定数
DHT12 dht12; //Preset scale CELSIUS and ID 0x5c.
Adafruit_BMP280 bme;

// === 関数プロトタイプ宣言
uint8_t getBattery(uint16_t, uint16_t);

// Time
char ntpServer[] = "ntp.jst.mfeed.ad.jp";   // ntpサーバ 
const long gmtOffset_sec = 9 * 3600;
const int  daylightOffset_sec = 0;
struct tm timeinfo;
String dateStr;
String timeStr;

File file;

void getTimeFromNTP(){
 // NTPサーバと時刻を同期
 configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
 while (!getLocalTime(&timeinfo)) {
   delay(1000);
 }
}

void setup() {
   M5.begin();

   M5.Lcd.setBrightness(10);

   M5.Lcd.println("WiFi begin");
   WiFi.begin(ssid, pass);
   while (WiFi.status() != WL_CONNECTED) {
     delay(500);
     M5.Lcd.print(".");
   }
   M5.Lcd.println("\nWiFi connected.");
 
   // timeSet
   getTimeFromNTP();

   Wire.begin();
   
   // ENV Unit Check
   Serial.println(F("ENV Unit(DHT12 and BMP280) test..."));

   while (!bme.begin(0x76)){  
     Serial.println("Could not find a valid BMP280 sensor, check wiring!");
     M5.Lcd.println("Could not find a valid BMP280 sensor, check wiring!");
   }
   // LCD初期化
   M5.Lcd.clear(BLACK);
   M5.Lcd.println("ENV Unit test...");
}

void getTime(){
 // 時刻の取得と表示
 getLocalTime(&timeinfo);
 dateStr = (String)(timeinfo.tm_year + 1900)
         + "/" + (String)(timeinfo.tm_mon + 1)
         + "/" + (String)timeinfo.tm_mday;
 timeStr = (String)timeinfo.tm_hour
         + ":" + (String)timeinfo.tm_min
         + ":" + (String)timeinfo.tm_sec;

 //M5.Lcd.setTextColor(WHITE,BLACK);
 //M5.Lcd.setCursor(0, 200, 1);
 M5.Lcd.println(dateStr + "   ");
 M5.Lcd.println(timeStr + "   ");
}


// ================================================================== //
// バッテリ残量取得
// 戻り値 : uint8_t 0 ~ 100(%)
// ================================================================== //
uint8_t getBattery() {
 uint8_t vat = 0xFF;
 Wire.beginTransmission(0x75);
 Wire.write(0x78);                   // 0x78 バッテリ残量取得レジスタアドレスオフセット
 Wire.endTransmission(false);
 if (Wire.requestFrom(0x75, 1)) {
   vat = Wire.read() & 0xF0;         // 下位4ビット 0 マスク
   if      (vat == 0xF0) vat = 0;
   else if (vat == 0xE0) vat = 25;
   else if (vat == 0xC0) vat = 50;
   else if (vat == 0x80) vat = 75;
   else if (vat == 0x00) vat = 100;
   else                  vat = 0xFF;
 } else vat = 0xFF;

 return vat;
}


void writeData(char *paramStr) {
 // SDカードへの書き込み処理(ファイル追加モード)
 // SD.beginはM5.begin内で処理されているので不要
 file = SD.open(fname, FILE_APPEND);
 file.println(dateStr + "," + timeStr + "," + paramStr);
 file.close();
}

void loop() {
   // 温度の取得
   float tmp = dht12.readTemperature();

   // 湿度の取得
   float hum = dht12.readHumidity();

   // 気圧の取得[hPa = Pa * 0.01]
   float pressure = bme.readPressure() * 0.01;

   uint8_t batt = getBattery();

   char buff[128];

   // 温度、湿度、気圧をシリアル通信で送信
   Serial.printf("Temperatura: %2.2f*C  Humedad: %0.2f%%  Pressure: %0.2fPa\r\n", tmp, hum, pressure);

   //LCD表示クリア&色設定
   M5.Lcd.setCursor(0, 0); // カーソル
   M5.Lcd.setTextColor(WHITE, BLACK);  // 色
   M5.Lcd.setTextSize(4);  // 文字サイズ

   // 時刻表示
   getTime();
   M5.Lcd.printf("--------\n");

   // 温度、湿度、気圧、バッテリー情報
   M5.Lcd.printf("Temp:%2.1f \nHumi:%2.0f%% \nPres:%2.0fhPa \nBatt: %d%%", tmp, hum, pressure,batt);

#if FILEWRITE
   // ファイル出力
   sprintf(buff,"%2.1f ,%2.0f% ,%2.0f, %d%", tmp, hum, pressure,batt);
   writeData(buff);
#endif

   // ボタンイベント処理
   //Aボタンを押したときに明るくするテスト。今はDELAYの切り替わりのタイミングでしか動作しない
   if (M5.BtnA.wasPressed()) {
     M5.Lcd.setBrightness(100);
   } else {
     M5.Lcd.setBrightness(10);
   }
   M5.update();
   
   delay(DELAY);
} 

せつめい

このプログラムを実行するには、

・DHT12.h
・DHT12.cpp
・Adafruit_Sensor.h
・Adafruit_BMP280.h

が必要です。BMP280はArduinoIDEの「ライブラリを管理」からインストールします、DHT12.h 他は nishizumi-lab さんからもらってきましょう。

冒頭の

// ファイル保存するかどうか。ファイルに保存するならここを true にする
#define FILEWRITE false

が false のままだと SDカードにログファイル生成をしません。ただの環境表示+時計プログラムになります。コメントにあるように true にすることでファイルを生成してどんどん追記していきます。

ファイル名は

// 保存するファイル名
const char* fname = "/env_log.csv";

で指定します。

また、

// ループのウェイト、何秒待つかをミリ秒で指定
const long DELAY = 10000;    // ミリ秒

こちらは今は10秒ずつ取得する形にしてあります。ファイル生成をするとどんどん増えてしまうのでこのぐらい(1分や10分単位でも十分?)にしていますが、時計にするなら逆に1秒単位にしてもよいかもです。

※M5Stackは思ったより丈夫(?)で、ファイル書き込みのプログラムを動作ちゅうにSDカードを引っこ抜いてもプログラムは停止しないで動き続けます(再度刺すとちゃんと刺したところから追記されている模様)毎回ファイルをオープンしているからですが、平然と動いているのは感心しました。なかなかエライ子ですねw

わかっているバグというか仕様というか

それぞれサンプルソースを合体させたものですから、あんまりエラーチェックはしっかりしていません。

特に問題になりそうなのはネットワークの接続。

WiFi環境がないところだとこのままでは動作しませんね。外でも使えるようにWiFiが無かったらトラップして、電波が無い場所でも動作するようにないといけないかも?

それと、NTPサーバにつながらないと時間がわからないという盲点がありました。(M5Stackって時計ついてないのですねぇ)
このあたり、なんらかの工夫が必要かもです。ファイルの日時を保存しているのだからそこからの推測でネットにつながっていない場所で立ち上げたらその続きになるとか……(何時間オフになっていたかわからないから無理かー、うにゅー)

また、WiFiが飛んでいてもたまにうまくつながらず、えんえん待ち続けてしまうことがあります。そんな時はリセットボタンをぽちしてあげると、無事つながったりします。このあたりもタイムアウト処理入れた方が良いですね。

おわりに

当然ですが利用しているサンプルはリンク先のみなさまに著作権があります。(公開してくださってありがとうございます!)
それらをまぜまぜしてコラージュしたのは私ですが、本プログラムリスト(スケッチ)は私の備忘録と、この試行錯誤っぷりを見て勉強になる数奇な運命の方もひょっとしたらおられるかもしれないわんという、あくまで学習用に公開するものであります。このスケッチをもし利用するようなことがあっても、それはあくまで自己責任でおねがいします。なんかやばいことがおきても責任はとりかねます。またENV-UNITなどの表示が正しいかどうかもわかりませんので、そこのところはよろしくお願いします。

この記事が参加している募集

よろしければサポートお願いします!いただいたサポートはクリエイターとしての活動費にさせていただきます!感謝!,,Ծ‸Ծ,,