Footcontroller MIDI

Salve, ho da poco acquistato un Arduino Uno e parecchi componenti per realizzare una footcontroller MIDI per gestire Multieffetti Rack.

Dato che per mestiere sono un programmatore Cad-Cam mi sono disegnato il progetto:

Vi metto il link dove ho caricato il rendering del progetto:
https://plus.google.com/photos/104025063528945292989/albums/5861939625544980081?authkey=CNitkLSXn4TKQA

Componenti Acquistati:

Arduino Store

  • 1 x Arduino Duemilanove w/ Atmega328 (A000001) = €15.00
  • 1 x Getting Started With Arduino 2nd Edition (B000001) = €16.00
  • 1 x The Arduino Starter Kit (K000007) = €79.90
  • 3 x ATMega328 - Microprocessore (A000048) = €12.00

Ho letto il Libro di Sciamanna "Arduino", "Getting Started With Arduino" e quello dello Starter Kit, eseguendo parecchi degli esempi illustrati all'interno.

Vorrei iniziare con un progetto terra terra vi elenco le caratteristiche:

  • 2 Push Button (rispettivamente Preset P1 e P2)
  • 2 Led (che si accendono ogni volta che premi o P1 oppure P2)
  • MIDI Output (che invia un Program Change)

es:

  • quando premo P1, invia un ProgrmChange 10 su Canale10.
  • quando premo P2, invia un ProgrmChange 2 su Canale10.

Le prove che ho fatto questa mattina non hanno dato i risultati sperati.

Questo è grosso modo il progetto:

Questo è il codice che ho usato:

#include <Bounce.h>

/*
Prova 1
Inviare ProgramChange tramite Push Button e Relativi Led.
Componenti:
2 Push Button
2 Led
1 Presa Femmina MIDI 5 pin
*/

#include <MIDI.h>

const int BUTTON1 = 8;     // il numero del pin del pushbutton_1 
const int BUTTON2 = 9;     // il numero del pin del pushbutton_2 

const int LED1 =  3;      // il numero del pin del Led_1
const int LED2 =  2;      // il numero del pin del Led_2

// variabili:
int buttonState1 = 0;         // variabile che legge lo stato del pushbutton_1 
int buttonState2 = 0;         // variabile che legge lo stato del pushbutton_2

Bounce bouncer1 = Bounce( BUTTON1,5 );
Bounce bouncer2 = Bounce( BUTTON2,5 );


void setup() {

  Serial.begin(31250);   //  Imposta MIDI baud rate:

  pinMode(LED1, OUTPUT);    // imposta i pin dei Led1 come output:
  pinMode(LED2, OUTPUT);    // imposta i pin dei Led1 come output:

  pinMode(BUTTON1, INPUT);    // imposta i pin dei pushbutton1 come input:
  pinMode(BUTTON2, INPUT);    // imposta i pin dei pushbutton2 come input:  
}


void loop(){
   // Update and monitor a change of input
  if ( bouncer1.update() ) {
    
    // Get the state of the button
   int value1 = bouncer1.read();
 
   // Toggle the LED if the button is held
   if ( value1 == HIGH) {  
    digitalWrite(LED1, HIGH);
    MIDI.send(ProgramChange,10,0,10);
    // Make the button retrigger in 500 milliseconds
    bouncer1.rebounce(500);
   } 
   else {
     // spegni il LED:
    digitalWrite(LED1, LOW); 
   }
  }
  
 
     // Update and monitor a change of input
  if ( bouncer2.update() ) {
    
    // Get the state of the button
   int value2 = bouncer2.read();
 
   // Toggle the LED if the button is held
   if ( value2 == HIGH) {  
    digitalWrite(LED2, HIGH);
    MIDI.send(ProgramChange,2,0,10);
    // Make the button retrigger in 500 milliseconds
    bouncer2.rebounce(500);
   } 
   else {
     // spegni il LED:
    digitalWrite(LED2, LOW); 
   }
  }
}

Oggi, ho fatto diverse prove con il codice citato nel post precedente e ho monitorato tutto con il programma midiox:

il program change veniva recepito ma andava in continuazione come se lo inviassi di continuo.

Inoltre ho provato a inviare lo stesso Program Change tramite una master keyboard per vedere cosa veniva visualizzato nel Midiox, in questo caso, come c'era da aspettarsi, veniva inviata una sola riga di comando contenente il program change voluto.

Suggerimenti? =(

praticamente dici che il commando midi viene spedito ripetutamente non solo una volta per ogni pressione di pulsante?

per cosa ti serve il

 bouncer1.rebounce(500);

nel codice?

Ciao Uwe

Ciao, intanto ti volevo ringraziare della risposta, tornando al post ho messo il Boucer perchè notavo che mi mandava il messaggio in continuo e leggendo in rete ho letto che il Bounce (anti-rimbalzo) serve proprio a questo, solo che essendo alle prime armi ho preso lo sketch di esempio e l'ho riadattato ma ancora devo capire bene come funziona.
Nel week end purtroppo non ho avuto modo di approfondire, ma leggendo in rete ho visto che per cambiare i Control change in genere usano:
**Serial.print(data1,data2,Ch); **
forse si può usare anche per i Program Change al posto di:
MIDI.send(ProgramChange,2,0,10);

Hai qualche buon consiglio da darmi?

PS. Ieri mi sono preso un'altro libro che tratta arduino:

speriamo che mi aiuti ad imparare le basi di programmazione di Arduino.

Saluti

Primo problema risolto!!!!

ci sono riuscito prendendo spunto da una "ricetta" precisamente la 5.3 del libro "Arduino. Progetti e soluzioni"

#include <MIDI.h>

const int b1 = 2;        // definisce il numero del pin del pushbutton_1
const int b2 = 3;        // definisce il numero del pin del pushbutton_2
const int b3 = 4;        // definisce il numero del pin del pushbutton_3
const int b4 = 5;        // definisce il numero del pin del pushbutton_4

const int L1 = 6;         // definisce il numero del pin del Led_1
const int L2 = 7;         // definisce il numero del pin del Led_2
const int L3 = 8;         // definisce il numero del pin del Led_3
const int L4 = 9;         // definisce il numero del pin del Led_4

const int debounceDelay = 100;  // milliseconds to wait until stable

// debounce returns true if the switch in the given pin is closed and stable
boolean debounce(int pin)
{
  boolean state;
  boolean previousState;

  previousState = digitalRead(pin);          // store switch state
  for(int counter=0; counter < debounceDelay; counter++)
  {
      delay(1);                  // wait for 1 millisecond
      state = digitalRead(pin);  // read the pin
      if( state != previousState)
      {
         counter = 0; // reset the counter if the state changes
         previousState = state;  // and save the current state
      }
  }
  // here when the switch state has been stable longer than the debounce period
  return state;
}

void setup()
{
  Serial.begin(31250);      // Imposta MIDI baud rate
  
  pinMode(b1, INPUT);       // definisce il pin2 come INPUT
  pinMode(b2, INPUT);       // definisce il pin3 come INPUT
  pinMode(b3, INPUT);       // definisce il pin4 come INPUT
  pinMode(b4, INPUT);       // definisce il pin5 come INPUT
  
  pinMode(L1, OUTPUT);      // definisce il pin6 come INPUT
  pinMode(L2, OUTPUT);      // definisce il pin7 come INPUT
  pinMode(L3, OUTPUT);      // definisce il pin8 come INPUT
  pinMode(L4, OUTPUT);      // definisce il pin9 come INPUT
}

void loop()
{
  // loop riguardante il b1
  if (debounce(b1))
  {
    digitalWrite(L1, HIGH);
    MIDI.send(ProgramChange,10,0,1);
  }
  else
  {
    digitalWrite (L1, LOW);
  }
    // loop riguardante il b2
  if (debounce(b2))
  {
    digitalWrite(L2, HIGH);
    MIDI.send(ProgramChange,10,0,2);
  }
  else
  {
    digitalWrite (L2, LOW);
  }
    // loop riguardante il b3
  if (debounce(b3))
  {
    digitalWrite(L3, HIGH);
    MIDI.send(ProgramChange,10,0,3);
  }
  else
  {
    digitalWrite (L3, LOW);
  }
    // loop riguardante il B4
  if (debounce(b4))
  {
    digitalWrite(L4, HIGH);
    MIDI.send(ProgramChange,10,0,4);
  }
  else
  {
    digitalWrite (L4, LOW);
  }
}

Ora siccome devo aggiungere sia un display LCD, sia un Port-expander MCP23017 tramite I2C mi domandavo come poterle inserire nel codice.

Inoltre il Messaggio Midi deve essere configurabile tramite pushbutton, entrando in modalità programmazione il tutto visualizzato su LCD

esempio:

  • accendo la pedaliera: visalizzo un testo di benvenuto
  • seleziono il pushbutton1: si accende il Led1, invia il ProgramChange e visualizzo su LCD il testo relativo es: "preset1".
  • tengo premuto il pushbutton "Mode" 2 secondi: entro in modalità programmazione relativa al pushbutton selezionato in precedenza.
  • nella prima pagina LCD posso modificare il nome del preset visualizzato es: "preset1".
  • nella seconda pagina LCD posso modificare il numero del ProgramChange, che sarebbe solo il dato3 che vedete sotto dato che gli altri due rimangono sempre quelli nel mio caso.
  • MIDI.send(ProgramChange,dato1,dato2,dato3);
  • tengo premuto il pushbutton "Mode" 2 secondi e salvo il tutto e torno nella modalità preset

Suggerimenti?

Saluti

Primo grande successo!!!


Funziona tutto alla grande, ho appena unito tutte le parti affrontate singolarmente:

  • MIDI
  • LCD via I2C (PCF8574)
  • 2 port Expander MCP23017 (uno per i Led ed uno per i Pushbutton)
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#include "Adafruit_MCP23017.h"
#include <MIDI.h>

//LCD 
LiquidCrystal_I2C lcd(0x38,16,2);  // set the LCD address to 0x20 for a 16 chars and 2 line display

//MCP23017
Adafruit_MCP23017 mcp01;
Adafruit_MCP23017 mcp02;

const int mcp01_b1 = 4;        // definisce il numero del pin del pushbutton_1
const int mcp01_b2 = 5;        // definisce il numero del pin del pushbutton_2
const int mcp01_b3 = 6;        // definisce il numero del pin del pushbutton_3
const int mcp01_b4 = 7;        // definisce il numero del pin del pushbutton_4
const int mcp01_b5 = 11;        // definisce il numero del pin del pushbutton_1
const int mcp01_b6 = 10;        // definisce il numero del pin del pushbutton_2
const int mcp01_b7 = 9;        // definisce il numero del pin del pushbutton_3
const int mcp01_b8 = 8;        // definisce il numero del pin del pushbutton_4

const int mcp02_L1 = 11;         // definisce il numero del pin del Led_1
const int mcp02_L2 = 10;         // definisce il numero del pin del Led_2
const int mcp02_L3 = 9;         // definisce il numero del pin del Led_3
const int mcp02_L4 = 8;         // definisce il numero del pin del Led_4
const int mcp02_L5 = 4;         // definisce il numero del pin del Led_1
const int mcp02_L6 = 5;         // definisce il numero del pin del Led_2
const int mcp02_L7 = 6;         // definisce il numero del pin del Led_3
const int mcp02_L8 = 7;         // definisce il numero del pin del Led_4

//Debounce
const int debounceDelay = 10;  // milliseconds to wait until stable
boolean debounce(int pin)
{
  boolean state;
  boolean previousState;
  previousState = mcp01.digitalRead(pin);          // store switch state
  for(int counter=0; counter < debounceDelay; counter++)
  {
      delay(1);                  // wait for 1 millisecond
      state = mcp01.digitalRead(pin);  // read the pin
      if( state != previousState)
      {
         counter = 0; // reset the counter if the state changes
         previousState = state;  // and save the current state
      }
  }
  return state;
}

void setup()
{
//MIDI  
  Serial.begin(31250);      // Imposta MIDI baud rate
    
//LCD
  lcd.init();                      // initialize the lcd 
  lcd.backlight();
  lcd.print("Biagetti Custom");
  
//MCP23017
  mcp01.begin(1);           // use default address 0
  mcp02.begin(0);           // use default address 0
  
  mcp01.pinMode(mcp01_b1, INPUT);       // definisce il pin2 come INPUT
  mcp01.pinMode(mcp01_b2, INPUT);       // definisce il pin2 come INPUT
  mcp01.pinMode(mcp01_b3, INPUT);       // definisce il pin2 come INPUT
  mcp01.pinMode(mcp01_b4, INPUT);       // definisce il pin2 come INPUT
  mcp01.pinMode(mcp01_b5, INPUT);       // definisce il pin2 come INPUT
  mcp01.pinMode(mcp01_b6, INPUT);       // definisce il pin2 come INPUT
  mcp01.pinMode(mcp01_b7, INPUT);       // definisce il pin2 come INPUT
  mcp01.pinMode(mcp01_b8, INPUT);       // definisce il pin2 come INPUT
  
  mcp02.pinMode(mcp02_L1, OUTPUT);       // definisce il pin2 come INPUT
  mcp02.pinMode(mcp02_L2, OUTPUT);       // definisce il pin2 come INPUT
  mcp02.pinMode(mcp02_L3, OUTPUT);       // definisce il pin2 come INPUT
  mcp02.pinMode(mcp02_L4, OUTPUT);       // definisce il pin2 come INPUT
  mcp02.pinMode(mcp02_L5, OUTPUT);       // definisce il pin2 come INPUT
  mcp02.pinMode(mcp02_L6, OUTPUT);       // definisce il pin2 come INPUT
  mcp02.pinMode(mcp02_L7, OUTPUT);       // definisce il pin2 come INPUT
  mcp02.pinMode(mcp02_L8, OUTPUT);       // definisce il pin2 come INPUT

}

void loop()
{ 
  // loop riguardante il mcp01_b1
  if (debounce(mcp01_b1)) 
  {
    mcp02.digitalWrite(mcp02_L1, HIGH);
    MIDI.send(ProgramChange,10,0,1);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Preset 01");
  }
  else
  {
    mcp02.digitalWrite (mcp02_L1, LOW);
  }
  // loop riguardante il mcp01_b2
  if (debounce(mcp01_b2)) 
  {
    mcp02.digitalWrite(mcp02_L2, HIGH);
    MIDI.send(ProgramChange,10,0,2);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Preset 02");
  }
  else
  {
    mcp02.digitalWrite (mcp02_L2, LOW);
  }
    // loop riguardante il mcp01_b3
  if (debounce(mcp01_b3)) 
  {
    mcp02.digitalWrite(mcp02_L3, HIGH);
    MIDI.send(ProgramChange,10,0,3);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Preset 03");
  }
  else
  {
    mcp02.digitalWrite (mcp02_L3, LOW);
  }
    // loop riguardante il mcp01_b4
  if (debounce(mcp01_b4)) 
  {
    mcp02.digitalWrite(mcp02_L4, HIGH);
    MIDI.send(ProgramChange,10,0,4);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Preset 04");
  }
  else
  {
    mcp02.digitalWrite (mcp02_L4, LOW);
  }
    // loop riguardante il mcp01_b5
  if (debounce(mcp01_b5)) 
  {
    mcp02.digitalWrite(mcp02_L5, HIGH);
    MIDI.send(ProgramChange,10,0,5);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Preset 05");
  }
  else
  {
    mcp02.digitalWrite (mcp02_L5, LOW);
  }
    // loop riguardante il mcp01_b6
  if (debounce(mcp01_b6)) 
  {
    mcp02.digitalWrite(mcp02_L6, HIGH);
    MIDI.send(ProgramChange,10,0,6);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Preset 06");
  }
  else
  {
    mcp02.digitalWrite (mcp02_L6, LOW);
  }
    // loop riguardante il mcp01_b7
  if (debounce(mcp01_b7)) 
  {
    mcp02.digitalWrite(mcp02_L7, HIGH);
    MIDI.send(ProgramChange,10,0,7);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Preset 07");
  }
  else
  {
    mcp02.digitalWrite (mcp02_L7, LOW);
  }
    // loop riguardante il mcp01_b8
  if (debounce(mcp01_b8)) 
  {
    mcp02.digitalWrite(mcp02_L8, HIGH);
    MIDI.send(ProgramChange,10,0,8);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Preset 08");
  }
  else
  {
    mcp02.digitalWrite (mcp02_L8, LOW);
  }
}

I due MCP mi hanno fatto impazzire perchè se ne mettevo uno con:

 mcp01.begin();           // use default address 0

funzionava tutto
poi per metterne 2 analizzavo con I2C scanner e trovavo 0x20 e 0x21 e allora mettevo:

  mcp01.begin(0x21);           // use default address 0
  mcp02.begin(0x20);           // use default address 0

e non funzionava nulla! =(

allora preso dallo sconforto ho navigato il web in lungo in largo e niente!!

Poi oggi rileggendo il codice esempio allegato alla libreria ho notato che metteva lo 0 come standard adress e non 0x20 come da datasheet e allora ho pensato "tu guarda che idiota! avevo la soluzione sotto gli occhi da 2 giorni e non me ne ero accorto!

Ora che il primo obbiettivo è stato raggiunto sono dolori, devo passare alla possibilità di programmare la pedaliera midi direttamente con i pushbutton a bordo dello Chassis pensavo di utilizzare la libreria MENWIZ che ne dite?

ma prima volevo chiedere lumi sul come far rimanere il led acceso assegnato al relativo pushbutton fino alla pressione del successivo pushbutton, sicuramente in rete troverò la soluzione solo che per ora stacco!

Un saluto a tutti quelli che mi hanno aiutato fin qui! XD

Ora arrivano i dolori! e avrò bisogno del vostro aiuto =(

In pratica devo riuscire a modificare tramite LCD, il Testo del preset, il segnale MIDI ProgramChange e in futuro anche ControlChange senza l'ausilio del Computer.

Questo è il codice funzionante, solo che è possibile modificarlo solo attraverso il Computer:

  if (debounce(mcp01_b2)) 
  {
    mcp02.digitalWrite(mcp02_L2, HIGH);
    // questo è il segnale Midi che può essere modificato tramite LCD ed il valore è il 2 che può variare da 0-127 o 1-128.
    MIDI.send(ProgramChange,10,0,2);  
    lcd.clear();
    lcd.setCursor(0, 0);
    // questo è il testo che può essere modificato tramite LCD.
    lcd.print("Preset 02");

Avete suggerimenti su quali funzioni orientare gli studi? oppure consigliarmi su come strutturare lo sketch?

Grazie

Salve Ragazzi sono alle prese con la possibilità di modificare le variabili dei parametri MIDI e il testo stampato su LCD relativo ad ogni button.
il codice sopra funziona benissimo e ogni button accende il led relativo e manda il segnale MIDI impostato e scrive su LCD il Testo impostato.

Ora però ho bisogno di avere la possibilità premendo un pushbutton MODE di entrare in modalità programmazione relativa all'ultimo Preset selezionato.

esempio nel codice sopra è imposato:
se premo il pushbutton 2
accendo il led 2
scrivo su LCD "Preset 2"
mando il Program Change MIDI 2 al multieffetto

devo avere la possibilità di entrare in modalità programmazione e impostare esempio:
se premo il pushbutton 2
accendo il led 2
scrivo su LCD "Clean"
mando il Program Change MIDI 60 al multieffetto

quindi presumo che devo creare due variabili che possono essere modificate tramite LCD con pushbutton dedicati allo scopo.
Ma come posso visualizzarle su LCD e andarle a modificare?

ho fatto uno stupido diagramma a blocchi per farvi capire meglio quello di cui ho bisogno.
https://docs.google.com/file/d/0B0C7f_F5Q68sWmF4cUU4MEJPVHM/edit?usp=sharing

Grazie

Ciao Biagetti, poi com'è andata a finire? Ce l'hai fatta? Sono molto interessato! :open_mouth: