M5CoreInk with Env3_Hat
2021/12/28
使ってみるとバッテリが消耗しやすいので
NTP同期がないと不便と感じたので、
NTP同期を追加した。
2021/12/27+
バッテリ状態の表示を追加した。
2021/12/26
初版
M5CoreInk with Env3_Hat
M5CoreInk with Env3_Hat
概要
platformioベースのArduinoフレームワークで、
「M5Stack CoreInk 開発キット(1.5インチ Einkディスプレイ)」に「M5StickC ENV Hat III (SHT30/QMP6988)」を接続して、温度、湿度、気圧、時刻、バッテリ状態を表示する。
ホスト環境は、ubuntu20.04とする。
なお、platformioがインストール済みのものとする。
linuxのplatformioのインストールについては以下を参照のこと。
・arduinoフレームワーク用platformio.ini集
ソース(DISP3_ENV3_HAT)
src/main.ino
//#include <M5Stack.h>
#include "M5CoreInk.h"
#include "Wire.h"
#include "UNIT_ENV.h"
#include "esp_adc_cal.h"
#define NTP_SYNC
#ifdef NTP_SYNC
#include <WiFi.h>
const char* ssid = "your_ssid";
const char* password = "your_password";
const char* ntpServer = "ntp.jst.mfeed.ad.jp";
#endif
#define DISPTIME
#define DISPBAT
#include "time.h"
Ink_Sprite InkPageSprite(&M5.M5Ink);
SHT3X sht30;
QMP6988 qmp6988;
float tmp = 0.0;
float hum = 0.0;
float pressure = 0.0;
char titleStrbuff[64];
char tempStrbuff[64];
char humStrbuff[64];
char pressStrbuff[64];
#ifdef DISPTIME
char dateStrbuff[64];
//char weekStrbuff[64];
char timeStrbuff[64];
static const char *wd[7] = {"Sun","Mon","Tue","Wed","Thr","Fri","Sat"};
RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;
#endif
#ifdef DISPBAT
char batteryStrbuff[64];
int getBatCapacity() {
// 4.02 = 100%, 3.65 = 0%
const float maxVoltage = 4.02;
const float minVoltage = 3.65;
int cap = (int) (100.0 * (getBatVoltage() - minVoltage)
/ (maxVoltage - minVoltage));
if (cap > 100) {
cap = 100;
}
if (cap < 0) {
cap = 0;
}
return cap;
}
float getBatVoltage() {
analogSetPinAttenuation(35, ADC_11db);
esp_adc_cal_characteristics_t *adc_chars =
(esp_adc_cal_characteristics_t*) calloc(1,
sizeof(esp_adc_cal_characteristics_t));
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12,
3600, adc_chars);
uint16_t ADCValue = analogRead(35);
uint32_t BatVolmV = esp_adc_cal_raw_to_voltage(ADCValue, adc_chars);
float BatVol = float(BatVolmV) * 25.1 / 5.1 / 1000;
free(adc_chars);
return BatVol;
}
#endif
void ButtonTest(char* str)
{
InkPageSprite.clear();
InkPageSprite.drawString(35,59,str);
InkPageSprite.pushSprite();
// delay(2000);
}
void ENV_HAT(void)
{
InkPageSprite.clear();
if (sht30.get() == 0) {
tmp = sht30.cTemp;
hum = sht30.humidity;
pressure = qmp6988.calcPressure() / 100;
} else {
tmp = 0.0;
hum = 0.0;
pressure = 0.0;
}
Serial.printf("Temperature: %2.2f℃ Humidity: %0.2f%% Pressure: %4.2f hPa\r\n",
sht30.cTemp, sht30.humidity, qmp6988.calcPressure() / 100);
sprintf(titleStrbuff,"ENV III HAT sensing...");
sprintf(tempStrbuff,"temp: %2.1f *C", tmp);
sprintf(humStrbuff,"humi: %0.1f %% ", hum);
sprintf(pressStrbuff,"press: %0.2f hPa", pressure);
InkPageSprite.drawString(10,5,titleStrbuff);
InkPageSprite.drawString(10,20,tempStrbuff);
InkPageSprite.drawString(10,35,humStrbuff);
InkPageSprite.drawString(10,50,pressStrbuff);
#ifdef DISPTIME
#ifdef M5CI
M5.rtc.GetTime(&RTC_TimeStruct);
M5.rtc.GetData(&RTC_DateStruct);
#endif
#ifdef M5STICK_CP
M5.Rtc.GetTime(&RTC_TimeStruct);
M5.Rtc.GetData(&RTC_DateStruct);
#endif
#ifdef M5C2
M5.Rtc.GetTime(&RTC_TimeStruct);
M5.Rtc.GetDate(&RTC_DateStruct);
#endif
Serial.printf("Date: %04d-%02d-%02d\r\n",
RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date);
Serial.printf("Week: %s\r\n", wd[RTC_DateStruct.WeekDay]);
Serial.printf("Time: %02d:%02d:%02d\r\n",
RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds);
sprintf(dateStrbuff,"%04d-%02d-%02d(%s)",
RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date,
wd[RTC_DateStruct.WeekDay]);
sprintf(timeStrbuff,"%02d:%02d:%02d",
RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds);
InkPageSprite.drawString(10,80,dateStrbuff);
InkPageSprite.drawString(10,95,timeStrbuff);
#endif
#ifdef DISPBAT
Serial.printf("BAT:%2.2fV(%02d%%)\r\n",getBatVoltage(),getBatCapacity());
sprintf(batteryStrbuff,"BAT:%2.2fV(%02d%%)",getBatVoltage(),getBatCapacity());
InkPageSprite.drawString(10,185,batteryStrbuff);
#endif
InkPageSprite.pushSprite();
//delay(15000);
}
void setup() {
/*
//Initialize serial and wait for port to open:
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
*/
M5.begin();
if( !M5.M5Ink.isInit())
{
Serial.printf("Ink Init faild");
}
M5.M5Ink.clear();
delay(1000);
//creat ink refresh Sprite
if( InkPageSprite.creatSprite(0,0,200,200,true) != 0 )
{
Serial.printf("Ink Sprite creat faild");
}
Wire.begin(25, 26); // CoreInk HAT
//Wire.begin(32, 33); // CoreInk EXT. PORT
qmp6988.init();
#ifdef NTP_SYNC
// connect to WiFi
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" CONNECTED");
// Set ntp time to local
configTime(9 * 3600, 0, ntpServer);
// Get local time
struct tm timeInfo;
if (getLocalTime(&timeInfo)) {
Serial.print("NTP: ");
Serial.println(ntpServer);
// Set RTC time
RTC_TimeTypeDef TimeStruct;
TimeStruct.Hours = timeInfo.tm_hour;
TimeStruct.Minutes = timeInfo.tm_min;
TimeStruct.Seconds = timeInfo.tm_sec;
#ifndef M5CI
M5.Rtc.SetTime(&TimeStruct);
#endif
#ifdef M5CI
M5.rtc.SetTime(&TimeStruct);
#endif
RTC_DateTypeDef DateStruct;
DateStruct.WeekDay = timeInfo.tm_wday;
DateStruct.Month = timeInfo.tm_mon + 1;
DateStruct.Date = timeInfo.tm_mday;
DateStruct.Year = timeInfo.tm_year + 1900;
#ifdef M5STICK_CP
M5.Rtc.SetData(&DateStruct);
#endif
#ifdef M5C2
M5.Rtc.SetDate(&DateStruct);
#endif
#ifdef M5CI
M5.rtc.SetData(&DateStruct);
#endif
} // if (getLocalTime(&timeInfo)) {
//disconnect WiFi
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
#endif
}
void loop() {
/*
if( M5.BtnUP.wasPressed()) ButtonTest("Btn UP Pressed");
if( M5.BtnDOWN.wasPressed()) ButtonTest("Btn DOWN Pressed");
if( M5.BtnMID.wasPressed()) ButtonTest("Btn MID Pressed");
if( M5.BtnEXT.wasPressed()) ButtonTest("Btn EXT Pressed");
if( M5.BtnPWR.wasPressed()){
ButtonTest("Btn PWR Pressed");
M5.shutdown();
}
*/
ENV_HAT();
// control refresh rate with key sensing
for (int n = 0; n<30000000; n++) {
if( M5.BtnUP.wasPressed()){
ButtonTest("Btn UP Pressed");
break;
}
if( M5.BtnDOWN.wasPressed()){
ButtonTest("Btn DOWN Pressed");
break;
}
if( M5.BtnMID.wasPressed()){
ButtonTest("Btn MID Pressed");
break;
}
if( M5.BtnEXT.wasPressed()){
ButtonTest("Btn EXT Pressed");
break;
}
if( M5.BtnPWR.wasPressed()){
ButtonTest("Btn PWR Pressed");
M5.shutdown();
}
}
M5.update();
}
・時刻をNTP同期する機能はないので、時刻を合わせる場合、「NTPによる時刻設定(M5StickC_Plus, M5CoreInk, M5Core2)」のスケッチを利用する。
(最新版ではNTP同期を追加したので、これは不要となった)
・デバッグ用に温度、湿度、気圧、時刻、バッテリ状態がシリアル出力される。
・表示の電子インクの制限でフレッシュレートが15秒くらいになっているので、時刻の秒の表示はズレがある。
・課題:delay部分をループに代えて、そのなかでボタンをセンスするようにしたがボタン押下の反応は改善しなかった。他のやり方があるのかもしれない。
(ボタンをセンスするのは、今後の機能拡張のため)
platformio.ini
以下のplatformio.iniを使用する:
[env:M5CoreInk]
platform = espressif32
board = m5stick-c
framework = arduino
build_flags = -DM5CI
upload_poert = /dev/ttyUSB0
monitor_speed = 115200
lib_deps =
m5stack/M5-CoreInk @ ^0.0.2
knolleary/PubSubClient @ ^2.8
m5stack/UNIT_ENV @ ^0.0.2
lib_ldf_mode = deep+
参考情報
応用例:
ENV2_HAT_M5StickC_Plus
M5Paper Clock
M5CoreInk関連:
M5 CoreInkとEnvHat,TVOC/eCO2 ガスセンサユニット(SGP30)で環境モニタを作る
M5Stack CoreInk発売
バッテリ関連:
M5Stack CoreInk、M5Paperのバッテリーについて
CoreInkのバッテリーレベルを取得する
HAT関連:
M5StickC ENV Hat III (SHT30/QMP6988)
M5StickC ENV II Hat(SHT30/BMP280/BMM150搭載)
platformio関連:
arduinoフレームワーク用platformio.ini集
Arduino-IDE関連:
Arduino IDE environment - M5Paper
Arduino IDEのインストールと設定 (Windows, Mac, Linux対応)
M5Stackファミリ関連:
M5Paper Arduino Install
M5CoreInk Arduino Install
M5StickCPlus Arduino Install
M5Stamp-PICO Arduino Install
M5Stamp-C3 Arduino Install
Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(NTP-CLIENT編)
Wio-Terminal/M5Atom/ESP8622/ESP32ボードを共通のスケッチで動かす(v2)(STARWARS編)
Wio-Terminal/M5Atom/ESP8622/ESP32ボードを共通のスケッチで動かす(v2)(MQTT編)
Wio-Terminal/M5Atom/ESP8622/ESP32ボードを共通のスケッチで動かす(v2)(REST-API編)
Wio-Terminal/M5Atom/ESP8622/ESP32ボードを共通のスケッチで動かす(v2)(OSC編)
以上