Code for MIDI Foot Controller won't compile [SOLVED]

Heyho! (Rookie here :X)

I built a generally simple MIDI foot controller with 15 switches in a 5x3 grid with a Teensy 3.6 at it's heart. The switches are meant to be momentary. I'm "just" a web developer, so C/C++ is a blackbox to me, especially in the Arduino environment.

By trying to keep the code relatively clean and tidy with a class, I get all sorts of errors which I can't solve by googling.

I'm using Arudino 1.8.9 on macOS High Sierra–

Now to the my code, lads and ladies!

#include <Bounce.h>

#include <MIDI.h>

MIDI_CREATE_INSTANCE(HardwareSerial, Serial4, MIDI);

const int ledPin = LED_BUILTIN; // 18;
const int debounceDelay = 25; // originally 25; // in ms
const int MIDIChannel = 1;

class Footswitch {
  private:
    byte pin;
    byte cc;
    Bounce switch;
  public:
    Footswitch(byte pin, byte cc, int debounceDelay) {
      this->pin = pin;
      this->cc = cc;
      this->switch = Bounce(pin, debounceDelay);
    }
    void check() {
      switch.update();
      if (this->switch.risingEdge()) {
        digitalWrite(ledPin, HIGH);
        usbMIDI.sendControlChange(this->cc, 127, MIDIChannel);
        MIDI.sendControlChange(this->cc, 127, MIDIChannel);
      }

      if (this->switch.fallingEdge()) {
        digitalWrite(ledPin, LOW);
        usbMIDI.sendControlChange(this->cc, 0, MIDIChannel);
        MIDI.sendControlChange(this->cc, 0, MIDIChannel);
      }
    }
};


Footswitch fsArray[5][3] = {
  {
    Footswitch(2, 42, debounceDelay),
    Footswitch(3, 43, debounceDelay),
    Footswitch(4, 44, debounceDelay),
  },
  {
    Footswitch(5, 45, debounceDelay),
    Footswitch(6, 46, debounceDelay),
    Footswitch(7, 47, debounceDelay),
  },
  {
    Footswitch(8, 48, debounceDelay),
    Footswitch(9, 49, debounceDelay),
    Footswitch(10, 50, debounceDelay),
  },
  {
    Footswitch(11, 51, debounceDelay),
    Footswitch(12, 52, debounceDelay),
    Footswitch(24, 54, debounceDelay),
  },
  {
    Footswitch(25, 55, debounceDelay),
    Footswitch(26, 56, debounceDelay),
    Footswitch(27, 57, debounceDelay),
  },
};


// the setup function runs once when you press reset or power the board
void setup() {
  
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(ledPin, OUTPUT);

  for (int i = 0; i <= 4; ++i) {
    for (int j = 0; j <= 2; ++j) {
      // example uses INPUT_PULLUP, which resulted in false presses in our case
      pinMode(fsArray[i][j].pin, INPUT);
    }
  }

  MIDI.begin(MIDI_CHANNEL_OMNI);
}

// the loop function runs over and over again forever
void loop() {

  for (int i = 0; i <= 4; ++i) {
    for (int j = 0; j <= 2; ++j) {
      fsArray[i][j].check();
    }
  }
 

  // debugging: does the teensy get power at all?
  // digitalWrite(ledPin, HIGH);

  // MIDI Controllers should discard incoming MIDI messages.
  while (usbMIDI.read()) {}
}

The main error I'm getting is the following:

/path/to/loop-midi-controller/loop-midi-controller.ino:21:12: error: expected unqualified-id before 'switch'
     Bounce switch;
            ^
/path/to/loop-midi-controller/loop-midi-controller.ino: In constructor 'Footswitch::Footswitch(byte, byte, int)':
/path/to/loop-midi-controller/loop-midi-controller.ino:26:13: error: expected unqualified-id before 'switch'
       this->switch = Bounce(pin, debounceDelay);
             ^
/path/to/loop-midi-controller/loop-midi-controller.ino: In member function 'void Footswitch::check()':
/path/to/loop-midi-controller/loop-midi-controller.ino:29:13: error: expected '(' before '.' token
       switch.update();
             ^
/path/to/loop-midi-controller/loop-midi-controller.ino:30:17: error: expected unqualified-id before 'switch'
       if (this->switch.risingEdge()) {
                 ^
/path/to/loop-midi-controller/loop-midi-controller.ino:30:17: error: expected ')' before 'switch'
/path/to/loop-midi-controller/loop-midi-controller.ino:36:17: error: expected unqualified-id before 'switch'
       if (this->switch.fallingEdge()) {
                 ^
/path/to/loop-midi-controller/loop-midi-controller.ino:36:17: error: expected ')' before 'switch'
/path/to/loop-midi-controller/loop-midi-controller.ino: In function 'void setup()':
/path/to/loop-midi-controller/loop-midi-controller.ino:19:10: error: 'byte Footswitch::pin' is private
     byte pin;
          ^
/path/to/loop-midi-controller/loop-midi-controller.ino:83:29: error: within this context
       pinMode(fsArray[i][j].pin, INPUT);
                             ^
Fehler beim Kompilieren für das Board Teensy 3.6.

From what I can tell and the test programs I wrote, where I only checked for one switch, every switch works as expected. The case is finished and polished, so the last thing that's standing between me and looping the hell out of my music setup, is the code for all switches.

Thanks for helping!

<3

Louis

By trying to keep the code relatively clean and tidy with a class, I get all sorts of errors which I can't solve by googling.

Please post the full error messages

as far as i can tell the error is here

class Footswitch {
  private:
    byte pin;
    byte cc;
    Bounce switch;

where the type 'Bounce' is not known to the compiler, all (or nearly all) other error follow from that, since then 'switch' has not been declared. I don't use the <bounce.h> library, in which i suspect 'Bounce' should have been defined, though it myabe possible that it should be 'bounce' instead. anyway the answer should lie within <bounce.h>

'switch' is a reserved keyword. Use a different name.

Thanks for your replies!

oqibidipo:
'switch' is a reserved keyword. Use a different name.

Oh boii, ur so right! The syntax highlighter also reflects that– could've paid more attention, thanks!

Unfortunately I'm still getting errors. I fear it might have to do with the bounce library :frowning:

Deva_Rishi:
as far as i can tell the error is here

class Footswitch {

private:
    byte pin;
    byte cc;
    Bounce switch;


where the type 'Bounce' is not known to the compiler, all (or nearly all) other error follow from that, since then 'switch' has not been declared. I don't use the <bounce.h> library, in which i suspect 'Bounce' should have been defined, though it myabe possible that it should be 'bounce' instead. anyway the answer should lie within <bounce.h>

I'm pretty sure uppercase "Bounce" should work. At least it did in my prototype code for just one switch (without the class, array and nested loops).

Here's the updated code with new errors:

#include <Bounce.h>

#include <MIDI.h>

MIDI_CREATE_INSTANCE(HardwareSerial, Serial4, MIDI);

const int ledPin = LED_BUILTIN; // 18;
const int debounceDelay = 25; // originally 25; // in ms
const int MIDIChannel = 1;

class Footswitch {
  private:
    byte pin;
    byte cc;
    Bounce bounceSwitch;
  public:
    Footswitch(byte pin, byte cc, int debounceDelay) {
      this->pin = pin;
      this->cc = cc;
      this->bounceSwitch = Bounce(pin, debounceDelay);
    }
    void check() {
      bounceSwitch.update();
      if (this->bounceSwitch.risingEdge()) {
        digitalWrite(ledPin, HIGH);
        usbMIDI.sendControlChange(this->cc, 127, MIDIChannel);
        MIDI.sendControlChange(this->cc, 127, MIDIChannel);
      }

      if (this->bounceSwitch.fallingEdge()) {
        digitalWrite(ledPin, LOW);
        usbMIDI.sendControlChange(this->cc, 0, MIDIChannel);
        MIDI.sendControlChange(this->cc, 0, MIDIChannel);
      }
    }
};


Footswitch fsArray[5][3] = {
  {
    Footswitch(2, 42, debounceDelay),
    Footswitch(3, 43, debounceDelay),
    Footswitch(4, 44, debounceDelay),
  },
  {
    Footswitch(5, 45, debounceDelay),
    Footswitch(6, 46, debounceDelay),
    Footswitch(7, 47, debounceDelay),
  },
  {
    Footswitch(8, 48, debounceDelay),
    Footswitch(9, 49, debounceDelay),
    Footswitch(10, 50, debounceDelay),
  },
  {
    Footswitch(11, 51, debounceDelay),
    Footswitch(12, 52, debounceDelay),
    Footswitch(24, 54, debounceDelay),
  },
  {
    Footswitch(25, 55, debounceDelay),
    Footswitch(26, 56, debounceDelay),
    Footswitch(27, 57, debounceDelay),
  },
};


// the setup function runs once when you press reset or power the board
void setup() {
  
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(ledPin, OUTPUT);

  for (int i = 0; i <= 4; ++i) {
    for (int j = 0; j <= 2; ++j) {
      // example uses INPUT_PULLUP, which resulted in false presses in our case
      pinMode(fsArray[i][j].pin, INPUT);
    }
  }

  MIDI.begin(MIDI_CHANNEL_OMNI);
}

// the loop function runs over and over again forever
void loop() {

  for (int i = 0; i <= 4; ++i) {
    for (int j = 0; j <= 2; ++j) {
      fsArray[i][j].check();
    }
  }

  // debugging: does the teensy get power at all?
  // digitalWrite(ledPin, HIGH);

  // MIDI Controllers should discard incoming MIDI messages.
  while (usbMIDI.read()) {}
}

errors:

Arduino: 1.8.9 (Mac OS X), TD: 1.47, Board: "Teensy 3.6, MIDI, 180 MHz, Faster, US English"

/path/to/loop-midi-controller/loop-midi-controller.ino: In constructor 'Footswitch::Footswitch(byte, byte, int)':
/path/to/loop-midi-controller/loop-midi-controller.ino:18:54: error: no matching function for call to 'Bounce::Bounce()'
     Footswitch(byte pin, byte cc, int debounceDelay) {
                                                      ^
In file included from /path/to/loop-midi-controller/loop-midi-controller.ino:2:0:
/Applications/Arduino/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Bounce/Bounce.h:38:3: note: candidate: Bounce::Bounce(uint8_t, long unsigned int)
   Bounce(uint8_t pin, unsigned long interval_millis ); 
   ^
/Applications/Arduino/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Bounce/Bounce.h:38:3: note:   candidate expects 2 arguments, 0 provided
/Applications/Arduino/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Bounce/Bounce.h:33:7: note: candidate: constexpr Bounce::Bounce(const Bounce&)
 class Bounce
       ^
/Applications/Arduino/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Bounce/Bounce.h:33:7: note:   candidate expects 1 argument, 0 provided
/Applications/Arduino/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Bounce/Bounce.h:33:7: note: candidate: constexpr Bounce::Bounce(Bounce&&)
/Applications/Arduino/Arduino.app/Contents/Java/hardware/teensy/avr/libraries/Bounce/Bounce.h:33:7: note:   candidate expects 1 argument, 0 provided
/path/to/loop-midi-controller/loop-midi-controller.ino: In function 'void setup()':
/path/to/loop-midi-controller/loop-midi-controller.ino:14:10: error: 'byte Footswitch::pin' is private
     byte pin;
          ^
/path/to/loop-midi-controller/loop-midi-controller.ino:78:29: error: within this context
       pinMode(fsArray[i][j].pin, INPUT);
                             ^
Fehler beim Kompilieren für das Board Teensy 3.6.

Dieser Bericht wäre detaillierter, wenn die Option
"Ausführliche Ausgabe während der Kompilierung"
in Datei -> Voreinstellungen aktiviert wäre.

I think the problem is that there is no "Bounce" constructor that takes no arguments. You can't construct the 'bounceSwitch' without arguments and replace it later. I think you need something strange on the constructor to provide the constructor arguments for member objects, like:

    Footswitch(byte pin, byte cc, int debounceDelay) : bounceSwitch(pin, debounceDelay)
   {
      this->pin = pin;
      this->cc = cc;
    }

I'm not at all sure of the correct syntax but it is something like that.

Guys! Thanks so much, I got it working now with your suggestions and hints!

Here's the final code :slight_smile:

#include <Bounce.h>

#include <MIDI.h>

MIDI_CREATE_INSTANCE(HardwareSerial, Serial4, MIDI);

const int ledPin = LED_BUILTIN; // 18;
const int debounceDelay = 25; // originally 25; // in ms
const int MIDIChannel = 1;

class Footswitch {
  private:
    byte pin;
    byte cc;
    Bounce bounceSwitch;
  public:
    Footswitch(byte pin, byte cc, int debounceDelay) : bounceSwitch(pin, debounceDelay) {
      this->pin = pin;
      this->cc = cc;
      //this->bounceSwitch = Bounce(pin, debounceDelay);
    }
    void check() {
      bounceSwitch.update();
      if (this->bounceSwitch.risingEdge()) {
        digitalWrite(ledPin, HIGH);
        usbMIDI.sendControlChange(this->cc, 127, MIDIChannel);
        MIDI.sendControlChange(this->cc, 127, MIDIChannel);
      }

      if (this->bounceSwitch.fallingEdge()) {
        digitalWrite(ledPin, LOW);
        usbMIDI.sendControlChange(this->cc, 0, MIDIChannel);
        MIDI.sendControlChange(this->cc, 0, MIDIChannel);
      }
    }

    byte getPin() {
      return this->pin;
    }
};

int MidiCC = 102;

Footswitch fsArray[5][3] = {
  {
    Footswitch(2, MidiCC++, debounceDelay),
    Footswitch(3, MidiCC++, debounceDelay),
    Footswitch(4, MidiCC++, debounceDelay),
  },
  {
    Footswitch(5, MidiCC++, debounceDelay),
    Footswitch(6, MidiCC++, debounceDelay),
    Footswitch(7, MidiCC++, debounceDelay),
  },
  {
    Footswitch(8, MidiCC++, debounceDelay),
    Footswitch(9, MidiCC++, debounceDelay),
    Footswitch(10, MidiCC++, debounceDelay),
  },
  {
    Footswitch(11, MidiCC++, debounceDelay),
    Footswitch(12, MidiCC++, debounceDelay),
    Footswitch(24, MidiCC++, debounceDelay),
  },
  {
    Footswitch(25, MidiCC++, debounceDelay),
    Footswitch(26, MidiCC++, debounceDelay),
    Footswitch(27, MidiCC++, debounceDelay),
  },
};


// the setup function runs once when you press reset or power the board
void setup() {
  
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(ledPin, OUTPUT);

  for (int i = 0; i <= 4; ++i) {
    for (int j = 0; j <= 2; ++j) {
      // example uses INPUT_PULLUP, which resulted in false presses in our case
      pinMode(fsArray[i][j].getPin(), INPUT);
    }
  }

  MIDI.begin(MIDI_CHANNEL_OMNI);
}

// the loop function runs over and over again forever
void loop() {

  for (int i = 0; i <= 4; ++i) {
    for (int j = 0; j <= 2; ++j) {
      fsArray[i][j].check();
    }
  }

  // debugging: does the teensy get power at all?
  // digitalWrite(ledPin, HIGH);

  // MIDI Controllers should discard incoming MIDI messages.
  while (usbMIDI.read()) {}
}