M5StickC Plus に Grove Water Level Sensor をつなげるメモ
M5StickC Plus に Grove Water Level Sensor をつなげるメモです。
先日行われた 【オンラインコラボ企画】ゆるメカトロ・Noodl・ビジュアルプログラミングで合同もくもく会 で進めたものをまとめました。
Grove Water Level Sensor

スイッチサイエンスで Grove - 水位センサ(10cm) を購入しました。

このセンサーは 0 ~ 100 mm で 5mm 刻みで I2C でデータが取れます。実際の動かし方は Seeed 社本家の Wiki の Arduinoソースを参考にしました。
Grove - Water Level Sensor - Seeed Wiki
M5Stick C Plus の Hello World でハマる
M5StickC のソースのまま M5StickC Plus 動かそうとしたら全然動かなくて、「え、M5StickC Plus、M5StickCと違うの?」ってなったとき、以下の記事もとても助かりました。ありがとうございます~。
M5StickCとM5StickC Plusの違い – Lang-ship
M5StickC Plus の独立してる Arduino ライブラリとして入れて動かします。

このようなソースです。
// #include <M5StickC.h>
#include <M5StickCPlus.h>
void setup(){
// Initialize
M5.begin();
// LCD display
M5.Lcd.setRotation(3);
M5.Lcd.setTextSize(2);
M5.Lcd.println("[M5StickCPlus]");
M5.Lcd.println("");
M5.Lcd.setTextSize(3);
M5.Lcd.println("Hello World,");
M5.Lcd.setTextSize(2);
M5.Lcd.println("finally(>_<;)");
}
void loop() {
}
M5Stick C Plus に Grove Water Level Sensor をつなげる
あとは こちらのプログラム を M5Stick C Plus に合体させればOKです。

このセンサーはタッチセンサーのような仕組みで水をとらえているようで、実は指で抑えてもテストすることができます。
https://twitter.com/1ft_seabass/status/1299571231843180550
ちゃんと 0 cm のところから連続して触れると水位レベルとしてとらえられます。仮に、指が一部密着 0 cm のところから密着しているところまでが水位となりますのでテスト時は注意ください。
実際にはこのようなソースを書きました。
// #include <M5StickC.h>
#include <M5StickCPlus.h>
#include <Wire.h>
#ifdef ARDUINO_SAMD_VARIANT_COMPLIANCE
#define SERIAL SerialUSB
#else
#define SERIAL Serial
#endif
unsigned char low_data[8] = {0};
unsigned char high_data[12] = {0};
#define NO_TOUCH 0xFE
#define THRESHOLD 100
#define ATTINY1_HIGH_ADDR 0x78
#define ATTINY2_LOW_ADDR 0x77
void getHigh12SectionValue(void)
{
memset(high_data, 0, sizeof(high_data));
Wire.requestFrom(ATTINY1_HIGH_ADDR, 12);
while (12 != Wire.available());
for (int i = 0; i < 12; i++) {
high_data[i] = Wire.read();
}
delay(10);
}
void getLow8SectionValue(void)
{
memset(low_data, 0, sizeof(low_data));
Wire.requestFrom(ATTINY2_LOW_ADDR, 8);
while (8 != Wire.available());
for (int i = 0; i < 8 ; i++) {
low_data[i] = Wire.read(); // receive a byte as character
}
delay(10);
}
void check()
{
int sensorvalue_min = 250;
int sensorvalue_max = 255;
int low_count = 0;
int high_count = 0;
while (1)
{
uint32_t touch_val = 0;
uint8_t trig_section = 0;
low_count = 0;
high_count = 0;
getLow8SectionValue();
getHigh12SectionValue();
Serial.println("low 8 sections value = ");
for (int i = 0; i < 8; i++)
{
Serial.print(low_data[i]);
Serial.print(".");
if (low_data[i] >= sensorvalue_min && low_data[i] <= sensorvalue_max)
{
low_count++;
}
if (low_count == 8)
{
Serial.print(" ");
Serial.print("PASS");
}
}
Serial.println(" ");
Serial.println(" ");
Serial.println("high 12 sections value = ");
for (int i = 0; i < 12; i++)
{
Serial.print(high_data[i]);
Serial.print(".");
if (high_data[i] >= sensorvalue_min && high_data[i] <= sensorvalue_max)
{
high_count++;
}
if (high_count == 12)
{
Serial.print(" ");
Serial.print("PASS");
}
}
Serial.println(" ");
Serial.println(" ");
for (int i = 0 ; i < 8; i++) {
if (low_data[i] > THRESHOLD) {
touch_val |= 1 << i;
}
}
for (int i = 0 ; i < 12; i++) {
if (high_data[i] > THRESHOLD) {
touch_val |= (uint32_t)1 << (8 + i);
}
}
while (touch_val & 0x01)
{
trig_section++;
touch_val >>= 1;
}
SERIAL.print("water level = ");
SERIAL.print(trig_section * 5);
SERIAL.println("% ");
M5.Lcd.setCursor(0, 50);
// M5.Lcd.fillScreen(TFT_BLACK);
// M5.Lcd.print("water level = ");
M5.Lcd.setTextSize(5);
M5.Lcd.print(trig_section * 5);
// M5.Lcd.setTextSize(4);
M5.Lcd.println("% ");
SERIAL.println(" ");
SERIAL.println("*********************************************************");
delay(1000);
}
}
// the setup routine runs once when M5StickC starts up
void setup(){
// Initialize the M5StickC object
M5.begin();
M5.Lcd.setRotation(3);
M5.Lcd.setTextSize(2);
// LCD display
M5.Lcd.print("Hello World");
M5.Lcd.setCursor(0, 0);
M5.Lcd.setTextSize(3);
M5.Lcd.fillScreen(TFT_BLACK);
M5.Lcd.print("[water Lv]");
SERIAL.begin(115200);
Wire.begin();
}
// the loop routine runs over and over again forever
void loop() {
check();
}
実際にはこのように動きます。