bug compilatore o cosa ?

salve a tutti,

vorrei scrivere una funzione che permetta ad arduino di "parlare" con altri controllori( nel mio caso un wemos d1 r1) via seriale, ma mi è capitata una cosa stranissima che non so spiegare :o

ho scritto un codice del tipo

union prov{
  struct{
    int dato1;
    int dato2;
    int dato3;
    int dato4;
    int dato5;
    int dato6;
    int dato7;
    int dato8;
  }pro;
  byte arr[16];
}prova;


unsigned long intervallo;

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

  prova.pro.dato1 = 8 ;
  prova.pro.dato2 =28 ;
  prova.pro.dato3 =12 ;
  prova.pro.dato4 =50 ;
  prova.pro.dato5 =120 ;
  prova.pro.dato6 = 15;
  prova.pro.dato7 =120 ;
  prova.pro.dato8 = 17 ;
}


void loop(){

  if (millis() - intervallo > 5000){

      Serial.write(prova.arr,16);
      Serial.println();
      for(byte i = 0; i < 16; i++){  // messo qui solo per verificare cosa scrive la seriale
        Serial.println(prova.arr[i]);
      }
      intervallo = millis();
  }
}

il codice compila e la seriale printa un array di 16 byte:

[08][00][1C][00][0C][00]2[00]x[00][0F][00]x[00][11][00] 
8
0
28
0
12
0
50
0
120
0
15
0
120
0
17
0

ma se compilato x la weMos restituisce :

[08][00][00][00][1C][00][00][00][0C][00][00][00]2[00][00][00]
8
0
0
0
28
0
0
0
12
0
0
0
50
0
0
0

secondo voi è un errore di programmazione o di compilatore ? :confused: :confused: :confused:

Scordatevi QUALSIASI ERRORE dei compilatori ... sono oggetti stra-collaudati che funzionano perfettamente ... ... l'errore è SEMPRE (99.99%) nell'utilizzatore di tali strumenti!

Nel caso specifico ... è un tuo errore che non ti sei andato a studiare l'[u]architettura delle due MCU[/u] e le rispettive dimensioni standard delle variabili ... :smiling_imp:

Guglielmo

GRANDEEEEE!!!

in effetti anche io penso che il 99% dei problemi di un pc risieda tra la tastiera e la sedia e la cosa mi è parsa ancora piu strana quando, googlando, non è uscito nulla.

dalla risposta immagino che la wemos veda un int come un array di 4 byte e non 2 come arduino e questo mi complica unbel po le cose in quanto in ricezione caricavo direttamente l'array di byte dalla seriale nella union tramite il metodo Serial.readBytesUntil().

Dato che nel mio progetto il protocollo di comunicazione deve essere bidirezionale (arduino è "cuore" del progetto ma i menu risiedono su una pagina web servita dalla weMos) C'è un modo per convertire l'array della weMos( che a questo punto deve ssere di 32bytes, giusto?) in quella lato arduino (che invece sara di 16) automaticamente? o è sbagliato come approccio e mi conviene cambiare metodo ?

Guardati int16_t e uint16_t come tipo dato, così sei sicuro che sia sempre a 2 byte, questi tipi non sono specifici dalla piattaforma ma fissi per tutti.

mixmax122: C'è un modo per convertire l'array della weMos( che a questo punto deve ssere di 32bytes, giusto?) in quella lato arduino (che invece sara di 16) automaticamente? o è sbagliato come approccio e mi conviene cambiare metodo ?

La risposta te l'ha data maubarzi ... ... l'IDE include automaticamnete alcune librerie che includono al loro interno che ti da la possibilità di utilizzare le uniche definizione "certe" per la lunghezza delle variabili (dove tale modulo non fosse incluso automaticamente, basta fare #include ) .

Quindi, smettete di utilizzare le incerte "int, word, ecc." e imparate ad utilizzare le certe "uint16_t, int8_t, ecc." :)

Guglielmo

Da cui …

union prov{
  struct{
    int16_t dato1;
    int16_t dato2;
    int16_t dato3;
    int16_t dato4;
    int16_t dato5;
    int16_t dato6;
    int16_t dato7;
    int16_t dato8;
  }pro;
  uint8_t arr[16];
}prova;

Nota che può comunque sorgere un problema a causa della “union” e della “struct” che, sempre per ragioni di architettura, potrebbe non funzionare (difatti per alcuni standard, la “union” NON è ammessa senza una specifica “deviation” che, comunque, non è certificata dal chi definisce lo standard … es. MISRA C) poiché il compilatore, per ragioni di ottimizzazione nell’accesso alla memoria, potrebbe decidere di allinerare i dati nella “struct” inserendo dei byte “nascosti” … non per nulla esiste “#pragma pack:wink:

Guglielmo

intanto grazie ad entrambi, siete stati illuminanti

ricapitolando(x chi venisse dopo....): dato che non tutte le board allocano un 'int' allo stesso modo( la UNO alloca 2byte= 2^16 ma gia la DUE ne alloca 4 = 2^32) basterà sostituire il tipo da int a int16_t (o uint16_t in caso si voglia un unsigned) nella struct, per rendere entrambe le struct "certe"(come dice gpb01 xD)

ed ecco il codice funzionante:

union prov{
  struct{
    int16_t dato1;
    int16_t dato2;
    int16_t dato3;
    int16_t dato4;
    int16_t dato5;
    int16_t dato6;
    int16_t dato7;
    int16_t dato8;
  }pro;
  byte arr[16];
}prova;


unsigned long intervallo;

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

  prova.pro.dato1 = 8 ;
  prova.pro.dato2 =28 ;
  prova.pro.dato3 =12 ;
  prova.pro.dato4 =50 ;
  prova.pro.dato5 =120 ;
  prova.pro.dato6 = 15;
  prova.pro.dato7 =120 ;
  prova.pro.dato8 = 17 ;
}


void loop(){

  if (millis() - intervallo > 5000){

      Serial.write(prova.arr,16);
      Serial.println();
      for(byte i = 0; i < 16; i++){  // queto ciclo for è solo x il debug
        Serial.println(prova.arr[i]);
      }
      intervallo = millis();
  }
}

credo che il caso sia .....risolto! ancora grazie a tutti C.

gpb01: Da cui ...

union prov{
  struct{
    int16_t dato1;
    int16_t dato2;
    int16_t dato3;
    int16_t dato4;
    int16_t dato5;
    int16_t dato6;
    int16_t dato7;
    int16_t dato8;
  }pro;
  uint8_t arr[16];
}prova;

Nota che può comunque sorgere un problema a causa della "union" e della "struct" che, sempre per ragioni di architettura, potrebbe non funzionare (difatti per alcuni standard, la "union" NON è ammessa senza una specifica "deviation" che, comunque, non è certificata dal chi definisce lo standard ... es. MISRA C) poiché il compilatore, per ragioni di ottimizzazione nell'accesso alla memoria, potrebbe decidere di allinerare i dati nella "struct" inserendo dei byte "nascosti" ... non per nulla esiste "#pragma pack" ;)

Guglielmo

mi hai aperto un mondo.. ne ho ancora d pagine da leggere xD

x la struct: non avevo pensato che anche l'array della union potesse essere del tipo uint8_t ... dici che risparmio qualche byte di memoria ?