ricevere/decodificare/inviare messaggi

Ciao,
ho la necessità di decodificare dei messaggi in ingresso al mio arduino Mega e poi ritrasmetterli in uscita. Ho una schedai con due porte (midi in e midi out) che ho connesso all'arduino sulle TX/RX Serial1.

I messaggi sono composti da sequenze di byte secondo determinate regole:

Messaggio tipo1 è composto da 8+8 bit (2 byte):
primo byte = 11000000
secondo byte 0"xxxxxxx" (con "xxxxxxx" = mio programma)

Messaggio tipo2 composto da 8+8+8 bit (3 byte):
primo byte 10110000
secondo byte 0"zzzzzzz" (con "zzzzzzz" = controller da modificare)
terzo byte 0"yyyyyyy" (con "yyyyyyy" = valore da assegnare al controller)

Ho provato con Serial1.read all'interno di un "if" per sapere quando ricevo il byte 0xB0 oppure 0xC0 ma poi non so come "istruire" arduino per leggere 2 byte (vedi tipo1) e poi ritrasmetterli su TX1 se in ingresso riceve una sequenza 11000000 oppure leggere 3 byte (vedi tipo2) e poi ritrasmetterli su TX1 se riceve una sequenza 10110000.
Ho bisogno che il tempo tra lettura e re-invio sia il più rapido possibile.
La velocità con cui si susseguono i byte in ingresso non è "esagerata" e limitata a max 5 minuti. (non so se possa essere di aiuto ma giusto per dirlo :slight_smile: )

Grazie mille
Max

Maxgiovi:
Ho provato con Serial1.read all'interno di un "if" per sapere quando ricevo il byte 0xB0 oppure 0xC0 ma poi non so come "istruire" arduino per leggere 2 byte (vedi tipo1) e poi ritrasmetterli su TX1 se in ingresso riceve una sequenza 11000000 oppure leggere 3 byte (vedi tipo2) e poi ritrasmetterli su TX1 se riceve una sequenza 10110000.

Ad ogni byte letto imposti anche una variabile condizione/fase/situazione/stato o come preferisci chiamarla, e al byte successivo decidi cosa fare in base non solo al nuovo byte letto, ma anche alla condizione/fase/situazione/stato che hai impostato prima.

Posta il codice che hai tentato di usare.

Ciao,
P.

Mi pare semplice, ma non avendo postato il tuo codice possiamo solo darti indicazioni di massima.
Io farei una cosa del tipo:

...
byte buf[3]; // Buffer del pacchetto, buf[0] contiene il byte di start
byte bufptr = -1; // Puntatore ultimo byte, -1=ancora nessun pacchetto
const byte tipo1 = 0xC0;
const byte tipo2 = 0xB0;
...
  if ( Serial.available() )
  {
    byte b = Serial.read();
    switch (b)
    {
      case tipo1:
      case tipo2:
        // E' il primo byte di un pacchetto (byte start)
        bufptr = 0;
        buf[bufptr] = b;
        break;
      default:
        // Considero i byte solo dopo aver ricevuto il byte di start
        if ( bufptr > 0 )
        {
          buf[++bufptr] = b;
          if ( buf[0] == tipo1 && bufptr == 1 )
          {
            // Ricevuto pacchetto tipo 1!
            // Faccio quello che devo fare
...
            // Quindi resetto il buffer
            bufptr = -1;
          }
          else if ( buf[0] == tipo2 && bufptr == 2 )
          {
            // Ricevuto pacchetto tipo 2
            // Faccio quello che devo fare
...
            // Quindi resetto il buffer
            bufptr = -1;
          }
        }
      }
    }

Eccomi....scusate sono stato impegnato

posto il codice che ho provato e scopiazzato dal web. L'idea era quella di sostituire poi i Serial.println con dei Serial1.write.
Tuttavia se correttamente a video mi visualizza 2 numeri a fronte di un Program Change in ingresso, questi sono sempre uguali a 255. Mi sarei aspettato sempre 192 come primo (0xC0) e poi un'altro numero tra 0 e 127 come secondo numero.

void setup() {
  Serial1.begin(31250);
  Serial.begin(9600);
}

void loop() {
  if (Serial1.available() > 1) {//if at least 2 byte are received
    if (Serial1.read() == 0xC0) {

      byte commandByte = Serial1.read();//read first byte
      byte prognum = Serial1.read();//read next byte

      Serial.println(commandByte);
      Serial.println(prognum);
    }
  }
}

Maxgiovi:
Eccomi....scusate sono stato impegnato
posto il codice che ho provato e scopiazzato dal web. L'idea era quella di sostituire poi i Serial.println con dei Serial1.write.

Ok, ma copiato per copiato, provare il codice che ti ho scritto sopra, no?

Comunque parli di Program Change, 31250 bps, parliamo di MIDI quindi, prova questo codice, è la mia versione che ho "ritoccato" alla tua esigenza (ovviamente ti chiedo di cercare di capire COSA ho fatto...):

byte buf[3]; // Buffer del pacchetto, buf[0] contiene il byte di start
byte bufptr = -1; // Puntatore ultimo byte, -1=ancora nessun pacchetto
const byte PC = 0xC0;
const byte CC = 0xB0;

void setup() {
  Serial1.begin(31250);
  Serial.begin(9600);
}

void loop() {
  if ( Serial1.available() )
  {
    byte b = Serial1.read();
    switch (b)
    {
    case PC:
    case CC:
      // E' il primo byte
      bufptr = 0;
      buf[bufptr] = b;
      break;
    default:
      // Considero i byte solo dopo aver ricevuto il byte di start
      if ( bufptr >= 0 )
      {
        buf[++bufptr] = b;
        if ( buf[0] == PC && bufptr == 1 )
        {
          // Ricevuto Program Change
          Serial.print("PC ");
          Serial.println(buf[1], HEX);
          // Quindi resetto il buffer
          bufptr = -1;
        }
        else if ( buf[0] == CC && bufptr == 2 )
        {
          // Ricevuto Control Change
          Serial.print("CC ");
          Serial.print(buf[1], HEX);
          Serial.print(" ");
          Serial.println(buf[2], HEX);            
          // Quindi resetto il buffer
          bufptr = -1;
        }
      }
    }
  }
}

docdoc:
Ok, ma copiato per copiato, provare il codice che ti ho scritto sopra, no?

Grazie docdoc,

ci ho provato ma non ha dato risultati (ho provato ad inserire un Serial.print come poi hai proposto tu)
Non so se sia giusta la mia considerazione ma vedo che al primo "giro" con lo switch se ricevi un tipo1 o un tipo2 setti il puntatore a 0 (bufptr = 0), tuttavia nella condizione di defaulf entri nell'if solo se bufptr > 0...quindi temo che non ci entri mai.
Non so se sono in errore e forse basta correggere con un >=.

Ad ogni modo ti ringrazio perchè mi pare un'ottima soluzione. Proverò anche quella successiva.

Grazie
Max

Maxgiovi:
Non so se sono in errore e forse basta correggere con un >=.

Si, esatto, infatti nella seconda versione avevo già corretto la cosa, se vedi.
Fammi sapere.

docdoc:

byte bufptr = -1;

Mmmmmmmm......

docdoc:

byte bufptr = -1; // Puntatore ultimo byte, -1=ancora nessun pacchetto

Claudio_FF:
Mmmmmmmm......

Ho sostituito il byte con int perchè mi sembrava che byte va da 0 a 255. Oggi proverò lo sketch di docdoc che ringrazio per l'idea. Poi faccio sapere

Max

Funziona alla grande.

Grazie docdoc

Ho sostituito il byte con int perchè mi sembrava che byte va da 0 a 255. Oggi proverò lo sketch di docdoc che ringrazio per l'idea. Poi faccio sapere

Si, però funziona anche con il tipo byte a patto che bufptr (che chiamerei buf_idx perché è un indice) non arrivi mai a 255 che equivale a -1.

Ciao.

Maurotec:
Si, però funziona anche con il tipo byte a patto che bufptr (che chiamerei buf_idx perché è un indice) non arrivi mai a 255 che equivale a -1.

Mi sa di no, c'è quel:

default:
    // Considero i byte solo dopo aver ricevuto il byte di start
    if ( bufptr >= 0 )
    {

che farebbe già considerare buoni tutti i byte diversi dagli start

Maxgiovi:
Ho sostituito il byte con int perchè mi sembrava che byte va da 0 a 255.
Oggi proverò lo sketch di docdoc che ringrazio per l'idea. Poi faccio sapere

Si, scusa, è un mio refuso. In genere ho l'abitudine di mettere byte gli indici degli array (purché ovviamente non abbiano più di 255 elementi), ma poi ho cambiato l'inizializzazione a -1 per indicare che non ho ricevuto nulla dimenticando di cambiare anche il tipo.

Claudio_FF:
Mi sa di no, c'è quel:
if ( bufptr >= 0 )
che farebbe già considerare buoni tutti i byte diversi dagli start

Esatto, bufptr=-1 equivale a 255 quindi entrerebbe sempre nella "if". Va impostato ad int.