Детское пианино на Arduino

от
Прочее    arduino

Сегодня я научу вас, как сделать детское пианино на базе микроконтроллера Arduino UNO. Это не является серьезной поделкой, сборка оного не вызовет у вас никаких сложностей, более того, можно ничего не паять, а собрать на макетной плате. Музицировать на нем не получится, но если нажимать в нужном ритме клавиши, то услышите свою музыку, которую вы запишите.

Необходимо:

Arduino UNO
Бузер
Провода Dupont
Тактовые кнопки 12 мм.
Макетная плата


Конвертируем музыку в код
Основой этого проекта послужить сервис по переводу мелодий в формате MIDI в код, понятный для ардуино:
https://extramaster.net/tools/midiToArduino/

Суть данного сервиса проста, вы грузите музыку, получаете код, который в свою очередь загружаете на Arduino и вуаля, можно слушать любую музыку через бузер. Но есть и минусы, например память у Arduino UNO всего 32 Кб памяти и полностью записать музыку вы точно не сможете. Также нельзя слушать музыку в "многоголосье", то есть строго записываем только один инструмент.

Но нам это скучно, поэтому мы выбираем любую музыку, находим ее в формате MIDI и скачиваем. Далее загружаем на этот сервис и получаем подобный код:

  1. // Credit:
  2. // Midi to Arduino Converter
  3. //     - Andy Tran (extramaster), 2015
  4. // https://www.extramaster.net/tools/midiToArduino/
  5. //
  6. // Process:
  7. // Midi -> Midi tracks -> Note mappings -> Frequency
  8. //
  9. // CC0
  10.  
  11. // Set this to be the pin that your buzzer resides in. (Note that you can only have one buzzer actively using the PWM signal at a time).
  12. int tonePin = 11;
  13. void setup() {
  14.  
  15. }
  16.  
  17. void midi() {
  18.  
  19.     tone(tonePin, 146, 450.0);
  20.     delay(500.0);
  21.     tone(tonePin, 174, 225.0);
  22.     delay(250.0);
  23.     tone(tonePin, 164, 225.0);
  24.     delay(250.0);
  25.     tone(tonePin, 130, 225.0);
  26.     delay(250.0);
  27.     tone(tonePin, 164, 225.0);
  28.     delay(250.0);
  29.     tone(tonePin, 195, 225.0);
  30.     delay(250.0);
  31.     tone(tonePin, 233, 225.0);
  32.     delay(250.0);
  33.     tone(tonePin, 220, 450.0);
  34.     delay(500.0);
  35.     tone(tonePin, 174, 450.0);
  36.     delay(500.0);
  37.  
  38. }
  39.  
  40. void loop() {
  41.     // Play midi
  42.     midi();
  43. }
Подключаем бузер на 11 пин, запускаем на Arduino и слушаем, если все работает, то идем дальше.

Подготавливаем код
Копируем наш код и вставляем сюда:
https://wiki.droidbot.store/doku.php?id=piano_parser
Получаем готовые массивы с записанными в них тональностями звука и вставляем их вместо строчек:
  1. int myPins[] = {261, 311, 349, 311, 349};
  2. int myPing[] = {360.0, 360.0, 270.0, 270.0, 180.0, 360.0};

В этом коде:
  1. int tonePin = 11;
  2. int myPins[] = {349, 329, 329, 293, 293, 349, 329, 293, 293, 329, 349, 466, 440, 440, 349, 349, 466, 440, 329, 349, 329, 329, 293, 293, 349, 329, 293, 293, 329, 349, 466, 440, 440, 349, 349, 466, 440, 329, 349, 329, 329, 293, 293, 349, 329, 293, 293, 329, 349, 466, 440, 440, 349, 349, 466, 440, 329, 349, 329, 329, 293, 293, 349, 329, 293, 293, 329, 349, 466, 440, 440, 349, 349, 466, 440, 329, 293, 293, 293, 293, 293, 261, 261, 195, 220, 233, 293, 277, 220, 220, 293, 293, 293, 293, 293, 261, 261, 195, 233, 293, 233, 220, 293, 293, 293, 293, 293, 261, 261, 195, 220, 233, 293, 277, 220, 220, 293, 293, 293, 293, 293, 261, 261, 195, 195, 195, 233, 293, 329, 220, 220, 220, 261, 329, 349, 329, 329, 293, 293, 349, 329, 293, 293, 329, 349, 466, 440, 440, 349, 349, 466, 440, 329, 349, 329, 329, 293, 293, 349, 329, 293, 293, 329, 349, 466, 440, 440, 349, 349, 466, 440, 329, 293, 293, 293, 293, 293, 261, 261, 195, 220, 233, 293, 277, 220, 220, 293, 293, 293, 293, 293, 261, 261, 195, 233, 293, 233, 220, 293, 293, 293, 293, 293, 261, 261, 195, 220, 233, 293, 277, 220, 220, 293, 293, 293, 293, 293, 261, 261, 195, 195, 195, 233, 293, 329, 220, 220, 220, 261, 329, 349, 329, 329, 293, 293, 349, 329, 293, 293, 329, 349, 466, 440, 440, 349, 349, 466, 440, 329, 349, 329, 329, 293, 293, 349, 329, 293, 293, 329, 349, 466, 440, 440, 349, 349, 466, 440, 329, 293, 329, 349, 329, 293, 261, 261, 440, 349, 261, 293, 329, 349, 329, 293, 261, 233, 220, 277, 329, 349, 329, 349, 329, 329, 293, 293, 349, 329, 293, 293, 329, 349, 466, 440, 440, 349, 349, 466, 440, 329, 349, 329, 329, 293, 293, 349, 329, 293, 293, 329, 349, 466, 440, 440, 349, 349, 466, 440, 329, 349, 329, 329, 293, 293, 349, 329, 293, 293, 329, 349, 466, 440, 440, 349, 349, 466, 440, 329, 349, 329, 329, 293, 293, 349, 329, 293, 293, 329, 349, 466, 440, 440, 349, 349, 466, 440, 329};
  3. int myPing[] = {281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 281.25, 140.625, 140.625, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 562.5, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 281.25, 140.625, 140.625, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 562.5, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 281.25, 140.625, 140.625, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 562.5, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 281.25, 140.625, 140.625, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 562.5, 281.25, 140.625, 421.875, 281.25, 281.25, 140.625, 421.875, 281.25, 140.625, 421.875, 281.25, 281.25, 140.625, 421.875, 281.25, 140.625, 421.875, 281.25, 281.25, 140.625, 421.875, 140.625, 421.875, 140.625, 421.875, 562.5, 281.25, 140.625, 421.875, 281.25, 281.25, 140.625, 421.875, 281.25, 140.625, 421.875, 281.25, 281.25, 140.625, 421.875, 281.25, 140.625, 421.875, 281.25, 281.25, 140.625, 421.875, 140.625, 281.25, 281.25, 140.625, 421.875, 1125.0, 140.625, 140.625, 140.625, 281.25, 281.25, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 281.25, 140.625, 140.625, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 562.5, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 281.25, 140.625, 140.625, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 562.5, 281.25, 140.625, 421.875, 281.25, 281.25, 140.625, 421.875, 281.25, 140.625, 421.875, 281.25, 281.25, 140.625, 421.875, 281.25, 140.625, 421.875, 281.25, 281.25, 140.625, 421.875, 140.625, 421.875, 140.625, 421.875, 562.5, 281.25, 140.625, 421.875, 281.25, 281.25, 140.625, 421.875, 281.25, 140.625, 421.875, 281.25, 281.25, 140.625, 421.875, 281.25, 140.625, 421.875, 281.25, 281.25, 140.625, 421.875, 140.625, 281.25, 281.25, 140.625, 421.875, 1125.0, 140.625, 140.625, 140.625, 281.25, 281.25, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 281.25, 140.625, 140.625, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 562.5, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 281.25, 140.625, 140.625, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 562.5, 281.25, 140.625, 281.25, 140.625, 140.625, 281.25, 281.25, 281.25, 140.625, 140.625, 281.25, 140.625, 281.25, 281.25, 281.25, 281.25, 281.25, 562.5, 562.5, 562.5, 281.25, 281.25, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 281.25, 140.625, 140.625, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 562.5, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 281.25, 140.625, 140.625, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 562.5, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 281.25, 140.625, 140.625, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 562.5, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 281.25, 140.625, 140.625, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 140.625, 281.25, 562.5};
  4.  
  5. int i=0;         // переменная, для защиты от залипания кнопки
  6. int p=0;        // переменная, для защиты от залипания кнопки
  7. int g=0;       // переменная, для защиты от повтора
  8. void setup() {
  9.   Serial.begin(9600);
  10.   pinMode(3, INPUT_PULLUP);
  11. }
  12. bool flag = false;
  13. uint32_t btnTimer = 0;
  14. void loop() {
  15. g=sizeof(myPins)/sizeof(myPins[0]);
  16.   bool btnState = !digitalRead(3);
  17.   if (btnState && !flag && millis() - btnTimer > 1) {
  18.     flag = true;
  19.     btnTimer = millis();
  20.     Serial.println(i);   // Вывод позиции ноты
  21.     tone(tonePin, myPins[i], myPing[i]);
  22.     p=1;
  23.   }
  24.  
  25.   if (!btnState && flag && millis() - btnTimer > 120) {
  26.     flag = false;
  27.     btnTimer = millis();
  28. i=i+p;
  29. p=0;
  30.   }
  31. if (i>g) {
  32.   i=0;
  33. }
  34. }

И загружаем его на Arduino.

Сборка
Далее подключаем все по схеме:
  111.PNG

Вы можете использовать кнопки в любом количестве.

И все! Можно играть, главное соблюдать ритм. Для затравки дам свою любимую мелодию, заставка Евангелиона:
Открыть спойлер

И наконец фото готового проекта:
1mlm1F_eJhc.jpg



Скоро проект будет доступен под заказ в моем магазине, в виде набора с корпусом.