Can't make text to appear in the second row

Hi, i'm trying to make a midi controller for a Kemper Profiler that shows the rig name and slot name on a 16x2 lcd screen, i don't know any programming, so i've been using google to find codes and then trial and error, i also used chatgpt to help me understand some stuff.

So far this is my code, i managed to make the arduino (leonardo) send and receive sysex messages and show the receiven message on the screen (thos would be the slot and performance names) but for some reason everything is showing in the first row of the screen. This is the latest code i'm trying, it shows the performance and slot names when i press the buttons but on the first row only, and it shows the words "slot name" in the second row.

I have no idea how to make it work as intended, i tried lcd.setCursor but for some reason it's not working...

#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;

// Instantiate the MIDI over USB interface
USBMIDI_Interface myMIDI;

const int LCD_COLS = 16;
const int LCD_ROWS = 2;

// Custom MIDI callback that prints incoming SysEx messages.
struct MyMIDI_Callbacks : MIDI_Callbacks {
  
  // This callback function is called when a SysEx message is received.
void onSysExMessage(MIDI_Interface &interface, SysExMessage sysex) override {
    // Check if the message is from the USB MIDI interface
    if (&interface != &myMIDI) return;

    // Define variables to keep track of parsing state
    String currentName;

    // Iterate through the received SysEx message starting from the 6th byte
    for (int i = 6; i < sysex.length - 1; ++i) {
        uint8_t byte = sysex.data[i];
        
        // Check if the byte is within the printable ASCII range
        if (byte >= 0x20 && byte <= 0x7E) {
            currentName += char(byte);
        }
    }

 // Calculate the starting position to center the name on the LCD
    int startPosition = max(0, (LCD_COLS - currentName.length()) / 2);

    // Clear the LCD
    lcd.clear();

    // Print the performance name at the top (first row)
    lcd.setCursor(0, 0); // Set cursor to the first row
    lcd.print(currentName);
    Serial.println("Performance Name displayed: " + currentName); // Debugging statement

    // Print the slot name at the bottom (second row)
    lcd.setCursor(0, 1); // Set cursor to the second row
    lcd.print("Slot Name"); // Change "Slot Name" to the actual slot name variable
}


} callback {};


USBMIDI_CREATE_DEFAULT_INSTANCE();


const int buttonPin = {0};
const int buttonPin2 = {13};
const int buttonPin3 = {4};
const int buttonPin4 = {5};
const int buttonPin5 = {6};
const int buttonPin6 = {7};
const int buttonPin7 = {8};
const int buttonPin8 = {9};
const int buttonPin9 = {10};
const int buttonPin10 = {11};
const int buttonPin11 = {12};



int buttonState = 0;
int lastButtonState = 0;
int toggleState = 0;

int buttonState2 = 0;
int lastButtonState2 = 0;
int toggleState2 = 0;

int buttonState3 = 0;
int lastButtonState3 = 0;
int toggleState3 = 0;

int buttonState4 = 0;
int lastButtonState4 = 0;
int toggleState4 = 0;

int buttonState5 = 0;
int lastButtonState5 = 0;
int toggleState5 = 0;

int buttonState6 = 0;
int lastButtonState6 = 0;
int toggleState6 = 0;

int buttonState7 = 0;
int lastButtonState7 = 0;
int toggleState7 = 0;

int buttonState8 = 0;
int lastButtonState8 = 0;
int toggleState8 = 0;

int buttonState9 = 0;
int lastButtonState9 = 0;
int toggleState9 = 0;

int buttonState10 = 0;
int lastButtonState10 = 0;
int toggleState10 = 0;

int buttonState11 = 0;
int lastButtonState11 = 0;
int toggleState11 = 0;




 



// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void setup()
{
  Serial.begin(31250);
  Wire.begin();


  lcd.begin(LCD_COLS, LCD_ROWS);

    lcd.clear();
  delay(1000);
  myMIDI.begin();
MIDI.begin(MIDI_CHANNEL_OMNI);

  // Inicialización de pines de botones

  
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);
  pinMode(buttonPin3, INPUT_PULLUP);
  pinMode(buttonPin4, INPUT_PULLUP);
  pinMode(buttonPin5, INPUT_PULLUP);
  pinMode(buttonPin6, INPUT_PULLUP);
  pinMode(buttonPin7, INPUT_PULLUP);
  pinMode(buttonPin8, INPUT_PULLUP);
  pinMode(buttonPin9, INPUT_PULLUP);
  pinMode(buttonPin10, INPUT_PULLUP);
  pinMode(buttonPin11, INPUT_PULLUP);

    


// MIDI interface initialization is successful if it reached here
  // Set MIDI callbacks
  myMIDI.setCallbacks(callback);
  
  Serial.println("Setup completed."); // Indicate setup completion

// Request performance name
  uint8_t sysexPerformanceStartup[] = {0xF0, 0x00, 0x20, 0x33, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xF7};
  myMIDI.sendSysEx(sysexPerformanceStartup);
  Serial.println("Requesting performance name...");

  // Request slot name
  uint8_t sysexSlotStartup[] = {0xF0, 0x00, 0x20, 0x33, 0x02, 0x7F, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF7};
  myMIDI.sendSysEx(sysexSlotStartup);
  Serial.println("Requesting slot name...");


}




// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void loop()  {


 buttonState = digitalRead(buttonPin);
  if(buttonState != lastButtonState && buttonState == 1 && toggleState == 0) {
    MIDI.sendControlChange(22, 127, 1);
        
//MIDI.sendControlChange(99, 58, 1);
    //MIDI.sendControlChange(98, 3, 1);
    //MIDI.sendControlChange(6, 1, 1);
    //MIDI.sendControlChange(38, 1, 1);
  toggleState = 1;
  delay(300);
  }
  else if(buttonState != lastButtonState && buttonState == 1 && toggleState == 1) {
    MIDI.sendControlChange(22, 0, 1);

  toggleState = 0;
  delay(300);
  
  }
     lastButtonState = buttonState;
    
    
 buttonState2 =  digitalRead(buttonPin2);
  if(buttonState2 != lastButtonState2 && buttonState2 == 1 && toggleState2 == 0) {
    MIDI.sendControlChange(24, 127, 1);
  toggleState2 = 1;
  delay(300);
  }
 else if(buttonState2 != lastButtonState2 && buttonState2 == 1 && toggleState2 == 1) {
    MIDI.sendControlChange(24, 0, 1);
  toggleState2 = 0;
  delay(300);

  }
     lastButtonState2 = buttonState2;
buttonState3 = digitalRead(buttonPin3);

   if(buttonState3 != lastButtonState3 && buttonState3 == 1 && toggleState3 == 0) {
    MIDI.sendControlChange(27, 127, 1);
  toggleState3 = 1;
  delay(300);
  }
  else if(buttonState3 != lastButtonState3 && buttonState3 == 1 && toggleState3 == 1) {
    MIDI.sendControlChange(27, 0, 1);
  toggleState3 = 0;
  delay(300);
  
  
  }
lastButtonState3 = buttonState3;
buttonState4 = digitalRead(buttonPin4);
  
  if(buttonState4 != lastButtonState4 && buttonState4 == 1 && toggleState4 == 0) {
    MIDI.sendControlChange(28, 127, 1);
  toggleState4 = 1;
  delay(300);
  }
  else if(buttonState4 != lastButtonState4 && buttonState4 == 1 && toggleState4 == 1) {
    MIDI.sendControlChange(28, 0, 1);
  toggleState4 = 0;
  delay(300);
   }
 lastButtonState4 = buttonState4;

buttonState5 = digitalRead(buttonPin5);
  if(buttonState5 != lastButtonState5 && buttonState5 == 1 && toggleState5 == 0) {
    MIDI.sendControlChange(31, 127, 1);
  toggleState5 = 1;
 delay(300);
  }
  else if(buttonState5 != lastButtonState5 && buttonState5 == 1 && toggleState5 == 1) {
    MIDI.sendControlChange(31, 0, 1);
    
  toggleState5 = 0;
 delay(300);
  
  }
  
  lastButtonState5 = buttonState5;



  // Send a SysEx message when the button for slot name is pressed
    uint8_t sysexSlot[] = {0xF0, 0x00, 0x20, 0x33, 0x02, 0x7F, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF7};
buttonState6 = digitalRead(buttonPin6);
      if(buttonState6 != lastButtonState6 && buttonState6 == 1 && toggleState6 == 0) {
        MIDI.sendControlChange(50, 1, 1);
        toggleState6 = 1;
    // Send the SysEx message
    myMIDI.sendSysEx(sysexSlot);
          Serial.println(":"); // Print slot name
        lcd.print(""); // Print slot name
        Serial.println("SysEx message for slot name sent.");
        
 delay(300);
  }

  // Reset the flag when the button is released
  else if(buttonState6 != lastButtonState6 && buttonState6 == 1 && toggleState6 == 1) {
    MIDI.sendControlChange(50, 1, 1);
        myMIDI.sendSysEx(sysexSlot);
          Serial.println(":"); // Print slot name
        lcd.print(""); // Print slot name
        Serial.println("SysEx message for slot name sent.");
    toggleState6 = 0;
 delay(300);
   // messageSent = false;
   }
   lastButtonState6 = buttonState6;

 // Send a SysEx message when the button for slot name is pressed
    uint8_t sysexSlot2[] = {0xF0, 0x00, 0x20, 0x33, 0x02, 0x7F, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF7};
 buttonState7 = digitalRead(buttonPin7);   
  if(buttonState7 != lastButtonState7 && buttonState7 == 1 && toggleState7 == 0) {
    MIDI.sendControlChange(51, 1, 1);
  myMIDI.sendSysEx(sysexSlot2);
          Serial.println(""); // Print slot name
        lcd.print(""); // Print slot name
        Serial.println("SysEx message for slot name sent.");

 delay(300);
  }
  else if(buttonState7 != lastButtonState7 && buttonState7 == 1 && toggleState7 == 1) {
    MIDI.sendControlChange(51, 1, 1);
         myMIDI.sendSysEx(sysexSlot2);
          Serial.println(":"); // Print slot name
        lcd.print(""); // Print slot name
        Serial.println("SysEx message for slot name sent.");
  toggleState7 = 0;
 delay(300);
   
  }
   lastButtonState7 = buttonState7;

 // Send a SysEx message when the button for slot name is pressed
    uint8_t sysexSlot3[] = {0xF0, 0x00, 0x20, 0x33, 0x02, 0x7F, 0x43, 0x00, 0x00, 0x01, 0xF7};
buttonState8 = digitalRead(buttonPin8);
    if(buttonState8 != lastButtonState8 && buttonState8 == 1 && toggleState8 == 0) {
    MIDI.sendControlChange(52, 1, 1);
     myMIDI.sendSysEx(sysexSlot3);
        lcd.print(""); // Print slot  name
        Serial.println("SysEx message for slot  name sent.");
 delay(300);

  }
  else if(buttonState8 != lastButtonState8 && buttonState8 == 1 && toggleState8 == 1) {
    MIDI.sendControlChange(52, 1, 1);
      myMIDI.sendSysEx(sysexSlot3);
        lcd.print(""); // Print slot  name
        Serial.println("SysEx message for slot  name sent.");
  toggleState8 = 0;
 delay(300);
    
  }
  lastButtonState8 = buttonState8;
   // Send a SysEx message when the button for slot name is pressed
    uint8_t sysexSlot4[] = {0xF0, 0x00, 0x20, 0x33, 0x02, 0x7F, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF7};
buttonState9 = digitalRead(buttonPin9);
    if(buttonState9 != lastButtonState9 && buttonState9 == 1 && toggleState9 == 0) {
    MIDI.sendControlChange(53, 1, 1);
   myMIDI.sendSysEx(sysexSlot4);
        lcd.print(""); // Print slot name
        Serial.println("SysEx message for slot  name sent.");
        delay(300);

  }
  else if(buttonState9 != lastButtonState9 && buttonState9 == 1 && toggleState9 == 1) {
    MIDI.sendControlChange(53, 1, 1);
    myMIDI.sendSysEx(sysexSlot4);
        lcd.print(""); // Print slot name
        Serial.println("SysEx message for slot  name sent.");
  toggleState9 = 0;
 delay(300);
   
  }
   lastButtonState9 = buttonState9;

             // Send a SysEx message when the button for performance name is pressed
    uint8_t sysexPerformance[] = {0xF0, 0x00, 0x20, 0x33, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xF7}; 
  buttonState10 = digitalRead(buttonPin10);
    if(buttonState10 != lastButtonState10 && buttonState10 == 1 && toggleState10 == 0) {
       MIDI.sendControlChange(49,0, 1);
 myMIDI.sendSysEx(sysexPerformance);
        lcd.print(""); // Print perfornamce name
        Serial.println("SysEx message for performance name sent.");
           toggleState11 = 1;

        delay(300);
  }

  else if(buttonState10 != lastButtonState10 && buttonState10 == 1 && toggleState10 == 1) {
    MIDI.sendControlChange(49, 0, 1);
 myMIDI.sendSysEx(sysexPerformance);
        lcd.print(""); // Print perfornamce name
        Serial.println("SysEx message for performance name sent.");
    lastButtonState10 = buttonState10;
     
  toggleState10 = 0;
 delay(300);
   
  }
  lastButtonState10 = buttonState10;
  
  buttonState11 = digitalRead(buttonPin11);
               // Send a SysEx message when the button for performance name is pressed
    uint8_t sysexPerformance2[] = {0xF0, 0x00, 0x20, 0x33, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xF7}; 
    if(buttonState11 != lastButtonState11 && buttonState11 == 1 && toggleState11 == 0) {
          
        MIDI.sendControlChange(48, 0, 1);
        myMIDI.sendSysEx(sysexPerformance2);
        lcd.print(""); // Print performance name
        Serial.println("SysEx message for performance name sent.");

    lastButtonState11 = buttonState11;

     
  toggleState11 = 1;
 delay(300);
  }
  else if(buttonState11 != lastButtonState11 && buttonState11 == 1 && toggleState11 == 1) {
    MIDI.sendControlChange(48, 0, 1);
    myMIDI.sendSysEx(sysexPerformance2);
    lcd.print(""); // Print performance name
    Serial.println("SysEx message for performance name sent.");
  toggleState11 = 0;
 delay(300);
  
       }
      lastButtonState11 = buttonState11;


  myMIDI.update();
   }


I home someone knows how i could make it work and is willing to help, as i said, i'm pretty new to this so i have no idea what i'm doing :sweat_smile:
Thanks!

As far as I can see you only ever print currentName

        lcd.setCursor(0, 0);  // Set cursor to the first row
        lcd.print(currentName);

All of the other lcd.print() function calls apart from the text labels print nothing despite what the comments say

        lcd.print("");        // Print slot name
        lcd.print("");  // Print perfornamce name

and what could i do to make it work?
as i said i'm new to all this :sweat_smile:
i tried everything i found but i have no idea what i'm doing hahahahah

i tried adding strings for each one (slot and performance) and then trying lcd.print(currentSlotName); and it's still not working

Show code where you're not even trying to print the values is absolutely pointless. Show your efforts to solve the problem.

1 Like

Please post your revised sketch

lcd.setCursor(0, 0);

sets cursor to start of line, first row

lcd.setCursor(0, 1);

sets cursor to start of line, second row

As @UKHeliBob says, there are only two statements in the entire sketch that out anything in the screens and it looks like they do exactly what you say:

    lcd.setCursor(0, 0); // Set cursor to the first row
    lcd.print(currentName);
    Serial.println("Performance Name displayed: " + currentName); // Debugging statement

    // Print the slot name at the bottom (second row)
    lcd.setCursor(0, 1); // Set cursor to the second row
    lcd.print("Slot Name"); // Change "Slot Name" to the actual slot name variable

You didn't read the comment which clearly says

Change "Slot Name" to the actual slot name variable

And how wide is you LCD? Wide enough to see

Performance Name displayed:

plus whatever is in the variable currentName?

Also, take the sketch back to chatGPT and tell it you don't know about functions and arrays, and how they can make sketches easier to read and write, and would it please take a crack at rolling up those umpteen repeated blocks of code into a general function that would handle all the buttons or whatever makes you need so many repeated blocks.

Let us know what it says.

a7

I wonder why so many people try to learn to code essentially by brute force and won't take the time to RTFM. Could it be that they don't know where to find TFM?

As i said i barely have any idea of what i'm doing, so yes, my code has unnecessary things and probably redundancies too, and there are ways to make it better sure, but first i want to make it work as intended, and then i'll put some order.
I know the buttons could be better done, but that partr is temporary, i'll have to change how they work and what they do later

This is the code i'm using now, i did some changes, i made it send the sysex every 5 seconds and print it in the screen, but for some reason it's still printing the slot name (which should be in the second row) in the first one.
As i said for some reason setCursor is not working for me inside of my code (it does work if i use any test code).

The idea is to send a sysex requesting the current performance name and print it in the first row of the screen, and do the same with another sysex to print the current slot name in the second row of the screen.
But it only prints in the first row...


#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 {

  // This callback function is called when a SysEx message is received.
  void onSysExMessage(MIDI_Interface &interface, SysExMessage sysex) override {
    // Check if the message is from the USB MIDI interface
    if (&interface != &myMIDI) return;

    // Define variables to keep track of parsing state
    String currentName;
    String currentSlotName;

    // Iterate through the received SysEx message starting from the 6th byte
    for (int i = 6; i < sysex.length - 1; ++i) {
      uint8_t byte = sysex.data[i];

      // Check if the byte is within the printable ASCII range
      if (byte >= 0x20 && byte <= 0x7E) {
        currentName += char(byte);
      }
    }

    // Calculate the number of leading spaces to center the text on the LCD
    int numSpaces = max(0, (LCD_COLS - currentName.length()) / 2);

     // Clear the LCD and print the performance name on the first row
    lcd.clear();
    for (int i = 0; i < numSpaces; ++i) {
        lcd.print(" "); // Print leading spaces
    }
    lcd.print(currentName);
    Serial.println("Performance Name displayed: " + currentName); // Debugging statement

// Calculate the starting position to center the slot name on the LCD
numSpaces = max(0, (LCD_COLS - currentSlotName.length()) / 2);

// Set cursor to the first column of the second row
lcd.setCursor(0, 1);

// Print the slot name
for (int i = 0; i < numSpaces; ++i) {
    lcd.print(" "); // Print leading spaces
}
lcd.print(currentSlotName);

Serial.println("Slot Name displayed: " + currentSlotName); // Debugging statement

  }


} callback{};

USBMIDI_CREATE_DEFAULT_INSTANCE();

// Define the interval for sending SysEx messages (in milliseconds)
const unsigned long sysExInterval = 5000;  // 5 seconds

// Variables to store the last time SysEx messages were sent
unsigned long lastSysExTime = 0;




//Buttons Initialization
const int buttonPin = 0;
const int buttonPin2 = 13;
const int buttonPin3 = 4;
const int buttonPin4 = 5;
const int buttonPin5 = 6;
const int buttonPin6 = 7;
const int buttonPin7 = 8;
const int buttonPin8 = 9;
const int buttonPin9 = 10;
const int buttonPin10 = 11;
const int buttonPin11 = 12;







// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void setup() {
  Serial.begin(31250);
  Wire.begin();
  lcd.begin(LCD_COLS, LCD_ROWS);
  
  delay(1000);
  myMIDI.begin();
  MIDI.begin(MIDI_CHANNEL_OMNI);
  myMIDI.setCallbacks(callback);
  requestPerformanceName();
  requestSlotName();
  Serial.println("Setup completed.");  // Indicate setup completion
}




// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void loop() {
  // Check if it's time to send the SysEx messages
  unsigned long currentTime = millis();
  if (currentTime - lastSysExTime >= sysExInterval) {
    // Send SysEx message for requesting performance name
    requestPerformanceName();
    requestSlotName();

    // Update the last time SysEx messages were sent
    lastSysExTime = currentTime;
  }

  //Buttons 1 to 9
  if (digitalRead(buttonPin) == HIGH) {
    // Send Control Change message
    MIDI.sendControlChange(22, 127, 1);
    delay(300);  // Delay to prevent multiple presses
  }

  if (digitalRead(buttonPin2) == HIGH) {
    // Send Control Change message
    MIDI.sendControlChange(24, 127, 1);
    delay(300);  // Delay to prevent multiple presses
  }

  if (digitalRead(buttonPin3) == HIGH) {
    // Send Control Change message
    MIDI.sendControlChange(27, 127, 1);
    delay(300);  // Delay to prevent multiple presses
  }

  if (digitalRead(buttonPin4) == HIGH) {
    // Send Control Change message
    MIDI.sendControlChange(28, 127, 1);
    delay(300);  // Delay to prevent multiple presses
  }

  if (digitalRead(buttonPin5) == HIGH) {
    // Send Control Change message
    MIDI.sendControlChange(31, 127, 1);
    delay(300);  // Delay to prevent multiple presses
  }

  if (digitalRead(buttonPin6) == HIGH) {
    // Send Control Change message
    MIDI.sendControlChange(50, 1, 1);
    delay(300);  // Delay to prevent multiple presses
  }

  if (digitalRead(buttonPin7) == HIGH) {
    // Send Control Change message
    MIDI.sendControlChange(51, 1, 1);
    delay(300);  // Delay to prevent multiple presses
  }

  if (digitalRead(buttonPin8) == HIGH) {
    // Send Control Change message
    MIDI.sendControlChange(52, 1, 1);
    delay(300);  // Delay to prevent multiple presses
  }

  if (digitalRead(buttonPin9) == HIGH) {
    // Send Control Change message
    MIDI.sendControlChange(53, 1, 1);
    delay(300);  // Delay to prevent multiple presses
  }

  //Buttons 10 and 11
  // Handle button 10 press
  if (digitalRead(buttonPin10) == HIGH) {
    // Send Control Change message
    MIDI.sendControlChange(49, 0, 1);
    delay(300);  // Delay to prevent multiple presses
  }

  // Handle button 11 press
  if (digitalRead(buttonPin11) == HIGH) {
    // Send Control Change message
    MIDI.sendControlChange(48, 0, 1);
    delay(300);  // Delay to prevent multiple presses
  }

  // Update MIDI interface
  myMIDI.update();
}

// 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);
  Serial.println("Requested Performance Name");  // Debug message
}

//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);
    Serial.println("Requested Slot Name"); // Debug message
}

I'm new to all this, so have some patience with me :sweat_smile:

That's putting the cart before the horse. Start simple, remove unnecessary parts from your code, and make sure that you fully understand the remaining part. Then come up with a hypothesis of what might be going wrong, and add targeted Serial.print(...) statements to verify your hypothesis.

Specifically, you don't need USB-MIDI.h at all. It may even interfere with the USBMIDI_Interface you defined first. The buttons add noise as well. Add and clean them up later, once you fixed the issues with the display.
The specific bug you're looking for right now actually has nothing to do with the display itself, setCursor is a distraction. I would recommend even removing all the display-related code while debugging:

#include <Control_Surface.h>

// Instantiate the MIDI over USB interface
USBMIDI_Interface myMIDI;

// Custom MIDI callback that prints incoming SysEx messages.
struct MyMIDI_Callbacks : MIDI_Callbacks {

  // This callback function is called when a SysEx message is received.
  void onSysExMessage(MIDI_Interface &interface, SysExMessage sysex) override {
    // Check if the message is from the USB MIDI interface
    if (&interface != &myMIDI) return;

    // Define variables to keep track of parsing state
    String currentName;
    String currentSlotName;

    // Iterate through the received SysEx message starting from the 6th byte
    for (int i = 6; i < sysex.length - 1; ++i) {
      uint8_t byte = sysex.data[i];
      // Check if the byte is within the printable ASCII range
      if (byte >= 0x20 && byte <= 0x7E) {
        currentName += char(byte);
      }
    }

    Serial.println("Performance Name received: " + currentName);
    Serial.println("Slot Name received: " + currentSlotName);
  }


} callback{};

// Define the interval for sending SysEx messages (in milliseconds)
AH::Timer<millis> sysExTimer{ 5000 };  // 5 seconds

void setup() {
  Serial.begin(115200);

  myMIDI.begin();
  myMIDI.setCallbacks(callback);
  Serial.println("Setup completed.");  // Indicate setup completion
}

void loop() {
  // Check if it's time to send the SysEx messages
  if (sysExTimer) {
    // Send SysEx message for requesting performance name
    requestPerformanceName();
    requestSlotName();
  }
  // Update MIDI interface
  myMIDI.update();
}

// 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);
  Serial.println("Requested Performance Name");  // Debug message
}

//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);
  Serial.println("Requested Slot Name");  // Debug message
}

Do you see the issue now? What does it print in after Slot Name received: ?

Or, to be even more specific, where do you initialize currentSlotName? And how does your onSysExMessage handler distinguish between SysEx messages containing a "performance name" and messages containing a "slot name"?

I managed to make it work changing A LOT of stuff, not sure what was the issue tbh...
This is my code now, i added a few more things to it.

#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 
USBMIDI_Interface myMIDI;
USBMIDI_CREATE_DEFAULT_INSTANCE();

// Control Change values 
const int controlChangeValues[] = {22, 24, 27, 29, 31, 50, 51, 52, 53, 49, 48};

// Text messages 
const char* buttonMessages[][2] = {
  {"X OFF", "X ON"},
  {"MOD OFF", "MOD ON"},
  {"DELAY OFF", "DELAY ON"},
  {"REVERB OFF", "REVERB ON"}
};

unsigned long messageDisplayTime = 2500; // 3.5 seconds
unsigned long lastMessageTime = 0;
bool buttonMessageShowing = false;

// Show a message on the LCD
void showMessage(int buttonIdx, int state) {
  String message = buttonMessages[buttonIdx][state];
  int padding = (LCD_COLS - message.length()) / 2;  // Calculate padding for centering
  lcd.setCursor(0, 0);
  lcd.print("                ");  // Clear the first row
  lcd.setCursor(padding, 0);
  lcd.print(message);
  lastMessageTime = millis();  // Update the last message time
  buttonMessageShowing = true;
  Serial.print("Showing message: ");
  Serial.println(message);
}

// 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;

    // Handle the response for the effect module state
    if (sysex.length == 13 && sysex.data[0] == 0xF0 && sysex.data[1] == 0x00 && sysex.data[2] == 0x20 && sysex.data[3] == 0x33) {
      if (sysex.data[5] == 0x00 && sysex.data[6] == 0x01) {
        int buttonIdx = -1;
        switch (sysex.data[8]) {
          case 0x38: buttonIdx = 0; break; // Button 1
          case 0x3A: buttonIdx = 1; break; // Button 2
          case 0x3C: buttonIdx = 2; break; // Button 3
          case 0x3D: buttonIdx = 3; break; // Button 4
        }
        if (buttonIdx != -1) {
          int ccValue = (sysex.data[11] == 0x01) ? 0 : 1; // If on, send 0; if off, send 1
          MIDI.sendControlChange(controlChangeValues[buttonIdx], ccValue, 1);
          showMessage(buttonIdx, ccValue);
          Serial.print("Sent CC for button ");
          Serial.print(buttonIdx + 1);
          Serial.print(": ");
          Serial.println(ccValue);
        }
      }
    }

    // Performance and slot name display
    if (sysex.length >= 7) {
      if (sysex.data[0] == 0xF0 && sysex.data[1] == 0x00 && sysex.data[2] == 0x20 && sysex.data[3] == 0x33) {
        if (!buttonMessageShowing) {
          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);
    Serial.print("Displayed message on row ");
    Serial.print(row);
    Serial.print(": ");
    Serial.println(message);
  }
} callback{};

// Buttons Initialization
const int buttonPins[] = {0, 13, 4, 5, 6, 7, 8, 9, 10, 11, 12};
const int numButtons = sizeof(buttonPins) / sizeof(buttonPins[0]);

// Display a startup message
void displayProgressBar() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("     KEMPER      ");
  lcd.setCursor(0, 1);
  lcd.print("    PROFILER    ");
  Serial.println("Displayed progress bar");
}

// Track the state for button 5
bool button5State = false;

// Variables for initial delay
const unsigned long initialDelay = 37500; // 37.5 seconds
unsigned long setupTime = 0;
bool initialDelayCompleted = false;


//

void setup() {
  Serial.begin(31250);
  Wire.begin();
  lcd.begin(LCD_COLS, LCD_ROWS);
  displayProgressBar();  // Display the text 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);
  }

  // Store the setup time
  setupTime = millis();
}

// Define the interval between sending each SysEx message 
const unsigned long sysExInterval = 500;  
// Store the last time a SysEx message was sent
unsigned long lastSysExTime = 0;

// Debounce delay
const unsigned long debounceDelay = 300;
unsigned long lastDebounceTimes[numButtons] = {0};

// -----------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------
void loop() {
  unsigned long currentTime = millis();

  // Check if the initial delay is completed
  if (!initialDelayCompleted && (currentTime - setupTime >= initialDelay)) {
    initialDelayCompleted = true;
    lastSysExTime = currentTime; // Start SysEx timer after the initial delay
    Serial.println("Initial delay completed");
  }

  // Clear the message if it's been displayed for the specified duration
  if (buttonMessageShowing && (currentTime - lastMessageTime >= messageDisplayTime)) {
    lcd.setCursor(0, 0);
    lcd.print("                ");  // Clear the first row
    buttonMessageShowing = false;
    Serial.println("Cleared button message");
  }

  // Check if it's time to send the SysEx message
  if (initialDelayCompleted && (currentTime - lastSysExTime >= sysExInterval)) {
    if (!buttonMessageShowing) {
      requestPerformanceName();
      requestSlotName();
    }
    lastSysExTime = currentTime;  // Update the last SysEx message time
  }

  // Check buttons and send CC or SysEx
  for (int i = 0; i < numButtons; ++i) {
    if (digitalRead(buttonPins[i]) == HIGH) {
      if ((currentTime - lastDebounceTimes[i]) > debounceDelay) {
        if (i < 4) { // For buttons 1 to 4
          requestEffectModuleState(i);
        } else if (i == 4) { // Button 5
          button5State = !button5State;  // Toggle the state
          int ccValue = button5State ? 1 : 0;
          MIDI.sendControlChange(controlChangeValues[i], ccValue, 1);
          Serial.print("Sent CC for button 5: ");
          Serial.println(ccValue);
        } else if (i == 9 || i == 10) { // Buttons 10 and 11
          MIDI.sendControlChange(controlChangeValues[i], 0, 1);
          Serial.print("Sent CC for button ");
          Serial.print(i + 1);
          Serial.println(": 0");
        } else { // For buttons 6 to 8 and 12
          MIDI.sendControlChange(controlChangeValues[i], 127, 1);
          Serial.print("Sent CC for button ");
          Serial.print(i + 1);
          Serial.println(": 127");
        }
        lastDebounceTimes[i] = currentTime;  // Update the debounce time
      }
    }
  }

  // Update MIDI interface
  myMIDI.update();
}

// Request the effect state for buttons 1 to 4
void requestEffectModuleState(int buttonIdx) {
  uint8_t sysexMessage[][11] = {
    {0xF0, 0x00, 0x20, 0x33, 0x00, 0x00, 0x41, 0x00, 0x38, 0x03, 0xF7}, // Button 1
    {0xF0, 0x00, 0x20, 0x33, 0x00, 0x00, 0x41, 0x00, 0x3A, 0x03, 0xF7}, // Button 2
    {0xF0, 0x00, 0x20, 0x33, 0x00, 0x00, 0x41, 0x00, 0x3C, 0x03, 0xF7}, // Button 3
    {0xF0, 0x00, 0x20, 0x33, 0x00, 0x00, 0x41, 0x00, 0x3D, 0x03, 0xF7}  // Button 4
  };
  myMIDI.sendSysEx(sysexMessage[buttonIdx], sizeof(sysexMessage[buttonIdx]));
  Serial.print("Requested effect module state for button ");
  Serial.println(buttonIdx + 1);
}

// 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));
  Serial.println("Requested performance name");
}

// 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));
  Serial.println("Requested slot name");
}

Now it is working as intended, just missing an option to show the tuner info on the screen, but that's not a coding problem, i need first to figure out how to get that info (it doesn't seems to be MIDI or SysEx messages, or at least MIDI sniffing is not detecting it).
Thanks everyone for trying to help!

Don't do this. Choose one library and use it for everything, otherwise they will interfere.

Delete the following lines:

#include <USB-MIDI.h>
USBMIDI_CREATE_DEFAULT_INSTANCE();
  MIDI.begin(MIDI_CHANNEL_OMNI);

Then replace

MIDI.sendControlChange(controlChangeValues[i], ccValue, 1);

by

myMIDI.sendControlChange(controlChangeValues[i], ccValue);

i'll try thanks!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.