Spisu treści:

MIDI Drum Kit na Pythonie i Arduino: 5 kroków (ze zdjęciami)
MIDI Drum Kit na Pythonie i Arduino: 5 kroków (ze zdjęciami)

Wideo: MIDI Drum Kit na Pythonie i Arduino: 5 kroków (ze zdjęciami)

Wideo: MIDI Drum Kit na Pythonie i Arduino: 5 kroków (ze zdjęciami)
Wideo: DIY Electronic Drums - Arduino MIDI Drums 2024, Listopad
Anonim
Image
Image
Zestaw perkusyjny MIDI na Python i Arduino
Zestaw perkusyjny MIDI na Python i Arduino
Zestaw perkusyjny MIDI na Python i Arduino
Zestaw perkusyjny MIDI na Python i Arduino

Od dziecka zawsze chciałem kupić zestaw perkusyjny. W tamtych czasach cały sprzęt muzyczny nie miał wszystkich zastosowań cyfrowych, bo dzisiaj mamy ich pod dostatkiem, stąd ceny i oczekiwania były zbyt wysokie. Ostatnio zdecydowałem się na zakup najtańszego zestawu perkusyjnego z eBaya, z jedynym priorytetem: Możliwość rozebrania go i podpięcia do urządzenia własnego sprzętu i oprogramowania.

Zakup wcale nie zawiódł: przenośny zestaw perkusyjny zwijany z 9 różnymi nakładkami dźwiękowymi, dwoma przełącznikami nożnymi do stopy i hi-hatu oraz gniazdem zasilania micro-USB. To, co było naprawdę demotywujące, to dźwięki wyjściowe (rzeczywiste zastosowanie tego zestawu to podłączenie zewnętrznego głośnika i cieszenie się nim). Postanowiłem więc przekonwertować go na własny programowalny przez USB, zestaw perkusyjny MIDI oparty na Arduino i interfejs użytkownika oparty na Pythonie, aby był wygodny w użyciu i łatwy do modyfikacji, takich jak wybór głośności, nuty i kanału.

Cechy urządzenia:

  • Niska cena
  • Tworzenie zestawu perkusyjnego z dowolnych wejść cyfrowych - nawet z szeregu przycisków
  • Obsługa komunikacji i zasilanie tylko przez interfejs USB - Integracja konwertera USB na UART i urządzenia Arduino
  • Minimalne części do prawidłowego działania
  • Łatwy w użyciu interfejs użytkownika oparty na Pythonie
  • Pełna obsługa MIDI z regulowaną prędkością, nutą i pinami Arduino
  • Zapisz i załaduj niestandardowe konfiguracje bębnów przechowywane w pamięci urządzenia

Przejdźmy do projektu…

Krok 1: Teoria działania

teoria operacji
teoria operacji
teoria operacji
teoria operacji
teoria operacji
teoria operacji

Schemat blokowy

Przede wszystkim skupmy się na strukturze projektu i podzielmy go na osobne bloki:

Zestaw bębna zwijanego

Główna jednostka projektu. Składa się z 9 oddzielnych padów perkusyjnych, z których każdy jest szeregiem przycisków, które zmieniają swój stan logiczny w momencie uderzenia. Ze względu na swoją konstrukcję istnieje możliwość skonstruowania tego konkretnego zestawu perkusyjnego z dowolnych przycisków. Każdy pad perkusyjny jest podłączony do rezystora podciągającego na głównej płytce elektronicznej, dzięki czemu podczas wielokrotnych uderzeń w pad perkusyjny, do masy obwodu podłączony jest specjalny przełącznik, a na linii padów perkusyjnych występuje logiczne LOW. Gdy nie ma nacisku, przełącznik padów perkusyjnych jest otwarty i ze względu na rezystor podciągający do linii zasilającej, na linii padów perkusyjnych występuje logiczne WYSOKIE. Ponieważ celem projektu jest stworzenie kompletnego cyfrowego urządzenia MIDI, można pominąć wszystkie części analogowe na głównej płytce drukowanej. Należy zauważyć, że zestaw perkusyjny posiada dwa pedały do stopy i hi-hatu, które również są połączone z rezystorami podciągającymi i mają tę samą logikę działania, co wszystkie pady perkusyjne (omówimy to nieco później).

Arduino Pro-Mikro

Mózg zestawu perkusyjnego. Jego celem jest wykrycie sygnału wychodzącego z padu perkusyjnego i zapewnienie odpowiedniego wyjścia MIDI ze wszystkimi niezbędnymi parametrami: nutą, prędkością i czasem trwania sygnału. Ze względu na cyfrowy charakter padów perkusyjnych można je po prostu podłączyć do wejść cyfrowych arduino (łącznie 10 pinów). Aby zachować wszystkie pożądane ustawienia i informacje MIDI, będziemy używać jego pamięci - EEPROM, dlatego za każdym razem, gdy włączamy urządzenie, informacje MIDI są ładowane z EEPROM, dzięki czemu można je przeprogramować i ponownie skonfigurować. Ponadto Arduino Pro-Micro jest dostępny w bardzo małym opakowaniu i można go łatwo umieścić w wewnętrznej walizce zestawu perkusyjnego.

Konwerter FTDI USB na szeregowy

Aby zaprogramować i zdefiniować funkcje naszego urządzenia za pomocą aplikacji PC, należy przekonwertować interfejs USB na szeregowy, ponieważ Arduino Pro-Micro nie posiada USB. Ponieważ komunikacja pomiędzy urządzeniami oparta jest na UART, w tym projekcie zastosowano urządzenie FTDI, ze względu na prostotę obsługi niezależnie od dodatkowych właściwości.

Aplikacja PC - Python

Jeśli chodzi o tworzenie interfejsów użytkownika i szybkich projektów, Python jest doskonałym rozwiązaniem. Celem aplikacji interfejsu użytkownika jest ułatwienie redefiniowania właściwości MIDI dla naszego zestawu perkusyjnego, przechowywania informacji, programowania urządzenia i nawiązywania komunikacji między systemami bez konieczności ciągłego kompilowania kodu. Ponieważ do komunikacji z zestawem perkusyjnym używamy interfejsu szeregowego, w Internecie dostępnych jest wiele darmowych modułów, które obsługują każdy rodzaj komunikacji szeregowej. Dodatkowo, jak zostanie omówione dalej, interfejs UART składa się łącznie z trzech pinów: RXD, TXD i DTR. DTR służy do wykonywania resetu na module Arduino, więc gdy jesteśmy zainteresowani uruchomieniem aplikacji MIDI lub podłączeniem UI do urządzenia programującego, absolutnie nie ma potrzeby ponownego podłączania kabla USB lub czegokolwiek.

Krok 2: Części i instrumenty

Części

  • Zestaw bębna zwijanego
  • 2 x pedały podtrzymania dźwięku (zwykle zawarte w pakiecie DK).
  • FTDI - konwerter USB na szeregowy
  • Arduino Pro Micro
  • Kabel Micro-USB

Instrumenty

  • Lutownica/stacja
  • Cyna lutownicza
  • Drut jednożyłowy o cienkiej średnicy
  • Pinceta
  • Nóż
  • Obcęgi
  • Nóż
  • Śrubokręt
  • Drukarka 3D (opcjonalna - dla niestandardowych platform pedałów)

Oprogramowanie

  • IDE Arduino
  • Python 3 lub nowszy
  • JetBrains Pycharm
  • Bezwłosy interfejs MIDI
  • pętlaMIDI

Krok 3: Lutowanie i montaż

Lutowanie i montaż
Lutowanie i montaż
Lutowanie i montaż
Lutowanie i montaż
Lutowanie i montaż
Lutowanie i montaż

Ponieważ trzeba połączyć trzy moduły, proces lutowania i montażu jest krótki i prosty:

  • Połącz Arduino Pro-Micro z urządzeniem FTDI, upewnij się, że połączenia są zgodne z I/O zdefiniowanymi na każdym urządzeniu:

    • VBUS-VBUS
    • GND-GND
    • DTR-DTR
    • RXD-TXD
    • TXD-RXD
  • Usuń wszystkie śruby z plastikowej obudowy bębna, upewnij się, że możesz skupić się na kablu pad-płyta i jego rezystorach podciągających
  • Przylutuj cienkie przewody do modułu Arduino-FTDI, który zbudowaliśmy wcześniej:

    • Wejścia cyfrowe: D[2:11]
    • VBUS
    • D+
    • D-
    • GND
  • Włóż moduł do pojemnika na baterie, aby przewody unosiły się po tej samej stronie, co rezystory podciągające padów
  • Przylutuj wszystkie wejścia cyfrowe do zacisków padów perkusyjnych, jak pokazano na ostatnim rysunku.
  • Przylutuj magistralę micro-USB (VBUS, D+, D-, GND) do urządzenia FTDI, upewnij się, że nie ma błędów śledzenia tych przewodów.
  • Przymocuj moduł Arduino-FTDI za pomocą kleju na gorąco do obudowy baterii
  • Zamontuj urządzenie za pomocą odpowiednich śrub mocujących

Udało się, urządzenie jest zmontowane. Przejdźmy do kodu…

Krok 4: Programowanie A: Arduino

Programowanie A: Arduino
Programowanie A: Arduino

Opiszmy nasz szkic krok po kroku:

Przede wszystkim do poprawnego działania potrzebne są dwie biblioteki. EEPROM jest już preinstalowany w Arduino IDE, ale moduł debouncera dla stopy musi być zainstalowany osobno

#włącz #włącz

Przełączniki te są używane głównie w sekwencjach debugowania. Jeśli chcesz wypróbować połączenie terminali Arduino z padami perkusyjnymi i określić wszystkie wejścia cyfrowe, te przełączniki powinny być zdefiniowane

/* Przełączniki programistyczne: odkomentuj żądany tryb debugowania lub inicjalizacji *///#define LOAD_DEFAULT_VALUES // Załaduj stałe wartości zamiast EEPROM //#define PRINT_PADS_PIN_NUMBERS // Wydrukuj numer pinu, który jest podłączony do padu, który został trafiony przez port szeregowy

Pola stałe reprezentują wszystkie wartości domyślne, w tym wyliczenie padów perkusyjnych. Aby po raz pierwszy uruchomić urządzenie, trzeba znać dokładne połączenie pedałów Hi-Hat i Kick

/* Wyliczenie typu bębna */

enum DRUM_POSITION { KICK = 0, SNARE, HIHAT, RIDE, CYMBAL1, CYMBAL2, TOM_HIGH, TOM_MID, TOM_LO, HIHAT_PEDAL };

/* Wartości domyślne */

const uint8_t DRUM_NOTES[10] = { 36, 40, 42, 51, 49, 55, 47, 45, 43, 48}; const uint8_t DRUM_VELOCITIES[10] = { 110, 100, 100, 110, 110, 110, 110, 110, 110, 110}; const uint8_t DRUM_PINS[10] = { 8, 6, 4, 3, 11, 9, 5, 10, 2, 7 };

/* Czas trwania odbicia bębna kopnięcia */

const uint8_t KICK_DB_DURATION = 30;

EEPROM służy do przechowywania/ładowania wszystkich danych pochodzących z aplikacji PC. Opisany powyżej zakres adresów pokazuje dokładną lokalizację informacji MIDI dla każdego padu perkusyjnego

/* Mapowanie adresów EEPROM

Uwagi: |0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09|

Piny: |0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13| Prędkości |0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23| */ const uint8_t NOTES_ADDR = 0x00; const uint8_t VELOCITIES_ADDR = 0x14; const uint8_t PINS_ADDR = 0x0A;

Zmienne globalne służą do określenia stanu każdego padu i odpowiedniej komunikacji MIDI

/* Zmienne globalne */

uint8_t drumNotes[10], drumPrędkości[10], drumPins[10]; // Zmienne MIDI

uint8_t uartBuffer[64]; // Bufor UART do gromadzenia i przechowywania MIDI Data Debouncer kick(DRUM_PINS[KICK], KICK_DB_DURATION); // Obiekt Debouncer dla volatile bool bębna stopy previousState[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // Drum Pad poprzednie stany logiczne volatile bool currentState[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // Bieżące stany logiczne padu perkusyjnego

Funkcje pamięci EEPROM

/* Zapisz ustawienia w EEPROM*/

void przechowujEEPROM() {

memcpy(drumNotes, uartBuffer, 10); memcpy(drumPins, uartBuffer + 10, 10); memcpy(bębenPrędkości, uartBuffer + 20, 10); for (uint8_t i = 0; i < 10; i++) EEPROM.write(NOTES_ADDR + i, drumNotes); for (uint8_t i = 0; i < 10; i++) EEPROM.write(PINS_ADDR + i, drumPins); for (uint8_t i = 0; i < 10; i++) EEPROM.write(VELOCITIES_ADDR + i, drumVelocities); }

/* Załaduj ustawienia z EEPROM*/

void loadEEPROM() { for (uint8_t i = 0; i < 10; i++) drumNotes = EEPROM.read(NOTES_ADDR + i); for (uint8_t i = 0; i < 10; i++) drumPins = EEPROM.read(PINS_ADDR + i); for (uint8_t i = 0; i < 10; i++) drumVelocities = EEPROM.read(VELOCITIES_ADDR + i); }

Inicjalizacja zmiennych i tryb programowania, w przypadku pedałów i rozruchu Arduino są aktywowane jednocześnie

void enterProgrammingMode() {

bool potwierdzićBreak = false; uint8_t lineCnt = 0; uint8_t charCnt = 0; znak odczytZnak = 0; while(!confirmBreak) { if (Serial.available()) { uartBuffer[charCnt] = Serial.read(); if (charCnt >= 29) ConfirmBreak = true; w przeciwnym razie charCnt++; } } Serial.println("OK"); przechowujEEPROM(); }

void initValues() {

#ifdef LOAD_DEFAULT_VALUES memcpy(drumNotes, DRUM_NOTES, 10); memcpy(Prędkości bębna, VELOCITIES_DRUM, 10); memcpy(drumPins, DRUM_PINS, 10); #else załadujEEPROM(); #endif }

Obsługa komunikacji MIDI z opóźnieniem 1ms czasu podtrzymania nuty

/* Funkcja odtwarzania nut MIDI */

void midiOut(enum DRUM_POSITION drumIn) {

if (drumIn == HIHAT) { // Jeśli HI-HAT został uderzony, należy sprawdzić, czy pedał jest wciśnięty if (!digitalRead(drumPins[HIHAT_PEDAL])) { noteOn(0x90, drumNotes[HIHAT_PEDAL], drumVelocities [HIHAT_PEDAL]); opóźnienie(1); noteOn(0x90, nuty perkusyjne[HIHAT_PEDAL], 0); } else { noteOn(0x90, drumNotes[HIHAT], drumVelocities[HIHAT]); opóźnienie(1); noteOn(0x90, drumNotes[HIHAT], 0); } } else { // Zwykła perkusyjna transmisja MIDI noteOn(0x90, drumNotes[drumIn], drumVelocities[drumIn]); opóźnienie(1); noteOn(0x90, drumNotes[drumIn], 0); } }

void noteOn(int cmd, int skok, int prędkość) { Serial.write(cmd); Serial.write(skok); Serial.write(prędkość); }

Funkcje setup() i loop() z nieskończoną pętlą działania urządzenia:

pusta konfiguracja () {

Serial.początek(115200);

for (uint8_t i = 0; i < 10; i++) { pinMode(i + 2, INPUT); } #ifdef PRINT_PADS_PIN_NUMBERS while(true) { // Nieskończona pętla debugowania dla (uint8_t i = 0; i < 10; i++) { if (!digitalRead(i + 2)) { Serial.print("Pin No: D"); Serial.print(i + '0'); // Konwertuj liczbę na znak ASCII } } } #else initValues(); /* Tryb programowania: Jeśli dwa pedały są wciśnięte podczas uruchamiania - tryb jest aktywowany */ if (!digitalRead(drumPins[KICK]) && !digitalRead(drumPins[HIHAT_PEDAL])) enterProgrammingMode(); #endif }

void loop() { for (uint8_t i = 1; i < 9; i = i + 1) { currentState = digitalRead(drumPins); if (!bieżącystan &&poprzednistan) midiOut(i); // Porównaj stany i wykryj opadające zbocze previousState = currentState; } kick.aktualizacja(); // Kick drum używa własnego algorytmu debounce if (kick.edge()) if (kick.falling()) midiOut(KICK); }

Krok 5: Programowanie B: Python i interfejs użytkownika

Programowanie B: Python i interfejs użytkownika
Programowanie B: Python i interfejs użytkownika
Programowanie B: Python i interfejs użytkownika
Programowanie B: Python i interfejs użytkownika
Programowanie B: Python i interfejs użytkownika
Programowanie B: Python i interfejs użytkownika

Interfejs użytkownika Pythona jest nieco skomplikowany do zrozumienia na pierwszy rzut oka, dlatego spróbujemy wyjaśnić jego podstawy, jak używać, jaką funkcję ma każdy przycisk i jak poprawnie zaprogramować urządzenie Arduino.

Interfejs użytkownika - aplikacja

Interfejs użytkownika jest graficzną reprezentacją naszego programisty zestawów perkusyjnych, dzięki czemu jest naprawdę łatwy w użyciu i wygodny w programowaniu urządzenia Arduino w dowolnym momencie. UI składa się z kilku modułów graficznych powiązanych z ich sugerowanym działaniem. przejrzyjmy je jeden po drugim:

  1. Obraz zestawu perkusyjnego: interfejs użytkownika Pythona używa współrzędnych obrazu X-Y, aby określić, który typ bębna został wybrany. Jeśli wybrano prawidłowy region perkusyjny, pojawi się dodatkowy komunikat IO z polami nuty, prędkości i terminala Arduino dla dedykowanego padu perkusyjnego. Po zweryfikowaniu i zatwierdzeniu tych parametrów przez użytkownika wartości te mogą być przesyłane bezpośrednio do urządzenia Arduino.
  2. Obraz zewnętrznego kontrolera: Aby móc używać zestawu perkusyjnego MIDI ze środowiskiem tworzenia VST/Music, konieczne jest uruchomienie interpretera Serial-To-MIDI. Użyłem Hairless, który jest dostępny za darmo i można go uruchomić bezpośrednio z naszego interfejsu użytkownika, po prostu naciskając jego obraz.
  3. Lista portów COM: W celu komunikacji z Arduino należy określić dołączony port COM. Lista jest odświeżana po naciśnięciu przycisku Odśwież.
  4. Wczytaj/zapisz konfigurację: W kodzie zdefiniowane są domyślne wartości MIDI, które mogą być modyfikowane przez użytkownika poprzez interakcję z interfejsem użytkownika. Konfiguracja jest zdefiniowana w pliku config.txt w określonym formacie, który może być zapisany lub wczytany przez użytkownika.
  5. Program Device Button: Aby zapisać wszystkie zmodyfikowane wartości MIDI w pamięci EEPROM Arduino, należy nacisnąć dwa pedały nożne (Kick drum i Hi-hat pedal) i poczekać na zakończenie transmisji danych. Jeśli wystąpiły jakiekolwiek problemy z komunikacją, zostanie wyświetlone odpowiednie wyskakujące okienko. Jeśli transmisja się powiedzie, interfejs użytkownika wyświetli komunikat o pomyślnym zakończeniu.
  6. Przycisk wyjścia: po prostu wyjdź z aplikacji za zgodą użytkownika.

Najważniejsze cechy kodu w Pythonie

W kodzie dzieje się wiele rzeczy, więc będziemy rozwijać napisane funkcje, a nie cały kod.

Przede wszystkim, aby korzystać z UI, należy pobrać kilka modułów, aby kod działał:

import osimport Threading import tkinter as tk z tkinter importuj okno komunikatów z tkinter import * z PIL import ImageTk, obraz import numpy jako np import serial import glob

Niektóre moduły są zawarte w domyślnym pakiecie Pythona. Kilka modułów powinno być zainstalowanych za pomocą narzędzia PIP:

pip zainstalować poduszkę

pip zainstaluj numpy pip zainstaluj ScreenInfo

Zdecydowanie zaleca się uruchamianie aplikacji przez PyCharm. W przyszłych wydaniach planuję wyeksportować plik wykonywalny projektu.

Krótkie wyjaśnienie kodu

Znacznie łatwiej będzie zrozumieć kod, jeśli spojrzymy na jego wiersze z perspektywy funkcji i klas:

1. Główna funkcja - tutaj zaczyna się kod

if _name_ == '_main_': drumkit_gui()

2. Stałe zestawu perkusyjnego, współrzędne i domyślne informacje MIDI

class Drums: DRUM_TYPES = ["Kick", "Hihat", "Snare", "Crash 1", "Crash 2", "Tom High", "Tom Mid", "Tom Low", "Ride", "Hihat Pedal ", "Kontroler"]

WSPÓŁRZĘDNE_X = [323, 117, 205, 173, 565, 271, 386, 488, 487, 135, 79]

WSPÓŁRZĘDNE_Y = [268, 115, 192, 40, 29, 107, 104, 190, 71, 408, 208] WYMIAR_SZER. = [60, 145, 130, 120, 120, 70, 70, 130, 120, 70, 145] DŁUGOŚĆ_WYMIARÓW = [60, 60, 80, 35, 35, 40, 40, 70, 35, 100, 50]

DRUM_ENUM = ["Kick", "Snare", "Hihat", "Ride", "Crash 1", "Crash 2", "Tom High", "Tom Mid", "Tom Low", "Hihat Pedal"]

UWAGI_BĘBNA = [36, 40, 42, 51, 49, 55, 47, 45, 43, 48] PRĘDKOŚCI_BĘBNA = [110, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110] KOŁKI_BĘBNA = [8, 6, 4, 3, 11, 9, 5, 10, 2, 7]

3. Funkcje interfejsu użytkownika - Obsługa interfejsu użytkownika i obiektów graficznych

def zestaw_aktywny(ui)

def drugorzędny_ui(typ_bębenu)

klasa SelectionUi(tk. Frame)

Aplikacja klasy (tk. Frame)

def zestaw perkusyjny_gui()

def event_ui_clicked(event)

def getorigin(self, event)

4. Komunikacja szeregowa

def get_serial_ports()

def komunikacja_z_arduino(port)

5. Praca z plikami: Zapisz/Załaduj ustawienia z pliku txt

def save_config()

def load_config()

6. Uruchamianie zewnętrznej aplikacji hairless.exe z kodu przy użyciu funkcji Python Threading

class ExternalExecutableThread(threading. Thread)

def run_hairless_executable()

Aby uruchomić kod, do folderu projektu należy dołączyć listę plików:

  • config.txt: Plik ustawień
  • hairless.exe: bezwłosy konwerter MIDI
  • drumkit.png: Obraz, który definiuje wszystkie klikalne pady perkusyjne w naszym interfejsie użytkownika (należy pobrać z zestawu obrazów tego kroku)
  • drumgui.py: kod projektu

To wszystko, co musimy podkreślić, aby to zadziałało. Bardzo ważne jest dodanie do projektu plików: obrazu zestawu perkusyjnego, pliku wykonywalnego hairless.exe oraz pliku ustawień config.txt.

I.. Tutaj skończyliśmy!:)

Mam nadzieję, że ta instrukcja będzie przydatna.

Dziękuje za przeczytanie!:)

Zalecana: