#define INTERO (byte)0
#define DECIMALE (byte)1
#define KILO (byte)3
#define MEGA (byte)6
#define GIGA (byte)9
void setup() {
delay(1000);
Serial.begin(9600);
}
void loop() {
Serial.print(convert(INTERO, 112347293, MEGA));
Serial.print(".");
Serial.print(convert(DECIMALE, 45235424, KILO));
delay(10000);
}
unsigned long convert(byte t, unsigned long n, byte s)
{
byte len = 0;
unsigned long x = n;
do {
x /= 10;
len++;
}
while (x != 0);
// len contiene il numero di cifre del numero
if (len < s) .....
if (t = INTERO)
{
return n;
}
else
if (t = DECIMALE)
{
return n;
}
else return 0;
}
Quello che vuoi fare è molto semplice da mettere in pratica, ti sconsiglio caldamente di utilizzare la classe string perché è molto pesante da gestire ed è vorace di ram, anzi più in generale evitare sempre l'uso del C++ sulle piccole MCU.
Domani ti passo io il codice, ben spiegato, per quello che vuoi fare partendo da un valore long int, tutto realizzato con le normali funzioni per la gestione delle stringhe del C ANSI, lo posterò in questo topic così rimane disponibile per chi ha problemi simili, sono abbastanza comuni e mi capita di vedere soluzioni che fanno venire la pelle d'oca
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....