M5ATOMS3で作るコーディングキーボードに挑戦

© CC BY 4+ visibility298
© CC BY 4+
visibility298

小さいマイコン(M5ATOM)を使って楽器を作ろうと思っと思っていたところ、「かんぷれ」のクラウドファンディングを見つけ早速申し込んところ、来年の4月まで手に入らないとの事で、チャレンジしました。

動画
開発素材

デバイス

API

システム構成

<試作1号>

M5ATOM Matrixを使って音の出る電子楽器(キーボード)を作りました。そしてMatrix LED にドレミファソラシドをカラー表示しましました。
1)使ったもの
  |M5ATOM Matrix  |   1個|
  |プッシュスイッチ   |  7個|
  |ブレットボード    |   1個|
  |スピーカー     |   1個|
  |モバイルバッテリー |   1個|
2)回路(ピン端子ーーー音階)
   G22ーーード
   G19---レ
   G23---三
   G33---ファ
   G32---ソ
   G21---ラ
   G25---シ
   G39---ド
   G26---外部スピーカー
3)<試作1号のコード>

#include <M5Atom.h>

#define C4  261
#define D4  294
#define E4  329
#define F4  349
#define G4  392
#define A4  440
#define B4  493
#define C5  523
#define NOTE_DURATION 500 // 各音の持続時間(ミリ秒)

#define BUTTON_PIN_1 22
#define BUTTON_PIN_2 19
#define BUTTON_PIN_3 23
#define BUTTON_PIN_4 33
#define BUTTON_PIN_5 32
#define BUTTON_PIN_6 21
#define BUTTON_PIN_7 25
#define BUTTON_PIN_8 39 //M5ボタンのピン番号

void playTone(int freq, int duration) {
  ledcWriteTone(0, freq);
  delay(duration);
  ledcWriteTone(0, 0); // 音を止める
  delay(50); // 各音の間に少し休止を入れる
}

void setup() {
  M5.begin(true, false, true);
  M5.dis.clear(); 
  // 全てのピクセルを青色に設定
  for (int i = 0; i < 25; i++) {
    M5.dis.drawpix(i, 0x0000FF); // 0x0000FFは青色のRGB値
  }

  //M5.begin();  
  pinMode(BUTTON_PIN_1, INPUT_PULLUP);
  pinMode(BUTTON_PIN_2, INPUT_PULLUP);
  pinMode(BUTTON_PIN_3, INPUT_PULLUP);
  pinMode(BUTTON_PIN_4, INPUT_PULLUP);
  pinMode(BUTTON_PIN_5, INPUT_PULLUP);
  pinMode(BUTTON_PIN_6, INPUT_PULLUP);
  pinMode(BUTTON_PIN_7, INPUT_PULLUP);
  pinMode(BUTTON_PIN_8, INPUT_PULLUP);
  // スピーカーのピンを設定 (M5ATOMの場合、26ピンが一般的)
  ledcAttachPin(26, 0);
}

void loop() {
  
  if (digitalRead(BUTTON_PIN_1) == LOW) {
    int heartShape[25] = {
    //ドの表示  
    0, 0, 0, 0, 0,
    1, 1, 1, 1, 1,  
    0, 0, 1, 0, 0,  
    0, 1, 0, 1, 1,  
    0, 0, 0, 1, 1  
    };
    uint32_t heartColor = 0xFF0000; // 赤色、
     // マトリックスに形を描画
    for (int i = 0; i < 25; i++) {
      if (heartShape[i] == 1) {
        M5.dis.drawpix(i, heartColor);
      } else {
        M5.dis.drawpix(i, 0x000000); // 背景を黒色に設定
      }
    } 
    playTone(C4, NOTE_DURATION);

  } else if (digitalRead(BUTTON_PIN_2) == LOW) {
    int heartShape[25] = {
    //レの表示  
    0, 0, 0, 0, 0,  
    1, 1, 1, 1, 1,
    1, 0, 0, 0, 0,
    0, 1, 0, 0, 0,
    0, 0, 1, 0, 0   
    };
    uint32_t heartColor = 0x00FF00; // 緑色
     // マトリックスに形を描画
    for (int i = 0; i < 25; i++) {
      if (heartShape[i] == 1) {
        M5.dis.drawpix(i, heartColor);
      } else {
        M5.dis.drawpix(i, 0x000000); // 背景を黒色に設定
      }
    } 
    playTone(D4, NOTE_DURATION);

  } else if (digitalRead(BUTTON_PIN_3) == LOW) {
    int heartShape[25] = {
    //ミの表示
    1, 0, 0, 0, 0,  
    1, 0, 1, 0, 1,
    1, 0, 1, 0, 1,
    1, 0, 1, 0, 1,
    0, 0, 0, 0, 1 
    };
  uint32_t heartColor = 0x0000FF; // 青色
     // マトリックスに形を描画
    for (int i = 0; i < 25; i++) {
      if (heartShape[i] == 1) {
        M5.dis.drawpix(i, heartColor);
      } else {
        M5.dis.drawpix(i, 0x000000); // 背景を黒色に設定
      }
    } 
    playTone(E4, NOTE_DURATION);

  } else if (digitalRead(BUTTON_PIN_4) == LOW) {
    int heartShape[25] = {
    //ファの表示
    0, 1, 0, 0, 1,
    0, 0, 1, 0, 1,
    0, 0, 0, 1, 1,
    1, 0, 1, 0, 1,
    0, 1, 1, 0, 0 
    };
  uint32_t heartColor = 0xFF00FF; // 紫色
     // マトリックスに形を描画
    for (int i = 0; i < 25; i++) {
      if (heartShape[i] == 1) {
        M5.dis.drawpix(i, heartColor);
      } else {
        M5.dis.drawpix(i, 0x000000); // 背景を黒色に設定
      }
    } 
    playTone(F4, NOTE_DURATION);

  } else if (digitalRead(BUTTON_PIN_5) == LOW) {
    int heartShape[25] = {
    //ソの表示
    0, 0, 0, 0, 1,
    0, 0, 0, 1, 0,
    1, 0, 0, 0, 0,
    0, 1, 0, 0, 0,
    0, 0, 1, 1, 1  
    };
  uint32_t heartColor = 0xFFFF00; // 黄色
     // マトリックスに形を描画
    for (int i = 0; i < 25; i++) {
      if (heartShape[i] == 1) {
        M5.dis.drawpix(i, heartColor);
      } else {
        M5.dis.drawpix(i, 0x000000); // 背景を黒色に設定
      }
    } 
    playTone(G4, NOTE_DURATION);

  } else if (digitalRead(BUTTON_PIN_6) == LOW) {
    int heartShape[25] = {
    //ラの表示
    0, 0, 1, 0, 1,
    0, 0, 1, 0, 1,
    1, 0, 1, 0, 1,
    0, 1, 1, 0, 1,
    0, 0, 1, 0, 1 
    };
  uint32_t heartColor = 0x00FFFF; // 水色
     // マトリックスに形を描画
    for (int i = 0; i < 25; i++) {
      if (heartShape[i] == 1) {
        M5.dis.drawpix(i, heartColor);
      } else {
        M5.dis.drawpix(i, 0x000000); // 背景を黒色に設定
      }
    } 
    playTone(A4, NOTE_DURATION);
  } else if (digitalRead(BUTTON_PIN_7) == LOW) {
    int heartShape[25] = {
    ///シの表示
    1, 0, 0, 1, 1,
    1, 0, 0, 1, 1,
    0, 1, 0, 0, 0,
    0, 0, 1, 0, 0,
    0, 0, 0, 1, 0 
    };
  uint32_t heartColor = 0xFFFFFF; // 白色
     // マトリックスに形を描画
    for (int i = 0; i < 25; i++) {
      if (heartShape[i] == 1) {
        M5.dis.drawpix(i, heartColor);
      } else {
        M5.dis.drawpix(i, 0x000000); // 背景を黒色に設定
      }
    } 
    playTone(B4, NOTE_DURATION);
  } else if (digitalRead(BUTTON_PIN_8) == LOW) {
    int heartShape[25] = {
    //ドの表示  
    1, 1, 1, 1, 1,  
    0, 0, 1, 0, 0, 
    0, 1, 0, 0, 0,  
    0, 0, 0, 1, 1,  
    0, 0, 0, 1, 1  
    };
    uint32_t heartColor = 0xFFA500; // オレンジ色、
     // マトリックスに形を描画
    for (int i = 0; i < 25; i++) {
      if (heartShape[i] == 1) {
        M5.dis.drawpix(i, heartColor);
      } else {
        M5.dis.drawpix(i, 0x000000); // 背景を黒色に設定
      }
    } 
    playTone(C5, NOTE_DURATION);
  }
}

<試作2号>

M5ATOM Matrixでは、7音階は各キーで鳴らす事は出来ましたが、和音がどうしても上手く鳴らない為、M5ATOM S3を使うことにしました。これのディスプレーには、和音コードを表示します。
1)使ったもの
  ・M5ATOM S3       1個
  ・キースイッチ       9個
  ・キースイッチ基板     1個
  ・スピーカー        1個
  ・モバイルバッテリー    1個
  ・ケース          1個(これから作る)
2)回路(ピン端子ーーー和音コード)
   G5ーーーCメジャー
   G6---Dメジャー
   G7---Fメジャー
   G8---Gメジャー
   G1---Aメジャー
   G38---Bメジャー
   G39---♭
   G ーーー~
   G26---外部スピーカー

YouTube(試作2号機) https://youtu.be/R-dJpS1Z2LM

3)<試作2号のコード>

#include <M5AtomS3.h>
#include <Arduino.h>

#define SPEAKER_PIN 2

const int sampleRate = 8000; // サンプルレート
const int amplitude = 127; // 振幅
const int offset = 128; // オフセット

#define NOTE_DURATION 300 // 各音の持続時間(ミリ秒)

#define BUTTON_PIN_1 5
#define BUTTON_PIN_2 6
#define BUTTON_PIN_3 7
#define BUTTON_PIN_4 8
#define BUTTON_PIN_5 1
#define BUTTON_PIN_6 38
#define BUTTON_PIN_7 39
//  #define BUTTON_PIN_8  //M5ボタンのピン番号

void playTone(int freq, int duration) {
  ledcWriteTone(0, freq);
  delay(duration);
  ledcWriteTone(0, 0); // 音を止める
  delay(50); // 各音の間に少し休止を入れる
}

void setup() {
  M5.begin();   //true, false, true);

//  }
    pinMode(SPEAKER_PIN, OUTPUT);
    ledcSetup(0, sampleRate, 8); // チャンネル0、サンプルレート8000Hz、8ビット解像度
    ledcAttachPin(SPEAKER_PIN, 0); // GPIO 26にチャンネル0をアタッチ

    //  初期画面表示
    AtomS3.Display.setTextColor(GREEN);
    AtomS3.Display.setTextFont(&fonts::Font4);
    AtomS3.Display.setTextSize(1);  // 1~5
    AtomS3.Display.setRotation(1);  // 0~3
    AtomS3.Display.setTextDatum(bottom_center);    // middle__bottom__top
    AtomS3.Display.drawString("AtomS3", AtomS3.Display.width() / 2, AtomS3.Display.height() / 2);
    AtomS3.Display.setTextDatum(top_center);
    AtomS3.Display.drawString("Chorder", AtomS3.Display.width() / 2, AtomS3.Display.height() / 2);
 
    //M5.begin();  
  pinMode(BUTTON_PIN_1, INPUT_PULLUP);
  pinMode(BUTTON_PIN_2, INPUT_PULLUP);
  pinMode(BUTTON_PIN_3, INPUT_PULLUP);
  pinMode(BUTTON_PIN_4, INPUT_PULLUP);
  pinMode(BUTTON_PIN_5, INPUT_PULLUP);
  pinMode(BUTTON_PIN_6, INPUT_PULLUP);
  pinMode(BUTTON_PIN_7, INPUT_PULLUP);
//  pinMode(BUTTON_PIN_8, INPUT_PULLUP);
}

void playChord(float freq1, float freq2, float freq3, int duration) {
    for (int i = 0; i < sampleRate * duration / 1000; i++) {
        int sample = (sin(2 * PI * freq1 * i / sampleRate) + 
                      sin(2 * PI * freq2 * i / sampleRate) + 
                      sin(2 * PI * freq3 * i / sampleRate)) * amplitude / 3 + offset;
        ledcWrite(0, sample);
        delayMicroseconds(1000000 / sampleRate);
    }
    ledcWrite(0, 0); // 音を停止
}

void loop() {
  AtomS3.Display.setTextSize(3);
  AtomS3.Display.setTextDatum(middle_center);    // middle__bottom__top
  AtomS3.update();

    //1: Cメジャーコード (C4, E4, G4)
  if (digitalRead(BUTTON_PIN_1) == LOW) {
      AtomS3.Display.setTextColor(RED);
      AtomS3.Display.clear();
      AtomS3.Display.drawString("C", AtomS3.Display.width() / 2, AtomS3.Display.height() / 2);
    playChord(261.63, 329.63, 392.00, NOTE_DURATION);  // (C4, E4, G4)
    //ledcWrite(0, 0); // 音を停止

    //2: Dメジャーコード (D4, F#4, A4)
  } else if (digitalRead(BUTTON_PIN_2) == LOW) {
      AtomS3.Display.setTextColor(ORANGE);
      AtomS3.Display.clear();
      AtomS3.Display.drawString("D", AtomS3.Display.width() / 2, AtomS3.Display.height() / 2);
    playChord(293.66, 369.99, 440.00, NOTE_DURATION);  //  (D4, F#4, A4)

    //3: Eメジャーコード (E4, G#4, B4)
    } else if (digitalRead(BUTTON_PIN_3) == LOW) {
      AtomS3.Display.setTextColor(GREEN);
      AtomS3.Display.clear();
      AtomS3.Display.drawString("E", AtomS3.Display.width() / 2, AtomS3.Display.height() / 2);
    playChord(329.63, 415.30, 493.88, NOTE_DURATION);  // (E4, G#4, B4)

    //4: Fメジャーコード (F4, A4, C5)
    } else if (digitalRead(BUTTON_PIN_4) == LOW) {
      AtomS3.Display.setTextColor(YELLOW);
      AtomS3.Display.clear();
      AtomS3.Display.drawString("F", AtomS3.Display.width() / 2, AtomS3.Display.height() / 2);
    playChord(349.23, 440.00, 523.25, NOTE_DURATION);  //  (F4, A4, C5)

    //5: Gメジャーコード (G4, B4, D5)
    } else if (digitalRead(BUTTON_PIN_5) == LOW) {
      AtomS3.Display.setTextColor(BLUE);
      AtomS3.Display.clear();
      AtomS3.Display.drawString("G", AtomS3.Display.width() / 2, AtomS3.Display.height() / 2);
    playChord(392.00, 493.88, 587.33, NOTE_DURATION);    // (G4, B4, D5)

    //6: Aメジャーコード (A4, C#5, E5)
    } else if (digitalRead(BUTTON_PIN_6) == LOW) {
      AtomS3.Display.setTextColor(RED);
      AtomS3.Display.clear();
      AtomS3.Display.drawString("A", AtomS3.Display.width() / 2, AtomS3.Display.height() / 2);
    playChord(440.00, 554.37, 659.25, NOTE_DURATION);  //  (A4, C#5, E5)

    //7: Bメジャーコード (B4, D#5, F#5)
    } else if (digitalRead(BUTTON_PIN_7) == LOW) {
      AtomS3.Display.setTextColor(YELLOW);
      AtomS3.Display.clear();
      AtomS3.Display.drawString("B", AtomS3.Display.width() / 2, AtomS3.Display.height() / 2);
    playChord(493.88, 622.25, 739.99, NOTE_DURATION);  //  (B4, D#5, F#5)

    //8: Cメジャーコード (C5, E5, G5)
  //    } else if (digitalRead(BUTTON_PIN_8) == LOW) {

  //  playChord(523.25, 659.25, 783.99, NOTE_DURATION);  //  (C5, E5, G5)

    } 
  
}
ストーリー

<目標>

 「かんぷれ」のクラウドファンディングに、申し込みを行ったところ、目標を達成しても来年4月まで手に入らないと言う事なので、何か音の出る楽器を作ってみようと思いました。 まず初めに、手持ちのM5ATOM Matrixを使って、電子キーボードを作ってみました。次に「かんぷれ」のような和音(コード)が出る様にしようと思いましたが上手く上手く出来ませんでした。 次にM5ATOM S3を使ってみることにしました。Chat GPTのちからを借りて、しょぼいですが和音のようなものが出るようになりました。 今後は、他にもシンセサイザーなどを使ってもっといい音になるよう更に改造したいと思います。

メンバー

Nakkyi's Robot Garage

  • user
    ナッキィー @nakkyi9130
    • ロボット愛好家
    • ロボット設計・製作
    • プログラム・電子工作

関連イベント
  • event M5Stack Japan Creativity Contest 20242024-06-01 開催
  • event つくろか!3 〜よみがえれ、ものづくり百鬼夜行〜2024-10-26 開催

同じニオイがする作品
  • event 喋ると光るヘルメット
  • event スタックチャン meets Scratch with M5bitLess
  • event 丸いArduino互換機「Maruino」
  • event PAINTAR

イベントまとめ

コンテストまとめ

作品を登録しよう

モノづくりしている人に、つくった作品を見てもらえ、リアクションがもらえるかも?

close

目次