Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <SoftwareSerial.h>
- #define ETX 0xFA // Carattere di "End of Trasmission" custom
- // Struttura del telegramma; il solo carattere ETX non è sufficiente perché potrebbe essere contenuto nel messaggio
- // Usiamo allora anche un carattere CRC8 che svolge anche la funzione di controllo degli errori
- // BYTE0 BYTE1 .... BYTE10 + CRC8 + ETX
- // Uso una softare serial per simulare il funzionamento (pin 11 -TX collegato con il pin 1 -RX)
- SoftwareSerial mySerial(10, 11);
- union {
- struct {
- bool var1;
- bool var2;
- int var3;
- int var4;
- float var5;
- };
- uint8_t raw[10];
- } my_union;
- uint8_t rx_buffer[12]; // Il buffer per la ricezione seriale è grande sizeof(my_union.raw) + CRC + ETX
- void setup() {
- pinMode(2, INPUT_PULLUP);
- Serial.begin(9600);
- mySerial.begin(9600);
- // Inizializzo my_union con dei valori a caso
- my_union.var1 = false;
- my_union.var2 = true;
- my_union.var3 = 5;
- my_union.var4 = -5;
- my_union.var5 = 69.69f;
- // Stampo sulla seriale i raw data di my_union
- Serial.println();
- Serial.print("my_union before: ");
- print_hex(my_union.raw, sizeof(my_union.raw));
- }
- void loop() {
- if(digitalRead(2) == LOW){
- // Simuliamo qualche errore
- static int error = 0;
- error = (error + 1 ) % 5;
- // Messaggio ok
- if(error < 3){
- uint8_t crc = CRC8(my_union.raw, sizeof(my_union.raw));
- mySerial.write(my_union.raw, sizeof(my_union.raw));
- mySerial.write(crc);
- mySerial.write(ETX);
- }
- // Il messaggio è più lungo di quanto deve e manca il carattere ETX
- if(error == 3){
- mySerial.write(my_union.raw, sizeof(my_union.raw));
- mySerial.write(random(0xFF));
- mySerial.write(random(0xFF));
- mySerial.write(random(0xFF));
- mySerial.write(random(0xFF));
- }
- // Il messaggio è più corto di quanto deve e manca il carattere ETX
- if(error == 4){
- mySerial.write(my_union.raw, sizeof(my_union.raw) - 2);
- }
- delay(500);
- }
- uint32_t rx_timeout = millis();
- while(Serial.available()){
- static uint8_t i = 0;
- // Leggo il byte dalla seriale e lo memorizzo in rx_buffer
- uint8_t byte_in = (uint8_t)Serial.read();
- rx_buffer[i] = byte_in;
- // Controllo errori: qualcosa è andato storto durante la trasmissione/ricezione
- // Ho ricevuto troppi byte prima di ETX oppure sono in timeout
- if(i > sizeof(rx_buffer) || millis() - rx_timeout > 100) {
- // Debug dell'errore
- Serial.print("\n\nRX error: ");
- print_hex(rx_buffer, sizeof(rx_buffer));
- Serial.print("\n");
- // Questo è andato, aspettiamo il prossimo messaggio
- while(Serial.available()) // Svuoto il buffer seriale
- Serial.read();
- i = 0;
- break;
- }
- // Se byte_in == ETX dovrebbe essere l'ultimo carattere del messaggio
- // e quindi posso controlalre se il CRC8 ricevuto coincide con quello calcolato
- if(byte_in == ETX){
- // Calcolo CRC8 dei dati ricevuti
- uint8_t crc = CRC8(rx_buffer, sizeof(my_union.raw));
- // Stampiamo un po' di informazioni per debug
- Serial.print("\n\nCRC8: 0x");
- Serial.print(crc, HEX);
- Serial.print("\nrx_buffer: ");
- print_hex(rx_buffer, sizeof(rx_buffer));
- // Se il CRC8 calcolato è uguale al byte nella posizione prevista, il messaggio è buono
- if(crc == rx_buffer[i-1]){
- // Copio i dati ricevuti in my_union
- Serial.println("\nCRC OK, copy data to my_union");
- memcpy(my_union.raw, rx_buffer, sizeof(my_union.raw));
- // Stampiamo nuovamente my_union per verificare che tutto sia come previsto
- Serial.print("my_union after: ");
- print_hex(my_union.raw, sizeof(my_union.raw));
- Serial.print("\nvar5: ");
- Serial.println(my_union.var5);
- // Messaggio processato con successo, siamo pronti per il prossimo
- i = 0;
- break;
- }
- }
- // Incremento i per acquisire il prossimo byte dalla seriale
- i++;
- }
- }
- // Print to serial raw data + CRC8 + ETX
- void print_hex( uint8_t *data, size_t len){
- uint8_t crc = CRC8(data, len);
- for(uint8_t i=0; i<len; i++){
- Serial.print(" 0x"); Serial.print(data[i], HEX);
- }
- }
- // https://www.leonardomiliani.com/2013/un-semplice-crc8-per-arduino/
- // CRC-8 - algoritmo basato sulle formule di CRC-8 di Dallas/Maxim
- // codice pubblicato sotto licenza GNU GPL 3.0
- uint8_t CRC8(const uint8_t *data, size_t len) {
- uint8_t crc = 0x00;
- while (len--) {
- uint8_t extract = *data++;
- for (uint8_t tempI = 8; tempI; tempI--) {
- uint8_t sum = (crc ^ extract) & 0x01;
- crc >>= 1;
- if (sum) {
- crc ^= 0x8C;
- }
- extract >>= 1;
- }
- }
- return crc;
- }
Add Comment
Please, Sign In to add comment