IoT何をいまさら(63) Wio Terminal、時刻と温度をSD記録

JosephHalfmoon
Joseph Halfmoon

前回、RTC使って時刻を得られるようになったので、今回はダラダラとセンサの測定値とその測定時刻をSDカードに記録してみようと思います。手元にあるセンサの中から、ありがちな温湿度センサDHT11を選びました。Groveモジュール化されているもの。SDカードは引き出しの中から見つけた16GB品です。

さて使用するセンサは、Arduino環境における「お求めやすい定番」センサの代表格、DHT11温湿度センサです。何度かこの系統のセンサは取り上げさせていただいておりますが、以下の回では単体センサを使ってセンサを制御する下回りの部分からRISC-V搭載マイコンを使って動作確認をさせていただいております。

部品屋根性(11) DHT11、温湿度センサ

インタフェースは信号線一本で双方向の通信が可能な “1-wire” です。Arduino環境の場合、上の記事のような面倒なことはまったく必要なく簡単に使うことができます。以下に写真を掲げるGrove化されたモジュールは、SeeedStudio製Grove Beginner Kit付属のもの。詳しくはこちらをご覧ください。とくにモジュール内で電源とか信号レベルとか何もしていないので、3.3Vでも、5Vでも動作する使いやすいモジュールです。

Grove DHT11 temperature/humidity sensor このGroveモジュールをWio Terminalの正面右側のDigital/Analog兼用Groveポートに接続します。使用するピンは、Arduino環境的にはデジタルの0番ピンです。

センサの初期化と読み取り部分のコードはこんな感じ、非常に簡単。

#define DHTPIN 0
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

void dhtInit() {
  dht.begin();
}

void dhtRead(int *Stat, float *Temp, float *Humi) {
  *Temp = dht.readTemperature();
  *Humi = dht.readHumidity();
  if (isnan(*Temp) || isnan(*Humi)) {
    *Stat = 0; 
  } else {
    *Stat = 1;
  }
}

次に、得られた温湿度データですが、

  • LCD画面にダラダラと垂れ流し
  • 同時にSDカードのファイルにCSV型式で記録

といたしました。Wio TerminalのSDカードスロットですが、以下の写真のような感じです。シャーシとカードスロットの間に変な隙間などないので確実に抜き差しができる感じです。引き合いに出すと M5Stack GreyのSDカードスロットはちょっとスキマに遊びが多い感じで注意が必要。

Wio Terminal, SD card slot今週、改造を加えながら作ってきた メインの .ino ファイルは結局こんな感じになりました。長くなったので分割しながら説明してみます。

ヘッドのインクルードやら大域変数やら
#include <SPI.h>
#include <Seeed_FS.h>
#include "SD/Seeed_SD.h"
#include "TFT_eSPI.h"
#include "RTC_SAMD51.h"
#include "DateTime.h"
#include "DHT.h"

#define TXT_MAXBUF    (28)

int counter;
int dhtStat;
float dhtTemp;
float dhtHumi;
char cTime[TXT_MAXBUF];

File logFile;

インクルードすべきヘッダファイル類が大分増えました。SDカードを読み書きするために、SPI.hと Seeed_FS.h、Seeed_SD.hを、LCD画面出力のためにTFT_eSPI.h、RTCでの時刻設定、読み取りにRTC_SAMD51.hとDateTime.h、そしてDHT11センサの制御のためにDHT.hです。

過去数回の記事で説明したとおり、DHT11、RTC、LCD画面出力と5 way switch部分は、別の .ino ファイルに分割してあるのですが、結局分割しても

最後は一本の.cpp

にまとめてコンパイルされるようなので、ヘッダは先頭におまとめであります。

Setup()関数

初期化部分は、それぞれのデバイス毎に別ファイル内の関数を呼び出しているのが基本ですが、SDカードのところはベタに書いてしまっています。SDエラーのときはその場で無限ループ。

void setup() {
  txtInit(TFT_WHITE, TFT_BLACK);
  fiveWaySwitchInit();
  rtcInit("");
  dhtInit();
  counter = 0;
  if (!SD.begin(SDCARD_SS_PIN, SDCARD_SPI)) {
    txtPrint("SD failed!");
    while (1);    
  }
  txtPrint("Temparature Logging");
  txtPrint("U) start logging.");
  txtPrint("D) stop logging.");
  txtPrint("L) initilize RTC.");
  txtPrint("R) show current time.");
}

一応、LCD画面に5Wayスイッチ使った操作方法を表示して初期化を終わります。前回説明した手動時刻設定でRTCに現在時刻を立ててから計測を始める想定であります。

計測時に呼び出される関数

今回はDHT11だけなので非常に簡単。DHT11からステータス(DHT11と正常に通信できたら1)、温度、湿度を読み取り、RTCから現在時刻文字列を取得するだけ。この読み取り部分を変更すれば、他のセンサにも対応可能な筈。

void measurement() {
  dhtRead(&dhtStat, &dhtTemp, &dhtHumi);
  rtcNow(cTime, 1);
}
loop()関数

ちょと長いですが、そのままダラダラ書きます。

void loop() {
  bool countFlag;
  char buf[TXT_MAXBUF];
  char buf2[TXT_MAXBUF];

  switch (fiveWayPrompt()) {
    case 1:
      txtCLS();
      statusLine("U) START LOG");
      logFile = SD.open("temp.csv", FILE_WRITE);
      counter = 1;
      break;
    case 2:
      statusLine("D) END LOG");
      logFile.close();
      counter = 0;
      break;
    case 3:
      rtcNow(buf2, 0);
      statusEditNum(buf2);
      rtcInit(buf2);
      rtcNow(buf2, 1);
      txtPrint(buf2);
      statusLine("L) Initialize RTC");
      break;
    case 4:
      rtcNow(buf2, 1);
      txtPrint(buf2);
      statusLine("R) current Time");
      break;
    case 5:
      txtCLS();
      statusLine("PRESS) ");
      break; 
  }
  if (counter > 0) {
    measurement();
    sprintf(buf, "%d", counter++);
    txtPrint(buf);
    logFile.print(buf);
    logFile.print(",");
    sprintf(buf, "  %d, %4.1f, %3.0f", dhtStat, dhtTemp, dhtHumi);
    txtPrint(buf);
    logFile.print(buf);
    logFile.print(",");
    sprintf(buf, "  %s", cTime);
    txtPrint(buf);
    logFile.println(buf);
  }
  delay(3000);
}

現段階での問題点は、計測のタイミングと、5way switchのチェックなどUI部分の両方のタイミングを末尾のdelay()関数で決めていること。本来計測のタイミングとUIの制御などは独立であるべきでしょう。これはまた後で改良の予定であります。

さて、このコードで記録されたSDカード上のファイルを読み出したものが、こちら。フィールドは左から、

  1. レコード番号、
  2. DHT11読み取りステータス(1:成功、0:失敗)
  3. 温度(摂氏)
  4. 相対湿度(%)
  5. 測定時刻

であります。

1,  1, 19.9,  62,  2021/01/07 18:25:00
2,  1, 20.8,  64,  2021/01/07 18:25:03
3,  1, 20.9,  64,  2021/01/07 18:25:06
4,  1, 20.9,  63,  2021/01/07 18:25:10
5,  1, 20.9,  62,  2021/01/07 18:25:13
6,  1, 21.0,  66,  2021/01/07 18:25:17
7,  1, 21.0,  67,  2021/01/07 18:25:21
8,  1, 21.1,  66,  2021/01/07 18:25:24
9,  1, 21.0,  65,  2021/01/07 18:25:28
10,  1, 21.1,  65,  2021/01/07 18:25:32
11,  1, 21.1,  64,  2021/01/07 18:25:36
12,  1, 21.1,  63,  2021/01/07 18:25:40
13,  1, 21.1,  63,  2021/01/07 18:25:44
14,  1, 21.2,  62,  2021/01/07 18:25:48
15,  1, 21.1,  62,  2021/01/07 18:25:52
16,  1, 21.1,  62,  2021/01/07 18:25:56
17,  1, 21.2,  62,  2021/01/07 18:26:00
18,  1, 21.2,  62,  2021/01/07 18:26:03
19,  1, 21.2,  62,  2021/01/07 18:26:07
20,  1, 21.2,  62,  2021/01/07 18:26:11
21,  1, 21.2,  62,  2021/01/07 18:26:15

まあね、こんなんでも「温度湿度ロガー」の一応出来上がり。Arduino環境ならホントにお楽。なんだかな~。

IoT何をいまさら(62) Wio Terminal, RTC(実時間タイマ)を使う へ戻る

IoT何をいまさら(64) Wio Terminal、消費電力? へ進む