M5StickC
前回、M5StickCとENV II HATを使って、M5StickCのディスプレイとシリアルに地磁気のデータを出力するプログラムを作成しました。
今回は取得した地磁気データをSPIFFS領域に保存し、正面ボタンを押したら保存したデータをシリアルに出力、その後ファイルを新規作成、上書きすることで空にするプログラムを書いていきましょう。
プログラム全体
まずはプログラム全体をお見せします。
#include <M5StickC.h>
#include "SHT3X.h"
#include <Wire.h>
#include "Adafruit_Sensor.h"
#include <Adafruit_BMP280.h>
#include "bmm150.h"
#include "bmm150_defs.h"
#include <SPIFFS.h>
String file_name = "/M5Stack/notes.txt";
SHT3X sht3x;
BMM150 bmm = BMM150();
bmm150_mag_data value_offset;
Adafruit_BMP280 bme;
float tmp = 0.0;
float hum = 0.0;
float pressure = 0.0;
int cycle = 0;
void calibrate(uint32_t timeout)
{
int16_t value_x_min = 0;
int16_t value_x_max = 0;
int16_t value_y_min = 0;
int16_t value_y_max = 0;
int16_t value_z_min = 0;
int16_t value_z_max = 0;
uint32_t timeStart = 0;
bmm.read_mag_data();
value_x_min = bmm.raw_mag_data.raw_datax;
value_x_max = bmm.raw_mag_data.raw_datax;
value_y_min = bmm.raw_mag_data.raw_datay;
value_y_max = bmm.raw_mag_data.raw_datay;
value_z_min = bmm.raw_mag_data.raw_dataz;
value_z_max = bmm.raw_mag_data.raw_dataz;
delay(100);
timeStart = millis();
while((millis() - timeStart) < timeout)
{
bmm.read_mag_data();
/* Update x-Axis max/min value */
if(value_x_min > bmm.raw_mag_data.raw_datax)
{
value_x_min = bmm.raw_mag_data.raw_datax;
// Serial.print("Update value_x_min: ");
// Serial.println(value_x_min);
}
else if(value_x_max < bmm.raw_mag_data.raw_datax)
{
value_x_max = bmm.raw_mag_data.raw_datax;
// Serial.print("update value_x_max: ");
// Serial.println(value_x_max);
}
/* Update y-Axis max/min value */
if(value_y_min > bmm.raw_mag_data.raw_datay)
{
value_y_min = bmm.raw_mag_data.raw_datay;
// Serial.print("Update value_y_min: ");
// Serial.println(value_y_min);
}
else if(value_y_max < bmm.raw_mag_data.raw_datay)
{
value_y_max = bmm.raw_mag_data.raw_datay;
// Serial.print("update value_y_max: ");
// Serial.println(value_y_max);
}
/* Update z-Axis max/min value */
if(value_z_min > bmm.raw_mag_data.raw_dataz)
{
value_z_min = bmm.raw_mag_data.raw_dataz;
// Serial.print("Update value_z_min: ");
// Serial.println(value_z_min);
}
else if(value_z_max < bmm.raw_mag_data.raw_dataz)
{
value_z_max = bmm.raw_mag_data.raw_dataz;
// Serial.print("update value_z_max: ");
// Serial.println(value_z_max);
}
Serial.print(".");
delay(1);
}
value_offset.x = value_x_min + (value_x_max - value_x_min)/2;
value_offset.y = value_y_min + (value_y_max - value_y_min)/2;
value_offset.z = value_z_min + (value_z_max - value_z_min)/2;
}
void setup() {
M5.begin();
Wire.begin(0,26);
M5.Lcd.setRotation(3);
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setCursor(0, 0, 2);
M5.Lcd.println("ENV TEST");
pinMode(M5_BUTTON_HOME, INPUT);
if(bmm.initialize() == BMM150_E_ID_NOT_CONFORM) {
Serial.println("Chip ID can not read!");
while(1);
} else {
Serial.println("Initialize done!");
}
if (!bme.begin(0x76)){
Serial.println("Could not find a valid BMP280 sensor, check wiring!");
while (1);
}
calibrate(10);
Serial.println("Calibrate done..");
M5.Lcd.println("ENV TEST Done!");
if(SPIFFS.begin()){ // Start SPIFFS, return 1 on success. 启动闪存文件系统,若成功返回1
M5.Lcd.println("SPIFFS Begin.");
} else {
M5.Lcd.println("SPIFFS Failed to Begin.\nYou need to Run SPIFFS_Add.ino first");
}
delay(5000);
M5.Lcd.fillScreen(BLACK);
}
uint8_t setup_flag = 1;
void loop() {
M5.Lcd.fillScreen(BLACK);
bmm150_mag_data value;
bmm.read_mag_data();
value.x = bmm.raw_mag_data.raw_datax;
value.y = bmm.raw_mag_data.raw_datay;
value.z = bmm.raw_mag_data.raw_dataz;
//Serial.printf("%d, %d, %d, %d\n", cycle, value.x, value.y, value.z);
M5.Lcd.setCursor(0, 0, 2);
M5.Lcd.printf("X; %i", value.x);
M5.Lcd.setCursor(0, 20, 2);
M5.Lcd.printf("Y; %i", value.y);
M5.Lcd.setCursor(0, 40, 2);
M5.Lcd.printf("Z; %i", value.z);
File dataFile = SPIFFS.open(file_name, "a");
char writedata[256];
sprintf(writedata, "%d, %d, %d, %d", cycle, value.x, value.y, value.z);
dataFile.println(writedata);
dataFile.close();
cycle ++;
delay(1000);
M5.update(); //Check whether the key is pressed. 检测按键是否按下
M5.Lcd.fillScreen(BLACK);
if(M5.BtnA.isPressed()){ //If the button is pressed. 如果按键按下
if (SPIFFS.exists(file_name)){ //Check whether the file_name file exists in the flash memory. 确认闪存中是否有file_name文件
M5.Lcd.println("FOUND.");
M5.Lcd.println(file_name);
} else {
M5.Lcd.println("NOT FOUND.");
M5.Lcd.println(file_name);
}
File dataFile = SPIFFS.open(file_name, "r"); // Create aFile object dafaFile to read information to file_name in the SPIFFS. 建立File对象dafaFile用于向SPIFFS中的file_name读取信息
for(int i=0; i<dataFile.size(); i++){
Serial.print((char)dataFile.read());
}
dataFile.close();
dataFile = SPIFFS.open(file_name, "w");
dataFile.close();
cycle = 0;
}
if(!setup_flag){
setup_flag = 1;
if(bmm.initialize() == BMM150_E_ID_NOT_CONFORM) {
Serial.println("Chip ID can not read!");
while(1);
} else {
Serial.println("Initialize done!");
}
if (!bme.begin(0x76)){
Serial.println("Could not find a valid BMP280 sensor, check wiring!");
while (1);
}
calibrate(10);
Serial.println("Calibrate done..");
}
if(digitalRead(M5_BUTTON_HOME) == LOW){
setup_flag = 0;
while(digitalRead(M5_BUTTON_HOME) == LOW);
}
}
前回、スケッチ例からコピーしてきたところは解説を省略しますので、もし疑問に思った部分があったら、前回の記事をご覧ください。
それでは始めていきましょう。
インクルードと設定部分
まずはインクルードと設定部分です。
変更点はSPIFFSに関してで、ヘッダーファイルの追加とファイルパスの定義の追加です。
#include <SPIFFS.h>
String file_name = "/M5Stack/notes.txt";
setup関数
setup関数の最後のところにSPIFFS領域のイニシャライズの成否の条件分岐を追加しました。
if(SPIFFS.begin()){ // Start SPIFFS, return 1 on success. 启动闪存文件系统,若成功返回1
M5.Lcd.println("SPIFFS Begin.");
} else {
M5.Lcd.println("SPIFFS Failed to Begin.\nYou need to Run SPIFFS_Add.ino first");
}
loop関数
loop関数にSPIFFS領域の書き込みを追加しています。
File dataFile = SPIFFS.open(file_name, "a");
char writedata[256];
sprintf(writedata, "%d, %d, %d, %d", cycle, value.x, value.y, value.z);
dataFile.println(writedata);
dataFile.close();
ここで重要なのはSPIFFS領域には文字列で書き込む必要があるということです。
そのため「char writedata[256];」で文字列の変数を定義し、「sprintf(writedata, “%d, %d, %d, %d”, cycle, value.x, value.y, value.z);」で数値データを文字列のデータに変換しています。
そして「dataFile.println(writedata);」でSPIFFS領域に書き込みます。
ちなみに一度、「dataFile.printf(“%d, %d, %d, %d”, cycle, value.x, value.y, value.z);」としたら、シリアルに出力されたデータが文字化けしてでてきました。
細かい変更点ですが、この後のdelayの時間を500ミリ秒から1000ミリ秒に変更しています。
次に正面ボタンを押した際、シリアルに保存したデータを出力し、データ領域を空にする部分を追加しました。
M5.update(); //Check whether the key is pressed. 检测按键是否按下
M5.Lcd.fillScreen(BLACK);
if(M5.BtnA.isPressed()){ //If the button is pressed. 如果按键按下
if (SPIFFS.exists(file_name)){ //Check whether the file_name file exists in the flash memory. 确认闪存中是否有file_name文件
M5.Lcd.println("FOUND.");
M5.Lcd.println(file_name);
} else {
M5.Lcd.println("NOT FOUND.");
M5.Lcd.println(file_name);
}
File dataFile = SPIFFS.open(file_name, "r"); // Create aFile object dafaFile to read information to file_name in the SPIFFS. 建立File对象dafaFile用于向SPIFFS中的file_name读取信息
for(int i=0; i<dataFile.size(); i++){
Serial.print((char)dataFile.read());
}
dataFile.close();
dataFile = SPIFFS.open(file_name, "w");
dataFile.close();
cycle = 0;
}
こちらの部分はSPIFFSのスケッチからほぼコピーしています。
違うのは最初に「M5.Lcd.fillScreen(BLACK);」で画面を一度消していることと最後のファイルを空にして、さらに変数cycleを0に戻しているこの部分です。
dataFile = SPIFFS.open(file_name, "w");
dataFile.close();
cycle = 0;
ここでは「dataFile = SPIFFS.open(file_name, “w”);」でファイルを新規作成して、「dataFile.close();」で閉じるということでファイルを空にしています。
これでプログラムは完了です。
このスケッチをM5StickCに書き込み、正面ボタンを押した時のシリアルの出力を見てみるとこうなります。
ちゃんとデータが保存されていますし、正面ボタンを押してデータの出力、そしてデータ領域を空にするということまでできています。
ただ意図せずイニシャライズとキャリブレーションも同時に行われてしまっていますが、まぁそれはよしとしましょう。
ということでこれでプログラムが完成したので、これからこのスケッチを書き込んだM5StickCを持って、いろんな場所の地磁気を測ってみようと思います。
いくつかデータが溜まった時点で、データ解析に関して記事を書こうと思っています。
ではでは今回はこんな感じで。
コメント