Sommario:

MIDI Drum Kit su Python e Arduino: 5 passaggi (con immagini)
MIDI Drum Kit su Python e Arduino: 5 passaggi (con immagini)

Video: MIDI Drum Kit su Python e Arduino: 5 passaggi (con immagini)

Video: MIDI Drum Kit su Python e Arduino: 5 passaggi (con immagini)
Video: Драм-секвенсор Arduino: 8 дорожек, 16 шагов на такт, 8 тактов на паттерн 2024, Dicembre
Anonim
Image
Image
MIDI Drum Kit su Python e Arduino
MIDI Drum Kit su Python e Arduino
MIDI Drum Kit su Python e Arduino
MIDI Drum Kit su Python e Arduino

Ho sempre voluto comprare una batteria fin da quando ero bambino. All'epoca, tutte le apparecchiature musicali non avevano tutte le applicazioni digitali come ne abbiamo in abbondanza oggi, quindi i prezzi e le aspettative erano troppo alti. Recentemente ho deciso di acquistare una batteria più economica da eBay, con l'unica priorità: la possibilità di smontarla e collegare il mio hardware e software al dispositivo.

L'acquisto non è stato affatto deludente: batteria roll-up portatile con 9 diversi pad sonori, due pedali a pedale per grancassa e hi-hat e presa di alimentazione micro-USB. Ciò che è stato davvero demotivante, sono i suoni in uscita (l'uso effettivo per questo kit è collegare un altoparlante esterno e goderselo). Quindi, ho deciso di convertirlo nel mio programmabile tramite USB, batteria MIDI basata su Arduino e interfaccia utente basata su Python, per un uso pratico e modifiche facili come la selezione del volume, delle note e dei canali.

Caratteristiche del dispositivo:

  • Prezzo basso
  • Creazione di drum kit da qualsiasi ingresso digitale, anche da una serie di pulsanti
  • Supporto di comunicazione e alimentazione solo tramite interfaccia USB - Integrazione di convertitore da USB a UART e dispositivo Arduino
  • Parti minime per il corretto funzionamento
  • Interfaccia utente basata su Python di facile utilizzo
  • Supporto MIDI completo con velocità, note e pin Arduino regolabili
  • Salva e carica le configurazioni di batteria personalizzate archiviate nella memoria del dispositivo

Passiamo al progetto…

Passaggio 1: teoria del funzionamento

Teoria del funzionamento
Teoria del funzionamento
Teoria del funzionamento
Teoria del funzionamento
Teoria del funzionamento
Teoria del funzionamento

Diagramma a blocchi

Prima di tutto, concentriamoci sulla struttura del progetto e dividiamolo in blocchi separati:

Batteria arrotolabile

L'unità principale del progetto. Consiste di 9 drum pad separati, dove ogni pad è una serie di pulsanti che cambiano il loro stato logico mentre vengono colpiti. A causa della sua struttura, c'è la possibilità di costruire questo particolare drum kit da qualsiasi pulsante. Ogni drum pad è collegato alla resistenza di pull-up sulla scheda elettronica principale, quindi mentre il drum pad viene ripetutamente colpito, un interruttore specifico è legato alla massa del circuito e logico LOW è presente sulla linea del drum pad. Quando non viene applicata alcuna pressione, l'interruttore del pad della batteria è aperto e, a causa della resistenza di pull-up alla linea di alimentazione, è presente ALTO logico sulla linea del pad della batteria. Poiché lo scopo del progetto è creare un dispositivo MIDI digitale completo, tutte le parti analogiche sul PCB principale possono essere trascurate. È importante notare che la batteria ha due pedali per grancassa e charleston, anch'essi legati alle resistenze di pull-up e che condividono la stessa logica di funzionamento di tutti i drum pad (ne parleremo un po' più avanti).

Arduino Pro-Micro

Il cervello della batteria. Il suo scopo è rilevare se c'è un segnale che esce da un drum pad e fornire un'uscita MIDI appropriata con tutti i parametri necessari: nota, velocità e durata del segnale. A causa della natura digitale dei drum pad, possono essere semplicemente collegati agli ingressi digitali di Arduino (10 pin in totale). Per memorizzare tutte le impostazioni e le informazioni MIDI desiderate, utilizzeremo la sua memoria - EEPROM, quindi ogni volta che accendiamo il dispositivo, le informazioni MIDI vengono caricate dalla EEPROM, rendendola riprogrammabile e riconfigurabile. Inoltre, Arduino Pro-Micro è disponibile in una confezione molto piccola e può essere facilmente allocato nella custodia interna della batteria.

Convertitore da USB a seriale FTDI

Per programmare e definire le funzionalità del nostro dispositivo con l'aiuto dell'applicazione per PC, è necessario convertire l'interfaccia USB in seriale, perché Arduino Pro-Micro non ha USB. Poiché la comunicazione tra i dispositivi è basata su UART, in questo progetto viene utilizzato il dispositivo FTDI, grazie alla sua semplicità di utilizzo indipendentemente dalle sue proprietà aggiuntive.

Applicazione per PC - Python

Quando si tratta di sviluppo di interfacce utente e progetti veloci da costruire, Python è una soluzione eccezionale. Lo scopo dell'applicazione UI è quello di rendere molto più conveniente la ridefinizione delle proprietà MIDI per il nostro drum kit, memorizzare informazioni, programmare il dispositivo e rendere la comunicazione tra i sistemi senza la necessità di compilare il codice più e più volte. Poiché utilizziamo l'interfaccia seriale per comunicare con il drum kit, ci sono molti moduli gratuiti su Internet che supportano qualsiasi tipo di comunicazione seriale. Inoltre, come verrà discusso in seguito, l'interfaccia UART è composta da un totale di tre pin: RXD, TXD e DTR. DTR viene utilizzato per eseguire il ripristino sul modulo Arduino, quindi quando siamo interessati a eseguire l'app MIDI o collegare l'interfaccia utente al dispositivo di programmazione, non è assolutamente necessario ricollegare il cavo USB o altro.

Passaggio 2: parti e strumenti

Parti

  • Batteria arrotolabile
  • 2 x Sustain Pedals (solitamente inclusi nel pacchetto DK).
  • FTDI - Convertitore da USB a seriale
  • Arduino Pro Micro
  • Cavo Micro-USB

Strumenti

  • Saldatore/Stazione
  • stagno di saldatura
  • Filo unipolare di diametro sottile
  • pinzette
  • taglierina
  • pinza
  • Coltello
  • Cacciavite
  • Stampante 3D (opzionale - per piattaforme a pedale personalizzate)

Software

  • Arduino IDE
  • Python 3 o superiore
  • JetBrains Pycharm
  • Interfaccia MIDI senza peli
  • loopMIDI

Passaggio 3: saldatura e assemblaggio

Saldatura e assemblaggio
Saldatura e assemblaggio
Saldatura e assemblaggio
Saldatura e assemblaggio
Saldatura e assemblaggio
Saldatura e assemblaggio

Poiché ci sono tre moduli che devono essere combinati, il processo di saldatura e assemblaggio è breve e semplice:

  • Collegare insieme Arduino Pro-Micro con il dispositivo FTDI, assicurarsi che le connessioni siano conformi agli I/O definiti su ciascun dispositivo:

    • VBUS-VBUS
    • GND-GND
    • DTR-DTR
    • RXD-TXD
    • TXD-RXD
  • Rimuovi tutte le viti dall'involucro di plastica del tamburo, assicurati di poterti concentrare sul cavo pad-to-board e sui suoi resistori di pull-up
  • Saldare fili sottili per il modulo Arduino-FTDI che abbiamo costruito in precedenza:

    • Ingressi digitali: D[2:11]
    • VBUS
    • D+
    • D-
    • GND
  • Inserire il modulo all'interno della custodia della batteria in modo che i fili siano flottanti dallo stesso lato dei resistori di pull-up dei pad
  • Saldare tutti gli ingressi digitali ai terminali del drum pad come mostrato nell'ultima figura.
  • Saldare il bus micro-USB (VBUS, D+, D-, GND) al dispositivo FTDI, assicurarsi che non ci siano errori nel tracciare questi fili.
  • Attacca il modulo Arduino-FTDI con la colla a caldo alla custodia della batteria
  • Assemblare il dispositivo con l'apposito fissaggio a vite

Ce l'abbiamo fatta, il dispositivo è assemblato. Continuiamo con il codice…

Passaggio 4: Programmazione A: Arduino

Programmazione A: Arduino
Programmazione A: Arduino

Descriviamo il nostro schizzo passo dopo passo:

Prima di tutto, è necessario includere due librerie necessarie per il corretto funzionamento. La EEPROM è già preinstallata nell'IDE Arduino, ma il modulo antirimbalzo per grancassa deve essere installato separatamente

#include #include

Queste opzioni vengono utilizzate principalmente nelle sequenze di debug. Se vuoi provare la connessione dei terminali Arduino ai drum pad e determinare tutti gli ingressi digitali, questi interruttori dovrebbero essere definiti

/* Developer Switch: Decommenta la modalità desiderata per il debug o l'inizializzazione *///#define LOAD_DEFAULT_VALUES // Carica valori costanti invece di EEPROM //#define PRINT_PADS_PIN_NUMBERS // Stampa il numero di pin collegato a un pad che è stato colpito tramite la porta seriale

I campi costanti rappresentano tutti i valori predefiniti, inclusa l'enumerazione dei drum pad. Per far funzionare il dispositivo per la prima volta, è necessario conoscere l'esatto collegamento dei pedali Hi-Hat e Kick

/* Enumerazione del tipo di tamburo */

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

/* Valori standard */

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 };

/* Durata antirimbalzo della cassa */

const uint8_t KICK_DB_DURATION = 30;

La EEPROM viene utilizzata per memorizzare/caricare tutti i dati provenienti dall'applicazione PC. L'estensione degli indirizzi sopra descritta mostra la posizione esatta per le informazioni MIDI per ogni drum pad

/* Mappatura indirizzi EEPROM

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

Pin: |0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13| Velocità |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;

Le variabili globali vengono utilizzate per determinare lo stato di ciascun pad ed eseguire la comunicazione MIDI di conseguenza

/* Variabili Globali */

uint8_t drumNotes[10], drumVelocities[10], drumPins[10]; // Variabili MIDI

uint8_t uartBuffer[64]; // Buffer UART per la raccolta e la memorizzazione di dati MIDI Debouncer kick(DRUM_PINS[KICK], KICK_DB_DURATION); // Oggetto antirimbalzo per kick drum volatile bool previousState[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // Stati logici precedenti del drum pad volatile bool currentState[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // Stati logici correnti del pad della batteria

Funzioni EEPROM

/* Memorizza le impostazioni nella EEPROM*/

void storeEEPROM() {

memcpy(drumNotes, uartBuffer, 10); memcpy(drumPins, uartBuffer + 10, 10); memcpy(drumVelocities, 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); }

/* Carica le impostazioni dalla 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); }

Inizializzazione delle variabili e modalità di programmazione, nel caso di pedali e boot di Arduino vengono attivati contemporaneamente

void enterProgrammingMode() {

bool confirmBreak = false; uint8_t lineCnt = 0; uint8_t charCnt = 0; char readChar = 0; while(!confirmBreak) { if (Serial.available()) { uartBuffer[charCnt] = Serial.read(); if (charCnt >= 29) confirmBreak = true; else charCnt++; } } Serial.println("OK"); storeEEPROM(); }

void initValues() {

#ifdef LOAD_DEFAULT_VALUES memcpy(drumNotes, DRUM_NOTES, 10); memcpy(drumVelocities, DRUM_VELOCITIES, 10); memcpy(drumPins, DRUM_PINS, 10); #else caricaEEPROM(); #finisci se }

Gestori di comunicazione MIDI con ritardo di 1 ms di tempo di mantenimento della nota

/* Funzione di riproduzione della nota MIDI */

void midiOut(enum DRUM_POSITION drumIn) {

if (drumIn == HIHAT) { // Se HI-HAT è stato colpito, è necessario verificare se il pedale è premuto if (!digitalRead(drumPins[HIHAT_PEDAL])) { noteOn(0x90, drumNotes[HIHAT_PEDAL], drumVelocities [HIHAT_PEDAL]); ritardo(1); noteOn(0x90, drumNotes[HIHAT_PEDAL], 0); } else { noteOn(0x90, drumNotes[HIHAT], drumVelocities[HIHAT]); ritardo(1); noteOn(0x90, drumNotes[HIHAT], 0); } } else { // Trasmissione MIDI regolare di batteria noteOn(0x90, drumNotes[drumIn], drumVelocities[drumIn]); ritardo(1); noteOn(0x90, drumNotes[drumIn], 0); } }

void noteOn(int cmd, int pitch, int velocity) { Serial.write(cmd); Serial.write(passo); Serial.write(velocità); }

funzioni setup() e loop() con loop di operazioni del dispositivo infinito:

void setup() {

Serial.begin(115200);

for (uint8_t i = 0; i < 10; i++) { pinMode(i + 2, INPUT); } #ifdef PRINT_PADS_PIN_NUMBERS while(true) { // Ciclo di debug infinito per (uint8_t i = 0; i < 10; i++) { if (!digitalRead(i + 2)) { Serial.print("Pin No: D"); Serial.print(i + '0'); // Converti numero in carattere ASCII } } } #else initValues(); /* Modalità di programmazione: se vengono premuti due pedali durante l'avvio, la modalità è attivata */ if (!digitalRead(drumPins[KICK]) && !digitalRead(drumPins[HIHAT_PEDAL])) enterProgrammingMode(); #finisci se }

void loop() { for (uint8_t i = 1; i < 9; i = i + 1) { currentState = digitalRead(drumPins); if (!currentState && previousState) midiOut(i); // Confronta gli stati e rileva il fronte di discesa previousState = currentState; } kick.update(); // La grancassa utilizza un algoritmo di antirimbalzo personalizzato if (kick.edge()) if (kick.falling()) midiOut(KICK); }

Passaggio 5: programmazione B: Python e interfaccia utente

Programmazione B: Python e interfaccia utente
Programmazione B: Python e interfaccia utente
Programmazione B: Python e interfaccia utente
Programmazione B: Python e interfaccia utente
Programmazione B: Python e interfaccia utente
Programmazione B: Python e interfaccia utente

L'interfaccia utente di Python è un po' complicata da capire a prima vista, quindi cercheremo di spiegarne le basi, come si usa, quale funzione ha ogni pulsante e come programmare correttamente il dispositivo Arduino.

Interfaccia utente - Applicazione

L'interfaccia utente è una rappresentazione grafica per il nostro programmatore di batterie, che lo rende davvero facile da usare e conveniente per programmare il dispositivo Arduino in qualsiasi momento. L'interfaccia utente è composta da diversi moduli grafici legati al loro funzionamento suggerito. rivediamoli uno per uno:

  1. Immagine del set di batteria: l'interfaccia utente di Python utilizza le coordinate dell'immagine X-Y per determinare quale tipo di batteria è stato selezionato. Se è stata selezionata una regione di batteria valida, viene visualizzato il messaggio IO secondario, con i campi della nota, la velocità e il terminale Arduino per il pad della batteria dedicato. Dopo che questi parametri sono stati verificati dall'utente e approvati, questi valori possono essere trasmessi direttamente al dispositivo Arduino.
  2. Immagine del controller esterno: per poter utilizzare il drum kit MIDI con l'ambiente di creazione VST/Musica, è necessario eseguire l'interprete Serial-To-MIDI. Ho usato Hairless, che è disponibile gratuitamente e può essere eseguito direttamente dalla nostra interfaccia utente, semplicemente premendo la sua immagine.
  3. Elenco porte COM: per comunicare con Arduino, è necessario specificare la porta COM collegata. L'elenco viene aggiornato premendo il pulsante Aggiorna.
  4. Carica/Salva configurazione: ci sono valori MIDI predefiniti definiti nel codice, che possono essere modificati dall'utente tramite l'interazione con l'interfaccia utente. La configurazione è definita nel file config.txt in un formato specifico, che può essere salvato o caricato dall'utente.
  5. Pulsante Program Device: per memorizzare tutti i valori MIDI modificati nella EEPROM di Arduino, è necessario premere due pedali (Kick drum e Hi-hat pedal) dopodiché, attendere il completamento della trasmissione dei dati. In caso di problemi di comunicazione, verrà mostrato il pop-up appropriato. Se la trasmissione ha esito positivo, l'interfaccia utente mostrerà il suo messaggio di successo.
  6. Pulsante Esci: basta uscire dall'applicazione, con il permesso dell'utente.

Punti salienti del codice Python

Ci sono molte cose che accadono nel codice, quindi espanderemo le funzioni scritte piuttosto che l'intero codice.

Prima di tutto, per poter utilizzare l'interfaccia utente, è necessario scaricare diversi moduli, per far funzionare il codice:

import osimport threading import tkinter as tk da tkinter import messagebox da tkinter import * from PIL import ImageTk, Image import numpy as np import serial import glob

Alcuni dei moduli sono inclusi nel pacchetto Python predefinito. Diversi moduli dovrebbero essere installati tramite lo strumento PIP:

pip install Pillow

pip install numpy pip install ScreenInfo

Si consiglia vivamente di eseguire l'applicazione tramite PyCharm. Nelle versioni future, ho intenzione di esportare un eseguibile per il progetto.

Breve spiegazione del codice

Sarà molto più facile capire il codice se guardassimo le sue linee dal punto di vista delle funzioni e delle classi:

1. La funzione principale: qui inizia il codice

if _name_ == '_main_': drumkit_gui()

2. Costanti del kit di batteria, coordinate e informazioni MIDI predefinite

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

COORDINATE_X = [323, 117, 205, 173, 565, 271, 386, 488, 487, 135, 79]

COORDINATE_Y = [268, 115, 192, 40, 29, 107, 104, 190, 71, 408, 208] DIMS_WIDTH = [60, 145, 130, 120, 120, 70, 70, 130, 120, 70, 145] DIMS_LENGTH = [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"]

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

3. Funzioni dell'interfaccia utente - Gestione dell'interfaccia utente e degli oggetti grafici

def set_active(ui)

def secondary_ui(drum_type)

class SelectionUi(tk. Frame)

classe Applicazione (tk. Frame)

def drumkit_gui()

def event_ui_clicked(evento)

def getorigin(auto, evento)

4. Comunicazione seriale

def get_serial_ports()

def comunica_con_arduino(porta)

5. Lavorare con i file: memorizzare/caricare le impostazioni dal file txt

def save_config()

def load_config()

6. Esecuzione di un'applicazione esterna hairless.exe dal codice utilizzando le funzionalità di threading di Python

class ExternalExecutableThread(threading. Thread)

def run_hairless_executable()

Per eseguire il codice, c'è un elenco di file che devono essere allegati alla cartella del progetto:

  • config.txt: file delle impostazioni
  • hairless.exe: convertitore MIDI senza peli
  • drumkit.png: immagine che definisce tutti i drum pad cliccabili sulla nostra interfaccia utente (deve essere scaricata dal set di immagini di questo passaggio)
  • drumgui.py: Il codice del progetto

Questo è tutto ciò che dobbiamo sottolineare per farlo funzionare. È molto importante aggiungere file al progetto: immagine della batteria, eseguibile hairless.exe e file di impostazioni config.txt.

E.. Ecco fatto!:)

Spero che troverai utile questo istruibile.

Grazie per aver letto!:)

Consigliato: