unsigned long frequenza;
char stringa[20];
void setup() {
Serial.begin(19200);
delay(2000);
frequenza = 1234567890;
}
void loop() {
byte lunghezza;
byte scala;
//converto in stringa un unsigned long
ltoa(frequenza, stringa, 10);
//stampo l'unsigned long
Serial.print("Frequenza: ");
Serial.println(frequenza, DEC);
//stampo la sua conversione in stringa
Serial.print("Convertito in: ");
Serial.println(stringa);
//stampo la lunghezza in caratteri
lunghezza = strlen(stringa);
Serial.print("Lunghezza stringa: ");
Serial.println(strlen(stringa), DEC);
scala = 3; //kHz
stampaFrequenza(scala, lunghezza);
Serial.println(" kHz");
scala = 6; //MHz
stampaFrequenza(scala, lunghezza);
Serial.println(" MHz");
scala = 9; //GHz
stampaFrequenza(scala, lunghezza);
Serial.println(" GHz");
for(;;);
}
void stampaFrequenza(byte _scala, byte _lunghezza) {
byte punto;
if (_scala <= _lunghezza) {
punto = 255;
} else {
punto = _lunghezza - _scala;
}
for (byte i = 0; i < _lunghezza; i++) {
if (i == punto) {
Serial.print(".");
}
Serial.print(stringa[i]);
}
}
Come vedi, ci prendiamo la lunghezza della stringa, ottenuta dal numero convertito con ltoa ("L"toa, perché usiamo i long) e poi mettiamo il punto decimale a seconda della scala.
C'è solo da sistemare la parte che parsa la frequenza passata alla funzione che mette il punto per trattare il caso in cui la frequenza sia inferiore alla scala usata, così da mettere gli "0" prima del numero (es.: 0.001234)
Grande LEO!!!
Allora ho provato il tuo codice, ho dovuto implementare qualcosina nella void perché mi serve gestire i casi in cui ile cifre siano poche e ci sia bisogno di anteporre degli "0". Il seguente codice è il tuo modificato. funziona perfettamente da 1 a 10 cifre e tutti i miei problemi sono risolti:
unsigned long frq;
char frequenza[20];
void setup() {
Serial.begin(9600);
delay(2000);
frq = 1234567891;
}
void loop() {
byte lunghezza;
byte scala;
//converto in stringa un unsigned long
ltoa(frq, frequenza, 10);
//stampo l'unsigned long
Serial.print("Frequenza: ");
Serial.println(frq, DEC);
//stampo la sua conversione in stringa
Serial.print("Convertito in: ");
Serial.println(String(frequenza));
//stampo la lunghezza in caratteri
lunghezza = strlen(frequenza);
Serial.print("Lunghezza stringa: ");
Serial.println(strlen(frequenza), DEC);
scala = 0; //Hz
stampaFrequenza(scala, lunghezza);
Serial.println(" Hz");
scala = 3; //kHz
stampaFrequenza(scala, lunghezza);
Serial.println(" kHz");
scala = 6; //MHz
stampaFrequenza(scala, lunghezza);
Serial.println(" MHz");
scala = 9; //GHz
stampaFrequenza(scala, lunghezza);
Serial.println(" GHz");
for(;;);
}
void stampaFrequenza(byte _scala, byte _lunghezza) {
byte punto;
if (_scala >= _lunghezza) {
Serial.print("0.");
for (byte i = 0; i < _scala - _lunghezza; i++) {
Serial.print("0");
}
}
else {
punto = _lunghezza - _scala;
}
for (byte i = 0; i < _lunghezza; i++) {
if (i == punto) {
Serial.print(".");
}
Serial.print(frequenza[i]);
}
}
Ho provato ad eliminare i caratteri "_" posti davanti alle variabili nella void e funziona tutto ugualmente, poi mi spiegherai che significano, ma tieni conto che questo codice dovrà essere implementato nel più ampio firmware che ho già scritto, quindi certamente ogni variabile sarà di tipo globale, sempre che ci sia un legame con ciò.
Ti ringrazio di cuore, domani proverò l'implementazione e farò i test necessari, la soluzione è semplice ed economica, non so se Astro pensava a qualcosa del genere, vedremo poi cosa ci dirà.
• char * ltoa (long int __val, char *__s, int __radix)
• char * utoa (unsigned int __val, char *__s, int __radix)
• char * ultoa (unsigned long int __val, char *__s, int __radix)
poiché hai dichiarato unsigned long frq;
è possibile che si debba usare
ultoa
invece di
ltoa
?
Considera che nel mio caso il max valore trattato sarà 1.100.000.000.
I segni "_" davanti alle variabili della funzione stampaFrequenza li avevo messi per differenziare visivamente le variabili locali usate nella funzione. Potevo mettere "ciccio1" e "ciccio2" al posto di "_scala" e "_frequenza", era la stessa cosa.
Grazie, l'avevo trovato anch'io ieri sera questo pdf, è ben fatto, più o meno come quello che avevo scaricato tempo fa, per di più è in italiano, grande cosa! Ma spero sempre che qualcuno dei capi mi possa dire che implementeranno la stampa del reference originale.
Allora ragazzi, tutto bene, col codice di Leo ed alcune piccole modifiche (gestione degli 0 iniziali) ho risolto alla grande il mio problema, in questo momento il mio display visualizza 0.000000001 GHz cioè 1solo Hz sulla portata dei GHz, fenomenale!
Grazie Leo, sei un grande.
Buona Pasqua a te e a tutti gli amici del Forum, ma comunque io sono qui....
Menniti visto che ormai sei quasi cittadino britannico , ti passo un link che potrebbe interessati (a livello didattico visto che hai risolto) che parla di come affrontare il problema diversamente e della matematica in virgola fissa
BrainBooster:
Menniti visto che ormai sei quasi cittadino britannico , ti passo un link
Cioè quello che ho sempre raccomandato quando ci sono da fare calcoli che prevedono l'uso dei decimali e non si è obbligati ad utilizzare i float perché non si usano funzioni che li richiedono esplicitamente, p.e. i calcoli trigonometrici.
Posto che troverò le ore necessarie per leggere quell'articolo, io ho sempre capito che qui o si lavora con interi o si lavora col float, in quest'ultimo caso sembrerebbe l'unico modo per vedere i decimali in un numero. Ricordo vaghissimamente qualcosa riguardo i numeri in "virgola fissa", ma non saprei come ottenerli; probabilmente lo capirò (con miei immensi dubbi) leggendo quell'articolo, vedremo....
Perché siete limitati dal metodo "print" per "vedere" i dati, questa è l'altra faccia di wiring, a fronte della semplicità d'uso ci sono grosse limitazioni nella flessibilità.
Chi lavora con i micro in C puro non ha questi limiti, chi ha un minimo di esperienza di programmazione sa bene che i float sono il "male" quando si lavora con le piccole mcu a 8 bit