Go Down

Topic: USB Midi Foot Controller Help (Read 2771 times) previous topic - next topic

PieterP

#30
Aug 04, 2020, 10:28 am Last Edit: Aug 04, 2020, 10:29 am by PieterP
what I want my pedal project to do is:
7 switches each with own led. leds to light on/off depending if the switch is on/off.
Have 6 of those switches bankable.
Have 1 expression pedal.
Be USB
The following code is for 4 momentary push buttons that send MIDI Control Change events when pressed. They are latched in software, so if you press them once, they send an "on" message, and when you press them a second time, they send an "off" message.
The controller numbers of the buttons can be changed using banks. The active bank is selected using two push buttons (up and down), you can use other kinds of selectors as well.
The LEDs reflect the state of the buttons.
Code: [Select]
#include <Control_Surface.h> // Include the Control Surface library
 
// Instantiate a MIDI over USB interface
USBMIDI_Interface midi;
 
// Instantiate four Banks, with eight tracks per bank.
Bank<4> bank(8);
//   │       └───── number of tracks per bank
//   └───────────── number of banks
 
// Instantiate a Bank selector to control which one of the four Banks is active.
IncrementDecrementSelector<4> selector = {
    bank,       // Bank to manage
    {2, 3},     // Push button pins (increment, decrement)
    Wrap::Wrap, // Wrap around
};

// Instantiate an array of latched push buttons that send MIDI CC messages
// when pressed.
Bankable::CCButtonLatched<4> buttons[] {
  { bank, 4, 0x10 },
  //  │   │    └──── Base MIDI CC controller number
  //  │   └───────── Button pin number
  //  └───────────── Bank that changes the controller number
  { bank, 5, 0x11 },
  { bank, 6, 0x12 },
  { bank, 7, 0x13 },
};

// The bank controls the offset of the controller number relative to the
// button's base address. The amount of offset depends on the "number of
// tracks per bank" argument used when creating the bank. In this case,
// it's 8 tracks per bank, so for every bank you go up, 8 is added to the
// controller number of each button:
//
//         │  Button 1  │  Button 2  │  Button 3  │  Button 4  │  Offset
// ────────┼────────────┼────────────┼────────────┼────────────┤
// Bank 1  │    0x10    │    0x11    │    0x12    │    0x13    │  0×8=0
// Bank 2  │    0x18    │    0x19    │    0x1A    │    0x1B    │  1×8=8
// Bank 3  │    0x20    │    0x21    │    0x22    │    0x23    │  2×8=16
// Bank 4  │    0x28    │    0x29    │    0x2A    │    0x2B    │  3×8=24

// The array of pin numbers for LEDs that display the states of the buttons.
const pin_t ledPins[] = { 10, 11, 12, 13 };

// Get the length of an array
template <class T, size_t N> constexpr size_t length(T (&)[N]) { return N; }

static_assert(length(buttons) == length(ledPins),
              "Error: requires same number of buttons as LEDs");

void setup() {
  Control_Surface.begin();  // Initialize the Control Surface
  for (auto pin : ledPins)  // Set the pinMode to output for all LEDs
      pinMode(pin, OUTPUT);
}

void loop() {
  Control_Surface.loop();  // Update the Control Surface

  // Loop over all buttons and LEDs
  for (size_t i = 0; i < length(buttons); ++i)
      // Update the LED states to reflect the toggled switch states
      digitalWrite(ledPins[i], buttons[i].getState() ? HIGH : LOW);
}


If you want the LEDs to reflect the state by the software or device you're talking to, you can use the CCValueLED. It listens for incoming MIDI CC messages. This only works if the software/device sends feedback, of course.

The code is even simpler than the previous one:
Code: [Select]
#include <Control_Surface.h> // Include the Control Surface library
 
// Instantiate a MIDI over USB interface
USBMIDI_Interface midi;
 
// Instantiate four Banks, with eight tracks per bank.
Bank<4> bank(8);
//   │       └───── number of tracks per bank
//   └───────────── number of banks
 
// Instantiate a Bank selector to control which one of the four Banks is active.
IncrementDecrementSelector<4> selector = {
    bank,       // Bank to manage
    {2, 3},     // Push button pins (increment, decrement)
    Wrap::Wrap, // Wrap around
};

// Instantiate an array of latched push buttons that send MIDI CC messages
// when pressed.
Bankable::CCButtonLatched<4> buttons[] {
  { bank, 4, 0x10 },
  //  │   │    └──── Base MIDI CC controller number
  //  │   └───────── Button pin number
  //  └───────────── Bank that changes the controller number
  { bank, 5, 0x11 },
  { bank, 6, 0x12 },
  { bank, 7, 0x13 },
};

// The bank controls the offset of the controller number relative to the
// button's base address. The amount of offset depends on the "number of
// tracks per bank" argument used when creating the bank. In this case,
// it's 8 tracks per bank, so for every bank you go up, 8 is added to the
// controller number of each button:
//
//         │  Button 1  │  Button 2  │  Button 3  │  Button 4  │  Offset
// ────────┼────────────┼────────────┼────────────┼────────────┤
// Bank 1  │    0x10    │    0x11    │    0x12    │    0x13    │  0×8=0
// Bank 2  │    0x18    │    0x19    │    0x1A    │    0x1B    │  1×8=8
// Bank 3  │    0x20    │    0x21    │    0x22    │    0x23    │  2×8=16
// Bank 4  │    0x28    │    0x29    │    0x2A    │    0x2B    │  3×8=24

// Instantiate an array of LEDs that listen for incoming MIDI CC messages
// and displays their values.
Bankable::CCValueLED<4>leds[] {
  { bank, 10, 0x10 },
  //  │    │    └──── Base MIDI CC controller number
  //  │    └───────── LED pin number
  //  └────────────── Bank that changes the controller number
  { bank, 11, 0x11 },
  { bank, 12, 0x12 },
  { bank, 13, 0x13 },
};

void setup() {
  Control_Surface.begin();  // Initialize the Control Surface
}

void loop() {
  Control_Surface.loop();  // Update the Control Surface
}


For the expression pedal, you can have a look at the Conrol-Change-Potentiometer.ino example.

I read that I would need the midiusb control surface library, correct?
Correct, Control Surface uses MIDIUSB as a backend for most Arduino boards.

IN re: the LEDs.. look at the examples in the "MIDI-Callback" section if you wanna do this ~correctly~.
IN re: the LEDS.. if you want it to reflect the STATE of a condition in your DAW.. you gotta get into callbacks.
Not necessarily, Control Surface comes with many classes that automatically listen for MIDI input, see the full list of MIDI Input Elements.

If these classes don't suit your needs, you can use MIDI callbacks instead. They're the most flexible approach, because they allow you to interact with the incoming MIDI messages directly, but that requires a bit more programming, of course.

When beginners talk about the void function they normally mean the loop function. But any function can be a void function. If your YouTube person  didn't make that clear that marks him out as a beginner himself, so he might have made other mistakes.
You want to do this as often as possible so you put it at the very beginning of the void function.
?

Pieter

NervusTwitch

The following code is for 4 momentary push buttons that send MIDI Control Change events when pressed. They are latched in software, so if you press them once, they send an "on" message, and when you press them a second time, they send an "off" message.
The controller numbers of the buttons can be changed using banks. The active bank is selected using two push buttons (up and down), you can use other kinds of selectors as well.
The LEDs reflect the state of the buttons.
Code: [Select]
#include <Control_Surface.h> // Include the Control Surface library
 
// Instantiate a MIDI over USB interface
USBMIDI_Interface midi;
 
// Instantiate four Banks, with eight tracks per bank.
Bank<4> bank(8);
//   │       └───── number of tracks per bank
//   └───────────── number of banks
 
// Instantiate a Bank selector to control which one of the four Banks is active.
IncrementDecrementSelector<4> selector = {
    bank,       // Bank to manage
    {2, 3},     // Push button pins (increment, decrement)
    Wrap::Wrap, // Wrap around
};

// Instantiate an array of latched push buttons that send MIDI CC messages
// when pressed.
Bankable::CCButtonLatched<4> buttons[] {
  { bank, 4, 0x10 },
  //  │   │    └──── Base MIDI CC controller number
  //  │   └───────── Button pin number
  //  └───────────── Bank that changes the controller number
  { bank, 5, 0x11 },
  { bank, 6, 0x12 },
  { bank, 7, 0x13 },
};

// The bank controls the offset of the controller number relative to the
// button's base address. The amount of offset depends on the "number of
// tracks per bank" argument used when creating the bank. In this case,
// it's 8 tracks per bank, so for every bank you go up, 8 is added to the
// controller number of each button:
//
//         │  Button 1  │  Button 2  │  Button 3  │  Button 4  │  Offset
// ────────┼────────────┼────────────┼────────────┼────────────┤
// Bank 1  │    0x10    │    0x11    │    0x12    │    0x13    │  0×8=0
// Bank 2  │    0x18    │    0x19    │    0x1A    │    0x1B    │  1×8=8
// Bank 3  │    0x20    │    0x21    │    0x22    │    0x23    │  2×8=16
// Bank 4  │    0x28    │    0x29    │    0x2A    │    0x2B    │  3×8=24

// The array of pin numbers for LEDs that display the states of the buttons.
const pin_t ledPins[] = { 10, 11, 12, 13 };

// Get the length of an array
template <class T, size_t N> constexpr size_t length(T (&)[N]) { return N; }

static_assert(length(buttons) == length(ledPins),
              "Error: requires same number of buttons as LEDs");

void setup() {
  Control_Surface.begin();  // Initialize the Control Surface
  for (auto pin : ledPins)  // Set the pinMode to output for all LEDs
      pinMode(pin, OUTPUT);
}

void loop() {
  Control_Surface.loop();  // Update the Control Surface

  // Loop over all buttons and LEDs
  for (size_t i = 0; i < length(buttons); ++i)
      // Update the LED states to reflect the toggled switch states
      digitalWrite(ledPins[i], buttons[i].getState() ? HIGH : LOW);
}


If you want the LEDs to reflect the state by the software or device you're talking to, you can use the CCValueLED. It listens for incoming MIDI CC messages. This only works if the software/device sends feedback, of course.

The code is even simpler than the previous one:
Code: [Select]
#include <Control_Surface.h> // Include the Control Surface library
 
// Instantiate a MIDI over USB interface
USBMIDI_Interface midi;
 
// Instantiate four Banks, with eight tracks per bank.
Bank<4> bank(8);
//   │       └───── number of tracks per bank
//   └───────────── number of banks
 
// Instantiate a Bank selector to control which one of the four Banks is active.
IncrementDecrementSelector<4> selector = {
    bank,       // Bank to manage
    {2, 3},     // Push button pins (increment, decrement)
    Wrap::Wrap, // Wrap around
};

// Instantiate an array of latched push buttons that send MIDI CC messages
// when pressed.
Bankable::CCButtonLatched<4> buttons[] {
  { bank, 4, 0x10 },
  //  │   │    └──── Base MIDI CC controller number
  //  │   └───────── Button pin number
  //  └───────────── Bank that changes the controller number
  { bank, 5, 0x11 },
  { bank, 6, 0x12 },
  { bank, 7, 0x13 },
};

// The bank controls the offset of the controller number relative to the
// button's base address. The amount of offset depends on the "number of
// tracks per bank" argument used when creating the bank. In this case,
// it's 8 tracks per bank, so for every bank you go up, 8 is added to the
// controller number of each button:
//
//         │  Button 1  │  Button 2  │  Button 3  │  Button 4  │  Offset
// ────────┼────────────┼────────────┼────────────┼────────────┤
// Bank 1  │    0x10    │    0x11    │    0x12    │    0x13    │  0×8=0
// Bank 2  │    0x18    │    0x19    │    0x1A    │    0x1B    │  1×8=8
// Bank 3  │    0x20    │    0x21    │    0x22    │    0x23    │  2×8=16
// Bank 4  │    0x28    │    0x29    │    0x2A    │    0x2B    │  3×8=24

// Instantiate an array of LEDs that listen for incoming MIDI CC messages
// and displays their values.
Bankable::CCValueLED<4>leds[] {
  { bank, 10, 0x10 },
  //  │    │    └──── Base MIDI CC controller number
  //  │    └───────── LED pin number
  //  └────────────── Bank that changes the controller number
  { bank, 11, 0x11 },
  { bank, 12, 0x12 },
  { bank, 13, 0x13 },
};

void setup() {
  Control_Surface.begin();  // Initialize the Control Surface
}

void loop() {
  Control_Surface.loop();  // Update the Control Surface
}


For the expression pedal, you can have a look at the Conrol-Change-Potentiometer.ino example.
Correct, Control Surface uses MIDIUSB as a backend for most Arduino boards.
Not necessarily, Control Surface comes with many classes that automatically listen for MIDI input, see the full list of MIDI Input Elements.

If these classes don't suit your needs, you can use MIDI callbacks instead. They're the most flexible approach, because they allow you to interact with the incoming MIDI messages directly, but that requires a bit more programming, of course.
?

Pieter
Thank you for all that information. That has cleared up some things for me, I think. I'll find out when I try using the info.

NervusTwitch

Void is simply telling the compiler that this function returns no values. When beginners talk about the void function they normally mean the loop function. But any function can be a void function. If your YouTube person  didn't make that clear that marks him out as a beginner himself, so he might have made other mistakes.
He may have made that clear I kinda glanced thru a couple videos. He seemed to make things fairly clear.

If your interested in knowing if he really knows this stuff here is a link. He has many vids. His name is Paul McWhorter

https://www.youtube.com/watch?v=fJWR7dBuc18

NervusTwitch

OK I have the switches and exp pedal working perfect.
I tried the leds and got nothing but a ton of errors when compiling the code.
I also opted to not do banks since it wasnt really needed for my needs but I did add another switch and led in its place.
Also when using this code with my amp sim I have to go into the program and manually set to latching, problem is  3-4 of the settings do not allow me to set them for latching.
I didnt really understand your examples of the leds or how to make latching especially since I decided to not use banks.

Heres the code, I know I messed it up just not understanding. As mentioned in previous replies, this is my 1st time to try coding.

Code: [Select]
// midi.controller  for 7 switch DAW control
// by Cameron @the.nw.enterprise, http://thenorthwestenterprise.com/
// Library Source https://github.com/tttapa/Control-Surface
// Dependency library maybe should also be installed: https://github.com/PaulStoffregen/Encoder
// Written for PRO MICRO

#include <Encoder.h>
#include <Control_Surface.h> // Include the library


// Instantiate a MIDI interface
USBMIDI_Interface midi; // uncomment for native MIDI over USB

/*Instantiate CCbuttons
Will fire 127 on press and 0 on release. Use a momentary switch, like the others.
Assign CC number from here:
https://tttapa.github.io/Control-Surface-doc/Doxygen/d4/dbe/namespaceMIDI__CC.html
https://www.midi.org/specifications-old/item/table-3-control-change-messages-data-bytes-2
*/

CCButton button9 = {0, {MIDI_CC::Sound_Controller_8, CHANNEL_1},};  //switch  CC#77
CCButton button10 = {1, {MIDI_CC::Sound_Controller_9, CHANNEL_1},};  //switch  CC#78
CCButton button2 = {2, {MIDI_CC::Sound_Controller_1, CHANNEL_1},};  //switch  CC#70
CCButton button3 = {3, {MIDI_CC::Sound_Controller_2, CHANNEL_1},};  //switch  CC#71
CCButton button4 = {4, {MIDI_CC::Sound_Controller_3, CHANNEL_1},};  //switch  CC#72
CCButton button5 = {5, {MIDI_CC::Sound_Controller_4, CHANNEL_1},};  //switch  CC#73
CCButton button6 = {6, {MIDI_CC::Sound_Controller_5, CHANNEL_1},};  //switch  CC#74
CCButton button7 = {7, {MIDI_CC::Sound_Controller_6, CHANNEL_1},};  //switch  CC#75
CCButton button8 = {8, {MIDI_CC::Sound_Controller_7, CHANNEL_1},};  //switch  CC#76



// Setup for an Analog pot for an EXP pedal on cc #11
CCPotentiometer potentiometer = {
  A3, {MIDI_CC::Expression_Controller, CHANNEL_1}
};

const pin_t ledPins[] = { 9, 10, 16, 14, 15, 18, 19, 20 };

 
// Get the length of an array
template <class T, size_t N> constexpr size_t length(T (&)[N]) { return N; }

static_assert(length(8) == length(8),
              "Error: requires same number of buttons as LEDs");

void setup() {
  Control_Surface.begin();  // Initialize the Control Surface
  for (auto pin : ledPins)  // Set the pinMode to output for all LEDs
      pinMode(pin, OUTPUT);
}

void loop() {
  Control_Surface.loop();  // Update the Control Surface

  // Loop over all buttons and LEDs
  for (size_t i = 0; i < length(8); ++i)
      // Update the LED states to reflect the toggled switch states
      digitalWrite(ledPins[i], buttons[i].getState() ? HIGH : LOW);
}

PieterP

#34
Aug 05, 2020, 11:50 am Last Edit: Aug 05, 2020, 11:52 am by PieterP
Why did you get rid of the "buttons" array? The rest of the code relies on the array existing.

The "length" function returns the length of an array, so
Code: [Select]
static_assert(length(8) == length(8)) doesn't make any sense, because "8" is an integer, not an array. The goal of the assertion is to check that the number of buttons is the same as the number of LEDs, otherwise, the code below could access out of bounds of one of the arrays.

The CCButton class doesn't latch the switch state, so it doesn't have a "getState" method, it only has a "getButtonState" method, which returns either Falling, Pressed, Rising, Released.

Also when using this code with my amp sim I have to go into the program and manually set to latching, problem is  3-4 of the settings do not allow me to set them for latching.
Are you using CCButton or CCButtonLatched? CCButton sends the state of input pin directly. CCButtonLatched latches the input: press once to send "on" message (release does nothing), press a second time to send "off" message (release does nothing).
It sounds to me like you need CCButtonLatched, not CCButton.

I didnt really understand your examples of the leds or how to make latching especially since I decided to not use banks.
If you don't want to use banks, just remove the "Bankable::", the number of banks, and the "bank" argument from the buttons:
Code: [Select]
#include <Control_Surface.h> // Include the Control Surface library
 
// Instantiate a MIDI over USB interface
USBMIDI_Interface midi;

// Instantiate an array of latched push buttons that send MIDI CC messages
// when pressed.
CCButtonLatched buttons[] {
  {  4, 0x10 },
  // │    └──── MIDI CC controller number
  // └───────── Button pin number
  { 5, 0x11 },
  { 6, 0x12 },
  { 7, 0x13 },
};

// The array of pin numbers for LEDs that display the states of the buttons.
const pin_t ledPins[] = { 10, 11, 12, 13 };

// Get the length of an array
template <class T, size_t N> constexpr size_t length(T (&)[N]) { return N; }

static_assert(length(buttons) == length(ledPins),
              "Error: requires same number of buttons as LEDs");

void setup() {
  Control_Surface.begin();  // Initialize the Control Surface
  for (auto pin : ledPins)  // Set the pinMode to output for all LEDs
      pinMode(pin, OUTPUT);
}

void loop() {
  Control_Surface.loop();  // Update the Control Surface

  // Loop over all buttons and LEDs
  for (size_t i = 0; i < length(buttons); ++i)
      // Update the LED states to reflect the toggled switch states
      digitalWrite(ledPins[i], buttons[i].getState() ? HIGH : LOW);
}

NervusTwitch

Why did you get rid of the "buttons" array? The rest of the code relies on the array existing.


I see, I didnt understand the buttons array. I was looking at your whole example differently than meant.
Like I said total new guy at this,never touched code in my life.

So I would add the buttons array(your entire code) to my already existing code I have working? But remove the word bankable.
 My Current:

Code: [Select]
// midi.controller  for 7 switch DAW control
// by Cameron @the.nw.enterprise, http://thenorthwestenterprise.com/
// Library Source https://github.com/tttapa/Control-Surface
// Dependency library maybe should also be installed: https://github.com/PaulStoffregen/Encoder
// Written for PRO MICRO

#include <Control_Surface.h> // Include the library

// Instantiate a MIDI interface
//USBDebugMIDI_Interface usbmidi(115200); // uncomment this for serial monitor in ide
//HardwareSerialMIDI_Interface serialmidi = {Serial, MIDI_BAUD}; //uncomment this for 5-pin operation- this sends on TX
USBMIDI_Interface midi; // uncomment for native MIDI over USB
//HairlessMIDI_Interface hair (); // uncomment this for Hairless

/*Instantiate CCbuttons
Will fire 127 on press and 0 on release. Use a momentary switch, like the others.
Assign CC number from here:
https://tttapa.github.io/Control-Surface-doc/Doxygen/d4/dbe/namespaceMIDI__CC.html
https://www.midi.org/specifications-old/item/table-3-control-change-messages-data-bytes-2
*/

CCButton button2 = {2, {MIDI_CC::Sound_Controller_1, CHANNEL_1},};  //switch  CC#70
CCButton button3 = {3, {MIDI_CC::Sound_Controller_2, CHANNEL_1},};  //switch  CC#71
CCButton button4 = {4, {MIDI_CC::Sound_Controller_3, CHANNEL_1},};  //switch  CC#72
CCButton button5 = {5, {MIDI_CC::Sound_Controller_4, CHANNEL_1},};  //switch  CC#73
CCButton button6 = {6, {MIDI_CC::Sound_Controller_5, CHANNEL_1},};  //switch  CC#74
CCButton button7 = {7, {MIDI_CC::Sound_Controller_6, CHANNEL_1},};  //switch  CC#75
CCButton button8 = {8, {MIDI_CC::Sound_Controller_7, CHANNEL_1},};  //switch  CC#76


// Setup for an Analog pot for an EXP pedal on cc #11
CCPotentiometer potentiometer = {
  A0, {MIDI_CC::Expression_Controller, CHANNEL_1}
};


void setup() {
Control_Surface.begin(); // Initialize Control Surface
}

void loop() {
Control_Surface.loop(); // Update the Control Surface
}

NervusTwitch

Alright so I played with the code some more.
I have the buttons working correct and expression pedal.

But adding the leds like I thought you said in your last reply breaks the code when compiling.

It works until I add everything after "CCPtotntiometer". This section Im having a hard time understanding, so Im a bit lost there. I starting to understand more just those led sections.

Code: [Select]
#include <Encoder.h>
#include <Control_Surface.h> // Include the Control Surface library
 
// Instantiate a MIDI over USB interface
USBMIDI_Interface midi;
 
// Instantiate four Banks, with eight tracks per bank.

//   │       └───── number of tracks per bank
//   └───────────── number of banks
 
// Instantiate a Bank selector to control which one of the four Banks is active.


// Instantiate an array of latched push buttons that send MIDI CC messages
// when pressed.
CCButtonLatched buttons[] {
  { 4, 0x10 },
  //  │   │    └──── Base MIDI CC controller number
  //  │   └───────── Button pin number
  //  └───────────── Bank that changes the controller number
  { 1, 0x11 },
  { 0, 0x12 },
  { 2, 0x13 },
  { 3, 0x14 },
  { 4, 0x15 },
  { 5, 0x16 },
  { 6, 0x17 },
  { 7, 0x18 },
 
};

// The bank controls the offset of the controller number relative to the
// button's base address. The amount of offset depends on the "number of
// tracks per bank" argument used when creating the bank. In this case,
// it's 8 tracks per bank, so for every bank you go up, 8 is added to the
// controller number of each button:
//
//         │  Button 1  │  Button 2  │  Button 3  │  Button 4  │  Offset
// ────────┼────────────┼────────────┼────────────┼────────────┤
// Bank 1  │    0x10    │    0x11    │    0x12    │    0x13    │  0×8=0
// Bank 2  │    0x18    │    0x19    │    0x1A    │    0x1B    │  1×8=8
// Bank 3  │    0x20    │    0x21    │    0x22    │    0x23    │  2×8=16
// Bank 4  │    0x28    │    0x29    │    0x2A    │    0x2B    │  3×8=24

// Instantiate an array of LEDs that listen for incoming MIDI CC messages
// and displays their values.
CCValueLED leds[] {
  { 10, 0x10 },
  //  │    │    └──── Base MIDI CC controller number
  //  │    └───────── LED pin number
  //  └────────────── Bank that changes the controller number
  { 9, 0x10 },
  { 10, 0x11 },
  { 16, 0x12 },
  { 14, 0x13 },
  { 15, 0x14 },
  { 18, 0x15 },
  { 19, 0x16 },
  { 20, 0x17 },
 
 
};


// Setup for an Analog pot for an EXP pedal on cc #11
CCPotentiometer potentiometer = {
  A3, {MIDI_CC::Expression_Controller, CHANNEL_1}
};


// The array of pin numbers for LEDs that display the states of the buttons.
const pin_t ledPins[] = { 9, 10, 16, 14, 15, 18, 19, 20 };

// Get the length of an array
template <class T, size_t N> constexpr size_t length(T (&)[N]) { return N; }

static_assert(length(buttons) == length(ledPins),
              "Error: requires same number of buttons as LEDs");

void setup() {
  Control_Surface.begin();  // Initialize the Control Surface
  for (auto pin : ledPins)  // Set the pinMode to output for all LEDs
      pinMode(pin, OUTPUT);
}

void loop() {
  Control_Surface.loop();  // Update the Control Surface

  // Loop over all buttons and LEDs
  for (size_t i = 0; i < length(buttons); ++i)
      // Update the LED states to reflect the toggled switch states
      digitalWrite(ledPins[i], buttons[i].getState() ? HIGH : LOW);
}

PieterP

You seem very confused, I'd recommend taking a step back and starting with a simple sketch.
Don't start throwing different components together until you understand how each component works separately.
Feel free to ask specific questions about the parts you don't understand.

The two code blocks I posted in reply #30 are two separate programs/sketches.
The first one uses the LEDs to display the state of the latched buttons.
The second one listens for incoming MIDI messages and displays the value of these messages to the LEDs.
You cannot do both at once, so you'll have to choose one.

NervusTwitch

You seem very confused, I'd recommend taking a step back and starting with a simple sketch.
Don't start throwing different components together until you understand how each component works separately.
Feel free to ask specific questions about the parts you don't understand.

The two code blocks I posted in reply #30 are two separate programs/sketches.
The first one uses the LEDs to display the state of the latched buttons.
The second one listens for incoming MIDI messages and displays the value of these messages to the LEDs.
You cannot do both at once, so you'll have to choose one.
Did not realise I used both.
I have 8 momentary switches each with an LED. I just want to show the state of the latched button.Plus I have the expression pedal,no led.
The button pins

Using your code and deleting the banks in the code everything but led's function.

So where I have the list of CCbuttonLatched and CCValueLeds, did I do that part correct?
If so then the corrections need to be made here?

Code: [Select]
// The array of pin numbers for LEDs that display the states of the buttons.
const pin_t ledPins[] = { 9, 10, 16, 14, 15, 18, 19, 20 };

// Get the length of an array
template <class T, size_t N> constexpr size_t length(T (&)[N]) { return N; }

static_assert(length(buttons) == length(ledPins),
              "Error: requires same number of buttons as LEDs");

void setup() {
  Control_Surface.begin();  // Initialize the Control Surface
  for (auto pin : ledPins)  // Set the pinMode to output for all LEDs
      pinMode(pin, OUTPUT);
}

void loop() {
  Control_Surface.loop();  // Update the Control Surface

  // Loop over all buttons and LEDs
  for (size_t i = 0; i < length(buttons); ++i)
      // Update the LED states to reflect the toggled switch states
      digitalWrite(ledPins[i], buttons[i].getState() ? HIGH : LOW);
}


I'm assuming this is the bad section...? Just need to learn where I made the mistakes,its how I learn.

Code: [Select]
// The array of pin numbers for LEDs that display the states of the buttons.
const pin_t ledPins[] = { 9, 10, 16, 14, 15, 18, 19, 20 };


I do appreciate all the help, Thank you.

NervusTwitch

Played with the code some more. No errors, but also no LED's. All the switches work though.

Code: [Select]
#include <Encoder.h>
#include <Control_Surface.h> // Include the Control Surface library
 
// Instantiate a MIDI over USB interface
USBMIDI_Interface midi;
 
// Instantiate four Banks, with eight tracks per bank.

//   │       └───── number of tracks per bank
//   └───────────── number of banks
 
// Instantiate a Bank selector to control which one of the four Banks is active.


// Instantiate an array of latched push buttons that send MIDI CC messages
// when pressed.
CCButtonLatched buttons[] {
  { 4, 0x10 },
  //  │   │    └──── Base MIDI CC controller number
  //  │   └───────── Button pin number
  //  └───────────── Bank that changes the controller number
  { 1, 0x11 },
  { 0, 0x12 },
  { 2, 0x13 },
  { 3, 0x14 },
  { 4, 0x15 },
  { 5, 0x16 },
  { 6, 0x17 },
  { 7, 0x18 },
 
};

// The bank controls the offset of the controller number relative to the
// button's base address. The amount of offset depends on the "number of
// tracks per bank" argument used when creating the bank. In this case,
// it's 8 tracks per bank, so for every bank you go up, 8 is added to the
// controller number of each button:
//
//         │  Button 1  │  Button 2  │  Button 3  │  Button 4  │  Offset
// ────────┼────────────┼────────────┼────────────┼────────────┤
// Bank 1  │    0x10    │    0x11    │    0x12    │    0x13    │  0×8=0
// Bank 2  │    0x18    │    0x19    │    0x1A    │    0x1B    │  1×8=8
// Bank 3  │    0x20    │    0x21    │    0x22    │    0x23    │  2×8=16
// Bank 4  │    0x28    │    0x29    │    0x2A    │    0x2B    │  3×8=24




// Setup for an Analog pot for an EXP pedal on cc #11
CCPotentiometer potentiometer = {
  A3, {MIDI_CC::Expression_Controller, CHANNEL_1}
};


// Instantiate an array of LEDs that listen for incoming MIDI CC messages
// and displays their values.
CCValueLED leds[] {
  { 10, 0x10 },
  //  │    │    └──── Base MIDI CC controller number
  //  │    └───────── LED pin number
  //  └────────────── Bank that changes the controller number
  { 9, 0x11 },
  { 10, 0x12 },
  { 16, 0x13 },
  { 14, 0x14 },
  { 15, 0x15 },
  { 18, 0x16 },
  { 19, 0x17 },
  { 20, 0x18 },
};

void setup() {
  Control_Surface.begin();  // Initialize the Control Surface
}

void loop() {
  Control_Surface.loop();  // Update the Control Surface
}

PieterP

I have 8 momentary switches each with an LED. I just want to show the state of the latched button.Plus I have the expression pedal,no led.
Then you have to use the sketch without CCValueLED.
Like I said before, CCValueLED listens for incoming MIDI messages. It's meant to be used for DAWs that send MIDI feedback. If the LEDs aren't working with your code from reply #39, that probably means your DAW doesn't send any feedback.

Using your code and deleting the banks in the code everything but led's function.

So where I have the list of CCbuttonLatched and CCValueLeds, did I do that part correct?
If so then the corrections need to be made here?

Code: [Select]
// The array of pin numbers for LEDs that display the states of the buttons.
const pin_t ledPins[] = { 9, 10, 16, 14, 15, 18, 19, 20 };

// Get the length of an array
template <class T, size_t N> constexpr size_t length(T (&)[N]) { return N; }

static_assert(length(buttons) == length(ledPins),
              "Error: requires same number of buttons as LEDs");

void setup() {
  Control_Surface.begin();  // Initialize the Control Surface
  for (auto pin : ledPins)  // Set the pinMode to output for all LEDs
      pinMode(pin, OUTPUT);
}

void loop() {
  Control_Surface.loop();  // Update the Control Surface

  // Loop over all buttons and LEDs
  for (size_t i = 0; i < length(buttons); ++i)
      // Update the LED states to reflect the toggled switch states
      digitalWrite(ledPins[i], buttons[i].getState() ? HIGH : LOW);
}

I'm not sure what you mean, there's no array of CCButtonLatched or CCValueLED in that code.

I'm assuming this is the bad section...? Just need to learn where I made the mistakes,its how I learn.

Code: [Select]
// The array of pin numbers for LEDs that display the states of the buttons.
const pin_t ledPins[] = { 9, 10, 16, 14, 15, 18, 19, 20 };

Why? That's just an array declaration/initialization of some pin numbers, it doesn't do anything if you don't use it.

There's an important distinction:
Instantiating MIDI Elements (e.g. CCButton, CCValueLED, USBMIDI_Interface ...) has side effects. The Control Surface library will detect that you created them, and will initialize and update them for you when you call Control_Surface.begin() and Control_Surface.loop().
If you instantiate most other types (integers, pin_t, float ...), there are no side effects. If you instantiate them but don't use them, your code doesn't behave any differently than before you instantiated them.

I'll try to explain it from the beginning:

The most basic sketch uses just an array of CCButtonLatched. Control Surface will automatically initialize them for you, and then update them continuously in the loop. When it detects a button press, it sends a MIDI message.

If you want to add LEDs to display the state of these buttons, you have to add some code yourself:

1. You have to initialize the LED pins in the setup, set their pin states to OUTPUT mode.
Code: [Select]
 for (auto pin : ledPins)  // Set the pinMode to output for all LEDs
      pinMode(pin, OUTPUT);

2. You have to check the state of each button, and then update the LED state appropriately.
Code: [Select]
 // Loop over all buttons and LEDs
  for (size_t i = 0; i < length(buttons); ++i)
      // Update the LED states to reflect the toggled switch states
      digitalWrite(ledPins[i], buttons[i].getState() ? HIGH : LOW);


You should be able to understand at least these 4 lines of code before combining it with any other code.
Search terms: "C++ range based for loop", "Arduino pinMode", "C++ for loop", "Arduino digitalWrite", "C++ conditional operator", "C++ array"

NervusTwitch

Then you have to use the sketch without CCValueLED.
Like I said before, CCValueLED listens for incoming MIDI messages. It's meant to be used for DAWs that send MIDI feedback. If the LEDs aren't working with your code from reply #39, that probably means your DAW doesn't send any feedback.
I'm not sure what you mean, there's no array of CCButtonLatched or CCValueLED in that code.
Why? That's just an array declaration/initialization of some pin numbers, it doesn't do anything if you don't use it.

Sorry I post the wrong section of code for the question.
I had the leds setup with the CCValue also in this code but removed that part.

Code: [Select]
/*Instantiate CCbuttons
Will fire 127 on press and 0 on release. Use a momentary switch, like the others.
Assign CC number from here:
https://tttapa.github.io/Control-Surface-doc/Doxygen/d4/dbe/namespaceMIDI__CC.html
https://www.midi.org/specifications-old/item/table-3-control-change-messages-data-bytes-2
*/

CCButton button9 = {0, {MIDI_CC::Sound_Controller_8, CHANNEL_1},};  //switch  CC#77
CCButton button10 = {1, {MIDI_CC::Sound_Controller_9, CHANNEL_1},};  //switch  CC#78
CCButton button2 = {2, {MIDI_CC::Sound_Controller_1, CHANNEL_1},};  //switch  CC#70
CCButton button3 = {3, {MIDI_CC::Sound_Controller_2, CHANNEL_1},};  //switch  CC#71
CCButton button4 = {4, {MIDI_CC::Sound_Controller_3, CHANNEL_1},};  //switch  CC#72
CCButton button5 = {5, {MIDI_CC::Sound_Controller_4, CHANNEL_1},};  //switch  CC#73
CCButton button6 = {6, {MIDI_CC::Sound_Controller_5, CHANNEL_1},};  //switch  CC#74
CCButton button7 = {7, {MIDI_CC::Sound_Controller_6, CHANNEL_1},};  //switch  CC#75
CCButton button8 = {8, {MIDI_CC::Sound_Controller_7, CHANNEL_1},};  //switch  CC#76



I'll work thru your last reply and try to get this learned. Believe I do try and search on the errors I get and such before replying back here. I'll get it.Im more the hardware side of things than software.

NervusTwitch

if it matters, I need to correct an earlier reply.

"I have 8 momentary switches each with an LED. I just want to show the state of the latched button.Plus I have the expression pedal,no led."

These are switches that do not have LED builtin, they are separate mounted LED's from the switches.

cameron206

FYI, I am really getting a lot out of this.
I never experimented with latchedCCbuttons... I had just been using actual latching switches :)


NervusTwitch

FYI, I am really getting a lot out of this.
I never experimented with latchedCCbuttons... I had just been using actual latching switches :)


Well glad Im some help.

Im still cant get the leds to work at all. Im thinking the code he made im not understanding at all about what to put where.
Buttons are pretty straight forward to me but not those LED's code.

Go Up