Inhoudsopgave:

MIDI-drumkit op Python en Arduino: 5 stappen (met afbeeldingen)
MIDI-drumkit op Python en Arduino: 5 stappen (met afbeeldingen)

Video: MIDI-drumkit op Python en Arduino: 5 stappen (met afbeeldingen)

Video: MIDI-drumkit op Python en Arduino: 5 stappen (met afbeeldingen)
Video: Control Arduino with Python using Firmata / PyFirmata 2024, November
Anonim
Image
Image
MIDI-drumstel op Python en Arduino
MIDI-drumstel op Python en Arduino
MIDI-drumstel op Python en Arduino
MIDI-drumstel op Python en Arduino

Als kind wilde ik altijd al een drumstel kopen. Destijds had alle muziekapparatuur niet alle digitale toepassingen zoals we er tegenwoordig veel hebben, vandaar dat de prijzen en de verwachtingen te hoog waren. Onlangs heb ik besloten om een goedkoopste drumstel van eBay te kopen, met als enige prioriteit: de mogelijkheid om het af te breken en mijn eigen hardware en software op het apparaat te bevestigen.

De aankoop viel helemaal niet tegen: draagbare roll-up drumkit met 9 verschillende soundpads, twee voetschakelaarpedalen voor kickdrum en hi-hat en micro-USB-stopcontact. Wat echt demotiverend was, zijn de uitvoergeluiden (het werkelijke gebruik van deze kit is om een externe luidspreker aan te sluiten en ervan te genieten). Dus besloot ik het om te zetten naar mijn eigen programmeerbare via USB, MIDI-drumkit op basis van Arduino en gebruikersinterface op basis van Python, voor handig gebruik en gemakkelijke aanpassingen zoals volume-, noot- en kanaalselecties.

Kenmerken van het apparaat:

  • Lage prijs
  • Een drumstel maken van alle digitale ingangen - zelfs een reeks drukknoppen
  • Communicatie-ondersteuning en voeding alleen via USB-interface - Integratie van USB naar UART-converter en Arduino-apparaat
  • Minimaal onderdelen voor een goede werking
  • Gebruiksvriendelijke gebruikersinterface op basis van Python
  • Volledige MIDI-ondersteuning met instelbare snelheid, noot en Arduino-pinnen
  • Opslaan en laden van aangepaste drumconfiguraties die zijn opgeslagen in het geheugen van het apparaat

Laten we verder gaan met het project…

Stap 1: Theorie van de werking

Theorie van de werking
Theorie van de werking
Theorie van de werking
Theorie van de werking
Theorie van de werking
Theorie van de werking

Blokdiagram

Laten we ons eerst concentreren op de projectstructuur en deze in afzonderlijke blokken verdelen:

Roll-up drumstel

De hoofdeenheid van het project. Het bestaat uit 9 afzonderlijke drumpads, waarbij elke pad een reeks knoppen is die hun logische status veranderen terwijl ze worden aangeslagen. Vanwege de structuur is er een mogelijkheid om dit specifieke drumstel uit willekeurige drukknoppen te bouwen. Elke drumpad is verbonden met de pull-up-weerstand op het elektronische hoofdbord, dus terwijl de drumpad herhaaldelijk wordt geraakt, is een specifieke schakelaar verbonden met de aarde van het circuit en is logisch LOW aanwezig op de drumpadlijn. Als er geen druk wordt uitgeoefend, is de drumpad-schakelaar open en vanwege de pull-up-weerstand naar de voedingslijn is logisch HOOG aanwezig op de drumpad-lijn. Omdat het doel van het project is om een compleet digitaal MIDI-apparaat te maken, kunnen alle analoge onderdelen op de hoofdprintplaat worden verwaarloosd. Het is belangrijk op te merken dat de drumkit twee pedalen heeft voor kickdrum en hi-hat, die ook zijn verbonden met de pull-up-weerstanden en dezelfde bedieningslogica delen als alle drumpads (we zullen het een beetje later bespreken).

Arduino Pro-Micro

Het brein van een drumstel. Het doel is om te detecteren of er een signaal uit een drumpad komt en om de juiste MIDI-uitvoer te leveren met alle benodigde parameters: noot, snelheid en duur van het signaal. Vanwege het digitale karakter van drumpads, kunnen ze eenvoudig worden gekoppeld aan arduino digitale ingangen (10 pinnen in totaal). Om alle gewenste instellingen en MIDI-informatie op te slaan, gaan we het geheugen gebruiken - EEPROM, dus elke keer dat we het apparaat opstarten, wordt MIDI-informatie geladen vanuit EEPROM, waardoor het opnieuw programmeerbaar en configureerbaar is. Arduino Pro-Micro is ook verkrijgbaar in een zeer kleine verpakking en kan eenvoudig worden toegewezen aan de binnenkoffer van de drumkit.

FTDI USB naar serieel converter

Om onze apparaatfuncties te programmeren en te definiëren met behulp van een pc-toepassing, is het nodig om de USB-interface naar serieel te converteren, omdat Arduino Pro-Micro geen USB heeft. Omdat de communicatie tussen apparaten is gebaseerd op UART, wordt het FTDI-apparaat in dit project gebruikt vanwege de eenvoud van gebruik, ongeacht de aanvullende eigenschappen.

PC-toepassing - Python

Als het gaat om de ontwikkeling van gebruikersinterfaces en snel te bouwen projecten, is Python een uitstekende oplossing. Het doel van de UI-toepassing is om het veel handiger te maken om MIDI-eigenschappen voor onze drumkit opnieuw te definiëren, informatie op te slaan, het apparaat te programmeren en communicatie tussen de systemen tot stand te brengen zonder dat de code steeds opnieuw hoeft te worden gecompileerd. Omdat we een seriële interface gebruiken om met drumkits te communiceren, zijn er tal van gratis modules op internet die alle soorten seriële communicatie ondersteunen. Bovendien, zoals later zal worden besproken, bestaat de UART-interface uit in totaal drie pinnen: RXD, TXD en DTR. DTR wordt gebruikt om een reset uit te voeren op de Arduino-module, dus als we geïnteresseerd zijn in het uitvoeren van de MIDI-app of het verbinden van de gebruikersinterface met het programmeerapparaat, is het absoluut niet nodig om de USB-kabel of wat dan ook opnieuw aan te sluiten.

Stap 2: Onderdelen en instrumenten

Onderdelen

  • Roll-up drumstel
  • 2 x Sustain-pedalen (meestal inbegrepen in DK-pakket).
  • FTDI - USB naar serieel converter
  • Arduino Pro Micro
  • Micro-USB-kabel

instrumenten

  • Soldeerbout/station
  • Soldeertin
  • Dunne diameter enkele kerndraad
  • Pincet
  • Snijder
  • tang
  • Mes
  • Schroevendraaier
  • 3D-printer (optioneel - voor aangepaste pedaalplatforms)

Software

  • Arduino IDE
  • Python 3 of hoger
  • JetBrains Pycharm
  • Haarloze MIDI-interface
  • loopMIDI

Stap 3: Solderen en monteren

Solderen en monteren
Solderen en monteren
Solderen en monteren
Solderen en monteren
Solderen en monteren
Solderen en monteren

Omdat er drie modules moeten worden gecombineerd, is het soldeer- en montageproces kort en eenvoudig:

  • Bevestig Arduino Pro-Micro aan elkaar met FTDI-apparaat, zorg ervoor dat de verbindingen voldoen aan I/O gedefinieerd op elk apparaat:

    • VBUS-VBUS
    • GND-GND
    • DTR-DTR
    • RXD-TXD
    • TXD-RXD
  • Verwijder alle schroeven uit de plastic behuizing van de drum, zorg ervoor dat u zich kunt concentreren op de pad-naar-board-kabel en de pull-up-weerstanden
  • Soldeer dunne draden voor Arduino-FTDI-module die we eerder hebben geconstrueerd:

    • Digitale ingangen: D[2:11]
    • VBUS
    • D+
    • NS-
    • GND
  • Plaats de module in de batterijhouder zodat de draden aan dezelfde kant zweven als de pull-up-weerstanden van de pads
  • Soldeer alle digitale ingangen op de drumpad-aansluitingen zoals weergegeven in de laatste afbeelding.
  • Soldeer de micro-USB-bus (VBUS, D+, D-, GND) aan het FTDI-apparaat, zorg ervoor dat er geen fouten zijn bij het traceren van deze draden.
  • Bevestig de Arduino-FTDI-module met hete lijm aan de batterijhouder
  • Monteer het apparaat met de juiste schroevenbevestiging

We hebben het gedaan, het apparaat is gemonteerd. Laten we doorgaan naar de code …

Stap 4: Programmeren A: Arduino

Programmering A: Arduino
Programmering A: Arduino

Laten we onze schets stap voor stap beschrijven:

Allereerst is het nodig om twee noodzakelijke bibliotheken op te nemen voor de juiste werking. EEPROM is al voorgeïnstalleerd in de Arduino IDE, maar de debouncer-module voor kickdrum moet apart worden geïnstalleerd

#include #include

Deze schakelaars worden voornamelijk gebruikt bij het debuggen van sequenties. Als u de Arduino-terminalsverbinding met de drumpads wilt uitproberen en alle digitale ingangen wilt bepalen, moeten deze schakelaars worden gedefinieerd

/* Switches voor ontwikkelaars: verwijder de gewenste modus voor foutopsporing of initialisatie *///#define LOAD_DEFAULT_VALUES // Laad constante waarden in plaats van EEPROM //#define PRINT_PADS_PIN_NUMBERS // Print pincode die is verbonden met een pad dat is geraakt via een seriële poort

Constante velden vertegenwoordigen alle standaardwaarden, inclusief de drumpad-telling. Om het apparaat voor de allereerste keer te gebruiken, moet u de exacte aansluiting van Hi-Hat- en Kick-pedalen weten

/* Opsomming trommeltype */

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

/* Standaard waarden */

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

/* Kick drum debounce duur */

const uint8_t KICK_DB_DURATION = 30;

EEPROM wordt gebruikt om alle gegevens van de pc-toepassing op te slaan/te laden. De hierboven beschreven adressen omvatten de exacte locatie voor MIDI-informatie voor elke drumpad

/* Toewijzing van EEPROM-adressen

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

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

Globale variabelen worden gebruikt om de status van elke pad te bepalen en dienovereenkomstig MIDI-communicatie uit te voeren

/* Globale variabelen */

uint8_t drumNotes[10], drumVelocities[10], drumPins[10]; // MIDI-variabelen

uint8_t uartBuffer[64]; // UART-buffer voor het verzamelen en opslaan van MIDI-gegevens Debouncer kick (DRUM_PINS [KICK], KICK_DB_DURATION); // Debouncer-object voor kickdrum vluchtige bool previousState [9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // Vorige logische toestanden van drumpad vluchtig bool currentState [9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // Huidige logische toestanden van drumpads

EEPROM-functies

/* Bewaar instellingen in de EEPROM*/

void winkelEEPROM() {

memcpy(drumNotes, uartBuffer, 10); memcpy(drumPins, uartBuffer + 10, 10); memcpy(drumVelocities, uartBuffer + 20, 10); voor (uint8_t i = 0; i < 10; i++) EEPROM.write(NOTES_ADDR + i, drumNotes); voor (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); }

/* Laad instellingen uit de EEPROM*/

void loadEEPROM() { for (uint8_t i = 0; i < 10; i++) drumNotes = EEPROM.read (NOTES_ADDR + i); voor (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); }

Initialisatie van variabelen en programmeermodus, in het geval van pedalen en Arduino boot worden gelijktijdig geactiveerd

void enterProgrammingMode() {

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

ongeldige initValues() {

#ifdef LOAD_DEFAULT_VALUES memcpy(drumNotes, DRUM_NOTES, 10); memcpy(drumVelocities, DRUM_VELOCITIES, 10); memcpy(drumPins, DRUM_PINS, 10); #else laadEEPROM(); #stop als }

MIDI-communicatie-handlers met een vertraging van 1 ms noothoudtijd

/* Speel MIDI-nootfunctie */

void midiOut(enum DRUM_POSITION drumIn) {

if (drumIn == HIHAT) { // Als HI-HAT is geraakt, moet worden gecontroleerd of het pedaal is ingedrukt if (!digitalRead(drumPins[HIHAT_PEDAL])) { noteOn(0x90, drumNotes[HIHAT_PEDAL], drumVelocities [HIHAT_PEDAL]); vertraging(1); noteOn (0x90, drumNotes [HIHAT_PEDAL], 0); } else { noteOn(0x90, drumNotes[HIHAT], drumVelocities[HIHAT]); vertraging(1); noteOn(0x90, drumNotes[HIHAT], 0); } } else { // Reguliere drum MIDI-transmissie noteOn (0x90, drumNotes [drumIn], drumVelocities [drumIn]); vertraging(1); noteOn(0x90, drumNotes[drumIn], 0); } }

void noteOn (int cmd, int toonhoogte, int snelheid) { Serial.write (cmd); Serieel.schrijven (pitch); Serieel.schrijven (snelheid); }

setup() en loop() functies met oneindige apparaatbedieningslus:

ongeldige setup() {

Serieel.begin(115200);

voor (uint8_t i = 0; ik < 10; i++) { pinMode(i + 2, INPUT); } #ifdef PRINT_PADS_PIN_NUMBERS while(true) {// Oneindige foutopsporingslus voor (uint8_t i = 0; i < 10; i++) {if (!digitalRead(i + 2)) {Serial.print("Pin No: D"); Serial.print(i + '0'); // Converteer getal naar ASCII-teken } } } #else initValues(); /* Programmeermodus: Als tijdens het opstarten twee pedalen worden ingedrukt, wordt de modus geactiveerd */ if (!digitalRead(drumPins[KICK]) && !digitalRead(drumPins[HIHAT_PEDAL])) enterProgrammingMode(); #stop als }

void loop () { for (uint8_t i = 1; i < 9; i = i + 1) { currentState = digitalRead (drumPins ); if (!currentState && previousState) midiOut(i); // Vergelijk staten en detecteer dalende flank previousState = currentState ; } kick.update(); // Kickdrum gebruikt een aangepast debounce-algoritme if (kick.edge()) if (kick.falling()) midiOut(KICK); }

Stap 5: Programmeren B: Python & gebruikersinterface

Programmering B: Python & gebruikersinterface
Programmering B: Python & gebruikersinterface
Programmering B: Python & gebruikersinterface
Programmering B: Python & gebruikersinterface
Programmering B: Python & gebruikersinterface
Programmering B: Python & gebruikersinterface

De gebruikersinterface van Python is op het eerste gezicht een beetje ingewikkeld om te begrijpen, daarom zouden we proberen de basis uit te leggen, hoe te gebruiken, welke functie elke knop heeft en hoe het Arduino-apparaat correct te programmeren.

Gebruikersinterface - Toepassing

UI is een grafische weergave voor onze drumkit-programmeur, waardoor het heel gemakkelijk te gebruiken en handig is om het Arduino-apparaat op elk moment te programmeren. UI bestaat uit verschillende grafische modules die zijn gekoppeld aan hun voorgestelde werking. laten we ze een voor een bekijken:

  1. Drumset-afbeelding: Python UI gebruikt X-Y-afbeeldingscoördinaten om te bepalen welk drumtype is geselecteerd. Als een geldig drumgebied is geselecteerd, verschijnt er een secundair IO-bericht, met velden voor noot, snelheid en Arduino-terminal voor speciale drumpad. Nadat deze parameters door de gebruiker zijn geverifieerd en goedgekeurd, kunnen deze waarden rechtstreeks naar het Arduino-apparaat worden verzonden.
  2. Afbeelding van externe controller: om een MIDI-drumkit te kunnen gebruiken met een VST/Music-creërende omgeving, moet een Serial-To-MIDI-interpreter worden uitgevoerd. Ik heb Hairless gebruikt, dat gratis beschikbaar is en rechtstreeks vanuit onze gebruikersinterface kan worden uitgevoerd, gewoon door op de afbeelding te drukken.
  3. COM-poortlijst: om met Arduino te kunnen communiceren, moet de bijbehorende COM-poort worden gespecificeerd. De lijst wordt vernieuwd door op de knop Vernieuwen te drukken.
  4. Configuratie laden/opslaan: er zijn standaard MIDI-waarden gedefinieerd in de code, die door de gebruiker kunnen worden gewijzigd via interactie met de gebruikersinterface. Configuratie wordt gedefinieerd in het config.txt-bestand in een specifiek formaat, dat door de gebruiker kan worden opgeslagen of geladen.
  5. Programmeerapparaatknop: om alle gewijzigde MIDI-waarden in Arduino EEPROM op te slaan, moet u daarna twee voetpedalen (kickdrum en hihatpedaal) indrukken en wachten tot de gegevensoverdracht is voltooid. Als er communicatieproblemen waren, wordt de juiste pop-up weergegeven. Als de verzending slaagt, toont de gebruikersinterface het succesvolle bericht.
  6. Afsluitknop: Sluit de applicatie gewoon af, met toestemming van de gebruiker.

Hoogtepunten van Python-code

Er zijn veel dingen aan de hand in de code, dus we zullen ingaan op de geschreven functies in plaats van op de hele code.

Allereerst, om de gebruikersinterface te gebruiken, moeten verschillende modules worden gedownload om de code te laten werken:

import osimport threading import tkinter als tk van tkinter import messagebox van tkinter import * van PIL import ImageTk, Image import numpy als np import seriële import glob

Sommige modules zijn opgenomen in het standaard Python-pakket. Verschillende modules moeten via de PIP-tool worden geïnstalleerd:

pip installeren kussen

pip install numpy pip install ScreenInfo

Het wordt sterk aanbevolen om de applicatie via PyCharm uit te voeren. In de toekomstige releases ben ik van plan een uitvoerbaar bestand voor het project te exporteren.

Korte Code Uitleg:

Het zal veel gemakkelijker zijn om de code te begrijpen als we de regels ervan bekijken vanuit het perspectief van functies en klassen:

1. De hoofdfunctie - hier begint de code

if _name_ == '_main_': drumkit_gui()

2. Drumkit-constanten, coördinaten en standaard MIDI-informatie

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

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

COORDINATEN_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-pedaal"]

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. UI-functies - Behandeling van gebruikersinterface en grafische objecten

def set_active(ui)

def secundaire_ui(drum_type)

klasse SelectionUi(tk. Frame)

klasse Toepassing (tk. Frame)

def drumkit_gui()

def event_ui_clicked(event)

def getorigin (zelf, evenement)

4. Seriële communicatie

def get_serial_ports()

def communication_with_arduino(poort)

5. Werken met bestanden: instellingen opslaan/laden uit het txt-bestand

def save_config()

def load_config()

6. Externe applicatie hairless.exe uitvoeren vanuit de code met behulp van Python Threading-mogelijkheden

klasse ExternalExecutableThread(threading. Thread)

def run_hairless_executable()

Om de code uit te voeren, is er een lijst met bestanden die aan de projectmap moeten worden toegevoegd:

  • config.txt: Instellingenbestand
  • hairless.exe: Haarloze MIDI-converter
  • drumkit.png: Afbeelding die alle klikbare drumpads in onze gebruikersinterface definieert (moet worden gedownload van de afbeeldingenset van deze stap)
  • drumgui.py: De projectcode

Dat is alles wat we moeten benadrukken om het te laten werken. Het is erg belangrijk om bestanden aan het project toe te voegen: drumset image, hairless.exe uitvoerbaar bestand en instellingenbestand config.txt.

En.. Hier hebben we het gedaan!:)

Ik hoop dat je dit instructable nuttig zult vinden.

Bedankt voor het lezen!:)

Aanbevolen: