momoのアイコン画像
momo 2021年02月28日作成 (2022年02月19日更新) © MIT
製作品 製作品 閲覧数 770
momo 2021年02月28日作成 (2022年02月19日更新) © MIT 製作品 製作品 閲覧数 770

アシスト付き電子ピアノ

アシスト付き電子ピアノ

はじめに

5線で7セグ/LEDとスイッチ入力ができるLED&KEY(TM1638)を使って、
簡易電子ピアノを作りました。ただ、自分はピアノは全然弾けません…。
なので、次の音をLEDで示すようにアシスト機能を付けました。

部品

  • XIAO
  • TM1638 LED&KEY
  • 圧電スピーカー

回路図

キャプションを入力できます

概観

キャプションを入力できます

プログラム

#include <TM1638lite.h>

class Speaker {
    private:
        int port_no;
        int a2d(char a) {
            return (('0' <= a) && (a <= '9')) ? (a - '0') : 0;
        };
    public:
        Speaker(int port) {
            this->port_no = port;
        };
        void Init(void) {
            pinMode(this->port_no, OUTPUT);
        };  
        void Sound(char nte, unsigned int len, unsigned oct) {
            static const struct {char n; int f[2];} tbl[] = {
                {'c', {262, 523}},
                {'d', {294, 587}},
                {'e', {330, 659}},
                {'f', {349, 689}},
                {'g', {392, 784}},
                {'a', {440, 880}},
                {'b', {494, 988}},
                {'.', {0, 0}}};

            Serial.printf("%c %d %d\n", nte, len, oct);
            
            if (len < 2) {
                len = 800;
            } else if (len < 4) {
                len = 400;
            } else if (len < 8) {
                len = 200;                
            } else {
                len = 400;                
            }

            if (oct > 1) {
                oct = 1;
            }
            
            for (int i=0; i<sizeof(tbl)/sizeof(tbl[0]); i++) {
                if (nte == tbl[i].n) {
                    tone(this->port_no, tbl[i].f[oct], len);
                    delay(len);
                }
            }
        };

        void Play(char *snd) {
            int o = 0;
            while ('\0' != *snd) {
                if ('o' == *snd) {
                    snd++;
                    o = a2d(*snd++);                    
                } else {
                    Sound(*snd++, a2d(*snd++), o);
                }
            }
        };
};

TM1638lite tm(9, 8, 7);
Speaker spk(10);

static char *drm = 
    "o0c2d4e2c4e2c2e2.4"
    "d2e4f4f4e4d4f2.4"
    "e2f4g2e4g2e2g2.4"
    "f2g4a4a4g4f4a2.4"
    "g2c4d4e4f4g4a2.4"
    "a2d4e4f4g4a4b2.4"
    "b2e4f4g4a4b4o1c2.4"
    "o1c4o0b4a2f2b2g2o1c2.4"
    "o0c4d4e4f4g4a4b4o1c4.4"
    "o1c4o0b4a4g4f4e4d4.4"
    "c4e4e2e4g4g2d4f4f2a4b4b2.4"
    "c4e4e2e4g4g2d4f4f2a4b4b2.4"
    "g2c2a2f2e2c4d2.4"
    "g2c2a2b2c2d2o1c1.4"
    "\0";

static char *pos = drm;

void setup()
{
    tm.reset();
    tm.displayText("--------");
    tm.setLED(0, 1);

    spk.Init();    
    spk.Play(drm);
}

void loop()
{
    int f, o;
    unsigned char k = get_key_input();
    
    for (int i=0; i<8; i++) {
        tm.displayASCII(i, "-o"[k & 1]);
        if (k & 1) {
            spk.Sound("cdefgabc"[i], 4, (i == 7) ? 1:0);
        }
        k >>= 1;
        tm.setLED(i, 0);
    }
    
    f = 1;
    o = 0;
    while (*pos && f) {
        switch (*pos++) {
            case 'o': o = (('1' == *(pos) ? 7 : 0)); break;
            case 'c': tm.setLED(o, 1); f = 0; break;
            case 'd': tm.setLED(1, 1); f = 0; break;
            case 'e': tm.setLED(2, 1); f = 0; break;
            case 'f': tm.setLED(3, 1); f = 0; break;
            case 'g': tm.setLED(4, 1); f = 0; break;
            case 'a': tm.setLED(5, 1); f = 0; break;
            case 'b': tm.setLED(6, 1); f = 0; break;
            case '\0': pos = drm; break;
            default:
                ;
        }
    }
}

unsigned char get_key_input(void)
{
    static unsigned char pre = 0;
    unsigned char ege;

    do {
        unsigned char btn = tm.readButtons();   
        ege = (~pre) & btn;    
        pre = btn;        
        delay(100);
    } while(!ege);
    
    return ege;
}

動作

最初に見本のメロディーが流れます。
そのあと、上のLEDが点灯している位置のキーを順に押下していくと、ドレミの曲が弾けます。

momoのアイコン画像
組み込みSWエンジニア
ログインしてコメントを投稿する