#M5StickCPlus のSPIFFS領域(内部フラッシュ)を扱うシンプルなサンプルコード #Arduino

M5StickCPlusには標準でSDカードなし

センシングしたデータなどを電源が切れても保存しておくためのデータ保存について。M5StackにはSDカードが使えるようですが、M5StickCPlusには残念ながら標準では付いていません。

調べるとSPIFFSというフラッシュメモリの一部を使える事が分かりました。上記のサイトなどを参考にさせて頂きつつ、分かりにくかったところにコメントやSerial.print入れまくって自分なりに整理したものを置いておきます。

サンプルコード SPIFFS_Sample.ino

#include <M5StickCPlus.h>
#include "FS.h"
#include "SPIFFS.h"

const char *FILE_PATH = "/log.txt"; //テキスト保存するファイル名
const char *INIT_STR = ""; //初期化するテキスト;

void readFile() {

  File file = SPIFFS.open(FILE_PATH, "r");
  if (!file || file.isDirectory()) {
    Serial.printf("Failed to open file for reading: %s\r\n", FILE_PATH);
    return;
  } else {
    Serial.printf("Success to open file for reading: %s\r\n", FILE_PATH);
  }

  Serial.println("/////////////////////READ START/////////////////////");

  while (file.available()) {
    Serial.write(file.read());
  }

  Serial.println("/////////////////////READ END/////////////////////");

  file.close();
}

void removeFile() {

  //ファイルが存在すればリムーブできる
  if (SPIFFS.remove(FILE_PATH)) {

    //Serial.println("Remove success.");
    Serial.printf("Remove success: %s\r\n", FILE_PATH);
  } else {

    Serial.printf("Remove failed. Not available.: %s\r\n", FILE_PATH);
  };
}

void writeFile(const char *str) {
  File file = SPIFFS.open(FILE_PATH, FILE_APPEND);

  if (!file) {
    Serial.printf("Failed to open file for appending.: %s\r\n", FILE_PATH);
    return;
  } else {

    Serial.printf("Success to open file for appending.: %s\r\n", FILE_PATH);    

    if (file.print(str)) {

      Serial.printf("File writen: %s\r\n", str);

    } else {

      Serial.printf("File write failed: %s\r\n", str);
    }
  }

  Serial.print("File size:");
  Serial.println(file.size());

  file.close();
}


void resetFile() {

  removeFile();
  writeFile(INIT_STR);
}


void setup() {

  M5.begin();

  if (!SPIFFS.begin(true)) {
    Serial.println("SPIFFS Mount Failed");
    return;
  } else {
    Serial.println("SPIFFS Mount Success");
  }

  resetFile();
  writeFile("Test\r\n");
  writeFile("Test2\r\n");
  writeFile("139.85289,135.7654\r\n");
  readFile();
  readFile();
}

void loop() {
 
}

#M5StickCPlus + Speaker Hat でサンプル音を鳴らす Speaker.ino の改良 #Arduino

M5StickCPlus + Speaker Hat

M5StickCPlusで音を鳴らすサンプルにはArduino IDE / M5StickCPlus ライブラリ付属の Speaker.ino がありますが、ビープ音を鳴らす実装しかされていませんでした。音のデータ配列を鳴らす関数もあるのですがデータが入ってなかったので探してくっつけてみました。

見つけた音データはどうやらM5Stackの起動音的なものらしいです。探して分かったのですがバイナリデータがデカいのでサンプルコードから外されているのかなと思いました。

https://github.com/m5stack/M5Stack/blob/7e863fb9934bcb25f15afa720e9299b8a8e9a8fd/examples/Basics/FactoryTest/startup_music.c

また音を再生する上で26番PINにデータを送るのですがいろいろ試した結果 dacWrite 関数で出力するのが一番素直に再生されているようだったのでledcWriteToneから変更しています。

デモ

ボタンを押すとサンプル音が鳴りました!音質は8bitで古いサンプラーのような味のある音です。

これでM5StickCPlusに付属のMicで録音した音、Webからダウンロードした音・SDカード等から読み出した音を再生したりできそうです。

コード

#include <M5StickCPlus.h>

const int speakerPin = 26;

#define SAMPLES	(40000)
// BITSPERSAMPLE:	8,
// CHANNELS:	1,
#define SAMPLERATE	(20000)
// NORMALIZED:	FALSE,

extern const unsigned char m5stack_startup_music[];

void setup() {

    // put your setup code here, to run once:
    M5.begin();
    M5.Lcd.setRotation(0);
    M5.Lcd.setCursor(25, 80, 4);
    M5.Lcd.println("speaker");
    
}

void playMusic(const uint8_t* music_data,uint16_t sample_rate) {
    
    uint32_t length         = strlen((char*)music_data);
    uint32_t delay_interval = ((uint32_t)1000000 / sample_rate);
    for (int i = 0; i < length; i++) {
        
        dacWrite(speakerPin,music_data[i]);
        delayMicroseconds(delay_interval);
    }

}

void loop() {

  M5.update();

  if(M5.BtnA.wasReleased()){

    M5.Lcd.setCursor(25, 80, 4);
    M5.Lcd.println("playing!");

    //音楽の再生
    playMusic(m5stack_startup_music,SAMPLERATE);
    
    M5.Lcd.setCursor(25, 80, 4);
    M5.Lcd.println("speaker");

  }
   
}

// music from https://github.com/m5stack/M5Stack/blob/7e863fb9934bcb25f15afa720e9299b8a8e9a8fd/examples/Basics/FactoryTest/startup_music.c
const unsigned char m5stack_startup_music[] = {

 //ここに上のリンクの配列データを貼り付ける

 };

#M5StickCPlus でビープを鳴らす

M5Stackがアツいらしい

ちょいと試作をしてみようと思い久しぶりにArduino界隈に触れてみました。M5 Stackという開発環境が流行っているようなので上記の本を元に勉強を進めています。

購入したのはM5 StickC Plus

用途的に細くて軽い方が良かったのでSwitch ScienceにてM5 StickC Plusという製品を買いました。本を進めていると搭載Beep音を鳴らす所でM5 Stackのコードでは単純には動かないものがあり、M5 StickC Plusでは少し書き方が違うので調べました。

M5以下のSpeakerクラスが実装されておらず、代わりにBeepクラスが実装されているようでした。

修正後動いた!

コード(上記の本のサンプルコードのM5 Stick C Plus用 改変版)

#include <M5StickCPlus.h>

//各音符の周波数を定義しています
#define NOTE_C4 261.626  //ド4 C4
#define NOTE_C4b 277.183 //ド#4 C#4
#define NOTE_D4 293.665  //レ4 D4
#define NOTE_D4b 311.127 //レ#4 D#4
#define NOTE_E4 329.628  //ミ4 E4
#define NOTE_F4 349.228  //ファ4 F4
#define NOTE_F4b 369.994 //ファ#4 F#4
#define NOTE_G4 391.995  //ソ4 G4
#define NOTE_G4b 415.305 //ソ#4 G#4
#define NOTE_A4 440.000  //ラ4 A4
#define NOTE_A4b 466.164 //ラ#4 A#4
#define NOTE_B4 493.883  //シ4 B4
#define NOTE_C5 523.251  //ド5 C5
#define NOTE_C5b 554.365 //ド#5 C#5
#define NOTE_D5 587.330  //レ5 D5
#define NOTE_D5b 622.254 //レ#5 D#5
#define NOTE_E5 659.255  //ミ5 E5
#define NOTE_F5 698.456  //ファ5 F5
#define NOTE_F5b 739.989 //ファ#5 F#5
#define NOTE_G5 783.991  //ソ5 G5
#define NOTE_G5b 830.609 //ソ#5 G#5
#define NOTE_A5 880.000  //ラ5 A5
#define NOTE_A5b 932.328 //ラ#5 A#5
#define NOTE_B5 987.767  //シ5 B5
#define NOTE_C6 1046.502 //ド6 C6

//音符の長さをミリ秒で定義しています
#define R_4 2800
#define R_3 2100
#define R_2 1400
#define R_1 700
#define R_1_2 350
#define R_1_3 233.3
#define R_1_4 175
#define R_1_6 116.6
#define R_1_8 87.5
#define R_1_12 58.3
#define R_1_16 43.75

//エルガー「愛の挨拶」のメロディ
float salut[][2] =
{
  {NOTE_G5b, R_1},   {NOTE_B4, R_1_2}, {NOTE_G5b, R_1_2},
  {NOTE_F5b, R_1_2}, {NOTE_E5, R_1_2}, {NOTE_D5b, R_1_2}, {NOTE_E5, R_1_2},
  {NOTE_A5, R_1},   {NOTE_A5, R_1}, {NOTE_A5, R_1},    {NOTE_B4, R_1_2}
};

void setup() {
  M5.begin();
}

void loop() {
  //ボタンA(左のボタン)が押されたとき
  if (M5.BtnA.wasPressed()) {
    //スピーカーからブザー音を鳴らします
    M5.Beep.beep();
  }
  //ボタンB(中央のボタン)が押されたとき
  if (M5.BtnB.wasPressed()) {
    //配列salutを順番に読み込みます
    for (int i = 0; i < sizeof(salut) / sizeof(salut[0]); i++) {
      //[i][0]番目の要素の周波数をスピーカーから鳴らします。
      M5.Beep.tone(salut[i][0]);
      //[i][1]番目の要素の時間待ちます(音符の長さ)
      delay(salut[i][1]);
    }
    M5.Beep.end();
  }

  // M5Stackのボタン操作やスピーカーの状態を更新します
  M5.update();
}

秋月で売ってるESP-WROOM-02 DIPへ、FTDI USBシリアル変換アダプターで書き込むぞい

FullSizeRender 3

秋月電子通商Wi-Fiモジュール ESP-WROOM-02 DIPへSwitch ScienceのFTDI USBシリアル変換アダプターで書き込むためのブレッドボードメモ。

  • 書き込んだプログラムを走らせる場合、IO0とGNDを繋げているジャンパーピンを取り外す。
  • FIDI USBシリアル変換アダプタの電圧を3.3vにしておく。(ジャンパーピンで電圧を変更できる。)
  • 抵抗10KΩ

FTDI USBシリアル変換アダプターでCerevo CDP-ESP8266へArduinoファーム書き込んだ思い出

Cerevo CDP-ESP8266

FullSizeRender 5

手持ちの半田コテが少し太かったので、半田付け難しかった。

Switch Science FTDI USBシリアル変換アダプター

FullSizeRender 4

接続はCerevo Tech Blogを参考にしました。画面上は、数年前にArduino Pro miniに書き込むように購入していたUSBシリアル変換アダプタ。3.3v出力ができたので簡単だった。左はI2C確認用にPCA9622DR搭載したLEDモジュール。ESP8266のIO5とIO4と接続している。

FullSizeRender 6

モジュールの組み合わせで色々試すのは分かってきたので、次はユニバーサル基板で回路組んでみたい。