Ciao ragazzi mi servirebbe una mano per un'ottimizzazione del codice.
Visto che non sono molto bravo con stringhe, array e conversioni varie chiedo a voi per imparare.
Il codice che metto sotto è molto semplice nella logica, in pratica riceve via seriale dei dati nel seguente formato dato#crc16 (base 10)& e deve vedere se il dato è arrivato corretto. Come vedete dal codice io mi sono ricostruito la stringa in arrivo e poi ho spezzettato il tutto ma non so se è il modo migliore di operare pensando all'occupazione di memoria e alle performance, perchè a funzionare funziona.
Ecco il codice:
#include <SoftwareSerial.h>
#include <stdlib.h>
#include "crc16.h"
unsigned int myCrc16;
SoftwareSerial mySerial(2, 3); // RX, TX
String str ="";
String crcToCheck="";
String datoToCheck="";
byte checkStart;
byte checkEnd;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(57600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.println("Goodnight moon!");
mySerial.begin(57600);
}
void loop() // run over and over
{
if (mySerial.available()){
char c = mySerial.read();
str = str + c;
if ( c == '&'){
//controllo crc
Serial.println("Dato in arrivo: " + str);
checkStart=str.indexOf('#');
checkEnd=str.indexOf('&');
crcToCheck = str.substring(checkStart+1, checkEnd);
datoToCheck = str.substring(0, checkStart);
Serial.println("crcToCheck " + crcToCheck);
char buf[1];
datoToCheck.toCharArray(buf, sizeof(datoToCheck));
Serial.print("Dato da controllare: ");
Serial.println(buf);
myCrc16 = calc_crc16(buf, sizeof(buf));
Serial.print("Crc calcolato da rx: ");
Serial.println(myCrc16, 10);
str = "";
byte crcToCheckArraySize = crcToCheck.length() + 1;
char crcToCheckArray[crcToCheckArraySize];
crcToCheck.toCharArray(crcToCheckArray, crcToCheckArraySize);
if ( myCrc16 == atol(crcToCheckArray) )
Serial.println("OK");
else
Serial.println("ko");
}
}
}
Ma fare il CRC di 1 solo carattere ogni volta mi sembra una cosa inutile.
Se vuoi essere sicuro della trasmissione, spedisci 2 volte lo stesso carattere: se il primo è diverso dal secondo, la trasmissione è arrivata corrotta. NOn c'è bisogno di un CRC
Riscriverei il codice in modo da ricomporre il testo spedito (ossia ricevere tutti i byte del messaggio) e poi calcolare il CRC su di esso.
leo72:
Ma fare il CRC di 1 solo carattere ogni volta mi sembra una cosa inutile.
Assolutamente si, per giunta usa il CRC16, ovvero deve spedire 3 byte con un solo byte di payload, un overhead del 200%
l'uso del crc ha senso solo se quando parliamo di array dati di una certa lunghezza e quando serve un ottimo livello di affidabilità delle trasmissioni-
Normalmente un banale checksum, 8 o 16 bit, è più che sufficiente per verificare l'integrità dei dati in buona parte delle applicazioni di uso comune, non andiamo a complicarci la vita quando è inutile
Vabè era anche per giocare non aveva nessuno scopo finale.
Ma in linea generale è fatto bene quel codice o si pò evitare l'uso di qualche funzione/conversione?
Il metodo che dovresti usare è quello di strutturare la trasmissione : un blocco di caratteri di lunghezza fissa (il pacchetto del messaggio) + il CRC.
In questo modo ottimizzi il tutto e eviti di dover usare un carattere separatore (# nel tuo caso) che, in una normale trasmissione di bytes, potrebbe capitare nel corpo del messaggio.
In pratica, ogni "pacchetto" dovrebbe essere fatto come : XXXXXXX.........XXXXXXXCC dove le XXXXX sono un numero FISSO di caratteri (es. ogni pacchetto deve trasferire 64 bytes SEMPRE) seguito da 2 byte di CRC.
Hai dei punti del codice un pò "pericolosi":
esempio: datoToCheck.toCharArray(buf, sizeof(datoToCheck));
Tu il buf lo dichiari di 1, alla funzione passi sizeof() di datotocheck, ovvero la dimensione dell'oggetto. Se anche la sizeof ritornasse quanti caratteri formano la stringa, comunque passi un valore >1. La funzione toCharArray usa il 2° parametro per sapere quanto è grande il buf, per evitare di andare a scrivere "oltre" alla sua dimensione.
La classe String usa internamente malloc e realloc, perciò ogni volta che fai str = str + c; esegue di sotto 1kg di codice.
Secondo me se usi direttamente vettori di caratteri a cui dai una dimensione adeguata (sai in partenza a quanto dimensionarli) e poi usi le varie funzioni sui vettori di stringa (strlen, strncpy, strstr, etc.), velocizzi.
Logicamente le String semplificano il codice ma non lo ottimizzano di certo.
gpb01:
Concordo con nid69ita ... evita le String per le trasmissioni dati e, come ti dicevo, vai con dei semplici char[] di cui fissi a priori le dimensioni
Assolutamente si, anzi ancora meglio evitare sempre come la peste le string, e più in generale il C++, quando si lavora con piccole mcu 8 bit con limitatissime risorse, ANSI C forever