Arduino Baseado MIDI Expression Pedal Pedal Por jeffb42 , jul 17, 2009 4.99 ( 43 votos)
Classifique esta: vote 1voto 2votos 3votos 4v emCompartilhar00 emCompartilhar
Download de projetos - 28,91 KB
Artigo 1 º: Introdução ao Arduino Plataforma Hardware Artigo 2: Interface um Arduino com LCDs
Introdução Este é o meu terceiro artigo sobre a plataforma de hardware Arduino e é a conclusão da série. Neste artigo, vou descrever como construir um pedal de volume MIDI usando um microcontrolador Arduino.
Fundo Eu tenho um processador de efeitos que eu construí uma canção em torno de onde eu variar um dos parâmetros como eu jogo. O dispositivo tem portas MIDI, mas não responde ao controlador MIDI contínua (CC) de mensagens, no entanto pode-se alterar os parâmetros enviando o sistema MIDI dispositivo exclusivo (SysEx) mensagens. Eu poderia ter implementado uma solução apenas de software, mas eu queria um dispositivo standalone e eu não quero ter que ligar um computador para o meu equipamento. Eu também poderia ter implementado uma solução de hardware usando apenas desligar os componentes de prateleira, incluindo um pedal de expressão , um controlador MIDI Pedal Solutions e um processador MIDI Solutions evento , mas este ainda seria um pouco volumoso e eu queria algo mais compacto. Um dia me deparei com o site do Pequeno Urso Eletrônica, que vende kits de pedais de expressão e eu tive a idéia de combinar um gabinete pedal com um microcontrolador e construir o meu primeiro dispositivo eletrônico
- um pedal de expressão personalizada que gera SysEx. Sei que este é um caso muito especializado e que um pedal de volume MIDI teria um apelo mais abrangente para que eu tenha incluído um esboço para um pedal de volume MIDI também.
Metronome2 Antes de eu começar a falar sobre a expressão esboços pedal, vamos rever o esboço metrônomo eu apresentei no primeiro artigo. Se bem se lembram, o ritmo foi codificado dentro do programa e se o tempo necessário para ser mudado, o código teve que ser modificado e recompilado. Em Metronome2 eu adicionei um potenciômetro 10K Ohm, ligado ao pino analógico 0:
(Esta imagem é um pouco difícil de fazer. Se você ver a imagem ampliada, você será capaz de ver os pinos do Arduino melhor.)
Os pinos analógicos tomar dispositivos 10K Ohm e têm um alcance de 0-1023. O esboço a seguir exibe o valor do potenciômetro à medida que muda: Recolher | Código Copiar / / Raw valor potenciômetro espectador / / Constantes
const const
int POT_PIN = 0 ; int SERIAL_PORT_RATE = 9600 ;
vazio setup ()
/ / Pot ligado ao pino analógico 0
/ / Executar uma vez, quando o esboço
começa
{ Serial.begin (SERIAL_PORT_RATE);
/ / Inicia a comunicação com a porta serial
} vazio loop () { int nValue = analogRead (POT_PIN); Serial.println (nValue); }
/ / Executar uma e outra vez
Se você executar com o monitor serial, você vai ver que temos um problema - mesmo quando você não tocar o potenciômetro, o valor ainda muda. Este não foi um problema com o esboço de esqui, pois só tem cinco valores (-2 através +2), mas com o esboço Metronome2 (e mais tarde com o esboço pedal de volume), este será um problema depois de definir o tempo, você vai querer o ritmo a ser constante e não flutuar. Para superar isso, o código foi adicionado para suportar um limite e rejeitar valores muito próximos do último conhecido bom valor: Recolher | Código Copiar / / espectador potenciômetro com limite / / Constantes
const
int POT_PIN = 0 ;
/ / Pot ligado ao pino analógico 0
const
int POT_THRESHOLD = 3 ;
/ / quantidade limite para se proteger
contra falsos valores
const
int SERIAL_PORT_RATE = 9600 ;
vazio setup ()
/ / Executar uma vez, quando o esboço
começa
{ Serial.begin (SERIAL_PORT_RATE);
/ / Inicia a comunicação com a porta serial
} vazio loop () { static int s_nLastValue = 0 ;
/ / Executar uma e outra vez
int nValue = analogRead (POT_PIN); se (abs (nValue - s_nLastValue)
Isso é melhor, mas o código ainda precisa ser levado um passo adiante. O código precisa ser mapeado para um valor que está dentro de uma faixa que está procurando, eo código precisa para se proteger contra o mesmo valor a ser definido: Recolher | Código Copiar / / / / check flutuante valor potenciômetro contra limiar / / / / Constantes
const const
int POT_PIN = 0 ; int POT_THRESHOLD = 3 ;
/ / Pot ligado ao pino analógico 0 / / quantidade limite para se proteger
contra falsos valores
const
int SERIAL_PORT_RATE = 9600 ;
vazio setup ()
/ / Executar uma vez, quando o esboço
começa
{ Serial.begin (SERIAL_PORT_RATE);
/ / Inicia a comunicação com a porta serial
} / / Executar uma e outra vez vazio loop () { static int s_nLastPotValue = 0 ; static int s_nLastMappedValue = 0 ;
int nCurrentPotValue = analogRead (POT_PIN); se (abs (nCurrentPotValue - s_nLastPotValue)
se (nMappedValue == s_nLastMappedValue) retorno ; s_nLastMappedValue = nMappedValue; Serial.println (nMappedValue); }
/ / Mapa do
Se você achar que este é ainda muito barulhento (eu fiz, mas eu estava correndo um potenciômetro wah 200K em um pino que quer 10K), uma abordagem alternativa é verificar o valor contra um buffer de histórico: Recolher | Código Copiar / / / / check flutuante valor potenciômetro contra tampão história / / / / Constantes
const const
int POT_PIN = 0 ; int POT_THRESHOLD = 3 ;
/ / Pot ligado ao pino analógico 0 / / quantidade limite para se proteger
contra falsos valores
const
int HISTORY_BUFFER_LENGTH = 6 ,
/ / buffer de História comprimento / / (para se proteger contra o ruído que está
sendo enviado)
const
int SERIAL_PORT_RATE = 9600 ;
/ / Globals
estática
int s_history [HISTORY_BUFFER_LENGTH];
vazio setup ()
/ / Executar uma vez, quando o esboço
começa
{ Serial.begin (SERIAL_PORT_RATE);
/ / Inicia a comunicação com a porta serial
/ / Inicializar ele tampão
para ( int i = 0; i
int nCurrentPotValue = analogRead (POT_PIN); se (abs (nCurrentPotValue - s_nLastPotValue)
/ / Mapear o
valor / / para 0-255
se (nMappedValue == s_nLastMappedValue) retorno ; para ( int i = 0; i
(O valor atual ser reenviado não é um problema com o esboço do metrônomo, mas mais tarde vamos precisar deste para o pedal de expressão.)
Agora, adicionando este apoio para o potenciômetro no esboço do metrônomo, o código agora se parece com: Recolher | Código Copiar / * * Metronome2 * * Baseado no exemplo básico Arduino, Blink: * Http://www.arduino.cc/en/Tutorial/Blink * Funciona como um metrônomo visual. * / / / Constantes
const const const
int LED_PIN = 13 ; int POT_PIN = 0 ; int POT_THRESHOLD = 3 ;
/ / LED conectado ao pino digital de 13 / / Pot ligado ao pino analógico 0 / / quantidade limite para se proteger
contra falsos valores
nulos setup ()
/ / Executar uma vez, quando o esboço
começa
{ pinMode (LED_PIN, OUTPUT);
/ / Define o LED como saída
} vazio loop () { static int s_nLastPotValue = 0 ; static int s_nTempo = 0 ;
/ / Executar uma e outra vez
int nCurrentPotValue = analogRead (POT_PIN);
/ / Tem uma gama de 0-
1023
se (abs (nCurrentPotValue - s_nLastPotValue)> = POT_THRESHOLD) { s_nLastPotValue = nCurrentPotValue; int nTempo = map (nCurrentPotValue, 0 , 1023 , 50 , 255 ); / / Mapear o valor a 50-255
se (nTempo = s_nTempo!) { s_nTempo = nTempo; } } / / Atraso em milissegundos = 1 minuto 60 segundo 1000 milissegundos / / --------- * ---------- --------------- * / / (X) bate minuto segundo
int nDelay = ( int ) (( 60 . 0 * 1000 . 0 ) / ( bóia ) s_nTempo); PlayNote (nDelay); } vazio PlayNote ( int nDuration) { nDuration = (nDuration / 2 ); digitalWrite (LED_PIN, HIGH); atraso (nDuration);
/ / Defina o LED em / / Espera por metade do (original)
duração
digitalWrite (LED_PIN, LOW); delay (nDuration); }
/ / Defina o LED off / / Aguarde a metade (original) duração
VolumePedal Existem vários controladores de pé MIDI atualmente no mercado, como o Roland FC300 eo Behringer FCB1010 , mas esses controladores do pé são volumosos e se você só quer um único pedal de expressão que eles são um pouco exagerado. Infelizmente, um pedal de volume MIDI individual não existe no mercado neste momento, então eu decidi criar um usando um Arduino. O envio de uma mensagem MIDI CC mudança de volume é muito fácil e apenas três bytes precisam ser enviados: Recolher | Código Copiar Comando de mudança de CC (0xB0 - - 0xBF dependendo do canal MIDI) 0xB0 0x07 - comando Volume o valor - O valor do volume, entre 0 e 127
... Por isso os comandos MIDI reais enviados não são muito complicadas ou longas, no entanto, o hardware eo software de suporte demorou um pouco de trabalho ... (não muito, mas ainda algum trabalho e alguma tentativa e erro) Antes de olhar para o código-fonte, vamos passar por cima das peças. No mínimo, você vai precisar de:
Um processador Arduino. Para o meu pedal de expressão, eu usei um Arduino Pro Mini (a versão 5V) Um gabinete pedal de expressão Um potenciômetro wah (ele não vem com o gabinete pedal) Um pedal de 3 pólos Um LED (embora este é opcional) A ficha de alimentação DC Uma fonte de alimentação 9VDC Um plug MIDI A 220 Ohm resistente para a porta MIDI Um resistor de 1K Ohm para o LED A placa de ensaio de pré-montagem do circuito e verifique que as obras esboço Uma placa de circuito em branco para soldar tudo em Um conjunto de cabeçalhos para soldar o Arduino para a placa de circuito Arame O pedal de expressão gabinete que navios de pequeno urso Electronics é inacabado e é de alumínio nu. Antes de montar o seu projeto, você provavelmente vai querer pintar seu gabinete. Eu enviei o meu para PedalEnclosures.com e teve o gabinete pintado em um acabamento hammertone vermelho. Quanto a fiação vai, já cobrimos como ligar o LED e potenciômetro. Os únicos componentes restantes são a entrada 9VDC, o pedal ea porta MIDI Out. Para a porta MIDI Out, você vai precisar para se conectar:
Pin 5 a TX0
Pino 2 para GND O pino 4 de um resistor de 220 ohm, o qual é então ligado a uma fonte de alimentação de +5 VDC (VCC)
Para a tomada de entrada 9VDC ea pedal, soldar o pedal para que ele interrompe o circuito após a + V na ficha de entrada:
... E agora tudo se conectar à placa de ensaio:
A câmera que eu não era capaz de dar uma imagem muito boa de montagem final, por isso aqui está um resumo de cada pino do Arduino Mini:
Top Row RAW
Pedal + V
GND
Ficha de alimentação GND
RST VCC
+ V rail
A3 A2 A1 A0
Resistor variável Pot (conector do meio)
13
LED
12 11 10 Bottom Row TX0
MIDI Pino 5
RXI RST GND
Trilho do chão
2 3 4 5 6 7 8 9 + V Rail
220 Ohm resistor (conectado ao MIDI Pin 4) Pot + V
GND Rail
MIDI Pino 2 1K resistor (ligado à terra LED)
O código fonte para o pedal de volume MIDI é a seguinte: Recolher | Código Copiar / / # define DEBUG 1 / / Constantes
const const const
int LED_PIN = 13 ; int POT_PIN = 0 ; int POT_THRESHOLD = 7 ;
/ / LED conectado ao pino digital 13 / / Pot ligado ao pino analógico 0 / / quantidade limite para se proteger contra
falsos valores
const
int MIDI_CHANNEL = 0 ;
/ / MIDI Canal 1
# Ifdef DEBUG / / depuração Serial comunica em 9600 const int DEBUG_RATE = 9600 ; const int SERIAL_PORT_RATE = DEBUG_RATE; # else / / MIDI comunica a 31250 baud const int MIDI_BAUD_RATE = 31250 ; const int SERIAL_PORT_RATE = MIDI_BAUD_RATE; # endif vazio setup () { / / Define o pino digital como saída pinMode (LED_PIN, OUTPUT); / / Ligue o LED digitalWrite (LED_PIN, HIGH); / / Inicia a comunicação com a porta Serial.begin (SERIAL_PORT_RATE); serial
} vazio loop () { static int s_nLastPotValue = 0 ; static int s_nLastMappedValue = 0 ; int nCurrentPotValue = analogRead (POT_PIN); se (abs (nCurrentPotValue - s_nLastPotValue)
se (nMappedValue == s_nLastMappedValue) retorno ; s_nLastMappedValue = nMappedValue; MidiVolume (MIDI_CHANNEL, nMappedValue); } vazio MidiVolume (canal byte, o volume de bytes) { # Ifdef DEBUG Serial.println (volume, DEC); # Else Serial.print (0xB0 | (canal & 0x0F), BYTE);
/ / Controle de mudança de
comando
Serial.print (0x07, BYTE); Serial.print (volume & 0x7F, BYTE); # endif
/ / comando Volume / / Volume 0 -127
}
Atravessar o código, primeiro há: Recolher | Código Copiar
/ / # define DEBUG 1
Eu uso essa constante para definir ou não a construção é uma compilação de depuração. Para executar em modo de depuração, basta descomentar esta linha. Em seguida, há as constantes: Recolher | Código Copiar / / Constantes
const const const
int LED_PIN = 13 ; int POT_PIN = 0 ; int POT_THRESHOLD = 7 ;
/ / LED conectado ao pino digital de 13 / / Pot ligado ao pino analógico 0 / / quantidade limite para se proteger contra
falsos valores
const
int MIDI_CHANNEL = 0 ;
/ / MIDI Canal 1
# Ifdef DEBUG const int DEBUG_RATE = 9600 ; / / depuração Serial comunica em 9600 const int SERIAL_PORT_RATE = DEBUG_RATE; # else / / MIDI comunica a 31250 baud const int MIDI_BAUD_RATE = 31250 ; const int SERIAL_PORT_RATE = MIDI_BAUD_RATE; # endif
O LED indica que o aparelho está ligado. É opcional, mas se você anexar um LED, o LED deve ser conectado ao pino digital 13 (e não se esqueça do resistor e da orientação do LED). O potenciômetro é conectado ao pino analógico 0. As especificações Arduino afirmar que os pinos analógicos quer dispositivos com apenas resistência 10K Ohm, no entanto potenciômetros wah (que é o que vai usar com o pedal de expressão) só estão disponíveis em 100K e 200K. Eu comprei um potenciômetro de 200K e descobriu que, embora fosse um pouco barulhento, ele ainda trabalhava, e precisava definir o limite de 7: Recolher | Código Copiar const
int POT_THRESHOLD = 7 ;
/ / quantidade limite para se proteger contra
falsos valores
O próximo valor, o canal MIDI, é deixado como uma constante codificado. Assim como o esboço metrônomo, poderíamos acrescentar um potenciômetro para selecionar o canal MIDI, mas para os meus propósitos eu só precisava de o canal MIDI fixo para um canal. O próximo grupo de constantes diz respeito à taxa de porta serial. Tanto a porta MIDI eo print () comandos utilizados para depurar usar a porta serial e não coexistem bem. Um precisa de ser tanto no modo de depuração ou modo de liberação para que eu alternar entre os dois usando o # ifdef DEBUG cheque. Em seguida está o código. O setup () função é mínima e é típico do que já vimos até agora: Recolher | Código Copiar vazio setup () {
/ / Define o pino digital como saída pinMode (LED_PIN, OUTPUT); / / Ligue o LED digitalWrite (LED_PIN, HIGH); / / Inicia a comunicação com a porta Serial.begin (SERIAL_PORT_RATE); serial
}
A função seguinte, ciclo () , contém a maior parte do código: Recolher | Código Copiar vazio loop () { static int s_nLastPotValue = 0 ; static int s_nLastMappedValue = 0 ; int nCurrentPotValue = analogRead (POT_PIN); se (abs (nCurrentPotValue - s_nLastPotValue)
se (nMappedValue == s_nLastMappedValue) retorno ; s_nLastMappedValue = nMappedValue; MidiVolume (MIDI_CHANNEL, nMappedValue); }
s_nLastPotValue eo if (abs (nCurrentPotValue - s_nLastPotValue)
proteger contra o envio do valor se fosse o último valor enviado. MidiVolume () é onde os bytes são enviados. Como já foi mencionado anteriormente, a
apenas três bytes são necessários para enviar a mensagem de volume MIDI CC: Recolher | Código Copiar vazio MidiVolume (canal byte, o volume de bytes) { # Ifdef DEBUG Serial.println (volume, DEC); # Else Serial.print (0xB0 | (canal & 0x0F), BYTE);
/ /
Controle de mudança de
comando
Serial.print (0x07, BYTE); Serial.print (volume & 0x7F, BYTE); # endif
/ / / /
comando Volume Volume 0 -127
}
E é isso. Se você conectou o hardware corretamente, tudo deve funcionar neste momento. No Windows, há um programa gratuito disponível chamado MIDI-OX que permite que você veja todas as mensagens MIDI de entrada, e no Mac OSX, há um programa gratuito disponível chamado MIDI monitor que faz a mesma coisa. Se você executar um desses programas (e tem porta MIDI Out do seu pedal de expressão conectado ao computador), você deve ver as mensagens MIDI de volume CC vêm em como você se move o potenciômetro wah.
Montagem dos componentes finais Neste ponto, eu estava pronto para cometer o projeto para a placa de circuito final e montar os componentes. Eu transferi o desenho na placa de ensaio para a placa de circuito e conectores adicionais para que eu pudesse facilmente adicionar e remover o componente não diretamente na placa de circuito:
Esta foto foi tirada de perto. Ao fazer isso, a imagem produzida foi distorcida. O fio verde na parte inferior conecta o pino 5 do conector MIDI para TX0, mas nesta imagem parece que a conexão é RXI, não TX0.
Placa de circuito lançado horizontalmente para mostrar back side (o trilho superior é + V eo trilho inferior é GND).
Placa de circuito com componentes
Close-up das conexões da placa de circuito
Montagem interna de componentes
Ajustar o intervalo Depois que o hardware foi totalmente montado, o pote wah não tinha mais a sua gama completa de movimento (devido ao alcance limitado da placa superior) para que era necessária uma mudança de código menor. Quando o pote wah teve sua gama completa de movimento, s_nLastPotValue tinha um alcance de 0-1023 es_nLastMappedValue tinha uma gama de 0-127. Com a gama
limitada s_nLastPotValue agora tinha um alcance de 0-1002 e s_nLastMappedValue tinha uma gama de 0-125. Eu atualizei loop () com uma pequena alteração e tornou-se: Recolher | Código Copiar vazio loop () { static int s_nLastPotValue = 0 ; static int s_nLastMappedValue = 0 ; int nCurrentPotValue = analogRead (POT_PIN); se (abs (nCurrentPotValue - s_nLastPotValue)
se (nMappedValue> 127 ) nMappedValue = 127 ; se (nMappedValue == s_nLastMappedValue) retorno ; s_nLastMappedValue = nMappedValue; MidiVolume (MIDI_CHANNEL, nMappedValue); }
SysExPedal Algumas mensagens MIDI, como o MIDI Note On / Off comando eo comando de mudança de programa são específicas, fechado, e estritamente definido. No entanto fabrica necessário um mecanismo para transferir dados personalizados a partir de um dispositivo para outro, de modo que o open-ended System Exclusive (SysEx) mensagem foi adicionado à especificação MIDI. Uma mensagem SysEx começa com 0xF0 e termina com 0xF7. Tipicamente, o formato dentro destes marcadores é a seguinte: Recolher | Código Copiar 0xF0 xx xx xx xx xx ... xx 0xF7 -
SysEx início Fabricante ID Modelo ID canal MIDI dados 1 de dados 2 dados N SysEx final
... Mas o formato é deixada para o fabricante para definir. Como eu mencionei no início deste artigo, toda a razão para este projeto e entrar em programação de hardware é que eu tenho um processador de efeitos que não responde às mensagens MIDI CC, mas não respondeu às mensagens SysEx. Migrando do envio de mensagens de CC para o envio de mensagens SysEx é muito para a frente. Se você comparar o esboço SysExPedal com o esboço VolumePedal, você vai ver que os dois esboços são quase idênticos. Onde MidiVolume () foi chamado quando o potenciômetro mudou é agora SendSysEx () :
Recolher | Código Copiar vazio SendSysEx (canal byte, o volume de bytes) { # Ifdef DEBUG Serial.println (volume, DEC); # Else / / SysEx começar SerialOutput (0xF0); SerialOutput (0x00); / / Fabricante 0 SerialOutput (0x01); / / Modelo 1 SerialOutput (canal); / / MIDI end
# endif }
O que está aqui apresentada é um exemplo de um dispositivo ficcional. Uma vez que o formato de uma mensagem SysEx é exclusivo para um dispositivo específico (e no meu caso, um patch específico), eu decidi apenas postar o esboço cru do que uma mensagem SysEx seria semelhante.
Conclusão Isso traz à tona o terceiro artigo e conclui minha série sobre a plataforma de hardware Arduino. Nós fomos de ligar um LED simples para o desenvolvimento de um produto em pleno funcionamento. Espero que você será capaz de tomar algumas das idéias aqui apresentadas e construir seus próprios dispositivos exclusivos com base em um microcontrolador Arduino.
História
16 º de julho de 2009: pós inicial 16 º de julho de 2009: Artigo actualizado
Licença Este artigo, juntamente com qualquer código-fonte associado e arquivos, está licenciado sob a licença de código Projeto Open (CPOL)
Sobre o autor
jeffb42 Software Developer Estados Unidos
Em poucas palavras, o meu forte é o Windows, Macintosh e desenvolvimento multiplataforma, e os meus interesses estão em UI, processamento de imagem, e desenvolvimento de aplicações MIDI.