[RISOLTO] Shift register 74hc595 - MIDI

Buonasera a tutti!

Ho un problema nella gestione di 50 led collegati al mio arduino.

Tramite una "catena" di 7 shift register 74hc595 ho collegato 50 led all'arduino, in modo da poterne gestire l'accensione e lo spegnimento singolarmente.
Se invio 7 byte riesco ad accendere e spegnere i led come voglio, e fin qui tutto bene.

Quello che nella realtà mi serve fare è comandare questi led tramite input MIDI: io riceverò un segnale midi di tipo NotaOn e relativa nota per accendere uno specifico led, e un segnale NotaOff con relativa nota per spegnerlo. Quindi ad ogni led ho assegnato una nota in modo che in base al segnale midi ricevuto mi accenda o spenga quel singolo led.
Per fare questo mi sono creato dei bytes "oldConfig" che memorizzano lo stato di accensione dei led. Quando ricevo una nota midi in ingresso questa si va a sommare alla oldConfig in modo da determinare il nuovo stato di accensione dei led, che viene quindi inviato ai miei shift register.

Il codice che ho scritto è il seguente

//iniziazione della libreria MIDI
#include <MIDI.h>
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1,     HWinputMidi); //L'input MIDI avviene su RX1, HWinputMidi è il nome della funzione Midi creata


//byte che memorizzano le combinazioni per la corretta accensione dei led
byte oldConfig0 = B0; //chip 0
byte oldConfig1 = B0; //chip 1
byte oldConfig2 = B0; //chip 2
byte oldConfig3 = B0; //chip 3
byte oldConfig4 = B0; //chip 4
byte oldConfig5 = B0; //chip 5
byte oldConfig6 = B0; //chip 6

//Matrice di byte richiamata nelle funzioni di accensione dei led. La nota Midi ricevuta ed elaborata va a richiamare il relativo byte
byte ledOnMatrix[8] = {       B00000001,  // = 1
                              B00000010,  // = 2
                              B00000100,  // = 3
                              B00001000,  // = 4
                              B00010000,  // = 5
                              B00100000,  // = 6
                              B01000000,  // = 7
                              B10000000,  // = 8
                      };

//pin di output per i LED dei registri
int RlatchPin = 9;
int RclockPin = 10;
int RdataPin = 8;

void setup() {
  //pinMode per i LED registri
  pinMode(RlatchPin, OUTPUT);
  pinMode(RclockPin, OUTPUT);
  pinMode(RdataPin, OUTPUT);

   //creo le funzioni midi che mi servono
  // Initiate MIDI communications, listen to all channels
  HWinputMidi.begin(5);//Inizializzo il midi sul canale 5
  HWinputMidi.setThruFilterMode(0);//disattivo la funzione Thru del MIDI
  HWinputMidi.setHandleNoteOn(AccendiLedRegistri);//funzione per la lettura dei messaggi NoteOn
  HWinputMidi.setHandleNoteOff(SpegniLedRegistri);//funzione per la lettura dei messaggi NoteOff

  //Spengo tutti i led dell'organo
  regLedOn(B0);
  regLedOn(B0);
  regLedOn(B0);
  regLedOn(B0);
  regLedOn(B0);
  regLedOn(B0);
  regLedOn(B0);

}


//funzione che accende i Led dei registri
void regLedOn(byte number) {
  digitalWrite(RlatchPin, LOW);
  shiftOut(RdataPin, RclockPin, MSBFIRST, number);
  digitalWrite(RlatchPin, HIGH);
}


/* 
  lo schema delle impostazioni MIDI è il seguente:
  - chip 0 - ch5 - Note 0-7   (- 0) disponibili solo le note 1 e 2
  - chip 1 - ch5 - Note 8-15  (- 8)
  - chip 2 - ch5 - Note 16-23 (-16)
  - chip 3 - ch5 - Note 24-31 (-24)
  - chip 4 - ch5 - Note 32-39 (-32)
  - chip 5 - ch5 - Note 40-47 (-40)
  - chip 6 - ch5 - Note 48-55 (-48)
*/

//funzione per accensione led registri
void  AccendiLedRegistri(byte channel, byte noteByte, byte velocity) {
  if (channel == 5) { 
    //chip 0
    if (noteByte < 8) {
      regLedOn(oldConfig0 + ledOnMatrix[noteByte]); //chip 0 - sul chip 0 (il primo) leggo il vecchio byte e ci sommo il nuovo valore corrispondente al registro inserito.
      regLedOn(oldConfig1); //chip 1 - Sul chip 1 (sarebbe il secondo) rimando esattamente lo stesso byte dello stato attuale
      regLedOn(oldConfig2); //idem come sopra fino all'ultimo byte
      regLedOn(oldConfig3);
      regLedOn(oldConfig4);
      regLedOn(oldConfig5);
      regLedOn(oldConfig6);

      oldConfig0 = ledOnMatrix[noteByte] + oldConfig0; //imposto la oldConfig sul valore attuale
    }
    //chip 1
    if (noteByte < 16 && noteByte > 7) {
      noteByte = noteByte - 8;
      regLedOn(oldConfig0);
      regLedOn(oldConfig1 + ledOnMatrix[noteByte]);
      regLedOn(oldConfig2);
      regLedOn(oldConfig3);
      regLedOn(oldConfig4);
      regLedOn(oldConfig5);
      regLedOn(oldConfig6);

      oldConfig1 = ledOnMatrix[noteByte] + oldConfig1;
    }
    //chip 2
    if (noteByte < 24 && noteByte > 15) {
      noteByte = noteByte - 16;
      regLedOn(oldConfig0);
      regLedOn(oldConfig1);
      regLedOn(oldConfig2 + ledOnMatrix[noteByte]);
      regLedOn(oldConfig3);
      regLedOn(oldConfig4);
      regLedOn(oldConfig5);
      regLedOn(oldConfig6);

      oldConfig2 = ledOnMatrix[noteByte] + oldConfig2;
    }
    //chip 3
    if (noteByte < 32 && noteByte > 23) {
      noteByte = noteByte - 24;
      regLedOn(oldConfig0);
      regLedOn(oldConfig1);
      regLedOn(oldConfig2);
      regLedOn(oldConfig3 + ledOnMatrix[noteByte]);
      regLedOn(oldConfig4);
      regLedOn(oldConfig5);
      regLedOn(oldConfig6);

      oldConfig3 = ledOnMatrix[noteByte] + oldConfig3;
    }
 }
}
//funzione per lo spegnimento dei led registri
void  SpegniLedRegistri(byte channel, byte noteByte, byte velocity) {
  if (channel == 5) {//il funzionamento è identico al precedente con input NoteOff
    //chip 0
    if (noteByte < 8) {
      regLedOn(oldConfig0 - ledOnMatrix[noteByte]);
      regLedOn(oldConfig1);
      regLedOn(oldConfig2);
      regLedOn(oldConfig3);
      regLedOn(oldConfig4);
      regLedOn(oldConfig5);
      regLedOn(oldConfig6);

      oldConfig0 = oldConfig0 - ledOnMatrix[noteByte];
    }
    //chip 1
    if (noteByte < 16 && noteByte > 7) {
      noteByte = noteByte - 8;
      regLedOn(oldConfig0);
      regLedOn(oldConfig1 - ledOnMatrix[noteByte]);
      regLedOn(oldConfig2);
      regLedOn(oldConfig3);
      regLedOn(oldConfig4);
      regLedOn(oldConfig5);
      regLedOn(oldConfig6);

      oldConfig1 = oldConfig1 - ledOnMatrix[noteByte];
    }
    //chip 2
    if (noteByte < 24 && noteByte > 15) {
      noteByte = noteByte - 16;
      regLedOn(oldConfig0);
      regLedOn(oldConfig1);
      regLedOn(oldConfig2 - ledOnMatrix[noteByte]);
      regLedOn(oldConfig3);
      regLedOn(oldConfig4);
      regLedOn(oldConfig5);
      regLedOn(oldConfig6);

      oldConfig2 = oldConfig2 - ledOnMatrix[noteByte];
    }
    //chip 3
    if (noteByte < 32 && noteByte > 23) {
      noteByte = noteByte - 24;
      regLedOn(oldConfig0);
      regLedOn(oldConfig1);
      regLedOn(oldConfig2);
      regLedOn(oldConfig3 - ledOnMatrix[noteByte]);
      regLedOn(oldConfig4);
      regLedOn(oldConfig5);
      regLedOn(oldConfig6);

      oldConfig3 = oldConfig3 - ledOnMatrix[noteByte];
    }
 }
}
void loop() {
  HWinputMidi.read(); //leggo gli input midi


}

P.s nel codice ho troncato gli ultimi 3 shift register per motivi di lunghezza del messaggio

Ora, questo codice mi funziona senza problemi.
Il problema che ho è che questo sistema funziona bene solo se sul singolo led ricevo sempre l'input corretto, nel senso che se il led X è accesso posso ricevere solo un input NotaOff X per spegnerlo e viceversa. Se invece il led è acceso e ricevo input NotaOn questo mi va a pasticciare tutto scombinandomi tutti i led.
Quindi, la mia domanda è la seguente: c'è un modo di "leggere" lo stato del led in modo da ignorare l'input qualora il led sia già nello stato che richiederebbe l'input (notaOn-Acceso/notaOff-Spento)?
Se può essere d'aiuto tutto questo sistema funziona tramite midi con il software Hauptwerk, e lo sto utilizzando per visualizzare i registri dell'organo che sono attivati.
Grazie a tutti!

Se lavori con i bit come stai facendo tu, non devi fare la somma ma l'OR logico quindi non + ma ||

GRAZIE!

Non conoscevo l'esistenza di questa funzione. Grazie anche alla guida trovata a questa pagina sono riuscito a fare esattamente ciò che mi serviva.

Grazie di nuovo!