How to stop a message re-transmit?

Hi, I can not find another example to learn from.

I have a basic 1 button project that transmits 2 midi messages depending if the button is high or low. At the end of the loop, it then resends the midi message, overwhelming the device receiving the data.

So what I want to be able to do is for the arduino to only transmit the message once or twice and ONLY after the button state changes.

Is this possible?

Eventually I want to expand this to around 50 buttons.

TIA

Andy

#include <MIDI.h>
#include <midi_Defs.h>
#include <midi_Message.h>
#include <midi_Namespace.h>
#include <midi_Settings.h>

const int buttonOne = 6; // assign button pin to variable

MIDI_CREATE_INSTANCE(HardwareSerial,Serial, midiOut); // create a MIDI object called midiOut

void setup() {
  pinMode(buttonOne,INPUT); // setup button as input

  Serial.begin(31250); // setup MIDI output
}

void loop() {
  if(digitalRead(buttonOne) == HIGH) { // check button state
    delay(50); // software de-bounce
    if(digitalRead(buttonOne) == HIGH) { // check button state again
          midiOut.sendControlChange(56,127,1); // send a MIDI CC -- 56 = note, 127 = velocity, 1 = channel
        delay(20);
    }
  }

if(digitalRead(buttonOne) == LOW) { // check button state
    delay(50); // software de-bounce
    if(digitalRead(buttonOne) == LOW) { // check button state again
          midiOut.sendControlChange(56,0,1); // send a MIDI CC -- 56 = note, 127 = velocity, 1 = channel
      delay(20);
    }
  }

}

Look up state change detection here on the forum.

evanmars:
Look up state change detection here on the forum.

...or in the IDE's worked examples

Especially if you want to use a lot of buttons, it might be a good idea to use a library that handles debouncing and state change detection for you:

[color=#5e6d03]#include[/color] [color=#434f54]<[/color][b][color=#d35400]Control_Surface[/color][/b][color=#434f54].[/color][color=#000000]h[/color][color=#434f54]>[/color] [color=#434f54]// Include the Control Surface library    [/color]

[color=#434f54]// Instantiate a MIDI over USB interface[/color]
[b][color=#d35400]USBMIDI_Interface[/color][/b] [color=#00979c]midi[/color][color=#000000];[/color]

[color=#434f54]// Instantiate a CCButton object that sends MIDI CC events when the[/color]
[color=#434f54]// state of the button changes[/color]
[b][color=#d35400]CCButton[/color][/b] [color=#000000]button[/color] [color=#434f54]=[/color] [color=#000000]{[/color]
  [color=#000000]6[/color][color=#434f54],[/color]               [color=#434f54]// Push button on pin 6[/color]
  [color=#000000]{[/color][color=#000000]56[/color][color=#434f54],[/color] [color=#00979c]CHANNEL_1[/color][color=#000000]}[/color][color=#434f54],[/color] [color=#434f54]// Controller #56 on MIDI channel 1[/color]
[color=#000000]}[/color][color=#000000];[/color]

[color=#00979c]void[/color] [color=#5e6d03]setup[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Control_Surface[/color][/b][color=#434f54].[/color][color=#d35400]begin[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color] [color=#434f54]// Initialize Control Surface[/color]
[color=#000000]}[/color]

[color=#00979c]void[/color] [color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Control_Surface[/color][/b][color=#434f54].[/color][color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color] [color=#434f54]// Update the Control Surface[/color]
[color=#000000]}[/color]

The sketch above uses the Control Surface library I'm working on.

  • When the button on pin 6 is pressed, a MIDI Control Change message with a value of 0x7F (127) is sent for Controller #56.
  • When the button on pin 6 is released, a MIDI Control Change message with a value of 0x00 (0) is sent for Controller #56.
    If you want more than one button, use an array:
[b][color=#d35400]CCButton[/color][/b] [color=#000000]buttons[/color][color=#000000][[/color][color=#000000]][/color] [color=#434f54]=[/color] [color=#000000]{[/color]
  [color=#000000]{[/color][color=#000000]6[/color][color=#434f54],[/color] [color=#000000]{[/color][color=#000000]56[/color][color=#434f54],[/color] [color=#00979c]CHANNEL_1[/color][color=#000000]}[/color][color=#000000]}[/color][color=#434f54],[/color]
  [color=#000000]{[/color][color=#000000]7[/color][color=#434f54],[/color] [color=#000000]{[/color][color=#000000]57[/color][color=#434f54],[/color] [color=#00979c]CHANNEL_1[/color][color=#000000]}[/color][color=#000000]}[/color][color=#434f54],[/color]
  [color=#000000]{[/color][color=#000000]8[/color][color=#434f54],[/color] [color=#000000]{[/color][color=#000000]58[/color][color=#434f54],[/color] [color=#00979c]CHANNEL_1[/color][color=#000000]}[/color][color=#000000]}[/color][color=#434f54],[/color]
  [color=#434f54]// etc.[/color]
[color=#000000]}[/color][color=#000000];[/color]

If you need more buttons than you have pins, you can use multiplexers, or create a scanning matrix. Both options are supported by the library.

Pieter

Thank you Pieter, that's very helpful.

Although I am having as issue changing from USB to HardwareSerialMIDI_Interface.

I get the following error and I can't for the life of me work out the correct term. I've read loads of threads and I can't work it out.

I'd appreciate it if you could point me in the right direction.

Thanks!

C:\Users\Andy\Documents\Arduino\test\adv_midi\adv_midi.ino:6:1: warning: declaration does not declare anything [-fpermissive]

HardwareSerialMIDI_Interface ;

^~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

// Instantiate a MIDI over USB interface
// USBMIDI_Interface midi;

HardwareSerialMIDI_Interface ;

// Instantiate a CCButton object that sends MIDI CC events when the
// state of the button changes
CCButton button = {
  6,               // Push button on pin 6
  {56, CHANNEL_1}, // Controller #56 on MIDI channel 1
 };


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

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

You are trying to declare a variable of type HardwareSerialMIDI_Interface without giving it a name, and without providing the necessary parameters.

Try this:

HardwareSerialMIDI_Interface midi = {Serial, 31250};

You could also use TButton from TDuino like this:

#include <TDuino.h>

#define BUTTON_PIN 6

TButton button;

void buttonPress(byte pin, int state)
{
  midiOut.sendControlChange(56,127,1);
}

void buttonRelease(byte pin, int state)
{
  midiOut.sendControlChange(56,0,1);
}

void setup()
{
  button.attach(BUTTON_PIN);
  button.onPress(buttonPress);
  button.onRelease(buttonRelease);
  //button.setRepeat(500, 200); //Will allow multiple presses to generate if button is held down
}

void loop()
{
  button.loop();
}

Thanks guys,

Pieter, does your library have program Change? I can't find it.

Thanks

andypdmagee:
Pieter, does your library have program Change? I can't find it.

Yes, but there weren't any examples that used it. I added one now:

[color=#5e6d03]#include[/color] [color=#434f54]<[/color][b][color=#d35400]Control_Surface[/color][/b][color=#434f54].[/color][color=#000000]h[/color][color=#434f54]>[/color]

[b][color=#d35400]USBMIDI_Interface[/color][/b] [color=#00979c]midi[/color][color=#000000];[/color]

[b][color=#d35400]ProgramChanger[/color][/b][color=#434f54]<[/color][color=#000000]3[/color][color=#434f54]>[/color] [color=#000000]programChanger[/color] [color=#434f54]=[/color] [color=#000000]{[/color]
  [color=#000000]{[/color][b][color=#d35400]MIDI_PC[/color][/b][color=#434f54]:[/color][color=#434f54]:[/color][color=#00979c]Acoustic_Grand_Piano[/color][color=#434f54],[/color] [b][color=#d35400]MIDI_PC[/color][/b][color=#434f54]:[/color][color=#434f54]:[/color][color=#00979c]Rock_Organ[/color][color=#434f54],[/color] [b][color=#d35400]MIDI_PC[/color][/b][color=#434f54]:[/color][color=#434f54]:[/color][color=#00979c]Electric_Bass_Pick[/color][color=#000000]}[/color][color=#434f54],[/color] 
  [color=#00979c]CHANNEL_1[/color][color=#434f54],[/color]
[color=#000000]}[/color][color=#000000];[/color]

[b][color=#d35400]IncrementDecrementSelector[/color][/b][color=#434f54]<[/color][color=#000000]3[/color][color=#434f54]>[/color] [color=#000000]programSelector[/color] [color=#434f54]=[/color] [color=#000000]{[/color][color=#000000]programChanger[/color][color=#434f54],[/color] [color=#000000]{[/color][color=#000000]A0[/color][color=#434f54],[/color] [color=#000000]A1[/color][color=#000000]}[/color][color=#434f54],[/color] [color=#000000]Wrap[/color][color=#434f54]:[/color][color=#434f54]:[/color][color=#000000]NoWrap[/color][color=#000000]}[/color][color=#000000];[/color]

[color=#00979c]void[/color] [color=#5e6d03]setup[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Control_Surface[/color][/b][color=#434f54].[/color][color=#d35400]begin[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]

[color=#00979c]void[/color] [color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color] [color=#000000]{[/color]
  [b][color=#d35400]Control_Surface[/color][/b][color=#434f54].[/color][color=#5e6d03]loop[/color][color=#000000]([/color][color=#000000])[/color][color=#000000];[/color]
[color=#000000]}[/color]

You can either use a Selector to change the banks, or you can use programChanger.select(<number from 0 to N>), where N is the number of programs (the number between the ).

You can also send program change manually, using midi.sendPC(CHANNEL_1, 0x10).

Hi Pieter,

I can't get that sketch to compile.

Can the PC function operate like the CCButtons? This functionality was PERFECT for me, just the wrong type of message.

andypdmagee:
Hi Pieter,

I can't get that sketch to compile.

Did you update the library to the latest version?

andypdmagee:
Can the PC function operate like the CCButtons? This functionality was PERFECT for me, just the wrong type of message.

I'll add it in a couple of hours, it's pretty simple.

Ahhh, I understand, I'll update.
I find it difficult to learn new things, but very easy to learn it through reverse engineering!
Thanks for your help, I really appreciate it.

I added it: Add PCButton · tttapa/Control-Surface@ea7e08b · GitHub