【WiFi温度計】M5Stick Cを使って室内温度を測定・記録する

複数ポイントで測定・記録するシステムを、M5Stack Basicではなく、より小型で安価なM5Stick Cで実装してみました。


温度を測定するポイントをもっと増やしたいと考えましたが、M5Stack Basic+ENV Unitでは、1測定ポイントあたり4000円程度かかります。そこで、より安価なM5Stick Cで実装してみることしました。こちらだと2500円程度で収まります。

小型で低価格なM5Stick Cを使う

M5Stick Cは、M5Stackの小型版・機能限定版です。画面が小さく、機能も限定されていますが、小型で安価というメリットがあります。

M5Stack BasicとM5Stick C(右)

また、本体に拡張モジュールを合体できる構造になっており、気温や湿度、気圧などを測定できるENV Hatというモジュールが用意されています。

M5Stick C本体に合体できるENV Hat(左の白い部品)

M5Stick C+ENV Hatは非常にコンパクトでよいのですが、実際に試すと、本体の発熱を受けて、2~3℃程度高い値になってしまいました。

見た目は悪いですが、10cmほどのジャンパワイヤを挟むことで、本体の発熱の影響を受けないようにしました。

本体の発熱の影響を受けないようにジャンパワイヤ経由で接続

ちなみに、M5Stack Basicで使ったENV Unitも、M5StickCに接続可能です。ところが、試してみたところ、個体によって、正しく動作したり、温度が0になってしまったりと、動作が不安定になることがありました。

今回は、M5Stick C+ジャンパワイヤ+ENV Hatで、試すことにしました。

用意したもの
品名 実売価格
M5Stick C(本体コア) 2,000円程度
M5Stick C ENV Hat(気温などの環境センサーモジュール) 550円程度
ジャンパワイヤ オス-メス 8ピン 10~20cm 50~200円程度

M5Stick C用にコードを修正する

M5Stick Cは、M5Stackと同様に開発・使用することができます。一方で、仕様が異なる部分もあるため、コードをM5Stick C用に修正しました。

M5Stick C対応のメインコード
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#if defined(ARDUINO_M5Stack_Core_ESP32)
#include <M5Stack.h>
#elif defined(ARDUINO_M5Stick_C)
#include <M5StickC.h>
#endif
#include <Preferences.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <Wire.h> // for DHT12+BMP280
#include "DHT12.h" // for DHT12
#include "Adafruit_Sensor.h" // for DHT12
#include <Adafruit_BMP280.h> // for BMP280

DHT12 dht12;
Adafruit_BMP280 bme;
Preferences prefs;
HTTPClient http;

char wifi_ssid[128]; // 127文字まで
char wifi_pass[128]; // 127文字まで
String apiKey;
const String endPoint = "https://gw.machinist.iij.jp/endpoint";
const char* dataFormat = "{\"agent\": \"%s\", \"metrics\": [{\"namespace\": \"%s\", \"name\": \"%s\", "
"\"data_point\": {\"value\": %4.1f}, \"tags\": {\"sensor\": \"%s\"}}]}";
char core_name[16]; // 15文字まで
float sensor_offset1;
unsigned long nextUpdate;

void load_preferences() {
// WiFi設定
prefs.begin("wifi", true);
prefs.getString("ssid", wifi_ssid, sizeof(wifi_ssid));
prefs.getString("password", wifi_pass, sizeof(wifi_pass));
prefs.end();
// Machinist設定
prefs.begin("machinist", true);
apiKey = prefs.getString("apikey");
prefs.end();
// M5Stackコア設定
prefs.begin("core", true);
prefs.getString("name", core_name, sizeof(core_name));
prefs.end();
// M5Stackセンサー設定
prefs.begin("sensor", true);
sensor_offset1 = prefs.getFloat("offset1");
prefs.end();
}

void wifi_connect() {
M5.Lcd.print("WiFi Connetcing...");
WiFi.begin(wifi_ssid, wifi_pass);
// 接続完了するまでループ
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
M5.Lcd.print(".");
}
M5.Lcd.printf("Connected!\n");
}

void sendData(char *nameSpace, char *metricName, double metricValue, char *sensor_name) {
// 送信データを用意
char dataBuffer[1024]; // 1023文字まで
sprintf(dataBuffer, dataFormat, core_name, nameSpace, metricName, metricValue, sensor_name);
// データを送信
http.begin(endPoint);
http.addHeader("Content-Type", "application/json");
http.addHeader("Authorization", "Bearer " + apiKey);
http.POST(dataBuffer);
}

void setup() {
// 初期設定
M5.begin();
#if defined(ARDUINO_M5Stack_Core_ESP32)
M5.Power.begin();
#endif
// 画面設定
#if defined(ARDUINO_M5Stack_Core_ESP32)
M5.Lcd.setBrightness(3);
M5.Lcd.setTextSize(3);
#elif defined(ARDUINO_M5Stick_C)
M5.Axp.ScreenBreath(7);
M5.Lcd.setTextSize(2);
M5.Lcd.setRotation(3);
#endif
M5.Lcd.setTextColor(WHITE, BLACK);
// センサー設定
#if defined(ARDUINO_M5Stack_Core_ESP32)
Wire.begin();
#elif defined(ARDUINO_M5Stick_C)
Wire.begin(0,26); // for ENV Hat
#endif
while (!bme.begin(0x76)){
M5.Lcd.println("Could not find a valid BMP280 sensor, check wiring!");
}
// NVSの読み出し
load_preferences();
// WiFi接続
wifi_connect();
// 機器固有情報を表示
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(0, 0);
M5.Lcd.printf("Name:%s\n", core_name);
M5.Lcd.printf("Offset:%+4.2f\n", sensor_offset1);
#if defined(ARDUINO_M5Stack_Core_ESP32)
M5.Lcd.print("IP:");
M5.Lcd.println(WiFi.localIP());
#endif
// 初回データ送信時刻を設定
nextUpdate = millis() + 1000;
}

void loop() {
// 最新状態の取得
float temp = dht12.readTemperature() + sensor_offset1;
float humi = dht12.readHumidity();
float pres = bme.readPressure();
// 画面更新
#if defined(ARDUINO_M5Stack_Core_ESP32)
M5.Lcd.setCursor(0, 120);
M5.Lcd.printf("Temp:%4.1fC\nHumi:%2.0f%%\n", temp, humi);
M5.Lcd.printf("Pressure:%6.0fPa\n", pres);
#elif defined(ARDUINO_M5Stick_C)
M5.Lcd.setCursor(0, 40);
M5.Lcd.printf("T:%4.1fC H:%2.0f%%\nP:%6.0fPa\n", temp, humi, pres);
#endif
// Machinistへ送信
if ( nextUpdate <= millis() ) {
sendData("Env", "Temp", temp, "1");
// 次回送信は1分=60000ミリ秒後
nextUpdate = nextUpdate + 60000;
}
// 画面更新は1秒=1000ミリ秒後
delay(1000);
}

なお、M5Stack Basicのときと同様に、WiFi接続情報、MachinistのAPIキーなどをNVSに格納しておく必要があります。NVSへの書き込みコードは、前回の記事に掲載されているM5Stack Basicと同じものが利用できます。

複数ポイントで室内温度を測定・記録する

また、今回のコードは、M5Stack BasicにもM5Stick Cにも両対応しています。料対応にする方法については、次回の記事で説明します。

M5StackとM5Stick Cでコードを共通化する

測定値を画面に表示し、Machinistに送信する

使い方は、M5Stack Basic+ENV UnitもM5Stick C+ENV Hatも同じです。混在して使うことも問題ありません。誤差も同様な方法で修正できます。M5Stick Cは1台あたりの単価が安価な分、台数を増やせるのがよいところです。