Criando controladoras MIDI — parte 4

Gabriel Yshay
6 min readJan 23, 2020

--

Nessa quarta parte vamos descobrir como conectar mais coisas no Arduino do que temos portas disponíveis. As ideias que vamos ver aqui continuam o que vimos nas parte 1, parte 2 e parte 3.

Você talvez tenha percebido o problema: as controladoras que existem por ai geralmente tem muitos botões e muitos potenciômetros. Porem com o nosso Arduino conseguiríamos ter até 13 botões e 5 potenciômetros.

Isso é um problema antigo então a solução é algo que existe ja faz muito tempo também, ela se chama multiplexador.

O que é um multiplexador

Um multiplexador é um dispositivo que tem 8 (ou 16, geralmente) entradas e uma saída, com só uma entrada conectada na saída de cada vez. Seletores (na parte esquerda da imagem) selecionam qual entrada esta ligada na saída.

Os seletores funcionam com números binários: se colocarmos 000 nos seletores vamos ligar a entrada 0 (y0 na imagem) na saída. Se colocarmos 001, ligaremos a 1, 100 ligaremos a 4 e assim por diante.

Usando um multiplexador com o arduino

Um multiplexador bastante comum é o 74hc4051, você pode compra-lo por menos de 2 reais em lojas de eletrônica (inclusive na internet).

Por mais complexo que pareça isso, na verdade o circuito é bem simples.

Preste bem atenção na bolinha, que tem no desenho e tem no chip também para identificar o lado certo.

As entradas (y0 até y7) estão nos pinos 13, 14, 15, 12, 1, 5, 2 e 4, nessa ordem. Vamos ligar cada uma delas no pino do meio de um potenciômetro.

Nos pinos 11, 10 e 9 temos os seletores, vamos liga-los no Arduino para selecionar um potenciômetro de cada vez. Vamos ligar então nos pinos 8, 9 e 10 do Arduino, também nessa ordem. No pino 3 temos a saída, que deve ser ligada na porta A0 do Arduino e os pinos 6, 7, 8 simplesmente vamos ligar no terra. Finalmente no pino 16 vamos ligar 5v.

Para os potenciômetros, ligamos a perninha da esquerda no terra e a da direita no 5v, a do meio sera ligada no mux.

O Código

Agora vamos criar uma função que recebe um numero e seleciona o potenciômetro com aquele numero. Para fazer isso vamos ter que pegar cada um dos bits do numero e mandar para um pino do Arduino (de 8 a 10).

Se voce não está familiarizado com o sistema binário de uma olhada aqui.

Se a função recebe o numero 5, ela tem que escrever 1 na porta 8, 0 na porta 9 e 1 na porta 10 para assim o mux selecionar o potenciômetro 5.

Para pegar um bit de um numero vamos usar o operador "&". O & "sobrepõe" os dois números, e, para cada casinha do resultado, ela vale 1 se as casinhas dos dois números forem 1, se pelo menos uma das duas for zero então ela vale zero

1 & 1 = 10 & 0 = 00 & 1 = 01 & 0 = 0

Quando queremos então pegar um bit de um numero podemos usar o & com um numero que tenha tudo zero menos na casinha que queremos pegar (esses são os números 1, 2 e 4), esses números são chamados de mascaras de bit:

5 & 1 = 101 & 001 = 001 = 14 & 1 = 100 & 001 = 000 = 03 & 4 = 011 & 100 = 000 = 01 & 2 = 001 & 010 = 000 = 0

Agora vamos criar a função seleciona potenciômetro. Nela devemos receber uma posição e pegar cada bit dela para mandar para uma porta (e assim mandar para o mux).

void selecionaPotenciometro(int posicao){
digitalWrite(8, posicao & 0b1); // pega o bit 0
digitalWrite(9, posicao & 0b10); // pega o bit 1
digitalWrite(10, posicao & 0b100); // pega o bit 2
}

O código final

Agora com a função em mãos nos podemos ler cada potenciômetro e imprimi-lo na tela.

void setup(){
Serial.begin(112500); // inicia serial
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT); // diz que os pinos são saidas
}
void loop(){
for (int i = 0; i < 8; i++){ // vai contando de 0 até 7
selecionaPotenciometro(i); // seleciona o potenciômetro
int valor = analogRead(A0); // le o potenciômetro que
// agora está conectado com a porta A0
Serial.println(i, valor); // imprime cada potenciômetro na tela
}
Serial.println(); // linha em branco pra ficar facil de ler
}void selecionaPotenciometro(int posicao){
digitalWrite(8, posicao & 0b1); // pega o bit 0
digitalWrite(9, posicao & 0b10); // pega o bit 1
digitalWrite(10, posicao & 0b100); // pega o bit 2
}

Esse código tem bem mais coisas do que os códigos anteriores, tenha certeza de que voce entendeu e tente construir o circuito e rodar de verdade

Mandando MIDI

Agora sim vamos terminar essa ideia.

Na parte passada nos vimos como fazer a função mandaCC, agora nos vamos usa-la para mandar o CC de cada potenciômetro cada um com um numero de controle diferente (o 0 sera o controle 1, o 1 será o controle 2, o 2 sera o controle 3 e assim por diante).

void setup(){
Serial.begin(112500);// começa o serial
pinMode(8, OUTPUT); // coloca os pinos como saida
pinMode(9, OUTPUT); // coloca os pinos como saida
pinMode(10, OUTPUT); // coloca os pinos como saida
}
void loop() {
for( int i =0; i < 8; i++){
selecionaPotenciometro(i); // seleci. o pot.
int valor = analogRead(A0) / 4; // divide por 4 pra caber no midi
mandaCC(i + 1, valor); // manda o CC
}
}
void selecionaPotenciometro(int posicao){
digitalWrite(8, posicao & 0b1); // pega o bit 0
digitalWrite(9, posicao & 0b10); // pega o bit 1
digitalWrite(10, posicao & 0b100); // pega o bit 2
}
void mandaCC(controle, valor){ // peguei da parte 3
Serial.write(176); // = é CC
Serial.write(controle); // mando o controle
Serial.write(valor); // mando o valor
}

Esse programa ta por pouco de funcionar. Ele só tem um problema, toda vez que ele le um valor de um potenciômetro ele ja manda o MIDI instantaneamente, isso vai fazer ele mandar MIDI continuamente, fazendo o computador ficar confuso com tantas mensagens.

Para evitar isso vamos mandar MIDI somente se o controlador mudou o suficiente (ele pode mudar mas ser só ruído, não ser uma mudança causada por girar o potenciômetro, nesse caso não queremos mandar CC). Então temos que guardar o valor anterior do potenciômetro, vamos fazer isso guardando cada um em um array.

int valoresAnteriores[] ={0, 0, 0,0, 0, 0, 0, 0};
void setup(){
Serial.begin(112500);// começa o serial
pinMode(8, OUTPUT); // coloca os pinos como saida
pinMode(9, OUTPUT); // coloca os pinos como saida
pinMode(10, OUTPUT); // coloca os pinos como saida
}
void loop() {
for( int i =0; i < 8; i++){
selecionaPotenciometro(i); // seleci. o pot.
int valor = analogRead(A0) / 4; // divide por 4 pra caber no midi
if(valor - valoresAnteriores[i] > 2 || valor - valoresAnteriores[i] < -2){
valoresAnteriores[i] = valor;
mandaCC(i + 1, valor); // manda o CC
}
}
}
void selecionaPotenciometro(int posicao){
digitalWrite(8, posicao & 0b1); // pega o bit 0
digitalWrite(9, posicao & 0b10); // pega o bit 1
digitalWrite(10, posicao & 0b100); // pega o bit 2
}
void mandaCC(int controle, int valor){ // peguei da parte 3
Serial.write(176); // = é CC
Serial.write(controle); // mando o controle
Serial.write(valor); // mando o valor
}

O que está achando? ficou com alguma duvida? Me conta nos comentários!

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Gabriel Yshay
Gabriel Yshay

Written by Gabriel Yshay

Data Science, Hardware and Music

No responses yet

Write a response