TolentinoCotesta

union

May 24th, 2020
159
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.82 KB | None | 0 0
  1. #include <SoftwareSerial.h>
  2.  
  3. #define ETX 0xFA    // Carattere di "End of Trasmission" custom
  4.  
  5. // Struttura del telegramma; il solo carattere ETX non è sufficiente perché potrebbe essere contenuto nel messaggio
  6. // Usiamo allora anche un carattere CRC8 che svolge anche la funzione di controllo degli errori
  7.  
  8. // BYTE0 BYTE1 .... BYTE10 + CRC8 + ETX
  9.  
  10. // Uso una softare serial per simulare il funzionamento (pin 11 -TX collegato con il pin 1 -RX)
  11. SoftwareSerial mySerial(10, 11);
  12.  
  13. union {
  14.     struct {
  15.        bool var1;
  16.        bool var2;
  17.        int var3;
  18.        int var4;
  19.        float var5;
  20.     };
  21.     uint8_t raw[10];
  22. } my_union;
  23.  
  24. uint8_t rx_buffer[12];  // Il buffer per la ricezione seriale è grande sizeof(my_union.raw) + CRC + ETX
  25.  
  26. void setup() {
  27.   pinMode(2, INPUT_PULLUP);
  28.   Serial.begin(9600);
  29.   mySerial.begin(9600);
  30.  
  31.   // Inizializzo my_union con dei valori a caso
  32.   my_union.var1 = false;
  33.   my_union.var2 = true;
  34.   my_union.var3 = 5;
  35.   my_union.var4 = -5;
  36.   my_union.var5 = 69.69f;
  37.  
  38.   // Stampo sulla seriale i raw data di my_union
  39.   Serial.println();
  40.   Serial.print("my_union before: ");
  41.   print_hex(my_union.raw, sizeof(my_union.raw));
  42. }
  43.  
  44. void loop() {
  45.  
  46.   if(digitalRead(2) == LOW){
  47.  
  48.     // Simuliamo qualche errore
  49.     static int error = 0;
  50.     error = (error + 1 ) % 5;  
  51.    
  52.     // Messaggio ok
  53.     if(error < 3){
  54.       uint8_t crc = CRC8(my_union.raw, sizeof(my_union.raw));
  55.       mySerial.write(my_union.raw, sizeof(my_union.raw));
  56.       mySerial.write(crc);
  57.       mySerial.write(ETX);
  58.     }
  59.     // Il messaggio è più lungo di quanto deve e manca il carattere ETX
  60.     if(error == 3){
  61.       mySerial.write(my_union.raw, sizeof(my_union.raw));
  62.       mySerial.write(random(0xFF));
  63.       mySerial.write(random(0xFF));
  64.       mySerial.write(random(0xFF));
  65.       mySerial.write(random(0xFF));
  66.     }
  67.     // Il messaggio è più corto di quanto deve e manca il carattere ETX
  68.     if(error == 4){
  69.       mySerial.write(my_union.raw, sizeof(my_union.raw) - 2);
  70.     }
  71.    
  72.     delay(500);
  73.   }
  74.  
  75.   uint32_t rx_timeout = millis();
  76.   while(Serial.available()){
  77.     static uint8_t i = 0;
  78.  
  79.     // Leggo il byte dalla seriale e lo memorizzo in rx_buffer
  80.     uint8_t byte_in = (uint8_t)Serial.read();
  81.     rx_buffer[i] = byte_in;
  82.    
  83.     // Controllo errori: qualcosa è andato storto durante la trasmissione/ricezione
  84.     // Ho ricevuto troppi byte prima di ETX oppure sono in timeout
  85.     if(i > sizeof(rx_buffer) || millis() - rx_timeout > 100) {
  86.    
  87.       // Debug dell'errore
  88.       Serial.print("\n\nRX error: ");
  89.       print_hex(rx_buffer, sizeof(rx_buffer));
  90.       Serial.print("\n");
  91.      
  92.       // Questo è andato, aspettiamo il prossimo messaggio
  93.       while(Serial.available())    // Svuoto il buffer seriale
  94.         Serial.read();
  95.       i = 0;
  96.       break;      
  97.     }
  98.      
  99.     // Se byte_in == ETX dovrebbe essere l'ultimo carattere del messaggio
  100.     // e quindi posso controlalre se il CRC8 ricevuto coincide con quello calcolato
  101.     if(byte_in == ETX){
  102.  
  103.       // Calcolo CRC8 dei dati ricevuti
  104.       uint8_t crc = CRC8(rx_buffer, sizeof(my_union.raw));
  105.  
  106.       // Stampiamo un po' di informazioni per debug
  107.       Serial.print("\n\nCRC8: 0x");
  108.       Serial.print(crc, HEX);
  109.       Serial.print("\nrx_buffer: ");
  110.       print_hex(rx_buffer, sizeof(rx_buffer));
  111.      
  112.       // Se il CRC8 calcolato è uguale al byte nella posizione prevista, il messaggio è buono
  113.       if(crc == rx_buffer[i-1]){
  114.  
  115.         // Copio i dati ricevuti in my_union
  116.         Serial.println("\nCRC OK, copy data to my_union");
  117.         memcpy(my_union.raw, rx_buffer, sizeof(my_union.raw));
  118.  
  119.         // Stampiamo nuovamente my_union per verificare che tutto sia come previsto
  120.         Serial.print("my_union after: ");
  121.         print_hex(my_union.raw, sizeof(my_union.raw));
  122.         Serial.print("\nvar5: ");
  123.         Serial.println(my_union.var5);
  124.  
  125.         // Messaggio processato con successo, siamo pronti per il prossimo
  126.         i = 0;
  127.         break;
  128.       }      
  129.     }
  130.  
  131.     // Incremento i per acquisire il prossimo byte dalla seriale
  132.     i++;
  133.   }
  134.  
  135.  
  136. }
  137.  
  138.  
  139.   // Print to serial raw data  + CRC8 + ETX
  140. void print_hex( uint8_t *data, size_t len){
  141.   uint8_t crc = CRC8(data, len);
  142.   for(uint8_t i=0; i<len; i++){
  143.     Serial.print(" 0x"); Serial.print(data[i], HEX);
  144.   }
  145. }
  146.  
  147. // https://www.leonardomiliani.com/2013/un-semplice-crc8-per-arduino/
  148. // CRC-8 - algoritmo basato sulle formule di CRC-8 di Dallas/Maxim
  149. // codice pubblicato sotto licenza GNU GPL 3.0
  150. uint8_t CRC8(const uint8_t *data, size_t len) {
  151.   uint8_t crc = 0x00;
  152.   while (len--) {
  153.     uint8_t extract = *data++;
  154.     for (uint8_t tempI = 8; tempI; tempI--) {
  155.       uint8_t sum = (crc ^ extract) & 0x01;
  156.       crc >>= 1;
  157.       if (sum) {
  158.         crc ^= 0x8C;
  159.       }
  160.       extract >>= 1;
  161.     }
  162.   }
  163.   return crc;
  164. }
Add Comment
Please, Sign In to add comment