初めに
I2Cを使って取得可能ないくつかのセンサーデータをsdカードへ保存してみました。
環境
OS: windows 10.0
Arduino IDE:2.0.0
M5stack core2
M5Stack用温湿度気圧センサユニット Ver.3(ENV Ⅲ)link
TVOC/eCO2 ガスセンサユニット(SGP30)link
M5Stack用環境光センサユニット(BH1750FVI-TR)link
#イメージ
M5stack core2から各種センサーに繋いでます。センサーごとにアドレスが違うので、別々に読み出すことができます。
時間
一定時間置きに測定をする場合、ネット環境がなければ、RTCが必要ということが分かりました。RTCは、低消費電力なので別電源で時を刻むことができるため、ネットワークの環境がなくても時を刻んでくれます。そのため、RTCが実装されているM5stack core2を使うことにしました。
一定時間置きにデータをcsvに保存する。
RTCから時間情報を取得し、5分おききにデータ取得するようにしました。時間を5で割って、余りが0のときに、一度測定をして、4分後に測定するフラグを0にして5分おきに測定をできるようにしました。
bool meas_csv = false;
bool write_csv = false;
RTC_TimeTypeDef RTC_TimeStruct; // Time
if (RTC_TimeStruct.Minutes % 5 == 4 ) meas_csv = true;
// get the csv per 5min
if(RTC_TimeStruct.Minutes % 5 == 0){
if (meas_csv == true){
//write data per 5min.
meas_csv = false;
write_csv = true ;
}
}
日付のファイル名で保存する。
SDカードに保存するときの形式に合わせて、RTCのデータを変換するところが苦労しました。
下記のようにsnprintfを使うと、SDカードに保存するための形式に合うようになりました。
char fname[26];
snprintf(fname, 26, "/sensor_data/%04d%02d%02d.csv", RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date);
#プログラム
作成したプログラムは、下記のようになります。file.print
は、取得したデータの形式が違い、合わせこむ方法が分からなかったので、べた書きしてデータを取得するようにしています。
#include <M5Core2.h>
#include <WiFi.h>
#include "time.h"
#include "M5_ENV.h"
#include <M5_DLight.h>
#include "Adafruit_SGP30.h"
// sprite
TFT_eSprite sprite = TFT_eSprite(&M5.Lcd);
extern uint8_t m5_logo[];
// csv file
File file;
// set up sensor
SHT3X sht30;
QMP6988 qmp6988;
M5_DLight sensor;
uint16_t lux;
Adafruit_SGP30 sgp;
long last_millis = 0;
// for WiFi
char ssid[] = "xxxxxxx"; // your SSID
char pass[] = "xxxxxxx"; // your Pass word
float tmp = 0.0;
float hum = 0.0;
float pressure = 0.0;
int meas_btm = 1;
int con_count = 0;
int timer_reset = 0;
bool meas_csv = false;
bool write_csv = false;
char info[40];
// for Time
const char* ntpServer = "ntp.jst.mfeed.ad.jp"; // NTP server
const long gmtOffset_sec = 9 * 3600; // Time offset 9hr
const int daylightOffset_sec = 0; // No summer time
RTC_DateTypeDef RTC_DateStruct; // Data
RTC_TimeTypeDef RTC_TimeStruct; // Time
struct tm timeinfo;
String dateStr;
String timeStr;
void setup() {
M5.begin();
M5.Lcd.setBrightness(10);
M5.Lcd.setRotation(1);
M5.Lcd.setTextSize(2);
M5.Lcd.fillScreen(BLACK);
// connect wifi
if (timer_reset == 1){
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
M5.Lcd.print(".");
con_count++;
if(con_count >= 20){
break;
}
}
if(con_count < 20){
M5.Lcd.print("\nWiFi connected.");
setNTP2RTC();
}else{
M5.Lcd.print("\nWiFi did not connect.");
}
M5.Lcd.print("\nIP=");
M5.Lcd.print(WiFi.localIP());
delay(2 * 1000);
}
// Output logo on the display.
M5.Lcd.fillScreen(BLACK);
M5.Lcd.drawJpg(m5_logo,6374,60, 20);
M5.update();// update button state
delay(2 * 1000);
Wire.begin(); // // Wire init, adding the I2C bus.
qmp6988.init();
if (!sgp.begin()) {
M5.Lcd.println("Sensor not found");
while (1)
;
}
sensor.begin();
sensor.setMode(CONTINUOUSLY_H_RESOLUTION_MODE);
sprite.setColorDepth(8);
sprite.setTextSize(2);
sprite.fillScreen(BLACK);
sprite.createSprite(M5.lcd.width(), M5.lcd.height());
//make a directory
if(!SD.exists("/sensor_data")){
SD.mkdir("/sensor_data");
}
}
void loop() {
sprite.pushSprite( 0, 0);
M5.update();// update button state
if (RTC_TimeStruct.Minutes % 5 == 4 ) meas_csv = true;
// get the csv per 5min
if(RTC_TimeStruct.Minutes % 5 == 0){
if (meas_csv == true){
//write data per 5min.
meas_csv = false;
write_csv = true ;
M5.Rtc.GetDate(&RTC_DateStruct);
M5.Rtc.GetTime(&RTC_TimeStruct);
pressure = qmp6988.calcPressure()* 0.01;
if (sht30.get() == 0) { // Obtain the data of shT30.
tmp = sht30.cTemp; // Store the temperature obtained from shT30.
hum = sht30.humidity; // Store the humidity obtained from the SHT30.
} else {
tmp = 0, hum = 0;
}
// for Touch
TouchPoint_t pos= M5.Touch.getPressPoint();
if(pos.y > 240){
if(pos.x < 109)
sprite.setTextColor(RED,BLACK);
else if(pos.x > 218)
sprite.setTextColor(BLUE,BLACK);
else if(pos.x >= 109 && pos.x <= 218)
sprite.setTextColor(GREEN,BLACK);
}
lux = sensor.getLUX();
if (!sgp.IAQmeasure()) { //Commands the sensor to take a single eCO2/VOC
Serial.println("Measurement failed");
return;
}
delay(1 * 1000);
char fname[26];
snprintf(fname, 26, "/sensor_data/%04d%02d%02d.csv", RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date);
// write data
if(!SD.exists(fname)){
file = SD.open(fname, FILE_APPEND);
file.print("date,time,temperature,humidity,pressure,lux,TVOC,eCO2\n");
file.close();
delay(0.1 * 1000);
}
file = SD.open(fname, FILE_APPEND);
file.print(RTC_DateStruct.Month);
file.print("/");
file.print(RTC_DateStruct.Date);
file.print(",");
file.print(RTC_TimeStruct.Hours);
file.print(":");
if(RTC_TimeStruct.Minutes< 10) file.print("0");
file.print(RTC_TimeStruct.Minutes);
file.print(",");
file.print(tmp);
file.print(",");
file.print(hum);
file.print(",");
file.print(pressure);
file.print(",");
file.print(lux);
file.print(",");
file.print(sgp.TVOC);
file.print(",");
file.print(sgp.eCO2);
file.print("\n");
file.close();
}
}
}