6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【SDカード入門】M5StackでSD読み書きをやってみた♪

Last updated at Posted at 2021-07-21

今回もM5StakのSDカードの使い方をすすめました。
これで書き込みした数値データを、数値データとして利用出来るようになります。
前回までで、SDの読み書きは一応出来ていました。
通常は以下の参考・にあげたようなところまでのようです。これでデータをPCなどでは解析できます。
しかし、リアルタイムに処理する場合は不十分です。
つまり前回の段階では、読み込んで書き出しは出来ますが、数値としてではなくCharとして実施していました。
以下の参考①はSDに書き込まれた数値が単独であればずばりです。
しかし、実際には数値列だったりします。
そこで、参考②のように関数化する必要が出てきます。
そして、数値列を読む関数が、参考③にありました。
そこで、これらの参考を合体させてみると無事にM5StackのIMUで読み込んだ、pitich, roll, yaw, temperatureのデータを塊ごとに数値として取り扱うことが出きるようになリました。
今回、これを簡単にまとめようと思います。
【参考】
Logging data on MicroSD Cards with Arduino
任意の浮動小数点数を文字列に変換、逆変換して元に戻せるか
【C言語】文字列を数値に変換する方法(atoi・strtol など)
Loading Data from SD Card & Sending via Bluetooth to Android

コード解説

コード全体は、おまけに記載しました。
主要な部分のコード解説します。

Sampling

計測は、今までと同様な関数sampling()で実施します。
※setup()でmyFile = SD.open("/temp.txt", FILE_WRITE);しています。
10回計測し、save_temp()関数で書き込みします。

void setup() {
  M5.begin();
  M5.IMU.Init();
 。。。
  myFile = SD.open("/temp.txt", FILE_WRITE); 
  sampling();
  output2();
  Serial.print("Finished");
}


void sampling() {
  for(int i=0; i <10; i++) {
      M5.IMU.getAhrsData(&pitch,&roll,&yaw);
      M5.IMU.getTempData(&temp);
      
      M5.Lcd.printf(" %5.2f   %5.2f   %5.2f  %5.2f \n", pitch, roll, yaw, temp);
      Serial.printf(" %5.2f   %5.2f   %5.2f  %5.2f \n ", pitch, roll, yaw, temp);
      save_temp();
      delay(100);
    }
  }
  myFile.close();
}

save_temp

書き込みも以下のとおり簡単です。
※ここで書式を決めて書き込んでいることが割と重要です

void save_temp(){
  if (myFile) {
    myFile.printf("%5.2f, %5.2f, %5.2f, %5.2f \n", pitch, roll, yaw,temp);
  } else {
    Serial.println("error opening temp.txt");
  }
}

output

ながれは一緒なので、まず読み出して簡単な表示から。
myFile = SD.open("/temp.txt");して、あとは
Serial.write(myFile.read());でSerialモニターに出力できます。
しかし、これはcharを出力しているだけで、数値として使えません。

void output(){
  myFile = SD.open("/temp.txt");  //add "/"
  delay(1);
  if (myFile) {
    Serial.println("temp.txt:");
    M5.Lcd.println("temp.txt:");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      Serial.write(myFile.read());
      delay(10);
    }
  }
  // close the file:
  myFile.close();
}

output2

散々悩んで以下のコードにまとめました。
ほぼ参考③を踏襲ですが、char配列readingを関数conv_str2d(reading);で変換しています。
関数書式が分からなかったので、取得した数値配列をglobal変数としました。
一度、変換してしまえば、M5Stackのディスプレイにも綺麗に表示できました。

double num_[4];

void output2(){
  // re-open the file for reading:
  myFile = SD.open("/temp.txt");
  if (myFile) {
    Serial.println("temp.txt:");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      char reading[30] = "";
      char temp = myFile.read();
      int idx = 0;
      bool somethingWasRead = false;
      while (temp != -1 && temp != 13 && temp != 10){
        reading[idx] = temp;
        temp = myFile.read();
        idx++;
        somethingWasRead = true;
      }
      reading[idx++]='\0';
      //reading[idx] = 10;
      if (somethingWasRead){
       Serial.println(reading);
       delayMicroseconds(500);
      }
      conv_str2d(reading);
      Serial.printf("pitch %5.2f roll %5.2f yaw %5.2f temp %5.2f \n",num_[0],num_[1],num_[2],num_[3]);
      M5.Lcd.printf(" %5.2f %5.2f %5.2f %5.2f \n",num_[0],num_[1],num_[2],num_[3]);
     }
。。。
}

conv_str2d関数

問題の変換関数は以下のようにべたに記載しています。
※一行にまとめられますが、わかりやすいので展開して表示しています。

void conv_str2d(char reading[30]){
  char a[6];
  a[0]=reading[0];a[1]=reading[1];a[2]=reading[2];a[3]=reading[3];a[4]=reading[4];a[5]=reading[5];
  num_[0] = strtod(a, NULL);
  char b[6];
  b[0]=reading[7];b[1]=reading[8];b[2]=reading[9];b[3]=reading[10];b[4]=reading[11];b[5]=reading[12];
  num_[1] = strtod(b, NULL);
  char c[6];
  c[0]=reading[14];c[1]=reading[15];c[2]=reading[16];c[3]=reading[17];c[4]=reading[18];c[5]=reading[19];
  num_[2] = strtod(c, NULL);
  char d[6];
  d[0]=reading[21];d[1]=reading[22];d[2]=reading[23];d[3]=reading[24];d[4]=reading[25];d[5]=reading[26];
  num_[3] = strtod(d, NULL);
}

結果

よくできした!

Initializing SD card...initialization done.
  0.45   -0.05   -8.32  51.09 
   0.94   -0.14   -8.13  51.24 
   1.33   -0.21   -7.97  50.97 
   1.70   -0.25   -7.81  52.29 
   2.07   -0.31   -7.63  50.99 
   2.46   -0.36   -7.46  48.03 
   2.86   -0.43   -7.28  51.89 
   3.14   -0.43   -7.12  49.99 
   3.48   -0.46   -6.93  50.76 
   3.80   -0.49   -6.77  50.26 
 temp.txt:
 0.45, -0.05, -8.32, 51.09 
pitch  0.45 roll -0.05 yaw -8.32 temp 51.09 
 0.94, -0.14, -8.13, 51.24 
pitch  0.94 roll -0.14 yaw -8.13 temp 51.24 
 1.33, -0.21, -7.97, 50.97 
pitch  1.33 roll -0.21 yaw -7.97 temp 50.97 
 1.70, -0.25, -7.81, 52.29 
pitch  1.70 roll -0.25 yaw -7.81 temp 52.29 
 2.07, -0.31, -7.63, 50.99 
pitch  2.07 roll -0.31 yaw -7.63 temp 50.99 
 2.46, -0.36, -7.46, 48.03 
pitch  2.46 roll -0.36 yaw -7.46 temp 48.03 
 2.86, -0.43, -7.28, 51.89 
pitch  2.86 roll -0.43 yaw -7.28 temp 51.89 
 3.14, -0.43, -7.12, 49.99 
pitch  3.14 roll -0.43 yaw -7.12 temp 49.99 
 3.48, -0.46, -6.93, 50.76 
pitch  3.48 roll -0.46 yaw -6.93 temp 50.76 
 3.80, -0.49, -6.77, 50.26 
pitch  3.80 roll -0.49 yaw -6.77 temp 50.26 
Finished
### まとめ ・M5StackでSD書き込み読込みが出きるようになった

・数値データを描画したいと思う

おまけ

# include <SPI.h>
# include <SD.h>
//#define M5STACK_MPU6886 
//#include <M5Stack.h>
# include <M5Core2.h> //core2


float pitch = 0.0F;
float roll  = 0.0F;
float yaw   = 0.0F;
float temp = 0.0F;
int start;
File myFile;

void setup() {
  // Open serial communications and wait for port to open:
  //Serial.begin(115200);
  M5.begin();
  M5.IMU.Init();

  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextColor(GREEN , BLACK);
  M5.Lcd.setTextSize(2);
  start = micros();
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  Serial.print("Initializing SD card...");

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");

  myFile = SD.open("/temp.txt", FILE_WRITE);  //add "/"
  sampling();
  output2();
  Serial.print("Finished");
}

double num_[4];

void save_temp(){
  if (myFile) {
    myFile.printf("%5.2f, %5.2f, %5.2f, %5.2f \n", pitch, roll, yaw,temp);
  } else {
    Serial.println("error opening temp.txt");
  }
}

void sampling() {
  for(int i=0; i <10; i++) {
    M5.update(); // need to call update()
    M5.Lcd.setCursor(0, 0);
    if (M5.BtnB.isPressed()) {
      M5.Lcd.printf("B button is pressed.");
    } else {
      M5.Lcd.printf("B button is released.");
    }
    if (M5.BtnA.wasReleased() || M5.BtnA.pressedFor(1000, 200)) {
      Serial.println("Stop the measure");
      break;     
    }else{
      M5.IMU.getAhrsData(&pitch,&roll,&yaw);
      M5.IMU.getTempData(&temp);
      
      M5.Lcd.printf(" %5.2f   %5.2f   %5.2f  %5.2f \n", pitch, roll, yaw, temp);
      Serial.printf(" %5.2f   %5.2f   %5.2f  %5.2f \n ", pitch, roll, yaw, temp);
      save_temp();
      delay(100);
    }
  }
  myFile.close();
}

void output2(){
  // re-open the file for reading:
  myFile = SD.open("/temp.txt");
  if (myFile) {
    Serial.println("temp.txt:");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      char reading[30] = "";
      char temp = myFile.read();
      int idx = 0;
      bool somethingWasRead = false;
      while (temp != -1 && temp != 13 && temp != 10){
        reading[idx] = temp;
        temp = myFile.read();
        idx++;
        somethingWasRead = true;
      }
      reading[idx++]='\0';
      //reading[idx] = 10;
      if (somethingWasRead){
       Serial.println(reading);
       delayMicroseconds(500);
      }
      conv_str2d(reading);
      Serial.printf("pitch %5.2f roll %5.2f yaw %5.2f temp %5.2f \n",num_[0],num_[1],num_[2],num_[3]);
      M5.Lcd.printf(" %5.2f %5.2f %5.2f %5.2f \n",num_[0],num_[1],num_[2],num_[3]);
     }
    
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening temp.txt");
  }
}

void conv_str2d(char reading[30]){
  char a[6];
  a[0]=reading[0];a[1]=reading[1];a[2]=reading[2];a[3]=reading[3];a[4]=reading[4];a[5]=reading[5];
  num_[0] = strtod(a, NULL);
  char b[6];
  b[0]=reading[7];b[1]=reading[8];b[2]=reading[9];b[3]=reading[10];b[4]=reading[11];b[5]=reading[12];
  num_[1] = strtod(b, NULL);
  char c[6];
  c[0]=reading[14];c[1]=reading[15];c[2]=reading[16];c[3]=reading[17];c[4]=reading[18];c[5]=reading[19];
  num_[2] = strtod(c, NULL);
  char d[6];
  d[0]=reading[21];d[1]=reading[22];d[2]=reading[23];d[3]=reading[24];d[4]=reading[25];d[5]=reading[26];
  num_[3] = strtod(d, NULL);
}

void output(){
  myFile = SD.open("/temp.txt");  //add "/"
  delay(1);
  if (myFile) {
    Serial.println("temp.txt:");
    M5.Lcd.println("temp.txt:");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      Serial.write(myFile.read());
      delay(10);
    }
  }
  // close the file:
  myFile.close();
}

void loop(){
  //nothing
}
6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?