C programming - Aiuto

Ciao a tutti,

vorrei chiedere agli esperti programmatori di C se è possibile scrivere in un modo più elegante (e magari più efficiente) il codice che segue:


if (send) {
C++;
char vfoA[10];
dtostrf ((float)r1.getCurrentControl().value/1000000,3,6,vfoA);
sprintf(cmd, "C%d|slice t %d ",C,0);
String cmd2=String(cmd);
cmd2 += vfoA;
cmd2 += "\n";
fRig.send(cmd2);
send=0;
}


Il mio Arduino Due è connesso ad un dispositivo hardware attraverso la porta ethernet e può essere gestito attraverso una serie di comandi che sono strutturati nel seguente modo:

C12|slice t 0 14.035

  • il numero dopo la C è un contatore (int nel mio caso) che deve essere incrementato ogni volta che si invia un comando al dispositivo;

  • il numero dopo la t può essere un intero nel range [0,1,2,3]

  • l'ultimo numero invece è una frequenza espressa in MHz. In arduino, la classe fRig mantiene questo valore in una variabile di tipo int, pertanto ogni volta devo passare da int a float e poi convertire tutto in array di char.

Anche se il codice funziona correttamente, la domanda è se è possibile implementare la logica descritta in modo migliore.

Inoltre non mi è chiaro come devo gestire le clausole import nel codice:

  • il progetto è implementato in maniera molto limitata nel file FlexConsole.ino, mentre tutta la logica per la gestione del dispositivo è nella classe FlexRig.cpp (e relativo headerfile).
    Nessuna procedura del file .ino usa le classi della libreria Ethernet, eppure per poter compilare il programma, devo importare Ethernet.h ed SPI.h sia nel file .ino che nel file .cpp. E' corretto questo modo di operare o sto sbagliando qualcosa?

Grazie per qualsiasi aiuto mi potrete dare
Enzo

Da premettere che non uso Arduino IDE, ma il C o C++.

Tieni conto che non avendo tutto il codice e studiandolo non si può dire di più, specie per il fatto che non si possono motivare i consigli, per cui prendi quello che pensi serva e scarta il resto.

Dal momento che la classe FlexRig l'hai scritta tu anziché prendere argomento String, gli fai prendere un char *. Il metodo send() di FlexRig infatti prende come argomento un oggetto String che devi creare provvisoriamente dentro la if {}, al termine del quale l'oggetto cmd2 viene distrutto.

La creazione e distruzione di oggetti comporta l'uso di maggiori risorse hardware, se poi l'oggetto creato fa uso di allocazione/deallocazione dinamica di memoria come avviene in String la situazione peggiora.

La if {} in questione la possiamo vedere come un formattatore di comando, se ti serve formattare comandi in altre parti del codice puoi pensare di creare una funzione o addirittura una classe (anche dentro FlexRig.cpp) formattatrice (CommandFormatter()).

  • il progetto è implementato in maniera molto limitata nel file FlexConsole.ino, mentre tutta la logica per la gestione del dispositivo è nella classe FlexRig.cpp (e relativo headerfile).
    Nessuna procedura del file .ino usa le classi della libreria Ethernet, eppure per poter compilare il programma, devo importare Ethernet.h ed SPI.h sia nel file .ino che nel file .cpp. E' corretto questo modo di operare o sto sbagliando qualcosa?

Non so se sia normale per Arduino, in C++ basta includere gli header necessari nel header di libreria. Quindi nel tuo caso dovrebbe bastare includere Ethernet.h ed SPI.h nel header file FlexRig.h

Ciao.

Ciao Mauro,

grazie per avermi risposto.
Quindi se ho compreso bene, la if può (deve) diventare un metodo della classe FlexRig ed invece di prendere in input una stringa deve meglio ricevere un array di char.
Riguardo alle istruzioni di formattazione io pensavo di poter utilizzare solo la sprintf, ma quando provo a formattare un floating point mi viene fuori un punto interrogativo, ed è per tale ragione che ho usato la dtostrf.
Inoltre, vorrei chiederti in che modo si può sviluppare per arduino senza usare la IDE ufficiale. Al momento uso la IDE solo per il file .ino mentre il resto del programma lo sviluppo in Notepad++.

Grazie ancora per l'aiuto
Enzo

Quindi se ho compreso bene, la if può (deve) diventare un metodo della classe FlexRig ed invece di prendere in input una stringa deve meglio ricevere un array di char.

Non mi sento di usare l'imperativo "deve", di sicuro creare un oggetto String di appoggio solo per aggiungerci qualcosa è da evitare. Come dicevo prima se c'è necessità di formattare comandi composti con ad esempio float e interi con o senza segno, e altri caratteri di significato particolare per la codifica puoi pensare di creare una classe formattatrice e usare l'overloading C++, realizzando una cosa simile alla classe String che permette di aggiungere tanti tipi diversi.

Riguardo alle istruzioni di formattazione io pensavo di poter utilizzare solo la sprintf, ma quando provo a formattare un floating point mi viene fuori un punto interrogativo, ed è per tale ragione che ho usato la dtostrf.

Il motivo è legato alla libreria avrlibc che di default disabilita la formattazione del tipo float o double perché la dimensione del compilato aumenta parecchio. Per abilitare la formattazione è necessario passare un argomento al linker, come fare questo con arduino IDE io non lo so, posso solo dirti che la 1.5.x permette di fare ciò.

Hai nominato Notepad++, quindi presumo tu stia usando Windows, io conosco solo GNU/Linux
quindi ti dico come faccio io, tu poi devi adattare le cose al tuo sistema operativo.
La variabile ambiente LFLAGS (linker flags) viene letta dal linker ed è tramite questa che si passano argomenti. Nel mio caso scrivo così:

LFLAGS += -Wl,-u,vfprintf -lprintf_flt

-lprintf_flt viene espansa nel nome di file libprint_flt.a (.a static library).

Tu dovresti vedere come fare per inserire quella dicitura nella variabile ambiente LFLAGS, se riesci con l'IDE bene, in alternativa se conosci il tuo sistema puoi fare in modo di inserire la dicitura prima di avviare L'ide e provare se formatta.

Inoltre, vorrei chiederti in che modo si può sviluppare per arduino senza usare la IDE ufficiale. Al momento uso la IDE solo per il file .ino mentre il resto del programma lo sviluppo in Notepad++.

Arduino è comodo perché hai tutte le librerie incluse e non devi configurare nulla. Altri IDE ci sono, mi viene Eclipse con il plugin AVR, Atmel Studio (o come si chiama), l'altro Visual Studio (o qualcosa di simile). Ti conviene fare una ricerca con google, perché io di Windows sono zero.

Ciao.

Ora è molto più chiaro e soprattutto ora so come fare fronte al problema della formattazione dei comandi.
Circa il 50% della logica della mia applicazione farà uso del sistema per l'invio delle stringhe formattate, pertanto l'uso della printf in modalità "estesa" è un prezzo dche dovrò pagare. Questa è anche la ragione che mi ha spinto a chidere come migliorare questa parte di codice molto delicata.
Inoltre, poichè la board che utilizzo è Arduino Due, il problema della dimensione del programma è leggermente attenuato.
Riguardo all'utilizzo di un'altra IDE, su consiglio di un altro amico di questo forum, ho iniziato ad utilizzare Visual Micro ed ATMEL Studio 6. Tutto sembra funzionare alla perfezione e le facilities per lo sviluppo sono davvero tante.

Grazie ancora e buon Natale

Inoltre, poichè la board che utilizzo è Arduino Due, il problema della dimensione del programma è leggermente attenuato.

Si dal punto di vista spazio flash questo è vero, dal punto di vista RAM le cose stanno quasi come per la uno, con la differenza che se usi String sconsideratamente il programma ci potrebbe mettere molto più tempo prima di mostrare malfunzionamenti dovuti alla incapacità di allocare memoria, ma non è detto che accada.

Quindi ora puoi anche sviluppare C/C++ in modo classico senza il vincolo delle arduino library.
Visto che ci sono e che siamo sotto le feste ti faccio un altro regalino.

CFLAGS += -save-temps

Il compilatore terminato il lavoro non cancella i file temporanei .s (ASM) .i(risultato del preprocessore c++).
Io la tengo sempre abilitata per visionare entrambe i file, ma principalmente per vedere l'espansione delle macro operata dal preprocessore C/C++.

CFLAGS (C) CXXFLAGS(C++)

Ciao e Buone Feste anche a te.