Tabla de contenido:

Kit de batería MIDI en Python y Arduino: 5 pasos (con imágenes)
Kit de batería MIDI en Python y Arduino: 5 pasos (con imágenes)

Video: Kit de batería MIDI en Python y Arduino: 5 pasos (con imágenes)

Video: Kit de batería MIDI en Python y Arduino: 5 pasos (con imágenes)
Video: bateria electronica con pads 2024, Noviembre
Anonim
Image
Image
Kit de batería MIDI en Python y Arduino
Kit de batería MIDI en Python y Arduino
Kit de batería MIDI en Python y Arduino
Kit de batería MIDI en Python y Arduino

Siempre quise comprar una batería desde que era niño. En aquel entonces, todo el equipo musical no tenía todas las aplicaciones digitales como tenemos muchas hoy, por lo que los precios y las expectativas eran demasiado altos. Recientemente, decidí comprar un kit de batería más barato en eBay, con la única prioridad: poder desmontarlo y conectar mi propio hardware y software al dispositivo.

La compra no fue decepcionante en absoluto: kit de batería enrollable portátil con 9 almohadillas de sonido diferentes, dos pedales de interruptor de pie para bombo y charles y toma de corriente micro-USB. Lo realmente desmotivador son los sonidos de salida (el uso real de este kit es conectar un altavoz externo y disfrutarlo). Entonces, decidí convertirlo a mi propio programable a través de USB, kit de batería MIDI basado en Arduino e interfaz de usuario basada en Python, para un uso práctico y modificaciones fáciles como selección de volumen, nota y canal.

Características del dispositivo:

  • Precio bajo
  • Creación de un kit de batería a partir de cualquier entrada digital, incluso una variedad de botones
  • Soporte de comunicación y fuente de alimentación solo a través de la interfaz USB - Integración de convertidor USB a UART y dispositivo Arduino
  • Piezas mínimas para un correcto funcionamiento
  • Interfaz de usuario basada en Python fácil de usar
  • Soporte MIDI completo con velocidad ajustable, notas y pines Arduino
  • Guarde y cargue configuraciones de batería personalizadas almacenadas en la memoria del dispositivo

Procedamos al proyecto …

Paso 1: teoría de funcionamiento

teoría de operación
teoría de operación
teoría de operación
teoría de operación
teoría de operación
teoría de operación

Diagrama de bloques

En primer lugar, centrémonos en la estructura del proyecto y dividámoslo en bloques separados:

Kit de batería enrollable

La unidad principal del proyecto. Consiste en 9 pads de batería separados, donde cada pad es una matriz de botones que cambian su estado lógico mientras se pulsan. Debido a su estructura, existe la posibilidad de construir este kit de batería en particular desde cualquier botón. Cada almohadilla de batería está conectada a la resistencia pull-up en la placa electrónica principal, por lo tanto, mientras la almohadilla de batería se golpea repetidamente, un interruptor específico está conectado a la tierra del circuito y el LOW lógico está presente en la línea de la almohadilla de batería. Cuando no se aplica presión, el interruptor de la almohadilla de la batería está abierto y, debido a la resistencia de pull-up a la línea de alimentación, el nivel lógico ALTO está presente en la línea de la almohadilla de la batería. Debido a que el propósito del proyecto es crear un dispositivo MIDI digital completo, se pueden descuidar todas las partes analógicas de la PCB principal. Es importante notar que el kit de batería tiene dos pedales para bombo y charles, que también están conectados a las resistencias pull-up y comparten la misma lógica de operación que todos los pads de batería (lo discutiremos un poco más adelante).

Arduino Pro-Micro

El cerebro de la batería. Su propósito es detectar si hay una señal que sale de un pad de batería y proporcionar una salida MIDI adecuada con todos los parámetros necesarios: nota, velocidad y duración de la señal. Debido a la naturaleza digital de las almohadillas de batería, se pueden conectar simplemente a las entradas digitales arduino (10 pines en total). Para almacenar todos los ajustes deseados y la información MIDI, vamos a utilizar su memoria - EEPROM, por lo tanto, cada vez que encendemos el dispositivo, la información MIDI se carga desde EEPROM, haciéndolo reprogramable y reconfigurable. Además, Arduino Pro-Micro está disponible en un paquete muy pequeño y se puede asignar fácilmente en la caja interior del kit de batería.

Convertidor FTDI USB a serie

Para programar y definir las funciones de nuestro dispositivo con la ayuda de la aplicación de PC, es necesario convertir la interfaz USB en serie, porque Arduino Pro-Micro no tiene USB. Dado que la comunicación entre dispositivos se basa en UART, en este proyecto se utiliza el dispositivo FTDI, debido a su simplicidad de uso independientemente de sus propiedades adicionales.

Aplicación para PC - Python

Cuando se trata del desarrollo de interfaces de usuario y proyectos rápidos de construir, Python es una solución excelente. El propósito de la aplicación UI es hacer que sea mucho más conveniente redefinir las propiedades MIDI para nuestra batería, almacenar información, programar el dispositivo y hacer comunicación entre los sistemas sin la necesidad de compilar el código una y otra vez. Debido a que utilizamos una interfaz en serie para comunicarnos con el kit de batería, hay muchos módulos gratuitos en Internet que admiten cualquier tipo de comunicación en serie. Además, como se discutirá más adelante, la interfaz UART consta de un total de tres pines: RXD, TXD y DTR. DTR se usa para realizar un reinicio en el módulo Arduino, por lo tanto, cuando estamos interesados en ejecutar una aplicación MIDI o conectar la interfaz de usuario al dispositivo del programa, no hay absolutamente ninguna necesidad de volver a conectar el cable USB ni nada.

Paso 2: Partes e instrumentos

Partes

  • Kit de batería enrollable
  • 2 x pedales de sostenido (normalmente, incluidos en el paquete DK).
  • FTDI - Convertidor de USB a Serie
  • Arduino Pro Micro
  • Cable micro-USB

Instrumentos

  • Soldador / Estación
  • Estaño para soldar
  • Alambre de núcleo único de diámetro delgado
  • Pinzas
  • Cortador
  • Alicates
  • Cuchillo
  • Destornillador
  • Impresora 3D (opcional, para plataformas de pedales personalizadas)

Software

  • IDE de Arduino
  • Python 3 o superior
  • JetBrains Pycharm
  • Interfaz MIDI sin pelo
  • loopMIDI

Paso 3: soldadura y ensamblaje

Soldadura y montaje
Soldadura y montaje
Soldadura y montaje
Soldadura y montaje
Soldadura y montaje
Soldadura y montaje

Dado que hay tres módulos que deben combinarse, el proceso de soldadura y ensamblaje es corto y simple:

  • Conecte Arduino Pro-Micro con el dispositivo FTDI, asegúrese de que las conexiones cumplan con las E / S definidas en cada dispositivo:

    • VBUS-VBUS
    • GND-GND
    • DTR-DTR
    • RXD-TXD
    • TXD-RXD
  • Quite todos los tornillos de la caja de plástico del tambor, asegúrese de poder concentrarse en el cable de la placa a la placa y sus resistencias pull-up
  • Suelde cables delgados para el módulo Arduino-FTDI que hemos construido anteriormente:

    • Entradas digitales: D [2:11]
    • VBUS
    • D +
    • D-
    • GND
  • Inserte el módulo dentro de la caja de la batería para que los cables floten en el mismo lado que las resistencias pull-up de las almohadillas
  • Suelde todas las entradas digitales a los terminales del pad de batería como se muestra en la última figura.
  • Suelde el bus micro-USB (VBUS, D +, D-, GND) al dispositivo FTDI, asegúrese de que no haya errores al rastrear estos cables.
  • Conecte el módulo Arduino-FTDI con pegamento caliente a la caja de la batería
  • Ensamblar el dispositivo con los tornillos adecuados.

Lo hemos hecho, el dispositivo está montado. Continuemos con el código …

Paso 4: Programación A: Arduino

Programación A: Arduino
Programación A: Arduino

Vamos a describir nuestro boceto paso a paso:

En primer lugar, es necesario incluir dos bibliotecas necesarias para el correcto funcionamiento. EEPROM ya está preinstalado en Arduino IDE, pero el módulo antirrebote para bombo debe instalarse por separado

#include #incluya

Estos conmutadores se utilizan principalmente en secuencias de depuración. Si desea probar la conexión de los terminales Arduino a los pads de batería y determinar todas las entradas digitales, debe definir estos interruptores

/ * Developer Switches: Descomente el modo deseado para depurar o inicializar * /// # definir LOAD_DEFAULT_VALUES // Cargar valores constantes en lugar de EEPROM // # definir PRINT_PADS_PIN_NUMBERS // Imprimir el número de pin que está conectado a un pad que fue golpeado a través del puerto serial

Los campos constantes representan todos los valores predeterminados, incluida la enumeración del pad de batería. Para ejecutar el dispositivo por primera vez, es necesario conocer la conexión exacta de los pedales de charles y patadas

/ * Enumeración del tipo de tambor * /

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

/* Valores predeterminados */

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

/ * Duración antirrebote del bombo * /

const uint8_t KICK_DB_DURATION = 30;

EEPROM se utiliza para almacenar / cargar todos los datos provenientes de la aplicación de PC. El intervalo de direcciones descrito anteriormente muestra la ubicación exacta de la información MIDI para cada pad de batería

/ * Mapeo de direcciones EEPROM

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

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

Las variables globales se utilizan para determinar el estado de cada pad y realizar la comunicación MIDI en consecuencia

/* Variables globales */

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

uint8_t uartBuffer [64]; // UART Buffer para recopilar y almacenar datos MIDI Debouncer kick (DRUM_PINS [KICK], KICK_DB_DURATION); // Objeto de rebote para bombo volatile bool previousState [9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // La lógica anterior del pad de batería indica volatile bool currentState [9] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // Estados lógicos actuales del pad de batería

Funciones EEPROM

/ * Almacenar configuraciones en la EEPROM * /

void storeEEPROM () {

memcpy (drumNotes, uartBuffer, 10); memcpy (drumPins, uartBuffer + 10, 10); memcpy (drumVelocities, uartBuffer + 20, 10); para (uint8_t i = 0; i <10; i ++) EEPROM.write (NOTES_ADDR + i, drumNotes ); para (uint8_t i = 0; i <10; i ++) EEPROM.write (PINS_ADDR + i, drumPins ); para (uint8_t i = 0; i <10; i ++) EEPROM.write (VELOCITIES_ADDR + i, drumVelocities ); }

/ * Cargar configuraciones de la EEPROM * /

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

La inicialización de variables y el modo de programación, en el caso de los pedales y el arranque de Arduino se activan simultáneamente

void enterProgrammingMode () {

bool confirmBreak = falso; 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 ("Aceptar"); storeEEPROM (); }

void initValues () {

#ifdef LOAD_DEFAULT_VALUES memcpy (drumNotes, DRUM_NOTES, 10); memcpy (drumVelocities, DRUM_VELOCITIES, 10); memcpy (drumPins, DRUM_PINS, 10); #else loadEEPROM (); #terminara si }

Controladores de comunicación MIDI con retardo de 1 ms de tiempo de retención de notas

/ * Función de reproducción de notas MIDI * /

void midiOut (enumeración DRUM_POSITION drumIn) {

if (drumIn == HIHAT) {// Si se golpeó HI-HAT, es necesario comprobar si se presiona el pedal if (! digitalRead (drumPins [HIHAT_PEDAL])) {noteOn (0x90, drumNotes [HIHAT_PEDAL], drumVelocities [HIHAT_PEDAL]); retraso (1); noteOn (0x90, drumNotes [HIHAT_PEDAL], 0); } else {noteOn (0x90, drumNotes [HIHAT], drumVelocities [HIHAT]); retraso (1); noteOn (0x90, drumNotes [HIHAT], 0); }} else {// Transmisión MIDI de batería normal noteOn (0x90, drumNotes [drumIn], drumVelocities [drumIn]); retraso (1); noteOn (0x90, drumNotes [drumIn], 0); }}

void noteOn (int cmd, int tono, int velocidad) {Serial.write (cmd); Serial.write (tono); Serial.write (velocidad); }

funciones setup () y loop () con bucle de operación de dispositivo infinito:

configuración vacía () {

Serial.begin (115200);

para (uint8_t i = 0; i <10; i ++) {pinMode (i + 2, INPUT); } #ifdef PRINT_PADS_PIN_NUMBERS while (true) {// Bucle de depuración infinito para (uint8_t i = 0; i <10; i ++) {if (! digitalRead (i + 2)) {Serial.print ("Pin No: D"); Serial.print (i + '0'); // Convertir el número a un carácter ASCII}}} #else initValues (); / * Modo de programación: Si se presionan dos pedales durante el arranque - el modo se activa * / if (! DigitalRead (drumPins [KICK]) &&! DigitalRead (drumPins [HIHAT_PEDAL])) enterProgrammingMode (); #terminara si }

bucle vacío () {para (uint8_t i = 1; i <9; i = i + 1) {currentState = digitalRead (drumPins ); if (! currentState && previousState ) midiOut (i); // Compara estados y detecta el borde descendente previousState = currentState ; } kick.update (); // El bombo utiliza un algoritmo antirrebote personalizado if (kick.edge ()) if (kick.falling ()) midiOut (KICK); }

Paso 5: Programación B: Python e interfaz de usuario

Programación B: Python e interfaz de usuario
Programación B: Python e interfaz de usuario
Programación B: Python e interfaz de usuario
Programación B: Python e interfaz de usuario
Programación B: Python e interfaz de usuario
Programación B: Python e interfaz de usuario

La interfaz de usuario de Python es un poco complicada de entender a primera vista, por lo tanto, intentaríamos explicar sus conceptos básicos, cómo usarlo, qué función tiene cada botón y cómo programar el dispositivo Arduino correctamente.

Interfaz de usuario: aplicación

La interfaz de usuario es una representación gráfica de nuestro programador de kits de batería, lo que hace que sea realmente fácil de usar y conveniente programar el dispositivo Arduino en cualquier momento. La interfaz de usuario consta de varios módulos gráficos que están vinculados a su operación sugerida. repasemos uno por uno:

  1. Imagen de conjunto de batería: la interfaz de usuario de Python utiliza coordenadas de imagen X-Y para determinar qué tipo de batería se seleccionó. Si se seleccionó una región de batería válida, aparece un mensaje de E / S secundario, con campos de nota, velocidad y terminal Arduino para una almohadilla de batería dedicada. Una vez que el usuario verifica y aprueba estos parámetros, estos valores se pueden transmitir directamente al dispositivo Arduino.
  2. Imagen de controlador externo: para poder utilizar el kit de batería MIDI con el entorno de creación de música / VST, es necesario ejecutar un intérprete de serie a MIDI. He usado Hairless, que está disponible de forma gratuita y se puede ejecutar directamente desde nuestra interfaz de usuario, simplemente presionando su imagen.
  3. Lista de puertos COM: para comunicarse con Arduino, es necesario especificar su puerto COM adjunto. La lista se actualiza presionando el botón Actualizar.
  4. Cargar / Guardar configuración: hay valores MIDI predeterminados definidos en el código, que el usuario puede modificar interactuando con la interfaz de usuario. La configuración se define en el archivo config.txt en un formato específico, que el usuario puede guardar o cargar.
  5. Botón de dispositivo de programa: para almacenar todos los valores MIDI modificados en Arduino EEPROM, es necesario presionar dos pedales (bombo y charles) después de eso, esperar a que se complete la transmisión de datos. Si hubo algún problema de comunicación, se mostrará la ventana emergente adecuada. Si la transmisión se realiza correctamente, la interfaz de usuario mostrará su mensaje de éxito.
  6. Botón de salida: simplemente salga de la aplicación, con el permiso del usuario.

Aspectos destacados del código Python

Hay muchas cosas que suceden en el código, por lo que ampliaremos las funciones escritas en lugar de todo el código.

En primer lugar, para utilizar la interfaz de usuario, es necesario descargar varios módulos para que el código funcione:

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

Algunos de los módulos están incluidos en el paquete Python predeterminado. Se deben instalar varios módulos a través de la herramienta PIP:

pip install almohada

pip instalar numpy pip instalar ScreenInfo

Se recomienda encarecidamente ejecutar la aplicación a través de PyCharm. En las versiones futuras, planeo exportar un ejecutable para el proyecto.

Breve explicación del código

Será mucho más fácil entender el código si miramos sus líneas desde la perspectiva de funciones y clases:

1. La función principal: aquí comienza el código

if _name_ == '_main_': drumkit_gui ()

2. Constantes de juego de batería, coordenadas e información MIDI predeterminada

clase de batería: DRUM_TYPES = ["Kick", "Hihat", "Snare", "Crash 1", "Crash 2", "Tom High", "Tom Mid", "Tom Low", "Ride", "Hihat Pedal ", "Controlador"]

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

COORDINATES_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. Funciones de la interfaz de usuario: manejo de la interfaz de usuario y los objetos gráficos

def set_active (ui)

def ui_secundaria (tipo_de_ tambor)

clase SelectionUi (tk. Frame)

Aplicación de clase (tk. Frame)

def drumkit_gui ()

def event_ui_clicked (evento)

def getorigin (yo, evento)

4. Comunicación en serie

def get_serial_ports ()

def comunicarse_con_arduino (puerto)

5. Trabajar con archivos: almacenar / cargar configuraciones desde el archivo txt

def save_config ()

def load_config ()

6. Ejecución de la aplicación externa hairless.exe desde el código utilizando las capacidades de subprocesamiento de Python

clase ExternalExecutableThread (threading. Thread)

def run_hairless_executable ()

Para ejecutar el código, hay una lista de archivos que deben adjuntarse a la carpeta del proyecto:

  • config.txt: archivo de configuración
  • hairless.exe: convertidor MIDI sin pelo
  • drumkit.png: imagen que define todos los pads de batería en los que se puede hacer clic en nuestra interfaz de usuario (debe descargarse del conjunto de imágenes de este paso)
  • drumgui.py: el código del proyecto

Eso es todo lo que necesitamos enfatizar para que funcione. Es muy importante agregar archivos al proyecto: imagen del conjunto de batería, ejecutable hairless.exe y archivo de configuración config.txt.

Y.. ¡Aquí lo hemos hecho!:)

Espero que encuentre útil este instructivo.

¡Gracias por leer!:)

Recomendado: