Go Down

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

j2sip

Been busy for the past week.. I have already assembled the pedalboard and it worked, from MIDI program change up to the LEDs lighting up. And also I got the LCD part right with this;

Code: [Select]
checkUp();
   checkDown();
}
   if( bPress){
       bPress = false;
      lcd.setCursor(2,1);
      lcd.print("               ");
      lcd.setCursor(2,1);
      lcd.print(buttonPushCounter[myStrings]);
   }




 So happy! But... the bank buttons of the amp sim that I'm using requires a CC (or any command other than PC) to properly use it. Programming 2 buttons(inside amp sim app) for Bank up and down can't override the state that it is (sending PC) so even if use a PC as far back as 126, it always sends that command.

Grumpy_Mike

Quote
for Bank up and down can't override the state that it is (sending PC
So use an if statement to test when you have a bank change button and send a CC else send the normal PC message.

Again post your code.

j2sip

Should i declare first that i'd like to send CC using button 5 and 6?

is it like this?

....If a button is pressed and it is 5 and 6, send CC.. else, send PC.

Grumpy_Mike


j2sip

Code: [Select]
#include <frequencyToNote.h>
#include <MIDIUSB.h>
#include <MIDIUSB_Defs.h>
#include <pitchToFrequency.h>
#include <pitchToNote.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display
#include <MIDI.h>


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

#include "MIDIUSB.h"

// 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,4,5,6};  // list of program change messages to send

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[] = {" Cleans ", "Marshall Crunch", "80's Glam", "Boogie Crunch", "  Dumble  ",
                     "  5150   ",  " Ambient ", " BowtiQ "};

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(2,1);
  lcd.print(buttonPushCounter[myStrings]);
}
}

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

{
    checkUp();
    checkDown();
}

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


   if( Up_buttonPin, Down_buttonPin  == HIGH){
       
       MidiUSB.sendMIDI(midiEventPacket_t event = 0x0B, 0xB0 | channel, control, value);
   }
  else }
       MidiUSB.sendMIDI(midiEventPacket_t event = 0x0C, 0xC0 | channel, patch);

 
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;
      // if the current state is HIGH then the button went from off to on:
      buttonPushCounter++;
      //Serial.println("on");
      //Serial.print("number of button pushes: ");
      //Serial.println(buttonPushCounter);
   // } else {
      // if the current state is LOW then the button went from on to off:
      //Serial.println("off");
    }
    // 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--;
 
     
      //Serial.println("on");
      //Serial.print("number of button pushes: ");
      //Serial.println(buttonPushCounter);
   // } else {
      // if the current state is LOW then the button went from on to off:
      //Serial.println("off");
    }
    // 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;
}


 



I get stuck here. expected primary expression before event error.


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


   if( Up_buttonPin, Down_buttonPin  == HIGH){
       
       MidiUSB.sendMIDI(midiEventPacket_t event = 0x0B, 0xB0 | channel, control, value);
   }
  else }
       MidiUSB.sendMIDI(midiEventPacket_t event = 0x0C, 0xC0 | channel, patch);

 


Honestly, I don't even know accepted commands in MidiUSB so i just kinda blindly try. Kindly point me out to the correct direction :D

Grumpy_Mike

Where did you get this from?
Code: [Select]
MidiUSB.sendMIDI(midiEventPacket_t event = 0x0B, 0xB0 | channel, control, value);

It should be more like:-
Code: [Select]

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


Quote
Honestly, I don't even know accepted commands in MidiUSB
Look at the MidiUSB.h file. At the bottom is a bit that says public:, all the calls you can make to the module follow that.

However, it is best to look at the examples in that folder as well to see how they are used.
Basically all you do is create a specific array which has a type midiEventPacket_t, this contains the details of what you want to send, then you send it. Sending it actually puts it in a buffer and the command will not actually be sent until the buffer is full. If you want that command to be sent immediately then you can call the flush method. It can be useful if you want to send a sequence of messages as fast as possible, put them in the buffer and only when you have all messages in the buffer then flush them.

You keep adding unnecessary libraries multiple times. Why are you doing this?
Code: [Select]
#include <frequencyToNote.h>
#include <MIDIUSB.h>
#include <MIDIUSB_Defs.h>
#include <pitchToFrequency.h>
#include <pitchToNote.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display
#include <MIDI.h>


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

#include "MIDIUSB.h"

You do not need the MIDI.h library having it in is only going to screw you up, and what is it with the pitchToNote.h, pitchToFrequency.h and frequencyToNote.h? Why are you including them? Who told you to do this? You see I didn't include those in my code so why add them.

My LiquidCrystal_I2C libiary is not the same as yours, this is a none standard library so where did you get it from? This is stopping me compiling your code on my machine.

j2sip

Quote
You do not need the MIDI.h library having it in is only going to screw you up, and what is it with the pitchToNote.h, pitchToFrequency.h and frequencyToNote.h? Why are you including them? Who told you to do this? You see I didn't include those in my code so why add them.

My LiquidCrystal_I2C libiary is not the same as yours, this is a none standard library so where did you get it from? This is stopping me compiling your code on my machine.
They all came from the midiUSB lib. i guess I could weed out the useless ones.

Forgot where I got that i2c lib. standard one didnt work.

Thank you for the guidance.


Grumpy_Mike

Quote
They all came from the midiUSB lib.
Yes they might but there is no need to include them, they will be called up by the .h or .cpp file if needed. You have no need to include them specifically.

j2sip

You might have noticed I included this

Code: [Select]
void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);


Does it have any bearing at all in the sketch?

And if this is the one sending the program change:

Code: [Select]
programChange(channel, programChanges[i]);

what is the equivalent of sending lets say CC#12?





j2sip

Separate question. When you said this,

Quote
Basically all you do is create a specific array
Shall I abandon the if-else statement that you first suggested? Or do they go together?

Grumpy_Mike

Quote
Shall I abandon the if-else statement that you first suggested? Or do they go together?
No they go together.

Quote
Does it have any bearing at all in the sketch?
Yes it is what you need to call if you want to send a control message. The variables you pass to this function define the channel it is sent on, the controller number and the value you want to set that controller to.

Quote
what is the equivalent of sending lets say CC#12?
What value? If you want to send a value of 65 to CC 12, then call that function
Code: [Select]
controlChange(0,12,65);
And don't forget to flush, as your mother used to tell you.

j2sip

...and kindly tell in what part of the sketch shall I insert the array and what it would look like. i mean, what kind of array.

Thanks again for the help.

Grumpy_Mike

I think you are miss understanding what I said.
The array is what you define in order to send a MIDI message.
It is this part
Code: [Select]
event = {0x0B, 0xB0 | channel, control, value}
Of this line
Code: [Select]
midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
I was trying to tell you how you send a MIDI message, it doesn't matter what message you want to send, they are all sent in this way.

j2sip

ohh,, Thank you so much for your patience. I already did that yesterday but it kept looking for "function" before it. There must be some line that I'm missing. I'll post the code later (I'm away from my PC). Thanks a lot again :)

j2sip

#29
Sep 07, 2019, 03:55 am Last Edit: Sep 07, 2019, 06:24 am by j2sip Reason: change code
This all I managed to cobble up. It gets an" expected primary-expression before 'channel'" error here:
Code: [Select]
controlChange(byte channel, byte control, byte value)

I'm not sure if Im doing the right thing.

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

  if( Up_buttonPin, Down_buttonPin == HIGH ){
  
        controlChange(byte channel, byte control, byte value)
        midiEventPacket_t event = {0x0B, 0xB0 | 0, 12, 65};
        MidiUSB.sendMIDI(event);
        MidiUSB.flush();
  }
        else (programChange(channel, programChanges[i])); // send the program change message
 MidiUSB.flush();

Go Up