Hi all,
I'm having a weird problem with translating multiple buttons into midi note triggers. I have the typical circuit working sending midi information out to a synth with a midi cable. I am able to get up to 3 buttons to trigger the correct midi notes (works polyphonically too). However, when I add a 4th or 5th button to the below sketch the midi stops working. The sketch still prints correctly to the serial monitor for all the buttons but the midi synth stops responding at all.
I'm a total beginner and have hacked this together from many of the midi examples online plus some help from a friend. We are a bit stumped now though!
This is the code (config.h is just a place to define PITCH_# variables):
#include "config.h"
#include <SoftwareSerial.h>
SoftwareSerial midiSerial(2, 3); // digital pins that we'll use for soft serial RX & TX
byte buttons[] = {4, 5, 6}; // <- this works...... but {4, 5, 6, 7}; does not!
byte buttonPitches[] = {PITCH_1, PITCH_2, PITCH_3, PITCH_4, PITCH_5};
#define NUMBUTTONS sizeof(buttons)
int buttonState[NUMBUTTONS];
int lastButtonState[NUMBUTTONS];
boolean buttonIsPressed[NUMBUTTONS];
// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 50; // the debounce time; increase if the output flickers
void setup() {
Serial.begin(9600);
midiSerial.begin(31250);
// define pins:
for (int i = 0; i < NUMBUTTONS; i++) {
pinMode(i, INPUT);
lastButtonState[i] = LOW;
buttonIsPressed[i] = false;
buttonState[i] = 0;
Serial.println(buttonState[i]);
}
}
void loop()
{
check_buttons();
// action();
}
void check_buttons() {
for (int currentButton = 0; currentButton < NUMBUTTONS; currentButton++) {
// read the state of the switch into a local variable:
int reading = digitalRead(buttons[currentButton]); // check to see if you just pressed the button and you've waited long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing then reset the debouncing timer
if (reading != lastButtonState[currentButton]) {
lastDebounceTime = millis();
}
// whatever the reading is at, it's been there for longer than the debounce delay, so take it as the actual current state:
if ((millis() - lastDebounceTime) > debounceDelay) {
// if the button state has changed:
if (reading != buttonState[currentButton]) {
buttonState[currentButton] = reading;
if (buttonState[currentButton] == HIGH) { //pushing down on the button
buttonIsPressed[currentButton] = true; // set your flag for the adjustment function
playMIDINote(0x90, buttonPitches[currentButton], 100);
}
if (buttonState[currentButton] == LOW) { //pushing down on the button
buttonIsPressed[currentButton] = false; // set your flag for the adjustment function
;
playMIDINote(0x90, buttonPitches[currentButton], 0);
}
}
}
// save the reading. Next time through the loop, it'll be the lastButtonState:
lastButtonState[currentButton] = reading;
}
}
void playMIDINote(byte cmd, byte data1, byte data2)
{
midiSerial.write(cmd);
midiSerial.write(data1);
midiSerial.write(data2);
//prints the values in the serial monitor so we can see what note we're playing
Serial.print("cmd: ");
Serial.print(cmd);
Serial.print(", data1: ");
Serial.print(data1);
Serial.print(", data2: ");
Serial.println(data2);
}
_Multi-Testing.zip (2.94 KB)