2 footswitch - up/down midi preset controller

Hi,

I'm trying to create a code for a simple 2 footswitch midi controller to scroll through presets 0-7 (on a guitar pedal) using two momentary switches and an arduino nano.

All is going well until i wanted to add a feature where pressing both switches at the same time recalled preset 127 as this is manual mode on the guitar pedal. It seems to mostly work however now to scroll through 0-7 I have to hold the opposite button down whilst pressing the other. Can anyone help with why this might be?

Thanks

#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

int progNo = 0;
int upLastTime, downLastTime, upNow, downNow;
int last_progNo;
int LED1 = 15;
int LED2 = 14;
int LED3 = 16;
int LED4 = 10;
int LED5 = 9;
int LED6 = 8;
int LED7 = 7;
int LED8 = 6;

void setup() {
  Serial.begin(9600);
  MIDI.begin();
  MIDI.setInputChannel(1);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  pinMode(LED4, OUTPUT);
  pinMode(LED5, OUTPUT);
  pinMode(LED6, OUTPUT);
  pinMode(LED7, OUTPUT);
  pinMode(LED8, OUTPUT);
  digitalWrite(2, HIGH); // enable pull up
  digitalWrite(3, HIGH); // enable pull up
  upLastTime = digitalRead(2);
  downLastTime = digitalRead(3);
}

void loop() {
  upNow = digitalRead(2);
  downNow = digitalRead(3);

  // Check if both up and down buttons are pressed
  if (upNow == HIGH && downNow == HIGH) {
    progNo = 127; // Set to preset 127
    MIDI.sendProgramChange(byte(progNo), 1);
    delay(20); // Debounce delay
  } else {
    // Check individual button presses
    if (upNow == HIGH && upLastTime == LOW) {
      progNo++; // Increment program change
      if (progNo > 7) progNo = 0; // Wrap around to 0
      MIDI.sendProgramChange(byte(progNo), 1);
      delay(20); // Debounce delay
    }

    if (downNow == HIGH && downLastTime == LOW) {
      progNo--; // Decrement program change
      if (progNo < 0) progNo = 7; // Wrap around to 7
      MIDI.sendProgramChange(byte(progNo), 1);
      delay(20); // Debounce delay
    }
  }

you mean SparkFun Pro Micro (some chinesian call it "Arduino Micro Pro"), am I right?

#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

const byte LEDs[] = { 15, 14, 16, 10, 9, 8, 7, 6};

void setup() {
  Serial.begin(9600);
  MIDI.begin();
  MIDI.setInputChannel(1);
  pinMode(2, INPUT_PULLUP);// enable pull up
  pinMode(3, INPUT_PULLUP);
  for (byte i = 0; i < 8; i++)pinMode(LEDs[i], OUTPUT);
}

void loop() {
  static byte progNo = 0;
  static bool upNow, downNow = false;
  upNow = digitalRead(2) == HIGH;       //Switches are NC
  downNow = digitalRead(3) == HIGH;

  // Check if both up and down buttons are pressed
  if (upNow  && downNow ) {
    progNo = 127; // Set to preset 127
    MIDI.sendProgramChange(byte(progNo), 1);
    delay(1000); // not a Debounce delay
  } else {
    // Check individual button presses
    if (upNow ) {
      if (progNo < 7)progNo++; // Increment program change
      else progNo = 0; // Wrap around to 0
      MIDI.sendProgramChange(byte(progNo), 1);
      delay(100);
    }

    if (downNow ) {
      if (progNo > 0)progNo--; // Decrement program change
      else progNo = 7; // Wrap around to 7
      MIDI.sendProgramChange(byte(progNo), 1);
      delay(100);
    }
  }
    for (byte i = 0; i < 8; i++)if (progNo != i)digitalWrite(LEDs[i], LOW); else digitalWrite(LEDs[i], HIGH);
}

Some first impressions -

// Check if both up and down buttons are pressed
  if (upNow == HIGH && downNow == HIGH) {
    progNo = 127;  // Set to preset 127
    MIDI.sendProgramChange(byte(progNo), 1);
    delay(20);  // Debounce delay
  } else {

Since you've set INPUT_PULLUP and if one assumes the switches are normally open, won't this test always be true?  Are the switches NO or NC?

 

    // Check individual button presses
    if (upNow == HIGH && upLastTime == LOW) {`

I can't see any place where upLastTime is updated.   Same for downLastTime.
 

pinMode(2, INPUT);
pinMode(3, INPUT);

The code will be easier to read and maintain if you give the input pins descriptive names - like was done for the LEDs.

Yeah! Sorry I do mean sparkfun pro micro

Thanks for the reply,

switches are normally open - off (on)

the upLastTime & downLastTime are lower in the code (apologies I did post the rest because it had a lot of irrelevant LED stuff).

I’ll give the input pins names tomorrow and reupload with the full code if this help!

Hi,

I've given the Up and Down pins names as you said and i'll copy the full code in.

[code]
#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

int progNo = 0;
int upLastTime, downLastTime, upNow, downNow;
int last_progNo;
int LED1 = 15;
int LED2 = 14;
int LED3 = 16;
int LED4 = 10;
int LED5 = 9;
int LED6 = 8;
int LED7 = 7;
int LED8 = 6;
int UP = 2;
int DOWN = 3;

void setup() {
  Serial.begin(9600);
  MIDI.begin();
  MIDI.setInputChannel(1);
  pinMode(UP, INPUT);
  pinMode(DOWN, INPUT);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  pinMode(LED4, OUTPUT);
  pinMode(LED5, OUTPUT);
  pinMode(LED6, OUTPUT);
  pinMode(LED7, OUTPUT);
  pinMode(LED8, OUTPUT);
  digitalWrite(UP, HIGH); // enable pull up
  digitalWrite(DOWN, HIGH); // enable pull up
  upLastTime = digitalRead(UP);
  downLastTime = digitalRead(DOWN);
}

void loop() {
  upNow = digitalRead(UP);
  downNow = digitalRead(DOWN);

  // Check if both up and down buttons are pressed
  if (upNow == HIGH && downNow == HIGH) {
    progNo = 127; // Set to preset 127
    MIDI.sendProgramChange(byte(progNo), 1);
    delay(20); // Debounce delay
  } else {
    // Check individual button presses
    if (upNow == HIGH && upLastTime == LOW) {
      progNo++; // Increment program change
      if (progNo > 7) progNo = 0; // Wrap around to 0
      MIDI.sendProgramChange(byte(progNo), 1);
      delay(20); // Debounce delay
    }

    if (downNow == HIGH && downLastTime == LOW) {
      progNo--; // Decrement program change
      if (progNo < 0) progNo = 7; // Wrap around to 7
      MIDI.sendProgramChange(byte(progNo), 1);
      delay(20); // Debounce delay
    }
  }
  digitalWrite(LED1, progNo == 0 ? HIGH : LOW);
  digitalWrite(LED2, progNo == 1 ? HIGH : LOW);
  digitalWrite(LED3, progNo == 2 ? HIGH : LOW);
  digitalWrite(LED4, progNo == 3 ? HIGH : LOW);
  digitalWrite(LED5, progNo == 4 ? HIGH : LOW);
  digitalWrite(LED6, progNo == 5 ? HIGH : LOW);
  digitalWrite(LED7, progNo == 6 ? HIGH : LOW);
  digitalWrite(LED8, progNo == 7 ? HIGH : LOW);

  if (progNo != last_progNo) {
    Serial.println(progNo); // Print only if the program number is different
  }

  last_progNo = progNo; // Store this program number for the next round
  upLastTime = upNow;
  downLastTime = downNow;
}
[/code]

are you ignoring my sketch?

Sorry, viewed your reply quickly last night and missed it!

Just tried your sketch and it seems to work better however, when looking on the serial monitor - the progNo always defaults to 127 if nothing is pressed and because of this when i try to scroll down through presets it will start at 127 - 126 - 125 etc.

#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

const byte LEDs[] = { 15, 14, 16, 10, 9, 8, 7, 6};

void setup() {
  Serial.begin(9600);
  MIDI.begin();
  MIDI.setInputChannel(1);
  pinMode(2, INPUT_PULLUP);// enable pull up
  pinMode(3, INPUT_PULLUP);
  for (byte i = 0; i < 8; i++)pinMode(LEDs[i], OUTPUT);
}

void loop() {
  static byte progNo = 0;
  static bool upNow, downNow = false;
  upNow = digitalRead(2) == HIGH;       //Switches are NC
  downNow = digitalRead(3) == HIGH;

  // Check if both up and down buttons are pressed
  if (upNow  && downNow ) {
    progNo = 127; // Set to preset 127
    MIDI.sendProgramChange(byte(progNo), 1);
    delay(1000); // not a Debounce delay
  } else {
    // Check individual button presses
    if (upNow ) {
      if (progNo < 7)progNo++; // Increment program change
      else progNo = 0; // Wrap around to 0
      MIDI.sendProgramChange(byte(progNo), 1);
      delay(50);
    }

    if (downNow ) {
      if (progNo > 0)progNo--; // Decrement program change
      else progNo = 7; // Wrap around to 7
      MIDI.sendProgramChange(byte(progNo), 1);
      delay(50);
    }
  }
    for (byte i = 0; i < 8; i++)if (progNo != i)digitalWrite(LEDs[i], LOW); else digitalWrite(LEDs[i], HIGH);

    Serial.println(progNo); // Print only if the program number is different
    
}

Just idle speculation:

DIY or load a button library (there are several in the IDE libraries) which offers a long press/short press feature.  A regular (short) press will cycle through the 0-7 options.  Let's arbitrarily choose the right switch to activate the manual mode on a long press and deactivate manual mode on a left switch long press - and return to the 0-7 mode.  If desired, one could even remember which 0-7 preset was active and restore it when exiting manual mode.

1 Like

I'll try this tonight, thank you!

then your buttons are not NC

Yeah sorry I edited my reply after I realised i’d made a mistake this morning, they’re normally open

#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

const byte LEDs[] = { 15, 14, 16, 10, 9, 8, 7, 6};

void setup() {
  Serial.begin(9600);
  MIDI.begin();
  MIDI.setInputChannel(1);
  pinMode(2, INPUT_PULLUP);// enable pull up
  pinMode(3, INPUT_PULLUP);
  for (byte i = 0; i < 8; i++)pinMode(LEDs[i], OUTPUT);
}

void loop() {
  static int progNo = 0;
  static bool upNow, downNow = false;
  upNow = digitalRead(2) == LOW;       //Switches are NO
  downNow = digitalRead(3) == LOW;

  // Check if both up and down buttons are pressed
  if (upNow  && downNow ) {
    progNo = 127; // Set to preset 127
    MIDI.sendProgramChange(byte(progNo), 1);
    delay(1000); // not a Debounce delay
  } else {
    // Check individual button presses
    if (upNow ) {
      progNo++; // Increment program change
      if (progNo > 7) progNo = 0; // Wrap around to 0
      MIDI.sendProgramChange(byte(progNo), 1);
      delay(100);
    }

    if (downNow ) {
      progNo--; // Decrement program change
      if (progNo < 0) progNo = 7; // Wrap around to 7
      MIDI.sendProgramChange(byte(progNo), 1);
      delay(100);
    }
  }
    for (byte i = 0; i < 8; i++)if (progNo != i)digitalWrite(LEDs[i], LOW); else digitalWrite(LEDs[i], HIGH);
}
1 Like

That's basically it! thank you very much for your help

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.