Oggi, tanto per provare a far qualcosa con arduino, ho pensato di creare uno sketch che legga il valore di luminosità da un sensore, e mi restituisca una cosa del tipo "Ricevo X % di luce", dove X è il valore percentuale di luce su 1023..
Ora, fin qua per fare 2 calcoli per me nessun problema, ma per lui si..
Dopo essermi reso conto che il risultato era sbagliato, ho provato pure a fargli moltiplicare il valore, ricevuto dal pin A0, x 10.. ma mi da un risultato sballato di qualche unità..
Sicuramente sono io che sbaglio, ma non capisco dove.. Ho provato a impostarlo sia in int, long, float.. Ma non lo prende mai giusto..
AleCune93:
Sicuramente sono io che sbaglio, ma non capisco dove.. Ho provato a impostarlo sia in int, long, float.. Ma non lo prende mai giusto..
Senza vedere il codice con cui fai l'acquisizione e i successivi calcoli è impossibile risponderti, però un micro non sbaglia a fare i conti, l'errore può essere solo di procedura e/o di impostazione del conto.
Esempio pratico se si usano dati di tipo int e si fa il calcolo 10/35 probabilmente uno si aspetta di avere il valore 16, quello reale è 16.6(periodico), per via del troncamento della parte decimale, in realtà il valore calcolato sarà 15 perché 10/3 = 3 (troncata la parte decimale) e 35 = 15, questo genere di disattenzioni può portare ad errori cumulativi con effetti devastanti in catene di calcolo complesse.
AleCune93:
float valluce=(analogRead(A0)*100)/1023; //calcolo la percentuale su A0
Sei cascato esattamente nell'errore che ho descritto nel mio esempio, analogRead ritorna un valore di tipo int, non appena vale più di 327 il calcolo sballa completamente perché vai in overflow, devi usare il casting e promuovere l'int in long int, 1023*100 = 102300 che è quasi il quadruplo del massimo numero positivo rappresentabile con in int, è pure inutile usare un float per valluce visto che sarà sempre un valore compreso tra 0 e 100, dichiaralo come byte.
byte valluce=((long int) analogRead(A0)*100)/1023; //calcolo la percentuale su A0
Aaaaaah capisco!!
Non credevo di dover fare il cast manualmente.. Ero convinto che dando flat alla variabile di destinazione il risultato al suo interno si sistemasse da solo =(
Comunque ho usato il flat per tenere anche le cifre dopo la virgola.. XD
Un altra cosa visto che ci sono.. Quando tento comunque di convertire la variabile float in String mi da un errore.. Perchè con tutte ce la faccio, ma con float (e double) no..!?
AleCune93:
Un altra cosa visto che ci sono.. Quando tento comunque di convertire la variabile float in String mi da un errore..
La LiquidCrystal non supporta i float, i double su Arduino non esistono, il tipo dato c'è solo per compatibilità, però rimane sempre un float a 32 bit.
Ok, ringrazio nid e leo per la semplificazione delle operazioni.. Sinceramente, anche se dovrebbe essere una cosa naturale, non avevo proprio pensato a semplificarle.. è già tanto se non ho fatto passaggio per passaggio XD
Invece, astrobeed.. Quella dell'inesistenza del double proprio non la sapevo .. Però io intendevo chiedere perchè non mi fa il cast di una variabile da float a String, mentre altre (per esempio int -> String) funzionano
AleCune93:
cast di una variabile da float a String,
Il casting è applicabile solo alle variabili numeriche, non è applicabile ad un tipo string perché è esclusivamente un array di caratteri alfanumerici e non di numeri.
Perfetto.. vi ringrazio veramente per avermi aiutato in questo dubbio .. Mi rivedrete sicuramente presto, immagino che questa non sia l'ultima domanda che mi porrò su arduino ..
Cosa intendi per casting da float a string (le hai fatte da altri numerici a string e funzionano)
Nel tuo codice non usi String
Ma la lcd.print(valluce);
non stampa il float? La classe LCD si basa su print e la print di un float dovrebbe accettarlo.
Hai provato dopo aver corretto il calcolo: float valluce=analogRead(A0)/10.23; ??
dove percLuce è una float..
Messa cosi funziona.. Sinceramente non me lo aspettavo.. Devo ancora conoscerlo arduino XD
Ora però non venirmi a dire che se devo concatenare un testo e una float dentro una variabile devo fare 2 operazioni simili a quelle che ho usato per l'lcd, perchè se cosi fosse butto arduino e mi do all'ippica =(
Attenzione, le variabili di Arduino sono variabili C o C++
Le variabili base sono char,int,long,float
Le stringhe NON esistono, sono vettori di caratteri (così come potresti avere un vettore di long)
Poi esiste la classe String, ma serve per creare oggetti di tipo String.
Quando fai Serial.println("numero=" + String(12.333));
Il compilatore si incacchia perchè per prima cosa cerca di costruire un oggetto di tipo String e cerca un costruttore che non c'e'.
Ovvero il compilatore cerca nella WString.cpp e WString.h (tra i vari file di Arduino) String::String(float)
ovvero puoi creare un oggetto String da char, int, long eventualmente unsigned, da altra String ma non da float
Ti sembra di creare la String sempre allo stasso modo ma in realtà stai "chiamando" funzioni diverse (si chiama overloading e concetto di "firma")
Nel caso della print, il compilatore cerca la funzione print(tipoparametro) giusto.
E' come se io creassi:
int somma(int a,int b)
{ return(a+b);
}
float somma(float a,float b)
{ return(a+b);
}
se chiamo:
Serial.println(somma(2+3)); // chiama la prima somma, in base alla "firma" int,int
Serial.println(somma(2.0+3.0)); // chiama la seconda somma firma=float,float
Oddio.. Mi sento veramente ignorante a fare ste cannate.. XD
Dopo questa tua spiegazione penso di aver capito come funziona.. Devo macinarci su un pochino per capirlo bene..
Vero, non è semplice da capire ed è una cosa alquanto complessa. Una volta "digerita" dovrebbe aiutare a capire il perchè a volte il compilatore non accetta cose che riterremmo ragionevoli. XD