- The Profiler Model referred to in this thread is ...
- ☑️ Profiler Head/Rack
I'm trying to modify my midi controller (it used to send CCs via midi cable) to send CCs and SysEx messages via usb, so i can request some info (effect status, rig/performance/slot names...) and for some reason my kemper freezes when i send a message.
#include <Control_Surface.h>
#include <USB-MIDI.h>
#include <Wire.h>
#include <hd44780.h> // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h> // i2c expander i/o class header
hd44780_I2Cexp lcd;
const int LCD_COLS = 16;
const int LCD_ROWS = 2;
// Instantiate the MIDI over USB interface
USBMIDI_Interface myMIDI;
// Custom MIDI callback that prints incoming SysEx messages.
struct MyMIDI_Callbacks : MIDI_Callbacks {
void onSysExMessage(MIDI_Interface& interface, SysExMessage sysex) override {
// Check if the message is from the USB MIDI interface
if (&interface != &myMIDI) return;
// Check the first few bytes of the SysEx message to determine its type
if (sysex.length >= 7) {
if (sysex.data[0] == 0xF0 && sysex.data[1] == 0x00 && sysex.data[2] == 0x20 && sysex.data[3] == 0x33) {
if (sysex.data[6] == 0x07) {
displayMessage(sysex, 6, 0); // Performance name on the first row
} else if (sysex.data[6] == 0x03) {
displayMessage(sysex, 6, 1); // Slot name on the second row
}
}
}
}
void displayMessage(SysExMessage& sysex, int startIdx, int row) {
String message;
for (int i = startIdx; i < sysex.length - 1; ++i) {
uint8_t byte = sysex.data[i];
if (byte >= 0x20 && byte <= 0x7E) {
message += char(byte);
}
}
int padding = (LCD_COLS - message.length()) / 2; // Calculate padding for centering
lcd.setCursor(0, row);
lcd.print(" "); // Clear the entire row
lcd.setCursor(padding, row); // Set cursor to the calculated position
lcd.print(message);
}
} callback{};
USBMIDI_CREATE_DEFAULT_INSTANCE();
// Buttons Initialization
const int buttonPins[] = {0, 13, 4, 5, 6, 7, 8, 9, 10, 11, 12};
const int numButtons = sizeof(buttonPins) / sizeof(buttonPins[0]);
const int controlChangeValues[] = {22, 24, 27, 28, 31, 50, 51, 52, 53, 49, 48};
// Function to display a fake progress bar
void displayProgressBar() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" KEMPER ");
lcd.setCursor(0, 1);
lcd.print(" PROFILER ");
}
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void setup() {
Serial.begin(31250);
Wire.begin();
lcd.begin(LCD_COLS, LCD_ROWS);
displayProgressBar(); // Display the fake progress bar on startup
myMIDI.begin();
MIDI.begin(MIDI_CHANNEL_OMNI);
myMIDI.setCallbacks(callback);
// Initialize button pins as inputs
for (int i = 0; i < numButtons; ++i) {
pinMode(buttonPins[i], INPUT);
}
}
// Define the interval between sending each SysEx message (in milliseconds)
const unsigned long sysExInterval = 1000; // 2 seconds
// Variable to store the last time a SysEx message was sent
unsigned long lastSysExTime = 0;
// Variable to store the last time a Control Change message was sent
unsigned long lastCCTime = 0;
// Debounce delay
const unsigned long debounceDelay = 600;
unsigned long lastDebounceTimes[numButtons] = {0};
// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void loop() {
unsigned long currentTime = millis();
// Check if it's time to send the SysEx message
if (currentTime - lastSysExTime >= sysExInterval) {
requestPerformanceName();
requestSlotName();
lastSysExTime = currentTime; // Update the last SysEx message time
}
// Check buttons and send Control Change messages
for (int i = 0; i < numButtons; ++i) {
if (digitalRead(buttonPins[i]) == HIGH) {
if ((currentTime - lastDebounceTimes[i]) > debounceDelay) {
MIDI.sendControlChange(controlChangeValues[i], 127, 1);
lastDebounceTimes[i] = currentTime; // Update the debounce time
}
}
}
// Update MIDI interface
myMIDI.update();
delay(100);
}
// Function to request performance name
void requestPerformanceName() {
uint8_t sysexPerformance[] = {0xF0, 0x00, 0x20, 0x33, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xF7};
myMIDI.sendSysEx(sysexPerformance, sizeof(sysexPerformance));
}
// Function to request slot name
void requestSlotName() {
uint8_t sysexSlot[] = {0xF0, 0x00, 0x20, 0x33, 0x02, 0x7F, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF7};
myMIDI.sendSysEx(sysexSlot, sizeof(sysexSlot));
}
Display More
I'm new to programming and SysEx and all, but i find weird that it only crashes when i send a message.
The idea is to send CC and SysEx, so far I send SysEx every X time (the one in the code is just for testing, I don't know how often i caa request it without the kemper having issues) and send CCs when pressing the buttons, but the kemper "randoml"y freezes some times.
I'm using the front USB A port, right now i don't have any other way to test it.
I tried many things and i changed the code many times, this is the closest i've been to make it work, but for some reason the unit keeps freezing...
Any idea why could it be or what could cause It?
I'd also like to make some buttons to request stomps status (mostly X, Mod, Delay, and Reverb, but if I could find the ones for the other stack it would be great too) and act accordingly, if it's off turn it on and so, but I can't find the SysEx messages for that, I only have the Mod one and only cause I got it from support.
EDIT: I changed the code, it'sstill freezing, not all the times, but it still happens