Go Down

Topic: chiarimenti su operatore di comparazione == [Risolto] (Read 1 time) previous topic - next topic

latofra

Oct 15, 2012, 09:26 pm Last Edit: Oct 16, 2012, 01:27 pm by latofra Reason: 1
Salve a tutti

Sto cercando di realizzare un discriminatore con arduino IDE 1.0.1 scheda Mega 2560

In pratica leggo il valore di una tensione su porta analogica 0 e se il valore è uguale ad es. 3.21  accende un led " VERDE" lo stesso succede se raggiunge  3.22 V. accende " ROSSO" a 3.23 si accende il led "Giallo"
Questa variazione la simulo con un potenziometro posto con gli estremi tra + 5V e GND.
La tensione che viene instradata sulla porta 0 verificata con multimetro digitale è ad es. 3.21 ma il led "in questo caso verde " non ne vuol sapere di accendersi l'operatore di comparazione == non fa' il suo dovere
qualcuno sa dirmi perche' . Se invece uso l'operatore <= allora mi funziona ma il problema e' che io voglio che solo se = alla tensione che voglio io devono  accendersi il rispettivi led
Grazie  allego lo sketch


Code: [Select]
#define inputPin1 0 //definisco i pin utilizzati di arduino pin analog 0

int valore1 = 0;


int numletture = 10;
float valorex= 0;// variabile di appoggio x comparazione
float media1 = 0;// variabile x media


float gradino = 0.00486;// fattore di conversione per gradino 0.0049 * 1023= 5V

void setup() {

 // put your setup code here, to run once:

 pinMode(11,OUTPUT);//inizializzo pin 11 come uscita digitale
 pinMode(12,OUTPUT);
 pinMode(10,OUTPUT);
 Serial.begin(115200);// inizializzo la seriale software

}

void loop()  // put your main code here, to run repeatedly:
{
 for (int k=0; k < 10; k++){  // Ciclo for per 10 letture

   valore1 = analogRead(inputPin1);//Leggo da analog input 0
   delay(10);

   media1 = (valore1) + media1;// aggiungo lettura su variabile media1

 }

 media1 = (media1 / 10);// infine divido x 10 per la media letture
 media1=(media1*gradino);//converto in volt
 valorex=media1;//valorex variabile di appoggio per discriminatore

 if (valorex == 3.21 )
 {
   Led41();//se valore x = 3.21 V accendi led verde
 }
 if (valorex == 3.22 )

 {
   Led42();////se valore x = 3.22 V accendi led Rosso
 }

 if  (valorex == 3.23) {
   Led43();// //se valore x = 3.2 V accendi led Giallo
 }



 Serial.print("PORTA ANALOGICA 0 =") ;// Stampo le medie lette da analog 0
 Serial.print(media1);
 Serial.println();// aggiungo linefeed
 media1=0; //Azzero le medie per le prossime letture



}
void Led41(){
 digitalWrite(10,HIGH);
 delay(20);
 digitalWrite(10,LOW);
 }
void Led42(){
 digitalWrite(11,HIGH);
 delay(20);
 digitalWrite(11,LOW);
 }
void Led43(){
 digitalWrite(12,HIGH);
 delay(20);
 digitalWrite(12,LOW);
 }

gingardu

mah,,,    per accendere 3 led   io metterei 3 if
visto che hai un multimetro  porti la tensione a i valori che ti interessano con il voltmetro  e leggi  la lettura  con analogRead e prendi nota dei tre valori

poi fai i tre if

se non hai un potenziometro lineare  10 giri  la vedo dura trovare il valore preciso
Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

latofra

Grazie per la risposta

Ho provato anche i tre if come da te consigliato ma non cambia la sostanza
per quanto riguarda il potenziometro nessun problema ho gia' verificato con multimetro oscilloscopio Tektronics 213 DMM e' uno strumento preciso e riesco ad trimmare abbastanza preciso ma non riesco ad accendere i led anche spostando da un estremo all'altro cioe' da 0 a 4.99 Volt. Se utilizzo l'operatore <= tutto ok per me' e' un mistero .


ale92

proprio perchè ti va con il <= (sempre se non ci sono altri problemi che al momento non vedo) è sempre più probabile il fatto che non prendi il valore preciso...prova a fare una cosa con range tipo
Code: [Select]

if ((valorex >= 3.20 ) && (valorex <= 3.21))

invece di
Code: [Select]

if (valorex == 3.21 )

giusto per fare un esempio

poi io partirei da range abbastanza larghi così da vedere se il concetto in se funziona e piano piano lì restringi più che puoi (fino a che funziona praticamente)

latofra

Ok vado  per tentativi e restringo  il campo

grazie

Provo e faccio sapere

latofra

Perfetto funziona grazie per il suggerimento grandioso ale92 in effetti le finestre erano troppo strette nel mio skecth .
Scusa come faccio a mettere risolto sul mio Post .
Grazie

uwefed

I valori possibili sono:
ADC= 658 valore calcolato= 3.19788002
ADC= 659 valore calcolato= 3.20274019
ADC= 660 valore calcolato= 3.20760011
ADC= 661 valore calcolato= 3.21246004
ADC= 662 valore calcolato= 3.21732020
ADC= 663 valore calcolato= 3.22218012
ADC= 664 valore calcolato= 3.22704005
ADC= 665 valore calcolato= 3.23190021
ADC= 666 valore calcolato= 3.23676013
ADC= 667 valore calcolato= 3.24162006
ADC= 668 valore calcolato= 3.24648022
ADC= 669 valore calcolato= 3.25134015

Spiegami dove trovi una corrispondenza ai valori 3.21 ; 3.22  o 3.23
Il == funziona correttamente, Il ragionamento su cui si basa il programma é sbagliato.

Suggerimenti:
* non controllare le tensioni calcolate ma i valori ADC letti
* la lettura non é mai cosí stabile che Ti legge i valori 661, 663 o 663 fissi.

Ciao Uwe

latofra

Grazie Uwe

Avevo provato anche a ragionare in termini dei numeri che mi riporta l'ADC ma non ne ero venuto a capo .
Potrebbe essere il mio ragionamento sbagliato ma bene o male con un potis dovrebbe primo o dopo lampeggiare qualcosa o no.Anche perche' l'oscillazione è di uno o due valori in piu' o in meno.
In definitiva se io misuro 3.21 e mi dopo la mia conversione vedo 3.21 perche' l'operatore di ccomparazione non funge?




uwefed


Grazie Uwe

Avevo provato anche a ragionare in termini dei numeri che mi riporta l'ADC ma non ne ero venuto a capo .
Potrebbe essere il mio ragionamento sbagliato ma bene o male con un potis dovrebbe primo o dopo lampeggiare qualcosa o no.Anche perche' l'oscillazione è di uno o due valori in piu' o in meno.
In definitiva se io misuro 3.21 e mi dopo la mia conversione vedo 3.21 perche' l'operatore di ccomparazione non funge?


No, non avresti mai visto accendere un LED, perché se fai un confronto con 3,21 la tensione calcolata deve essere 3,210000 e non 3,21 e qualcosa.

Se usi dei Float non puoi usare il == ma devi sempre definire un valore sopre a uno sotto il quale la condizione é valida. Percui:

if ((valorex >=3,205) && (valorex <3,215))

Ti da un  controllo se il valore é di 3,21 (arrotondato).

Ciao Uwe


gingardu

#9
Oct 16, 2012, 09:05 am Last Edit: Oct 16, 2012, 09:14 am by gingardu Reason: 1

Grazie per la risposta

Ho provato anche i tre if come da te consigliato ma non cambia la sostanza
per quanto riguarda il potenziometro nessun problema ho gia' verificato con multimetro oscilloscopio Tektronics 213 DMM e' uno strumento preciso e riesco ad trimmare abbastanza preciso ma non riesco ad accendere i led anche spostando da un estremo all'altro cioe' da 0 a 4.99 Volt. Se utilizzo l'operatore <= tutto ok per me' e' un mistero .




questo li fa accendere   (mettere nel void loop  e assicurarsi che i pin siano settato come output e messi LOW nel setup)

map(analogRead(A0), 0, 1023, 0, 500);

if  (analogRead(A0) >= 321 && analogRead(A0) < 322) digitalWrite (10, HIGH);
if  (analogRead(A0) >= 322 && analogRead(A0) < 323) digitalWrite (11, HIGH);
if  (analogRead(A0) >= 323 && analogRead(A0) < 324) digitalWrite (12, HIGH);


e se metti anche queste righe si spengono se il  potenziometro fa segnare una tensione diversa


if  (analogRead(A0) <  321 && analogRead(A0) >=322) digitalWrite (10, LOW);
if  (analogRead(A0) <  322 && analogRead(A0) >=323) digitalWrite (11, LOW);
if  (analogRead(A0) <  323 && analogRead(A0) >=324) digitalWrite (12, LOW);


IMHO  fare ==  su un analogRed   è gia una specie di controsenso
ci va sempre l'accoppiata    >=  <   


Le cose si possono considerare facili in due casi: quando le si conosce bene o quando non le si conosce affatto...

astrobeed


Se usi dei Float non puoi usare il == ma devi sempre definire un valore sopre a uno sotto il quale la condizione é valida.


Confermo, per via di come sono rappresentati i float è praticamente impossibile prevedere un valore esatto su cui eseguire un confronto "==", è sempre necessario prevedere una certa isteresi utilizzando una soglia minore e una superiore.
Aggiungo pure che su Arduino non è molto saggio utilizzare i float quando non è indispensabile (usa una mcu da solo 8 bit senza nessun supporto hardware per i float),meglio lavorare sempre con valori interi preventivamente moltiplicati x10,x100,x1000, etc, a seconda del numero di decimali desiderati.

lesto


In definitiva se io misuro 3.21 e mi dopo la mia conversione vedo 3.21 perche' l'operatore di ccomparazione non funge?


perchè la println "taglia" alla seconda cifra decimale, ma in realtà ce ne possono essere di più. Sul reference trovi quale println usare per visualizzare un numero arbitrario di valori dopo la virgola
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

latofra

Grazie a tutti per i preziosi consigli ho capito che beccare il giusto valore dopo la virgola e' un impresa titanica molto meglio prevedere delle finestre .I vostri consigli mi hanno spiegato in pratica come fare .
Per me il topic e' chiuso . Alla prossima

lesto


I valori possibili sono:
ADC= 658 valore calcolato= 3.19788002
ADC= 659 valore calcolato= 3.20274019
ADC= 660 valore calcolato= 3.20760011
ADC= 661 valore calcolato= 3.21246004
ADC= 662 valore calcolato= 3.21732020
ADC= 663 valore calcolato= 3.22218012
ADC= 664 valore calcolato= 3.22704005
ADC= 665 valore calcolato= 3.23190021
ADC= 666 valore calcolato= 3.23676013
ADC= 667 valore calcolato= 3.24162006
ADC= 668 valore calcolato= 3.24648022
ADC= 669 valore calcolato= 3.25134015


una precisazione; questi valori sono validi se calcolati con i float (vedi infinitesimale del calcolatore) e utilizzando la stessa logica che usa il chip.
Per fare un esempio, sempre con i float, avevo problemi che simulazioni fisiche su due sistemi differenti, nonostante gli stessi valori iniziali, avevano delle diversità dopo pochi step di esecuzione; per risolvere è bastato dare come direttiva al compilatore il parametro "strictfp" (questo in java, ma se ben ricordo c'è qualcosa di simile anche in C), in pratica disattivi tutte le ottimizzazioni non standard sul calcolo dei valori float, che sono diverse da CPU a CPU.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

astrobeed


che sono diverse da CPU a CPU.


Non da cpu a cpu, parliamo di micro senza fpu, ma da compilatore a compilatore e relative implementazioni su micro specifici dello stesso.
Di solito sul manuale del compilatore c'è sempre una sezione dedicata ai float dove viene descritta l'implementazione utilizzata, quella più diffusa è la IEEE 754, e le eventuali divergenze dallo standard utilizzato.

Go Up