Jonathan
Jonathan

Reputation: 1

Arduino MIDI Controller Freezes After Rapid Button Presses and Potentiometer Adjustments

I'm building a MIDI controller using an Arduino Leonardo and coding in C++. The controller has 16 buttons, 3 potentiometers, and an OLED screen. When I press too many buttons too quickly and adjust the potentiometers simultaneously, the entire controller freezes, including the OLED display. I have to reset the Arduino to make it functional again.

What I've Tried: Adjusting debounce times for buttons (e.g., from 10 ms to 50 ms). Reducing how often the OLED display updates. Calling MidiUSB.flush() less frequently. Debugging with Serial.print() but can't pinpoint the issue. Suspected Issues: I suspect the freezing might be caused by:

Overloading the MIDI communication buffer with too many flush() calls. Excessive processing in the loop() function, possibly from rapid OLED updates. The Arduino running out of memory or experiencing buffer overflows.

#include "MIDIUSB.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4 // Optional reset pin (most displays don't need it)
Adafruit_SSD1306 display(OLED_RESET);

#define SCREEN_WIDTH 128 // OLED display width
#define SCREEN_HEIGHT 64 // OLED display height


byte buttonPin[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, A3, A4, A5};
byte buttonPState[16] = {0}; // Array to store the previous state of each button
unsigned long lastDebounceTime[16] = {0}; // Array to store last debounce times
const int buttonTimeout = 10; // Debounce timeout in milliseconds

const int N_BUTTONS = 16;
const int N_POTS = 3;
const int POT_CHANGE_THRESHOLD = 2;

byte potPin[N_POTS] = {A0, A1, A2};
int potState[N_POTS] = {0};
int midiState[N_POTS] = {0};
int midiPState[N_POTS] = {0};
int CC[N_POTS] = {11, 12, 13};

byte MIDI_CH = 0;
byte NN[N_BUTTONS] = {36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};



void setup() {
  Serial.begin(115200);
   // Set button pins as input with pull-up resistors
  for (int i = 0; i < N_BUTTONS; i++) {
    pinMode(buttonPin[i], INPUT_PULLUP);
  }

    display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // Set the I2C address to 0x3C
  display.clearDisplay(); // Clear the display

  // Display "CAMDEN"
  display.setTextSize(3);  // Set text size
  display.setTextColor(WHITE); // Set text color
  display.setCursor(0, 10);  // Set cursor position
  display.println("CAMDEN"); // Print the text
  display.display();  // Update the display
  delay(2000); // Wait for 2 seconds

  // Clear the display
  display.clearDisplay(); // Clear the display

  // Display "TOWN"
  display.setCursor(0, 10);  // Set cursor position
  display.println("TOWN"); // Print the text
  display.display();  // Update the display
  delay(2000); // Wait for 2 seconds
  display.clearDisplay();
  display.display(); 
}

void loop() {
  buttons();
  potentiometers();
}

void noteOn(byte channel, byte note, byte velocity) {
  midiEventPacket_t noteOnPacket = {0x09, 0x90 | channel, note, velocity};
  MidiUSB.sendMIDI(noteOnPacket);
  MidiUSB.flush();
}

void noteOff(byte channel, byte note, byte velocity) {
  midiEventPacket_t noteOffPacket = {0x08, 0x80 | channel, note, velocity};
  MidiUSB.sendMIDI(noteOffPacket);
  MidiUSB.flush();
}



void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t controlChangePacket = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(controlChangePacket);
  MidiUSB.flush();
}

//-------BUTTONS---------//
void buttons() {
  for (int i = 0; i < N_BUTTONS; i++) {
    byte currentState = digitalRead(buttonPin[i]);
    if (currentState != buttonPState[i]) {
      if (millis() - lastDebounceTime[i] > buttonTimeout) {
        lastDebounceTime[i] = millis();
        buttonPState[i] = currentState;
        Serial.print("Button: ");
        Serial.print(i);
        if (currentState == LOW) {
          Serial.println(" On");
          noteOn(MIDI_CH, NN[i], 127);
          MidiUSB.flush();    

        } else {
          Serial.println(" Off");
          noteOff(MIDI_CH, NN[i], 0);
          MidiUSB.flush();
        }
      }
    }
  }
}

//-------POTENTIOMETERS---------//

void potentiometers() {
  for (int i = 0; i < N_POTS; i++) {
    potState[i] = analogRead(potPin[i]);
    midiState[i] = map(potState[i], 0, 1023, 0, 127);
    if (abs(midiState[i] - midiPState[i]) >= POT_CHANGE_THRESHOLD) {

      controlChange(MIDI_CH, CC[i], midiState[i]);
       MidiUSB.flush();

      Serial.print("POT ");
      Serial.print(i);
      Serial.print(" ");
      Serial.println(midiState[i]);
      midiPState[i] = midiState[i];

      // Display potentiometer value on OLED
      display.clearDisplay();
      display.setTextSize(2);
      display.setTextColor(WHITE);
      display.setCursor(0, 10);
      display.print("Pot ");
      display.print(i + 1); // Display pot number (1-indexed)
      display.print(": ");
      display.println(midiState[i]); // Display the value of the pot
      display.display();
    }
  }
}



Upvotes: 0

Views: 21

Answers (0)

Related Questions