Dubbio sul posizionamento di un pezzo di codice

Ciao a tutti!

Sto avendo un dubbio nel capire come mai, spostando una parte di codice da una posizione ad un'altra, succedono problemi nell'esecuzione del codice.

CIRCUITO:

Il sistema è realizzato con due Arduino Nano uno Master ed uno Slave.

Nel Master sono collegati dei pulsanti che comandano la 5v con resistenze di pulldown nei pin:
da 2 a 9 (8 pulsanti).

Nello Slave sono collegati dei leds con polo negativo in comune nei corrispettivi pin da 2 a 9 (8 leds).

Le due schedine comunicano via seriale (UART/USART).

PROTOCOLLO:

Il protocollo utilizza un sistema a codifica ASCII dove mando 4 bytes:

1.Byte = Indirizzo (contiene una matrice di caratteri da 0 a 9 da 'a' a 'z' e da 'A' a 'Z' - 62 caratteri)
2.Byte = CODE A (contiene una matrice di caratteri da 0 a 9 da 'a' a 'z' e da 'A' a 'Z' - 62 caratteri)

3.Byte = CODE B (contiene una matrice di caratteri da 0 a 9 da 'a' a 'z' e da 'A' a 'Z' - 62 caratteri)
Nel Master vengono utilizzati due caratteri: '1' se l'ingresso è a uno logico e '2' se l'ingresso e a zero logico.

4.Byte = Terminatore (il carattere di terminazione > '.' )

Il Master decodifica l'ingresso e lo manda via seriale:

1.Premo il pulsante 0 (collegato al pin 2) e in seriale viene inviato il messaggio: 001.
2.Rilascio il pulsante 0 e in seriale viene inviato il messaggio: 002.

1.Premo il pulsante 3 (collegato al pin 5) e in seriale viene inviato il messaggio: 031.
2.Rilascio il pulsante 3 e in seriale viene inviato il messaggio: 032.

Se ci sono più ingressi vengono codificati per creare messaggi anche con le lettere per esempio:

0a3. S4Z. 45J. ecc ecc

In totale posso inviare, facendo le combinazioni, 62*62 codici = 3844 variabili booleane con 2 bytes + un byte di valore e uno di terminazione.

Codice Master:

#define Num_In 8
#define Debug_Led 13
byte Pin_In[Num_In] = {2, 3, 4, 5, 6, 7, 8, 9};
bool Input[Num_In], Last_Input[Num_In];

char Char_Matrix[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};

#define Time_Cycle 500
int Counter_Cycle;

void setup() {

  delay(10);

  for (byte i = 0; i < Num_In; i++) {
    pinMode(Pin_In[i], INPUT);
  }

  pinMode(Debug_Led, OUTPUT);

  Serial.begin(115200);

  delay(100);

}

void loop() {

  delay(1);

  Read_Inputs();

  Serial_Process();

  Cycle_Process();

}

void Cycle_Process(){
  if(Counter_Cycle < Time_Cycle){
    Counter_Cycle++;
  }else{
    digitalWrite(Debug_Led, !digitalRead(Debug_Led));
    Counter_Cycle = 0;
  }
}

void Read_Inputs() {
  for (byte i = 0; i < Num_In; i++) {
    Input[i] = digitalRead(Pin_In[i]);
  }
}

void Serial_Process() {
  for (byte i = 0; i < Num_In; i++) {
    if (Input[i] != Last_Input[i]) {
      if (Input[i] == 1) {
        Serial_Message_ASCII(0, i, 1, '.');
      } else {
        Serial_Message_ASCII(0, i, 2, '.');
      }
      Last_Input[i] = Input[i];
    }
  }
  
}

void Serial_Message_ASCII(byte ADDRESS, byte CODE_A, byte CODE_B, byte TRM) {
  Serial.write(Char_Matrix[ADDRESS]);
  Serial.write(Char_Matrix[CODE_A]);
  Serial.write(Char_Matrix[CODE_B]);
  Serial.write(TRM);
}

Codice Slave:

#define Num_Out 8
#define Serial_Num_Out 64
#define Debug_Led 13
byte Pin_Out[Num_Out] = {2, 3, 4, 5, 6, 7, 8, 9};
bool Output[Num_Out], Serial_Out[Serial_Num_Out];

#define Char_Matrix_Size 62
char Char_Matrix[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};

#define Buffer_Size 8
byte Buffer[Buffer_Size];
byte Data_X, Data_Y;

#define Time_Cycle 500
int Counter_Cycle;

void setup() {

  delay(10);

  for (byte i = 0; i < Num_Out; i++) {
    pinMode(Pin_Out[i], OUTPUT);
  }

  pinMode(Debug_Led, OUTPUT);

  Serial.begin(115200);

  delay(100);

}

void loop() {

  delay(1);

  Serial_Process();

  Cycle_Process();

  for (byte i = 0; i < Num_Out; i++) {
    Output[i] = Serial_Out[i];
  }

  Write_Outputs();

}

void Cycle_Process() {
  if (Counter_Cycle < Time_Cycle) {
    Counter_Cycle++;
  } else {
    digitalWrite(Debug_Led, !digitalRead(Debug_Led));
    Counter_Cycle = 0;
  }
}

void Serial_Process() {

  if (Serial.available() > 0) {

    while (Serial.available() > 0) {

      Serial.readBytesUntil('.', Buffer, Buffer_Size);

      Serial_Decoder();

    }

    //Serial_Decoder();

  }

  //Serial_Decoder();

}

void Serial_Decoder() {

  //ADDRESS
  if (Buffer[0] == '0') {

    for (byte i = 0; i < Char_Matrix_Size; i++) {

      //CODE A
      if (Buffer[1] == Char_Matrix[i]) {

        if (Buffer[2] == '1') {
          Serial_Out[i] = 1;
        } else if (Buffer[2] == '2') {
          Serial_Out[i] = 0;

        }

      }

    }

  }

}

void Write_Outputs() {
  for (byte i = 0; i < Num_Out; i++) {
    digitalWrite(Pin_Out[i], Output[i]);
  }
}

Ora veniamo al dunque:

if (Serial.available() > 0) {

    while (Serial.available() > 0) {

      Serial.readBytesUntil('.', Buffer, Buffer_Size);

      Serial_Decoder();

    }

  }

  //Serial_Decoder();

Nella partizione di codice seguente il posizionamento della funzione Serial_Decoder() se posta all'interno del ciclo While funziona e vedo i led che si accedono e spengono quando premo i pulsanti collegati al Master.

Se invece la faccio eseguire all'esterno del codice che controlla se ci sono dati seriali tutto va in TILT !!! I leds si accendono e avvolte si bloccano sia in accensione o in spegnimento, non è reattiva la comunicazione come se si resetassero le variabili... e non riesco a capire il perchè :frowning:

Codice della funzione Serial_Decoder() :

void Serial_Decoder() {

  //ADDRESS
  if (Buffer[0] == '0') {

    for (byte i = 0; i < Char_Matrix_Size; i++) {

      //CODE A
      if (Buffer[1] == Char_Matrix[i]) {

        if (Buffer[2] == '1') {
          Serial_Out[i] = 1;
        } else if (Buffer[2] == '2') {
          Serial_Out[i] = 0;

        }

      }

    }

  }

}

Grazie a tutti dell'aiuto in anticipo !!!! :slight_smile:

guarda, il tuo programma non è bello,
ma almeno è ben indentato, e questo aiuta a capire

ora la domanda è: cosa succederebbe se arrivassero due o più trasmissioni molto vicine?

in un caso, quello che funziona, i dati vengo trattati appena dopo averli ricevuti
nell'altro caso invece avresti dei problemi di sincronia tra ricezione ed esecuzione

comunque ripensa a questa affermazione

che non è solo sbagliata: hai detto un'impossibilità grande come una casa, da li forse discendono i tuoi problemi

io l'aiuto in anticipo non te lo ho mica dato, forse ti sei sbagliato :grinning:

comunque concordo con Hardin, Salvor, primo sindaco di Terminus, organizzatore del colpo di stato che ha risolto la prima crisi Sheldon
insomma un tipo da non frequentare :sweat_smile:

comunque quel cndo di 64x64 è proprio campato in aria
se hai due byte utili al massimo, a proprio al massimo, puoi trasmettere 16 variabili booleane indipendenti, e questo se lo fai senza tutto quel tuo sovra-codificare, che rallenta l'esecuzione e accoppa l'efficenza

però credo di aver capito cosa vuoi dire:
puoi sorvegliare delle variabili booleane indipendenti e codificarne il cambio di stato
ma non sono tante qunte credi, ma al massimo 64
buona domenica

A prescindere dall'algoritmo che non fa impazzire nemmeno me.
Di base converti un numero in un codice corrispondente ASCII nel master per poi fare la conversione da ASCII ad un numero nello slave... c'è un passaggio di troppo per come la vedo io.

Ad ogni modo non è questo il punto!
Se porti fuori dal while la funzione di parsing, dopo aver ricevuto il primo messaggio vai a fare il controllo di continuo perché if (Buffer[0] == '0') { sarà sempre vero.

Non vedo infatti nessun clear del buffer ed essendo Buffer[] globale mantiene in memoria i valori dell'ultima stringa ricevuta.

Ciao Salvohardin il programma funziona ed è stato testato, quello che intendevo è abbastanza semplice:

Ogni byte, da come ho scritto, invia dei caratteri ASCII da '0' a '9' da 'a' a 'z' e da 'A' a 'Z'
Quindi avendo 2 bytes d'indirizzo e uno di valore il numero massimo di combinazioni è 62 elementi che contiene il primo byte per 62 elementi che contiene il secondo byte.

Tengo a precisare che gli elementi che vengono inviati in seriale sono di 62 caratteri e non 64...

64 elementi è la matrice Serial_Out[64] quando in essa ne uso solo 62... mi sono tenuto largo...

Ovvero: 3844 combinazioni indipendenti che, se associate a tante variabili booleane, posso controllarle in maniera indipendente.

Il valore del bit codificato viene determinato dal terzo byte e il quarto come terminatore del messaggio.

Chiaro, non è possibile utilizzarle tutti nel programma effettivo poichè nel codice slave vado a codificare se il primo byte e a zero e poi con il secondo le 62 variabili.

Il codice Salve è solo una "mezza" decodifica che mi serve solo per vedere se funziona il codice..
Oltre al fatto che Arduino Nano non avrebbe sufficiente memoria SRAM da dedicare per 3844 variabili booleane.

Quindi i problemi non sono legati al fatto che posso controllare 3844 variabili che tra l'altro nel codice non gestisco...

Il test che ho eseguito, in passato, è stato collegare 15 moduli DOTMATRIX in cascata da 256 leds ciascuno ad un Arduino Mega quindi: 256*15 = 3840 singoli led.

Scusate se forse mi sono spiegato male :frowning:

Quindi quello che chiedo non è un giudizio sul codice che funziona ma più che altro una delucidazione del perchè se sposto la funzione Serial_Decoder() al di fuori del controllo della recezione seriale tutto funziona male... mi sto perdendo qualcosa di come ragiona la funzione Serial.available()... bho

Hahaahha divertente proprio :frowning:

  1. Prima di tutto gli elementi sono 62 e non 64... non so dove lo avete letto... :frowning:
  2. Ho risposto a Salvorhardin di certe precisazioni che forse non avete capito... :smiley:
  3. Penso di aver chiesto un'altra domanda rispetto alle risposte che mi sono trovato...
  4. Il codice funziona ed è testato :smiley:

Ah interessante :smiley:

Però non ho ancora capito il perchè...

Non guardare com'è fatto l'algoritmo :smiley: lui funziona ed è stato testato per anni...
Vai a leggere cosa ho risposto a Salvorhardin...

Quello che chiedo è una delucidazione del perchè va in TILT il sistema quando metto la funzione Serial_Decoder() al di fuori del blocco di recezione seriale...

Ma infatti ho anche scritto che non è questo il punto e ho scritto anche perché la funzione Serial_Decoder() non si comporta come ti aspetti :roll_eyes:

Come ho risposto a Salvarhardin la funzione Serial_Decoder() è una mezza decodifica, quindi nel codice effettivo dello Slave vado a leggere massimo 62 varibili booleane... (ne ho dichiarate 64 per sicurezza)...
Sta di fatto che non centra cosa fa all'interno ma ben sì perchè se messa all'esterno del controllo di recezione seriale non funziona e se la metto dentro il ciclo While() va a meraviglia...

Evidentemente non ho capito con funziona bene il ciclo While con all'interno la funzione Serial.readBytesUntil()...

Prova a ripulire Buffer prima di scriverci altro

void Serial_Process() {
  if (Serial.available() > 0) {
    ///////////////////////////////////////
    memset(Buffer, 0, Buffer_Size);
    ///////////////////////////////////////
    while (Serial.available() > 0) {
      Serial.readBytesUntil('.', Buffer, Buffer_Size);
      // Serial_Decoder();
    }
    //Serial_Decoder();
  }
  Serial_Decoder();
}

Anzi, forse sarebbe meglio farlo dopo aver fatto il parsing

void Serial_Process() {
  if (Serial.available() > 0) {
    while (Serial.available() > 0) {
      Serial.readBytesUntil('.', Buffer, Buffer_Size);
      // Serial_Decoder();
    }
    //Serial_Decoder();
  }
  Serial_Decoder();
  ///////////////////////////////////////
  memset(Buffer, 0, Buffer_Size);
  ///////////////////////////////////////
}

Ohhhhhh Figo Grazie ! :smiley:

oHHHHHHHHHHHH Interessante !!!! :smiley:

Inoltre
Maschio
E possessore di un veicolo a motore termico
(Lo ho usato subito dopo il colpo di stato)
Confermo: non frequentatemi

A margine, non del tutto vero. Bitmappando i bit, occupi un ottavo dello spazio, per cui ce ne potrebbero stare oltre diecimila.

Sì ok ma per avere un testo leggibile e per quello che devo fare io utilizzo Array di varibili booleane, quindi lavorare con varibili booleane che occupano comunque un byte succede che è troppa memoria...

Adesso dovrei provare a vedere come mappare perchè non ho idea di come fare...

Puoi benissimo dichiarare una struttura lunga un BYTE che è accessibile bit a bit in forma leggibilissima ... esempio (do nome alla struttura BY ed i vari bit li chiamo b0, b1 .. b7, ma, ovviamente, puoi usare i nomi che vuoi):

struct BY {
  uint8_t b0 : 1;
  uint8_t b1 : 1;
  uint8_t b2 : 1;
  uint8_t b3 : 1;
  uint8_t b4 : 1;
  uint8_t b5 : 1;
  uint8_t b6 : 1;
  uint8_t b7 : 1;
};

Se nel codice dichiari una variabile di tipo BY avrai una variabile che occupa esattamente 8 bit che puoi ciascuno chiamare per nome mantenendo tutta la leggibilità ...

BY myByte;
...
...
myByte.b0 = 0;
myByte.b1 = 1;
...

Guglielmo

Questa non la conoscevo... Hai qualche riferimento per approfondire?

Se lo cerchi con Google, ottieni risultati interessanti.