MIDI Serial Communication

Ciao a tutti!

Sto provando a utilizzare Arduino per leggere dei messaggi MIDI per convertirli in testo su un display LCD.
In particolare devo leggere dei messaggi MIDI composti da 39 byte.
Questo il codice che ho scritto:

byte byte1;
byte byte2;
byte byte3;
byte byte4;
byte byte5;
byte byte6;
byte byte7;
byte byte8;
byte byte9;
byte byte10;
byte byte11;
byte byte12;
byte byte13;
byte byte14;
byte byte15;
byte byte16;
byte byte17;
byte byte18;
byte byte19;
byte byte20;
byte byte21;
byte byte22;
byte byte23;
byte byte24;
byte byte25;
byte byte26;
byte byte27;
byte byte28;
byte byte29;
byte byte30;
byte byte31;
byte byte32;
byte byte33;
byte byte34;
byte byte35;
byte byte36;
byte byte37;
byte byte38;
byte byte39;

void setup() {
  Serial1.begin(31250);
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
}

void checkMIDI() {

  if (Serial1.available()) {
    byte1 = Serial1.read();
    byte2 = Serial1.read();
    byte3 = Serial1.read();
    byte4 = Serial1.read();
    byte5 = Serial1.read();
    byte6 = Serial1.read();
    byte7 = Serial1.read();
    byte8 = Serial1.read();
    byte9 = Serial1.read();
    byte10 = Serial1.read();
    byte11 = Serial1.read();
    byte12 = Serial1.read();
    byte13 = Serial1.read();
    byte14 = Serial1.read();
    byte15 = Serial1.read();
    byte16 = Serial1.read();
    byte17 = Serial1.read();
    byte18 = Serial1.read();
    byte19 = Serial1.read();
    byte20 = Serial1.read();
    byte21 = Serial1.read();
    byte22 = Serial1.read();
    byte23 = Serial1.read();
    byte24 = Serial1.read();
    byte25 = Serial1.read();
    byte26 = Serial1.read();
    byte27 = Serial1.read();
    byte28 = Serial1.read();
    byte29 = Serial1.read();
    byte30 = Serial1.read();
    byte31 = Serial1.read();
    byte32 = Serial1.read();
    byte33 = Serial1.read();
    byte34 = Serial1.read();
    byte35 = Serial1.read();
    byte36 = Serial1.read();
    byte37 = Serial1.read();
    byte38 = Serial1.read();
    byte39 = Serial1.read();
    digitalWrite(13, HIGH); //turn on led
    Serial.print(byte1, HEX);
    Serial.print("-");
    Serial.print(byte2, HEX);
    Serial.print("-");
    Serial.print(byte3, HEX);
    Serial.print("-");
    Serial.print(byte4, HEX);
    Serial.print("-");
    Serial.print(byte5, HEX);
    Serial.print("-");
    Serial.print(byte6, HEX);
    Serial.print("-");
    Serial.print(byte7, HEX);
    Serial.print("-");
    Serial.print(byte8, HEX);
    Serial.print("-");
    Serial.print(byte9, HEX);
    Serial.print("-");
    Serial.print(byte10, HEX);
    Serial.print("-");
    Serial.print(byte11, HEX);
    Serial.print("-");
    Serial.print(byte12, HEX);
    Serial.print("-");
    Serial.print(byte13, HEX);
    Serial.print("-");
    Serial.print(byte14, HEX);
    Serial.print("-");
    Serial.print(byte15, HEX);
    Serial.print("-");
    Serial.print(byte16, HEX);
    Serial.print("-");
    Serial.print(byte17, HEX);
    Serial.print("-");
    Serial.print(byte18, HEX);
    Serial.print("-");
    Serial.print(byte19, HEX);
    Serial.print("-");
    Serial.print(byte20, HEX);
    Serial.print("-");
    Serial.print(byte21, HEX);
    Serial.print("-");
    Serial.print(byte22, HEX);
    Serial.print("-");
    Serial.print(byte23, HEX);
    Serial.print("-");
    Serial.print(byte24, HEX);
    Serial.print("-");
    Serial.print(byte25, HEX);
    Serial.print("-");
    Serial.print(byte26, HEX);
    Serial.print("-");
    Serial.print(byte27, HEX);
    Serial.print("-");
    Serial.print(byte28, HEX);
    Serial.print("-");
    Serial.print(byte29, HEX);
    Serial.print("-");
    Serial.print(byte30, HEX);
    Serial.print("-");
    Serial.print(byte31, HEX);
    Serial.print("-");
    Serial.print(byte32, HEX);
    Serial.print("-");
    Serial.print(byte33, HEX);
    Serial.print("-");
    Serial.print(byte34, HEX);
    Serial.print("-");
    Serial.print(byte35, HEX);
    Serial.print("-");
    Serial.print(byte36, HEX);
    Serial.print("-");
    Serial.print(byte37, HEX);
    Serial.print("-");
    Serial.print(byte38, HEX);
    Serial.print("-");
    Serial.println(byte39, HEX);
  }
}

void loop() {
  checkMIDI();
  delay(100);
  digitalWrite(13, LOW); //turn led off
}

Il problema che mi ritrovo è che se ricevo 3 byte questi vengono letti correttamente, se invece ne ricevo di più i byte che ricevo sono errati (solitamente pari a FF in HEX).

Possibile che ci sia qualcosa di errato nel codice o devo cercare l'errore da qualche altra parte?

Grazie!

P.S. Se qualcuno avesse anche qualche suggerimento per semplificare la scrittura del codice con qualche loop è ben accetto

ciao...ti crei un array di 39 elementi e non 39 bytes singoli.
usi il metodi Serial.readBytes(tuaArray,39)
stamoi con ciclo for...

byte mioArray[39];

void setup() {
  Serial1.begin(31250);
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);

}

void loop() {
  if (Serial.available()) {
    Serial.readBytes(mioArray, 39);
    digitalWrite(13,HIGH);
  }
  for (byte i = 0; i < sizeof(mioArray); i++) {
    Serial.print(mioArray[i], HEX);
    if (i < sizeof(mioArray) - 1) {
      Serial.print("-");
    }
    else {
      Serial.println();
      digitalWrite(13,LOW);
    }
  }
  delay(100);
}

PS: io ho seguito il tuo programma come "esito"...attenzione che se non si ricevono nuovi dati l'array conterrà l'ultimo valore inviato (su ogni singolo indice).

Grazie per la risposta.
Però non capisco perchè ora continua a stamparmi i byte anche quando non viene inviato nessun segnale alla porta seriale. In teoria se non mando segnali non dovrei vedere nessuna operazione.

Ad ogni modo anche con questa soluzione non ho risolto il problema iniziale, ovvero mi vengono letti solo i primi 3 byte.
Grazie

readBytes(array, lenght) legge e copia tanty byte quanto vale lenght...o fino al riempimento di array o fino ad un time out.
si è vero che stampa l'array in continuo...si risolve "facile"
però per quanto detto all'inizio...se salvi solo 3 byte....vuol dire che l'invio del dato non va bene...sei sicuro hai fatto delle semplice Serial.read() su quello che arriva?
prova questo...se non stampa mai vuol dire che i 39 byte non arrivano.
prova questo...

#define TIME_OUT 200

byte mioArray[39];
bool stringaCompleta = false;
unsigned long zeroBuffer = 0;

void setup() {
  Serial1.begin(31250);
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);

}

void loop() {
  zeroBuffer = millis();
  while (Serial.available()) {
    if (Serial.available() == sizeof(mioArray) && millis() - zeroBuffer < TIME_OUT) {
      Serial.readBytes(mioArray, sizeof(mioArray));
      digitalWrite(13, HIGH);
      stringaCompleta = true;
    }
    else if (millis() - zeroBuffer > TIME_OUT) {
      Serial.println("ERROR...TIME OUT!");
      int filled = Serial.available();
      for (int i = 0; i <= filled; i++) {
        char c = Serial.read();
      }
    }
  }
  if (stringaCompleta) {
    for (byte i = 0; i < sizeof(mioArray); i++) {
      Serial.print(mioArray[i], HEX);
      if (i < sizeof(mioArray) - 1) {
        Serial.print("-");
      }
      else {
        Serial.println();
        digitalWrite(13, LOW);
      }
    }
    stringaCompleta = false;
  }
}

Provato.
Ora ogni qualvolta invio il segnale MIDI mi stampa "ERROR...TIME OUT!"
Ammetto però che non mi è molto chiaro cosa hai fatto in questo codice.
Io l'ho solo modificato in merito all'indice della porta seriale, ricevo il segnale su Serial1, stampo su Serial. Di seguito il codice così come l'ho modificato, giusto per sicurezza che non sia qui l'errore
Grazie

#define TIME_OUT 200

byte mioArray[39];
bool stringaCompleta = false;
unsigned long zeroBuffer = 0;

void setup() {
  Serial1.begin(31250);
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);

}

void loop() {
  zeroBuffer = millis();
  while (Serial1.available()) {
    if (Serial1.available() == sizeof(mioArray) && millis() - zeroBuffer < TIME_OUT) {
      Serial1.readBytes(mioArray, sizeof(mioArray));
      digitalWrite(13, HIGH);
      stringaCompleta = true;
    }
    else if (millis() - zeroBuffer > TIME_OUT) {
      Serial.println("ERROR...TIME OUT!");
      int filled = Serial1.available();
      for (int i = 0; i <= filled; i++) {
        char c = Serial1.read();
      }
    }
  }
  if (stringaCompleta) {
    for (byte i = 0; i < sizeof(mioArray); i++) {
      Serial.print(mioArray[i], HEX);
      if (i < sizeof(mioArray) - 1) {
        Serial.print("-");
      }
      else {
        Serial.println();
        digitalWrite(13, LOW);
      }
    }
    stringaCompleta = false;
  }
}

Se ti stampa errore time out vuol dire che in 200 millisecondi non ricevi 39 byte...fai una prova e lascia tutto a Serial e non Serial1 ed invia da monitor seriale 39 byte...tipo 3 serie da 0 a 9 ed una da 9 ad 1...senza LN o CR.
Poi fai una prova ad inviare meno di 39 byte...

Oltre al consiglio di creare un array (ma perché hai fatto 39 variabili singole? Non sai come si gestiscono gli array?) aggiungo: che sono sti 39 byte? Le informazioni MIDI non sono mica pacchetti da 39 byte fissi...

Il primo byte è lo status byte che indica il canale ed il tipo di messaggio, ed i successivi dipendono quindi dal tipo di messaggio.

Ad esempio un NoteON è composto da 3 byte (e guarda caso...), uno Status, uno che indica la nota ed uno che fornisce la velocity, ad esempio:

Byte 0: Status = 148 (NoteON canale 5)
Byte 1: Nota = 64 (vado a memoria credo sia E4)
Byte 2: Velocity = 127

Quindi tu DEVI leggere il primo byte ed in base a questo capire quanti altri byte ci saranno, e leggere SOLO quelli.

Nota comunque che Serial.available() ti dice che sulla seriale ci sono dei dati, ma se non sai QUANTI sono, non puoi leggerne 39! La funzione ti restituisce però il numero di byte ricevuti e presenti nel buffer seriale, quindi ad esempio 3 indica che ha 3 byte, e quindi devi fare 3 e solo 3 read() ed analizzare quelli.

Per finire, considera che se Arduino riceve dati MIDI è possibile che oltre a Note ON riceva anche altri messaggi (Control Change, Program Change...) quindi se a te interessano solo le note, devi leggere lo status e leggere i dati solo dell'evento Note ON (e/o Note OFF) ignorando tutti gli altri o meglio acquisnedone i byte ma poi non eseguendo nulla, fino a che non determini un byte Status Note ON o Note OFF.

Se non hai conoscenze sufficienti sul protocollo MIDI ti conviene prima studiare quello, e poi 'pensare di implementare qualcosa su Arduino... :wink:

Docdoc innanzitutto grazie per la risposta.
Conosco abbastanza il protocollo MIDI e conoscevo già le nozioni che hai riportato.
Quello che sto cercando di fare però non è gestire il classici segnali midi di note, bensì i SysEx (Sistem Exclusive Message).
In particolare sto usando il software Hauptwerk che per inviare messaggi di testo usa questo sistema con il seguente protocollo:

The format of the system exclusive messages (for hardware developers) is:
- Byte 1: 0xf0 - system exclusive start.
- Byte 2: 0x7d - fixed manufacturer ID.
- Byte 3: 0x01 - message type code for Hauptwerk LCD output message.
- Byte 4: destination panel unique ID byte 1 (7-bit LSB).
- Byte 5: destination panel unique ID byte 2 (7-bit MSB).
- Byte 6: color code 0-127 (0=off/black, 1=white, 2=red, 3=green, 4=yellow, 5=blue, 6=magenta, 7=cyan, others user-defined).
- Bytes 7-38: the 32 ASCII (8-bit) bytes for the text to display.
- Byte 39: 0xf7 - end of system exclusive message.
If you are building a new MIDI organ console for Hauptwerk then incorporating about five (or even seven) 32-character LCD panels should
allow most key Hauptwerk status information to be displayed conveniently on the MIDI console.
Il tutto finalizzato a visualizzare dei messaggi su un display LCD 16x2.
Quindi i segnali midi che ricevo sono esattamente di 39 bytes.
Forse così è più chiaro quello che mi serve.

Samsos90:
Quello che sto cercando di fare però non è gestire il classici segnali midi di note, bensì i SysEx (Sistem Exclusive Message).
...
Il tutto finalizzato a visualizzare dei messaggi su un display LCD 16x2.
Quindi i segnali midi che ricevo sono esattamente di 39 bytes.
Forse così è più chiaro quello che mi serve.

Si, così è già più chiaro. non conosco Haupwerk e cosa faccia (ma non è un VST per organo??) ma confido che quella descrizione sia corretta ovviamente.

Resta comunque il fatto che tu DEVI essere certo che quello che stai ricevendo è un SysEx e dalla fonte attesa, quindi dovresti aspettare di ricevere esattamente i primi 3 byte del messaggio SysEx.

Quindi ad esempio (ma è solo un esempio di possibile implementazione, cis ono anche altri metodi ma per ora non voglio confonderti le idee) puoi definire come ti hanno già suggerito un buffer di byte da 39 elementi (diciamo "byte buf[39]") che conterrà l'intero SysEx, ed una variabile indice (diciamo "num") che "punta" all'ultimo valore inserito (inizialmente impostato -1 che significa "buffer vuoto").

Potresti leggere i caratteri uno alla volta nel loop se Serial.available è maggiore di zero e mettere il valore letto in una "byte mybyte;".
Nel loop se leggi il byte 0xf0 allora inizi a scrivere nel buffer ("buf[++num]=mybyte");
Se il carattere successivo è diverso da 0x7d allora resetti l'indice e così via anche per il terzo byte dell'intestazione.

Una volta che avrai ricevuto l'intestazione corretta (num == 2), allora devi leggere tutto il resto dei byte prima di fare qualcosa, ossia continuare ad accumulare i singoli byte ricevuti dentro al tuo array, e solo quanto ricevi l'ultimo (0xf7) allora prenderai i 32 caratteri (che suppongo/spero siano zero-delimited se sono stringhe di lunghezza variabile).

Hauptwerk è si un VST per organo, ma ha anche molte funzionalità aggiuntive gestite tutte mediante MIDI, tra cui la possibilità di inviare piccoli messaggi di testo per visualizzarli su piccoli display.

In merito alla tua risposta non sono sicuro di aver compreso esattamente quello che intendi.
Diciamo che in questo momento in cui sto cercando di realizzare il tutto ho sempre la certezza di inviare un SysEx, perchè dal software ho proprio la possibilità di inviare messaggi di esempio potendo modificare anche alcune opzioni. Ora sto utilizzando questo codice per leggerli:

byte sysExArray[39];

void setup() {
  Serial1.begin(31250);
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
}

void checkMIDI() {
  do {
    if (Serial1.available()) {
      Serial1.readBytes(sysExArray, 39);
      digitalWrite(13, HIGH); //turn on led
      for (byte i = 0; i < sizeof(sysExArray); i++) {
        Serial.print(sysExArray[i], HEX);
        if (i < sizeof(sysExArray) - 1) {
          Serial.print("-");
        }
        else {
          Serial.println();
          digitalWrite(13, LOW);
          for ( int i = 0; i < sizeof(sysExArray);  ++i )
            sysExArray[i] = (char)0;
        }
      }
    }
  }
  while (Serial1.available() > 0);
}
void loop() {
  checkMIDI();
  //delay(100);
  digitalWrite(13, LOW); //turn led off
}

Con questo codice ottengo nel Monitor seriale la mia "stringa" di byte, in cui il primo è sempre F0, il secondo 7D, il terzo 1, così come mi aspetto che sia. E fin qui tutto ok.
Come quarto, quinto e sesto byte ottengo dei valori che non mi aspetto con il impostazioni che ho definito, ma cmq ottengo qualcosa. Dal settimo byte in poi invece ottengo solo 0, come se non fosse stato inviato nessun altro byte.

Per come l'ho capita la tua soluzione serve più che altro a smistare questo messaggio tra tutti gli altri eventuali che posso ricevere. Ma secondo me il problema ce l'ho a monte, cioè che di 39 leggo solo 6 bytes, di cui solo i primi 3 mi risultano corretti.
Ti ringrazio ancora per i suggerimenti

Ma mi sembrava che docdoc te lo avesse detto, che la serial.available NON ti dice se sono arrivati TUTTI i byte, ma solo che ne sono arrivati, ed eventualmente quanti
comunque adesso te lo dico io:
tu hai fatto una confusione da inganniere tra available e letture e vettori e syzeof
tu devi decidere se leggi tutti i dati in una volta sola, e allora fai una singola readbytes, ma in quel caso devi assicurarti che il messaggio sia completo e integro e della lunghezza corretta
oppure leggi i byte mano a mano che arrivano, li interpreti e li metti al posto giusto dell'array
di più da un laureato in ingegneria deve essere endogeno
PS, smetti di copiincollare a muzzo senza capire
dallo stile di programmazione si capisce che hai copiato da almeno due fonti differenti, senza capire cosa fanno e senza "uniformarle",

Samsos90:
Diciamo che in questo momento in cui sto cercando di realizzare il tutto ho sempre la certezza di inviare un SysEx, perchè dal software ho proprio la possibilità di inviare messaggi di esempio potendo modificare anche alcune opzioni.

Si ma sei sicuro che il software mandi su QUELLA porta MIDI solamente i SysEx?
Fatti un programmino come "serial dumper" ossia mandi, uno per uno, nella Serial i byte che leggi dalla Serial1 una cosa semplice del tipo:

void setup() {
  Serial1.begin(31250);
  Serial.begin(9600);
  Serial.println("Aruino serial dump");
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
}

void loop() {
  if (Serial1.available()) {
    digitalWrite(13, HIGH);
    Serial.println(Serial1.read(), HEX);
    digitalWrite(13, LOW);
  }
}

e vedi cosa ricevi esattamente (inclusi i tuoi SysEx ovviamente). In caso di difficoltà posta qui l'ouput seriale.

Ma secondo me il problema ce l'ho a monte, cioè che di 39 leggo solo 6 bytes, di cui solo i primi 3 mi risultano corretti.

Questo probabilmente perché, come cercavo di dirti, Serial.available non indica che hai ricevuto nel buffer tutti i dati che attendi, ma che ne ha almeno uno. Nel tuo caso forse solo 6. Tu devi ATTENDERE che tutti i byte del messaggio siano presenti prima di analizzarli (o accumulandoli uno ad uno dentro ad una variabile come ti ho suggerito, oppure attenderai che Serial.available ritorni 39 -anche se questo te lo sconsiglio a meno che ti non sia stra-certo che ricevi solo ed eseclusivamente quei SysEx!-).

Da laureato in ingegneria non ho mai studiato informatica, per tanto tutto quello che so fare l'ho imparato da autodidatta, mi si perdoni se non sono un intenditore.
Inoltre il mio non è stato un copia incollare senza capire, anche se non mi sono preoccupato di uniformare la forma.

docdoc, grazie di nuovo; giusto per chiarirmi le idee, poi proverò il tuo suggerimento, il mio ciclo do while non fa esattamente quello che mi dici, cioè, fintanto che ci sono byte in arrivo leggili? Oppure dovrei prevedere nel while > o = a 39 in modo che lui mi compie il ciclo nel momento in cui li ha ricevuti tutti?

Se avete qualche guida o manuale in merito alla comunicazione seriale e alle sue funzioni per arduino ben volentieri, perchè quello che trovo qui sul sito non mi chiarisce molto le idee.
Grazie

OK, taca banda....
all'ora, il tuo problema è semplice da risolvere, se cerchi qui sul forum ne trovi a decine di casi simili al tuo
comunque ti do due dritte su come cominciare:

  1. segui una strada (e una soltanto, se vai in una direzione cambiare a metà è deleterio)
  2. pensa prima a quello che fai, e descrivi le azioni da compiere, in italiano (a tradurre in 'C' ci penserai dopo)
  3. se un programma non va, si corregge una volta sola, se continua a non andare fai prima a buttarlo e riscriverlo da capo che metterci pezze, fidati che ci sono passato
  4. e qui si comincia a entrare nel merito:
    tu devi ricevere un messaggio che ti arriva da seriale, e questo messaggio è "infilato" nello stesso canale di comunicazione con altri millemila messaggi che NON ti interessano, ma CHE DEVI tenere in considerazione (anche ignorare è forma di considerazione)
    tra i millemila messaggi che devi discriminare a te interessano solo quelli che sono ben descritti dal tuo post #7
    e quindi i primi passi
    crea un array di 39 byte, dove stivare i vari byte in arrivo
    crea un indice che ti dice quale byte stai aspettando (aumenta tutte le volte che ne arriva uno)
    crea una variabile di messaggioricevuto, che vale 0 se il messaggio non è ncora arrivato, 1 se ricevuto ma non correttamente terminato, 2 se ricevuto e correttamente terminato
    tratta un solo byte per volta, fai un serial.read tutte le volte che hai serial.available alta, leggi un solo byte e trattalo in questa maniera:
    se l'indice è 0 E il byte è lo start scrivilo nella posizione 0, aggiorna l'indice, altrimenti scarta. termina il trattamento
    se l'indice è 1 E il byte è il giusto manifacturer scrivilo in posizione 1, aggiorna l'indice, altrimenti azzera indice e scarta. termina il trattamento
    se l'indice è 2 E il byte corrisponde al giusto tipo di messaggio scrivilo in posizione 3 e aggiorna l'indice, altrimenti scartalo, azzera l'indice. termina il trattamento
    se l'indice è 38 E il byte è il corretto terminatore segnala portando a 2 la variabile di messaggioricevuto
    se l'indice è 38 MA il byte NON è il corretto terminatore segnala portando a 1 la variabile di messaggio ricevuto
    se l'indice è minore di 38 ma maggiore di 2 registra nella posizione corretta il byte e aggiorna l'indice
    ogni volta che riceevi un byte controlla se la variabile di messaggioricevuto ha cambiato stato
    se non ha cambiato stato NON hai ancora ricevuto un messaggio completo
    se sì ma non è confermato decidi tu cosa fare
    se invece è sì, confermato, lo usi, che ci farai? lo stamperai su un LCD? bene stampalo, MA ricordati di riportare a zero la variabile di messaggio ricevuto
    ti assicuro che un programma siffatto funziona, e dato che hai capito il programma precedente sono sicuro che capirai anche come realizzare questo

docdoc, ho provato a a usare il tuo programmino serial dumper e quello che ottengo sono esattamente i 6 byte di cui parlavo prima, i primi 3 corretti gli altri no. Non ricevo nessun altro byte.

Standardoil, ho provato anche a seguire la tua proposta che a parole mi è abbastanza chiara e di cui ho provato a scrivere il codice che aggiungo qui di seguito. Purtroppo non funziona, ma la cosa che mi lascia più perplesso è che non ricevo proprio niente, non mi si accende neanche il led, come se non arrivasse nessun segnale. A livello hardware sono sicuro che tutto è a posto perchè con l'altro script funziona.
Sicuramente ho fatto qualche errore, ma non riesco a individuare dove.
Grazie

byte sysExArray[39];
int indice = 0;
int variabile = 0;
byte byteRead;

void setup() {
  Serial1.begin(31250);
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
}


void loop() {
  if (Serial1.available()) {
    digitalWrite(13, HIGH);
    byteRead = Serial1.read();
    if (byteRead == 0xF0 && indice == 0) {
      sysExArray[0] = 0xF0;
      indice = 1;
    }
    if (byteRead == 0x7D && indice == 1) {
      sysExArray[1] = 0x7D;
      indice = 2;
    }
    else {
      indice = 0;
    }
    if (byteRead == 0x01 && indice == 2) {
      sysExArray[2] = 0x01;
      indice = 3;
      variabile = 1;
    }
    else {
      indice = 0;
    }
    if (variabile == 1 && indice > 2 && indice < 38) {
      sysExArray[indice] = byteRead;
      indice = indice + 1;
    }
    if (variabile == 1 && indice == 38) {
      sysExArray[38] = byteRead;
      indice == 0;
      variabile == 2;
    }
    if (variabile == 2) {
      for (byte i = 0; i < sizeof(sysExArray); i++) {
        Serial.print(sysExArray[i], HEX);
        if (i < sizeof(sysExArray) - 1) {
          Serial.print("-");
        }
        else {
          Serial.println();
          for ( int i = 0; i < sizeof(sysExArray);  ++i )
            sysExArray[i] = (char)0;
          variabile == 0;
        }
      }
    }
    digitalWrite(13, LOW);
  }
}

Buono il tentativo
Qualche problema. stasera dopo il lavoro
Invece mi preoccupa il fatto che non ricevi più di 6 byte comunque
Il programma di docdoc ti mostra tutto quello che c'è, se non vedi il tuo messaggio significa che non c'è, devi assicurarti che venga trasmesso

Samsos90:
docdoc, ho provato a a usare il tuo programmino serial dumper e quello che ottengo sono esattamente i 6 byte di cui parlavo prima, i primi 3 corretti gli altri no. Non ricevo nessun altro byte.

Fammi vedere i byte che ricevi.
E postami un link al documento tecnico di cui hai riportato la tabella della codifica SysEx.

EDIT: ma tu hai letto per caso anche QUESTO?

Leggo:

LCD panel system
Hauptwerk is able to control 32-character LCD panels using custom MIDI system exclusive messages to show labels specific to the sample set loaded. Usually this would be used to show stop, coupler, piston and other control names next to MIDI draw-knobs/tabs on an organ console so that their function is clear when multiple instruments are used. However, one LCD panel can also be designated as a status display panel, upon which Hauptwerk will display a summary of the information shown in its main window title and status bar, along with an indication of whether an error has occurred.
Each panel can be controlled from any MIDI output port with no restrictions. Full details of the LCD panel
system, including the format of the custom system exclusive messages, are given in the MIDI output section.

Peccato che il link a "MIDI output section" non funzioni, ma in generale mi dà l'idea che ci sia qualcosa da attivare nel VST per far inviare i messaggi da mostrare sul display.
Ho letto che in Advanced MIDI applications > MIDI LCD Displays (etc) , devi abilitare il display e scegliere la corretta porta e scegliere cosa mostrare su ogni riga del display stesso, l'hai fatto?
Oltre alle cose chieste sopra, posta uno screenshot di quelle impostazioni del VST.

Ho letto anche il file che linki tu, ma ho fatto riferimento a questo che è la guida completa. In particolare a pagina 221 ci sono le specifiche per l'uso di display LCD con anche la parte che avevo riportato.
Haputwerk Guide

Come intuisci bene questi messaggi di default sono disattivati in quanti ai più non interessa utilizzarli. Nell'immagine "MIDI LCD Setting" riporto la schermata in cui attivo questa opzione definendo le varie configurazione che mi interessano, e dove è presente anche il tasto per inviare messaggi di test.
Definita la porta MIDI OUT da utilizzare le altre due opzioni non mi interessano, in quanto l'Hardware ID serve nel caso in cui utilizzo più display e il lamp color serve se si utilizzano dei led rgb che non mi interessano.
Di fianco alla finestra riporto il monitor seriale con il messaggio ricevuto di soli 6 byte.

La cosa interessante è che all'interno del software ho la possibilità anche di definire dei messaggi MIDI personalizzati da inviare. Nell'immagine che allego "MIDI Custom Message" posto lo screen di quello che ho provato a fare, cioè a crearmi un messaggio MIDI personalizzato e ad inviarlo con l'apposito pulsante. Di fianco a questo ho messo quello che mi risulta sul monitor seriale con il codice serial dump postato prima. I byte che leggo ogni volta che premo il tasto send sono 3, ma la cosa curiosa che sono sempre diversi. Nell'immagine puoi vedere quello che ottengo premendo più volte, ricevendo ogni volta solo 3 byte.

A questo punto mi piacerebbe sapere se c'è un altro programma che potrei utilizzare per provare a inviare messaggi SysEx e vedere se con quello funziona, per fugare il dubbio che il problema stia in Hauptwerk, o meglio, di come lo sto usando (anche se in tutte le altre parti funziona più che perfettamente).

come promesso, magari un po' in ritardo, ti metto il programma con evidenzieti i problemi

byte sysExArray[39];
int indice = 0;
int variabile = 0;
byte byteRead;

void setup()
{
    Serial1.begin(31250);
    Serial.begin(9600);
    pinMode(13, OUTPUT);
    digitalWrite(13, LOW);
}


void loop()
{
    if (Serial1.available())
    {
        digitalWrite(13, HIGH);
        // non ti spettare comunque di vedere lampeggiare il led, troppo veloce il ciclo
        byteRead = Serial1.read();
        tratta(byteRead);
        // fai fare tutto in una funzione apposta, non complicarti la loop

        if (variabile == 2)
            // e il caso di variabile=1: messaggio arrivato strano?
            // come minimo devi COMUNQUE azzerare la variabile
        {
            for (byte i = 0; i < sizeof(sysExArray); i++)
            {
                Serial.print(sysExArray[i], HEX);

                if (i < sizeof(sysExArray) - 1)
                {
                    Serial.print("-");
                }
                else
                {
                    // e qui cosa vuoi fare=
                    // se non sei ancora arrivato a 38 ristampi di nuovo?
                    // oltretutto azzeri la varibile solo in una else di un if nidificato?
                    // riscrivi la parte di stampa, che forse è meglio
                    Serial.println();

                    for (int i = 0; i < sizeof(sysExArray);  ++i)
                        sysExArray[i] = (char)0;

                    variabile == 0;
                }
            }
        }

        digitalWrite(13, LOW);
    }
}


void tratta(byte c)
{
    if (c == 0xF0)
    {
        // start
        indice = 0; // questo non dovrebbe essere necessario, ma male non fa
        sysExArray[indice++] = c;
        return;
        // fine, trattato un carattere usciamo, non serve proseguire
        // i byte arriva UNO alla volta dalla seriale
    }

    if (indice == 1)
    {
        if (c == 0x7D)
        {
            sysExArray[indice++] = c;
        }
        else
        {
            indice = 0;
        }

        return;
    }

    if (indice == 2)
    {
        if (c == 0x01)
        {
            sysExArray[indice++] = c;
        }
        else
        {
            indice = 0;
        }

        return;
    }

    if (indice == 38)
    {
        //messaggio terminato
        if (c == 0xf7)
        {
            // correttamente
            variabile = 2;
        }
        else  // non correttamente
        {
            variabile = 1;
        }

        return;
    }

    //tutti gli altri casi esclusi
    sysExArray[indice++] = c;
    return;
}

dagli uno sguardo, e vedi se ti sembra leggibile
se non lo fosse parliamone
comunque PRIMA cerca di capire perchè quei messsaggi che cerchi non ci sono

Ciao.
Ho provato a fare un prova con questo programma MIDI Tools.
Con questo programma ho provato a generare un messaggio midi SysEx, sia tipo quelli che dovrebbe generarmi l'hauptwerk, sia altri più corti giusto per testarli.
Bene, con il programmino serial dumper ottengo sempre solo 3 byte. A questo punto il problema è evidente che sta nell'arduino (software o hardware).
A livello hardware ho seguito questa guida per crearmi l'input MIDI su arduino MIDI input

Qualcuno mi sa dire se ha lo stesso problema mio?
Grazie