0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

71歳の... ESP32-S3で簡単音楽。microSDカードの「きらきら星」を、「ledcWriteTone」で再生してみた。

Posted at

 これまで、Arduinoでの音楽再生として

 1.TMRpcm ライブラリ
 2.DFPlayer mini
 3.DACモジュール

など、いろいろ試してきました。今回は、もっとも簡単な方法です。「microSDカード」にデータを入れて置きます。ですから、カード内のテキストファイルを書き直すことにより曲はいくらでも変更できます。
 環境/構成です。

1.Windows 11 Pro
2.Arduino IDE 2.3.6
3.FREENOVE ESP32-S3 WROOM Cam ボード(FNK0085)
  microSDカードスロット付き(ただし、カメラモジュールは使わない)
4."SD_MMC.h" ライブラリ
5.microSDカード
6.PWMで音を出すための接続。目でもわかるようにLEDを直列に。
  PWM_PIN(14) -> 300Ω -> LED -> 小型speaker-> GND

 曲を用意します。有名な「きらきら星」のAパートです。周波数と継続時間(単位は500ms)を順にテキストファイルにします。そして、エンコードutf-8でカードに保存。ファイル名は何でもよいのでtone.txtとしておきます。

tone.txt
523 2
523 2
784 2
784 2
880 2
880 2
784 4
698 2
698 2
659 2
659 2
587 2
587 2
523 4

スケッチの中で次のように読取り、実行させます。

  String s, fn = _rt + "tone.txt";
  if (SD_MMC.exists(fn)) {
    File fp = SD_MMC.open(fn, FILE_READ);
    if (fp) {
      s = " --- " + fn + " begin ...";
      Serial.println(s);
      while (fp.available()) {  // read from the file until there's nothing else in it
        String line = fp.readStringUntil('\n');
        line.trim();
        Serial.println(line);
        l_buffer.push_back(line);
      }
      fp.close();  // close the file:
      s = " --- " + fn + " ends.";
      Serial.println(s);

      int tone=0;
      while(l_buffer[tone]){
        String line=l_buffer[tone];
        int n = 2;  // "freq duration"
        String za[n];
        int co[n];
        bool flag = true;
        if (split(line, ' ', za, n) != n) flag = false;
        for (int i = 0; i < n; i++) {
          if (!(co[i] = za[i].toInt())) {
            flag = false;
            break;
          }
        }
        if (flag) {
          ledcWriteTone(PWM_PIN, co[0]);  // freq
          delay(co[1] * 500);             // duration
          ledcWriteTone(PWM_PIN, 0);
        }
        tone++;
      }

    } else {  // if the file didn't open, print an error
      s = " --- " + fn + " open error.";
      Serial.println(s);
    }
  } else {
    s = " --- " + fn + " not exists.";
    Serial.println(s);
  }

 スケッチ全体です。標準の「sd_read_write.cpp」「sread_write.h」をスケッチと同じフォルダーにコピーしておいてください。

Play_Kirakira.ino
#include "sd_read_write.h"
#include "SD_MMC.h"
#include <string>
#include <vector>
using namespace std;

// SD_MMC FREENOVE ESP32-S3 WROOM 内蔵SDスロット使用のため
#define SD_MMC_CMD 38  // MISO. Please do not modify it.
#define SD_MMC_CLK 39  // CLK.  Please do not modify it.
#define SD_MMC_D0 40   // MOSI. Please do not modify it.

File fp;
const String _rt = "/";
std::vector<String> l_buffer;
const int PWM_PIN = 14;

void setup() {
  Serial.begin(115200);
  Serial.println("DOS PC Console Start");
  SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
  if (!SD_MMC.begin("/SD", true, true, SDMMC_FREQ_DEFAULT, 5)) {
    Serial.println("Card Mount Failed");
    return;
  }
  SD_Info();

  ledcAttach(PWM_PIN, 24000, 8);  // for tone

  String s, fn = _rt + "tone.txt";
  if (SD_MMC.exists(fn)) {
    File fp = SD_MMC.open(fn, FILE_READ);
    if (fp) {
      s = " --- " + fn + " begin ...";
      Serial.println(s);
      while (fp.available()) {  // read from the file until there's nothing else in it
        String line = fp.readStringUntil('\n');
        line.trim();
        Serial.println(line);
        l_buffer.push_back(line);
      }
      fp.close();  // close the file:
      s = " --- " + fn + " ends.";
      Serial.println(s);

      int tone=0;
      while(l_buffer[tone]){
        String line=l_buffer[tone];
        int n = 2;  // "freq duration"
        String za[n];
        int co[n];
        bool flag = true;
        if (split(line, ' ', za, n) != n) flag = false;
        for (int i = 0; i < n; i++) {
          if (!(co[i] = za[i].toInt())) {
            flag = false;
            break;
          }
        }
        if (flag) {
          ledcWriteTone(PWM_PIN, co[0]);  // freq
          delay(co[1] * 500);             // duration
          ledcWriteTone(PWM_PIN, 0);
        }
        tone++;
      }

    } else {  // if the file didn't open, print an error
      s = " --- " + fn + " open error.";
      Serial.println(s);
    }
  } else {
    s = " --- " + fn + " not exists.";
    Serial.println(s);
  }
}

void loop() {
}

int split(String data, char delimiter, String* dst, int num) {
  int index = 0;
  int len = data.length();
  for (int i = 0; i < len; i++) {
    char tmp = data.charAt(i);
    if (tmp == delimiter) {
      index++;
      if (index > num - 1) return -1;
    } else {
      dst[index] += tmp;
    }
  }
  return index + 1;
}

void SD_Info() {
  uint8_t cardType = SD_MMC.cardType();  // カード情報
  String s = "Card Type: ";
  if (cardType == CARD_MMC) s += "MMC";
  else if (cardType == CARD_SD) s += "SDSC";
  else if (cardType == CARD_SDHC) s += "SDHC";
  else s += "UNKNOWN";
  Serial.println(s);
  uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024 * 1024);
  s = "Card Size: " + (String)(cardSize) + "GB";
  Serial.println(s);
}

 10年以上前、STM32VLDiscoveryでもっと面倒なプログラムでやってました。それの簡易版が作れました。利用される場合は、microSDカードが壊れるかもしれませんので、自己責任で。最後まで見ていただきありがとうございました。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?