Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 7 of 7

Thread: Midi Controller help needed, "On" and "Off" preset

  1. #1
    Junior Member
    Join Date
    Jul 2020
    Posts
    5

    Midi Controller help needed, "On" and "Off" preset

    Hi I am new in the forum and new to coding. Bought a 6 button midi controller and was trying to code. Manage to add 2 different midi channel into the code.

    The mid controller works in way that when I switch on button 1, I need to off button 1 in order not the mess up the PC number.

    How can I switch on a random preset (e.g. button 3) without needing to off it.

    For e.g. When I switch to button 4, button 3 will off it and button 4 preset will come right up.

    Any help appreciated.

    Thanks!

    Code:
    //************LIBRARIES USED**************
    // 'include the Bounce library for 'de-bouncing' switches -- removing electrical chatter as contacts settle'
    #include <MIDI.h>
    #include <Bounce.h> 
    //'usbMIDI.h library is added automatically when code is compiled as a MIDI device'
    
    MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
    
    // ******CONSTANT VALUES******** 
    
    
    //********** PIN DEFINITIONS
    const int D_PINS = 5; // number of Digital PINS in main group (excl tap/bank)
    const int DIGITAL_PINS[D_PINS] = {0,1,2,3,4}; // pins to switchs 
    const int RED_LED_PINS[D_PINS] = {6,22,10,17,19};
    const int GREEN_LED_PINS[D_PINS] = {24,9,16,18,20};
    const int MODE_TAP_PIN = 5;  // momentary switch to set tempo and select bank
    const int MODE_TAP_LED_PIN = 15; // pin to LED for tempo/bank indicator
    
    //Alan
    const int RED_LED_PINS1[D_PINS] = {6}; // pins to switchs RED
    const int RED_LED_PINS2[D_PINS] = {22}; // pins to switchs RED
    const int RED_LED_PINS3[D_PINS] = {10}; // pins to switchs RED
    const int RED_LED_PINS4[D_PINS] = {17}; // pins to switchs RED
    const int RED_LED_PINS5[D_PINS] = {19}; // pins to switchs RED
    
    const int GREEN_LED_PINS6[D_PINS] = {24}; // pins to switchs GREEN
    const int GREEN_LED_PINS7[D_PINS] = {9}; // pins to switchs GREEN
    const int GREEN_LED_PINS8[D_PINS] = {16}; // pins to switchs GREEN
    const int GREEN_LED_PINS9[D_PINS] = {18}; // pins to switchs GREEN
    const int GREEN_LED_PINS10[D_PINS] = {20}; // pins to switchs GREEN
    
    const int DIGITAL_PINS0[D_PINS] = {0}; // pins to switchs 
    const int DIGITAL_PINS1[D_PINS] = {1}; // pins to switchs 
    const int DIGITAL_PINS2[D_PINS] = {2}; // pins to switchs 
    const int DIGITAL_PINS3[D_PINS] = {3}; // pins to switchs 
    const int DIGITAL_PINS4[D_PINS] = {4}; // pins to switchs 
    
    
    
           //********** MIDI DEFINITIONS*************
    // MODIFY THIS SECTION TO CUSTOMISE YOUR MIDISTOMP SIX 
    
    const int firstchannel = 1; // MIDI channel for USB MIDI
    const int secondchannel = 2; // MIDI channel for TRS MIDI
    const int thirdchannel = 3; // MIDI channel for TRS MIDI
    
    const int MODE_COUNT = 2; // number of rows of banks
    const int MODE_COUNT2 = 2; // number of rows of banks
    
    //CC configuration matrix!! TIMELINE
    const int MIDI_PC_NUMS[MODE_COUNT][D_PINS] = { //rows are banks up to MODE_COUNT
        {60,61,62,63,64},
        {65,66,67,68,69}
    };
    
    // BIGSKY
    const int MIDI_PC_NUMS2[MODE_COUNT2][D_PINS] = { //rows are banks up to MODE_COUNT
        {60,60,62,63,64},
        {60,60,60,60,60}
    };
    const int TAP_CC = 93;
    
    //const int TAP_CC_DOWN = 80+82;
    //const int TAP_CC_UP = 82+81;
    
    const int ON_Value = 127; // note-one velocity sent from buttons (should be 65 to  127)
    
    
    //********** PHYSICAL DEFINITIONS 
    const int BOUNCE_TIME = 30; // 5 ms is usually sufficient
    const int modeThreshold = 800; // how long to hold before mode changes
    const int flashOnTime = 150; // how long flashed LED is on
    const int flashOffTime = 250; // how long flashed LED is off
    const bool LED_ON = LOW; // LOW for active LOW wiring
    const bool LED_OFF = HIGH; // HIGH for active LOW wiring
    const int onClocks = 4; // number of clock messages with LED on for tempo flash
    const int waitflash = 2; // number of dark flash cylces after bank change before tempo flash resumes
    
    //******VARIABLES***********
    // a data array to remember the current state of each switch
    boolean state[MODE_COUNT][D_PINS];
    elapsedMillis modeTimer,flashTimer;
    boolean modeSelectActive = false;
    int bank = 0 ; 
    int flashcount= (-1*waitflash); // default is effective sequence stop of flash counter
    int shiftUp; // keeps track of whether the mode change needs to be handled (true) or was (false)
    int modeLED; // keeps track of whether LED is on without testing it..
    int ClockCount; // for tempo tracking
    boolean tempoFlashOn = true;// tempo flash defaults to on
    
    //************INITIALIZE LIBRARY OBJECTS**************
    
    // initialize the bounce objects 
    Bounce digital[] =   {
        Bounce(DIGITAL_PINS[0],BOUNCE_TIME), 
        Bounce(DIGITAL_PINS[1], BOUNCE_TIME),
        Bounce(DIGITAL_PINS[2], BOUNCE_TIME),
        Bounce(DIGITAL_PINS[3], BOUNCE_TIME),
        Bounce(DIGITAL_PINS[4], BOUNCE_TIME)
    }; 
    Bounce modeTap = Bounce(MODE_TAP_PIN, BOUNCE_TIME);
    
    //************SETUP**************
    void setup() {
      MIDI.begin(MIDI_CHANNEL_OMNI);
      
      //'set a handle for returning control change messages'
      usbMIDI.setHandleProgramChange(OnProgramChange);
      usbMIDI.setHandleSongPosition(onSongPosition);
      usbMIDI.setHandleClock(onClock);
      usbMIDI.setHandleStart(onStart);
      //'loop to configure input pins and internal pullup resisters for digital section'
      for (int i=0;i<D_PINS;i++){
        pinMode(DIGITAL_PINS[i], INPUT_PULLUP);
        pinMode(RED_LED_PINS[i], OUTPUT);
        pinMode(GREEN_LED_PINS[i], OUTPUT);
      }
      pinMode(MODE_TAP_PIN, INPUT_PULLUP);
      pinMode(MODE_TAP_LED_PIN, OUTPUT);
      digitalWrite(MODE_TAP_LED_PIN, LED_OFF);
    
      for (int i=0;i<D_PINS;i++){
        digitalWrite(GREEN_LED_PINS[i], LED_OFF);   // - GREEN OFF
        digitalWrite(RED_LED_PINS[i], LED_ON);   // - RED ON
      }
    }
    
    //************LOOP**************
    void loop() {
      getMain();
      getModeTap();
      flasher();
      while (usbMIDI.read()) {
        //' controllers must call .read() to keep the queue clear even if they are not responding to MIDI'
      }
        while (MIDI.read()){
    
      }
    }
    
    
    //************DIGITAL SECTION**************
    void getMain(){
      for (int i=0;i<D_PINS;i++){
        digital[i].update();
        if (digital[i].fallingEdge() || digital[i].risingEdge() ) {
          if (state[bank][i]) {
            usbMIDI.sendProgramChange(MIDI_PC_NUMS[bank][i], firstchannel); 
            MIDI.sendProgramChange(MIDI_PC_NUMS[bank][i], secondchannel); 
    
                    MIDI.sendProgramChange(MIDI_PC_NUMS2[bank][i], thirdchannel); 
    
           digitalWrite(RED_LED_PINS[i], LED_ON);
                  digitalWrite(GREEN_LED_PINS[i], LED_OFF);
    
          }else {
           usbMIDI.sendProgramChange(MIDI_PC_NUMS[bank][i], firstchannel); 
            MIDI.sendProgramChange(MIDI_PC_NUMS[bank][i], secondchannel);  
    
                     MIDI.sendProgramChange(MIDI_PC_NUMS2[bank][i], thirdchannel); 
    
            digitalWrite(RED_LED_PINS[i], LED_OFF);
                   digitalWrite(GREEN_LED_PINS[i], LED_ON);
    
          }
          state[bank][i] = !state[bank][i] ;
    
        }
      }
    }
    
    
    
    //************MODE/TAP SECTION**************
    void getModeTap(){
      modeTap.update();
      if (modeTap.fallingEdge()) {
        usbMIDI.sendControlChange(TAP_CC, ON_Value, firstchannel);
        MIDI.sendControlChange(TAP_CC, ON_Value, secondchannel); 
        modeTimer = 0;
        shiftUp = true;
        tempoFlashOn = false; 
        flashcount = 0; // is this error or magic?
        Serial.println("suspend tempo on tap");
      }    
      if (modeTap.risingEdge()){
        shiftUp = false;
        if (modeTimer<modeThreshold){
          tempoFlashOn = true; 
        Serial.println("resume tempo no mode change");
        }
      }
      if (modeTimer>modeThreshold && shiftUp) {
        shiftUp = false;
        bank++;
        bank = bank%MODE_COUNT;
        for (int i = 0; i < D_PINS ; i++){
          digitalWrite(GREEN_LED_PINS[i], !state[bank][i]);
          digitalWrite(RED_LED_PINS[i], state[bank][i]); 
        }
        // set counter of flashes 'owed' -- count them down after main part
        flashcount = bank + 1;
        flashTimer = 0 ; // is this needed?
      }
    }
    
    void flasher(){
      if (flashcount>= -1*waitflash){
        if (flashcount> 0){
          if (flashTimer>(flashOnTime+flashOffTime)){ 
            flashcount-- ;// decrement flashcount
            flashTimer = 0;
            if (modeLED){
              modeLED = false;
              digitalWrite(MODE_TAP_LED_PIN, LED_OFF);
            }
          }else{
            if (modeLED == false && flashTimer>flashOnTime){
              modeLED = true;
              digitalWrite(MODE_TAP_LED_PIN, LED_ON);
            }
          }
        }else{
          if (flashTimer>(flashOnTime+flashOffTime)){ 
            flashcount-- ;// decrement flashcount
            flashTimer = 0;
          }
        }
      }else{
        if (!tempoFlashOn){
          tempoFlashOn = true;
          Serial.println(flashcount);
          Serial.println("resume tempo after bank select");
        }
      }
    }
    
    void OnProgramChange(byte rcvChannel, byte controller, byte value) {
      if (rcvChannel == firstchannel){
        for (int i = 0; i < D_PINS ; i++){
          if (MIDI_PC_NUMS[bank][i] == controller) {
            if (value >= 64) {
              digitalWrite(GREEN_LED_PINS[i], LED_ON);
              digitalWrite(RED_LED_PINS[i], LED_OFF); //'receiving >64 turns green on and red off'
              state[bank][i] = true;
            }else{
              digitalWrite(GREEN_LED_PINS[i], LED_OFF);
              digitalWrite(RED_LED_PINS[i], LED_ON); //'receiving <64 turns red on and green off'
              state[bank][i] = false;
            } // 'if not the controller for i then skip this loop'    
          }
        }
      }
    }
    
    void onClock() {
      if (tempoFlashOn){
        if (ClockCount<=onClocks){
          digitalWrite(MODE_TAP_LED_PIN, LED_ON);
        }else{
          digitalWrite(MODE_TAP_LED_PIN, LED_OFF);
        }
      }
      ClockCount = (ClockCount+1)%24;
    }
    
    void onStart(){
      ClockCount = 0;
    }
    
    
    void onSongPosition(uint16_t semiQ){
      ClockCount= semiQ*6 ; 
    }

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    22,772
    Quote Originally Posted by musicgit View Post
    Bought a 6 button midi controller and was trying to code.
    Can you show us photos and details of the hardware you're actually using?

    This code is complex and honestly, I can't follow what is it doing and I can't understand your explanation of what you want to accomplish when I don't even have any idea of what this hardware even looks like.

  3. #3
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,360
    This is code I helped with....
    https://forum.pjrc.com/threads/58017...with-midi-read

    Note if you bought his controller the switches are toggles being used to act like momentary switches --so they don't 'read' their state but transition from the previous state when a transition is detected.

    So you want them to act like momentary switches.... CC value should send CC=0 when you lift you foot?

  4. #4
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,360
    No... reading again it sounds like you want selection of a new CC value as ON to send OFF for the previous CC?

    Edit
    ...just noticed it's sending program changes and not CC...

  5. #5
    Junior Member
    Join Date
    Jul 2020
    Posts
    5
    Hi all, firstly thanks for the respond. Let me try to explain what I want to achieve.

    Click image for larger version. 

Name:	IMG_7384.jpg 
Views:	5 
Size:	60.5 KB 
ID:	21179
    This is the state of the midi controller when I on it. The red colour buttons represent "OFF"

    Click image for larger version. 

Name:	IMG_7385.jpg 
Views:	5 
Size:	70.0 KB 
ID:	21180
    This is the state of the midi controller when I on it., The button becomes green which represent "ON"

    Each button represent a PC which it will send to my guitar effects, calling out the present.
    Right now every time I "ON" the button I need to switch it off so that there won't be error message. Error Messages meaning the PC numbers will go haywire, it will keep sending random PC to my guitar effects. My guitar effects will keep running random preset continuously.

    Click image for larger version. 

Name:	IMG_7386.jpg 
Views:	6 
Size:	75.5 KB 
ID:	21181
    This is the state when I "ON" 2 buttons and it will have error message

    Click image for larger version. 

Name:	IMG_7387.jpg 
Views:	4 
Size:	74.1 KB 
ID:	21182
    My ideal solution to this is that how can I "ON" the second button (the middle button) and the first one (extreme right) will be switch off automatically. Just like how the picture is right now. When I "ON" the middle button, the extreme right button will "OFF" automatically.

    So sorry if my explanation is bad, I tried my best wanting to explain how to get it to work. Thank you so much for spending time and effort to come up with solution. Appreciate that alot.

  6. #6
    Junior Member
    Join Date
    Jul 2020
    Posts
    5
    Quote Originally Posted by oddson View Post
    No... reading again it sounds like you want selection of a new CC value as ON to send OFF for the previous CC?

    Edit
    ...just noticed it's sending program changes and not CC...
    I think that is the person whom I bought the midi controller from. He does a few profiles for his midi controller. But the hassle to " OFF" the preset and then "ON" another one its not helping if I am playing live guitar when the change of preset must be immediate and accurate.

    Not wanting them to be momentary. Each button now has 2 state. "ON" and "OFF" Green and Red. Can I only make it in 1 state?

    "ON" only. But if I press a second button, the first button will be "OFF". So at any one time only 1 button will on "ON"

    So sorry, totally noob. Thanks for replying

  7. #7
    Junior Member
    Join Date
    Jul 2020
    Location
    The Road
    Posts
    8
    Quote Originally Posted by musicgit View Post
    "ON" only. But if I press a second button, the first button will be "OFF". So at any one time only 1 button will on "ON"
    I can't offer any detailed help with your setup, but in user interface lingo the term for the behavior you're looking for is "radio buttons": https://en.wikipedia.org/wiki/Radio_button

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •