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

アシスト付き電子ピアノ

アシスト付き電子ピアノ

はじめに

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エンジニア
ログインしてコメントを投稿する