Reputation: 1
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