Go Down

Topic: DIY 6 button MIDI foot controller that sends MIDI Program Change + LCD (Read 1 time) previous topic - next topic

Grumpy_Mike

You only use this
Code: [Select]
controlChange(byte channel, byte control, byte value)
When you are defining a function call. As in:-
Code: [Select]
void controlChange(byte channel, byte control, byte value) {
These tell the function what to call the three numbers that are passed to the function and what type of variable they are. These names are unique to that function and can be the same names as used in other parts of the program without affecting their value. We say that these variables are only within the "scope" of this function.

When you want to use the function from other code, that is call it up then you use:-
Code: [Select]
controlChange(channel, control, value);
But the parameters you pass to it do not have to be those names they can be any variable names or even constants.
So these are all acceptable:-
Code: [Select]

controlChange(activeChannel, currentControl, valueToSet);
controlChange(something, somethingElse, moreSomethings);
controlChange(rubbishName1, rubbishName2, rubbishName3);
controlChange(4, 8, 92);

Providing the variable names are declared and given a value before you use them.

j2sip

Code: [Select]
// to add more then simply add more pins tothe list
byte ledPin[] = {A3,A2,A1,A9,A8,A0};  // list of led pins
byte buttonPin[] = {10,6,1,5,7,0};    // list of buttons pins
byte buttonState[] = {0,0,0,0,0,0};  // start off with off
byte lastButtonState[] = {0,0,0,0,0,0};  // start off with off
byte programChanges[] = {0,1,2,3};  // list of program change messages to send
byte controlChanges[] = {1, 12, 65};


Is this correct? Do i need to change something here?

j2sip

#32
Sep 07, 2019, 10:27 am Last Edit: Sep 07, 2019, 01:33 pm by j2sip Reason: making up my mind
Code: [Select]
void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
  MidiUSB.flush();

   if( Up_buttonPin == HIGH ){
                 controlChange(0, 12, 127);
              } else {
              programChange(0, 120);
               MidiUSB.flush();
        }


I think that this >>if( Up_buttonPin == HIGH ) > is not how i'm supposed "call" it. It messed up with the LCD; bank names aren't scrolling anymore.


Is there a way to change the code so that my intention of using buttons 5 and 6 is already established at the start?

Grumpy_Mike

Regarding reply #32

Oh come on, please read that function to yourself again and see what the computer will do.

It will send a control change EVERY time and then look at the button and depending what it sees it will send either ANOTHER control change message or a Program change message. The extra control change message will always be to send a value of 127 to controller 12 on a channel 0, where as the first control change will be what ever the numbers passed to the function will be. You seem to be going backwards at a tremendous rate and gradually destroying the code where as you only had to add a simple if statement to decide what message to send.

Quote
It messed up with the LCD; bank names aren't scrolling anymore.
No the rest of your code, which you did not post, is messing up the LCD, but how I can only guess because you are changing things and not showing what you changed.

Regarding reply #31
Quote
Is this correct?
Who knows? It depends on the rest of the code that once again you failed to post.

Last time of telling. When posting your code post ALL of it.

j2sip

Code: [Select]
#include <MIDIUSB.h>
#include <LiquidCrystal_I2C.h>

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


// Simple MIDI output of program message through USB
// By Grumpy_Mike August 2019


// to add more then simply add more pins tothe list
byte ledPin[] = {A3,A2,A1,A9,A8,A0};  // list of led pins
byte buttonPin[] = {10,6,1,5,7,0};    // list of buttons pins
byte buttonState[] = {0,0,0,0,0,0};  // start off with off
byte lastButtonState[] = {0,0,0,0,0,0};  // start off with off
byte programChanges[] = {0,1,2,3,4,5};  // list of program change messages to send
byte controlChanges [] = {(0, 12, 127), (0, 13, 127)};
byte channel = 0; // for musicians this is channel 1

// this constant won't change:
const int  Up_buttonPin   = 0;    // the pin that the pushbutton is attached to
const int  Down_buttonPin = 7;

// Variables will change:
int buttonPushCounter = 0;   // counter for the number of button presses
int up_buttonState = 0;         // current state of the up button
int up_lastButtonState = 0;     // previous state of the up button

int down_buttonState = 0;         // current state of the up button
int down_lastButtonState = 0;     // previous state of the up button
bool bPress = false;

char *myStrings[] = {"      Fender", "     Plexy", "      Mesa", "      5150", "      Dumble",
                     "     Soldano   ",  "    Triple Rec " };

void setup() {
  for(int i =0;i< sizeof(buttonPin); i++){ // initialise input pins 
    pinMode(buttonPin[i], INPUT_PULLUP); // wire all buttons between input and ground
    pinMode(ledPin[i], OUTPUT);
  }
{
  Serial.begin(9600);
  pinMode( Up_buttonPin , INPUT_PULLUP);
  pinMode( Down_buttonPin , INPUT_PULLUP);
 
  lcd.init();                      // initialize the lcd
 
  // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Banks:");
  lcd.setCursor(1,1);
  lcd.print(buttonPushCounter);
}
}

void loop() {
  for(int i =0;i< sizeof(buttonPin); i++){  // look at all pins
  buttonState[i] = digitalRead(buttonPin[i]);
  if(buttonState[i] == LOW && lastButtonState[i] == HIGH) { // remember how you wired your buttons LOW = pressed
    ledOffAll();
    digitalWrite(ledPin[i],HIGH);
    programChange(channel, programChanges[i]); // send the program change message
    MidiUSB.flush();
    delay(50);
   }
   lastButtonState[i] = buttonState[i];
  }

   
}

void ledOffAll() {
    for(int i = 0 ; i< sizeof(ledPin); i++){
     digitalWrite(ledPin[i], LOW);
    }
}

void programChange(byte channel, byte patch) {
   midiEventPacket_t event = {0x0C, 0xC0 | channel, patch};
   MidiUSB.sendMIDI(event);}

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
  MidiUSB.flush();

   if( Up_buttonPin == HIGH ){
                 controlChange(0, 12, 127);
              } else {
              programChange(0, 120);
               MidiUSB.flush();
        }
         

{
    checkUp();
    checkDown();
}

   if( bPress){
       bPress = false;
      lcd.setCursor(2,1);
      lcd.print("            ");
      lcd.setCursor(221,1);
      lcd.print(buttonPushCounter[myStrings]);
   } 
 

void checkUp()
{
  up_buttonState = digitalRead(Up_buttonPin);

                                               // compare the buttonState to its previous state
  if (up_buttonState != up_lastButtonState) {
                                               // if the state has changed, increment the counter
    if (up_buttonState == LOW) {
        bPress = true;
         buttonPushCounter++;         // if the current state is HIGH then the button went from off to on:
                   
    }
    // Delay a little bit to avoid bouncing
    //delay(5);
 
  }
                                                 // save the current state as the last state, for next time through the loop
  up_lastButtonState = up_buttonState;
}
void checkDown()
{
  down_buttonState = digitalRead(Down_buttonPin);

                                                       // compare the buttonState to its previous state
  if (down_buttonState != down_lastButtonState) {
                                                           // if the state has changed, increment the counter
    if (down_buttonState == LOW) {
        bPress = true;
                                              // if the current state is HIGH then the button went from off to on:
      buttonPushCounter--;
         
    }
    // Delay a little bit to avoid bouncing
    //delay(5);
  }
  // save the current state as the last state, for next time through the loop
  down_lastButtonState = down_buttonState;
}


 


Sorry. This is the disadvantage of starting from scratch. I really am lost and clueless. don't have any idea what to do, that is why..

I don't see a CC in midiOx, only PC.

j2sip

Code: [Select]
#include <frequencyToNote.h>
#include <MIDIUSB.h>
#include <pitchToFrequency.h>
#include <pitchToNote.h>

// initialize everything

int slider1val = 0;
int a0val = 0;
int slider2val = 0;
int a1val = 0;
int slider3val = 0;
int a2val = 0;
int slider4val = 0;
int a3val = 0;

int b2 = 0;
int b2toggle = 0;
int b2down = 0;

int b3 = 0;
int b3toggle = 0;
int b3down = 0;

int b4 = 0;
int b4toggle = 0;
int b4down = 0;

int b5 = 0;
int b5toggle = 0;
int b5down = 0;

// these are the functions from MIDIUSBs demo, I left the noteOn and noteOff in even though we aren't using them.

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
  MidiUSB.flush();
}

void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
  MidiUSB.flush();
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
  MidiUSB.flush();
}


void setup() {
  // I've opened the serial port for logging reasons. You don't need that line really but I just left it in.
  // At this point we also set the pin modes for our 4 buttons. They are set to pullup and are on digital pins 2, 3, 4 and 5.
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
}

void loop() {
  // lets get some data from our buttons via digitalRead and throw them into some variables
  b2 = digitalRead(2);
  b3 = digitalRead(3);
  b4 = digitalRead(4);
  b5 = digitalRead(5);

  // lets check if the button is down, these are toggle buttons so we use b2toggle to remember what state the toggle is in. We do this for each button
  if (b2 == 0) {
    if (b2down == 0) {
      if (b2toggle == 0) {
         // the control change function sends on the same channel but with a different pitch on each button. The velocity is 127 as these are simple "on off" arcade buttons.
         controlChange(0, 5, 127);
         b2toggle = 1;
      } else {
        controlChange(0, 5, 0);
         b2toggle = 0;
      }
      b2down = 1;
    }
  } else {
    b2down = 0;
  }

   if (b3 == 0) {
    if (b3down == 0) {
      if (b3toggle == 0) {
         controlChange(0, 6, 127);
         b3toggle = 1;
      } else {
        controlChange(0, 6, 0);
         b3toggle = 0;
      }
      b3down = 1;
    }
  } else {
    b3down = 0;
  }

     
  if (b4 == 0) {
    if (b4down == 0) {
      if (b4toggle == 0) {
         controlChange(0, 7, 127);
         b4toggle = 1;
      } else {
        controlChange(0, 7, 0);
         b4toggle = 0;
      }
      b4down = 1;
    }
  } else {
    b4down = 0;
  }

     if (b5 == 0) {
    if (b5down == 0) {
      if (b5toggle == 0) {
         controlChange(0, 8, 127);
         b5toggle = 1;
      } else {
        controlChange(0, 8, 0);
         b5toggle = 0;
      }
      b5down = 1;
    }
  } else {
    b5down = 0;
  }


I found this and in 2 hours, I got what I wanted!! Yeah! I grafted some elements of our original code in it and, voila!!!! Thank you so much for your patience!

Grumpy_Mike

Quote
I found this
Sigh.
My heart sinks at those words, I thought I was teaching you how to write code. Still it is your choice. I won't waste any more time here.

j2sip

Don't feel bad. I found out that they are the same codes but yours was just a bit complicated for me. I learned a lot.

Go Up