analogRead mi da sempre 0

Salve a tutti,
Ho un problema con analogRead, in pratica devo misurare la caduta di tensione su una resisteza con analogRead, ma qualsiasi pin analogico usi, o qualsiasi resistenza il risultato mi da sempre 0, quale può essere il problema?

Facci vedere il collegamento che fai (anche uno schemino desegnato su un pezzo di carta e fotografato) …
… e metti il codice di prova che stai usando (…mi raccomando, in conformità al regolamento, punto 7, il codice va racchiuso tra i tag CODE che, in fase di edit, ti inserisce il bottone </> … primo a sinistra).

Guglielmo

Il circuito è semplicissimo poiché lo sto provando, utilizzo un arduino nano con uno shield, collego un cavo ai 5V e alla resistenza, poi l’altro capo della resistenza ad A0.

void setup() {
  Serial.begin(9600);

}

void loop() {
  Serial.println(analogRead(A0));
  delay(2000);
  
}

Quando stampo e non ho il cavo collegato ad A0 mi da dei valori casuali, quando collego il cavo ad A0 mi da sempre 0

Captura.PNG

Mi sa che ti devi andare a ristudiare la "legge di Ohm" perché ... in quel modo NON hai alcuna caduta di tensione (misurabile) ... ::slight_smile:

Se vuoi misurare qualche cosa DEVI fare un partitore di tensione, ovvero DUE resistenze in serie e misurare la caduta di tensione al centro tra le due.


Guglielmo

_P.S.: Quando non colleghi nulla è normale che hai dei valori casuali ... i pin in ingresso ad Arduino sono ad altissima impedenza e, se lasciati non collegati, captano qualsiasi disturbo ... _

Ho provato anche in questo modo, con questo codice:

int Vd0;
float V0;
float R0;
const int R=330000;
const int V=5;

void setup() {
Serial.begin(9600);

}

void loop() {
  
  Vd0=analogRead(A0);


  V0=Vd0*V/1023;


  R0=Vd0*R/(V-V0);

  Serial.println(Vd0);
  Serial.println(V0);
  Serial.println(R0);
  delay(1000);
}

Collego il verde ai 5V e il rosso a GND e il marrone in alto ad A0, ma in uscita mi da comunque sempre 0

Allora:

  1. comincia con due resistenze di uguale valore (così la caduta è 2.5V) e la cui somma NON superi i 10/15 KΩ

  2. Fai un banalissimo prgramma senza alcun calcolo che legge il pin analogico e stampa il valore direttamente

Guglielmo

Ho provato ma comunque mi stampa sempre 0, potrei aver bruciato i componenti durante la saldatura?

Bruciare le resistenze ? ? ? :o :o :o ... quasi impossibile :wink:

Verifica di aver effettuato esattamente il collegamento come ti ho disegnato; se hai messo le due resistenze uguali, senza collegarle all'alimentazione, misura con un multimentro (o con un tester) la resistenza agli estermi (dovresti leggere un valore pari alla somma delle due resistenze). Collega gli estremi all'alimentazione e con il mmultimetro (o con il tester) misura la tesnione tra GND ed il punto di collegamento delle due resistenze (dovresti leggere, con due resistenze uguali, circa 2.5V).

Fatte tutte queste verifiche, puoi pasare al collegamento con Arduino ...

Guglielmo

Ho rifatto il collegamento e adesso funziona, ho solo un altro problema adesso riguardo il calcolo della resistenza, i valori di tensione in uscita sono giusti ma il calcolo della resistenza è sbagliato, ho usato questo codice:

  int Vd;
  float V;
  float R;
void setup() {
  Serial.begin(9600);

}

void loop() {
  Vd=analogRead(A0);
  V=Vd*5/1023;
  R=Vd*1500/(5-V);
  Serial.println(Vd);
  Serial.println(V);
  Serial.println(R);
  delay(2000);

}

... potresti scrivermi la "formula" (basata sulla legge di Ohm) con cui pensi di calcolare il valore di Rx ? Che valori di resistenze stai usando nel partitore?

Guglielmo

In sostanza, hai impostato il partitore resistivo con una resistenza R1 fissa verso Vcc, e quella da misurare verso GND, esatto?

Tu con "V=Vd*5/1023;" praticamente vuoi mappare i valori da 0 a 1023 per trasformarli in Volt.

Intanto essendo la variabile Vd una "int" tutto il calcolo ti diventa intero (il fatto che vada a finire in una float è irrilievante), devi fare ad esempio questo per "far capire" che vuoi un calcolo float:

V=Vd*5.0/1023;

Poi però la seconda parte è sbagliata, ossia nel calcolo della resistenza non devi più usare Vd ma V (il valore 1500 suppongo sia della seconda resistenza R2).

Poiché tensione misurata è:

V = Vcc*R2/(R1+R2)

avrai:

R2 = R1*V/(Vcc-V)

Quindi se ho R1=1500 (sicuro?) e Vcc=5, se correggi la seconda espressione mettendo V al posto di Vd dovresti avere i valori corretti.

VittoM:
Ho rifatto il collegamento e adesso funziona, ho solo un altro problema adesso riguardo il calcolo della resistenza, i valori di tensione in uscita sono giusti ma il calcolo della resistenza è sbagliato, ho usato questo codice

ma scusa, non hai studiato telecomunicazioni e non sei molto ferrato in elettronica, sopratutto la parte hardware?
Oppure ho letto male la tua presentazione?

Ho risolto limitandomi al calcolo della tensione sulla resistenza, calcolando su un foglio quale dovrebbe essere e eliminando dal codice la parte di calcolo della resistenza. Per docdoc, hai ragione, la resistenza che usato non era da 1500 ma da 1000, ho sbagliato a scrivere, sostituendo come mi hai detto tu comunque i risultati sono giusti.
Grazie a tutti per i consigli :slight_smile:

Oltre al problema del calcolo della tensione e della resistenza, il tuo codice legge erroneamente il valore analogico. Il problema è che stai leggendo dal analog pin 14 (che non esiste) e non da A0. La definizione di A0 deve essere utilizzata con digitalRead / digitalWrite. Quando si utilizza analogo, il valore corretto è semplicemente 0.

No: Vd=analogRead(A0);
Si: Vd=analogRead(0);

sicuro? :smiley:
dal reference:

Parametri

pin: il numero del pin analogico da cui leggere ( da 0 a 5 su molte schede, da 0 a 7 su Mini e Nano, da 0 a 15 sul Mega )
Restituisce

int( 0 to 1023 )
Codice di Esempio

Il codice legge la tensione su analogPin e la visualizza.

int analogPin = A3; // manopola del potenziometro (terminale centrale) connessa ad A3
// terminali esterni connessi a massa e +5V
...
...

...e il pin 14 è il pin analogico 0 :wink:

>bitbank: NO, è sbagliato … sarebbe bastato andare a guardare nel “core” il file “wiring_analog.c” per soprire che, per Arduino UNO (ogni modello di MCU con differenti pin analogici, ha delle parti specifiche) viene fatto:

if (pin >= 14) pin -= 14; // allow for channel or pin numbers

… che rimette a posto le cose :smiling_imp:

Guglielmo

gpb01:
>bitbank: NO, è sbagliato ... sarebbe bastato andare a guardare nel "core" il file "wiring_analog.c" per soprire che, per Arduino UNO (ogni modello di MCU con differenti pin analogici, ha delle parti specifiche) viene fatto:

if (pin >= 14) pin -= 14; // allow for channel or pin numbers

... che rimette a posto le cose :smiling_imp:

Guglielmo

Grazie Guglielmo - È logico che esista il fail-safe per impedire alle persone di commettere questo errore.

bitbank:
È logico che esista il fail-safe per impedire alle persone di commettere questo errore.

Mah ... non lo considererei un errore ... sulle stesse schede, se guardi, i pin sono identificato come A0, A1, ecc. ...
... è che hanno voluto lasciare entrambe le possibilità, sia usare il numero (0, 1, 2, ...) sia usare la label (A0, A1, A2, ...). :slight_smile:

Guglielmo

gpb01:
sarebbe bastato andare a guardare nel "core" il file "wiring_analog.c" per soprire che, per Arduino UNO (ogni modello di MCU con differenti pin analogici, ha delle parti specifiche) viene fatto:

if (pin >= 14) pin -= 14; // allow for channel or pin numbers

Hm una mia curiosità: non capisco bene questa istruzione, se io impostassi per errore pin a 30 ad esempio, risulterebbe 16? Perché non fare modulo 14 ma si limita a sottrarre 14?

PS a parte che non trovo quella istruzione in wiring-analog.c dove la trovo?

La trovi dentro alla analogRead():

int analogRead(uint8_t pin)
{
	uint8_t low, high;

#if defined(analogPinToChannel)
#if defined(__AVR_ATmega32U4__)
	if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#endif
	pin = analogPinToChannel(pin);
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
	if (pin >= 54) pin -= 54; // allow for channel or pin numbers
#elif defined(__AVR_ATmega32U4__)
	if (pin >= 18) pin -= 18; // allow for channel or pin numbers
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
	if (pin >= 24) pin -= 24; // allow for channel or pin numbers
#else
	if (pin >= 14) pin -= 14; // allow for channel or pin numbers
#endif

#if defined(ADCSRB) && defined(MUX5)
	// the MUX5 bit of ADCSRB selects whether we're reading from channels
	// 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
	ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
#endif
  
	// set the analog reference (high two bits of ADMUX) and select the
	// channel (low 4 bits).  this also sets ADLAR (left-adjust result)
	// to 0 (the default).
#if defined(ADMUX)
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
	ADMUX = (analog_reference << 4) | (pin & 0x07);
#else
	ADMUX = (analog_reference << 6) | (pin & 0x07);
#endif
#endif

	// without a delay, we seem to read from the wrong channel
	//delay(1);

#if defined(ADCSRA) && defined(ADCL)
	// start the conversion
	sbi(ADCSRA, ADSC);

	// ADSC is cleared when the conversion finishes
	while (bit_is_set(ADCSRA, ADSC));

	// we have to read ADCL first; doing so locks both ADCL
	// and ADCH until ADCH is read.  reading ADCL second would
	// cause the results of each conversion to be discarded,
	// as ADCL and ADCH would be locked when it completed.
	low  = ADCL;
	high = ADCH;
#else
	// we dont have an ADC, return 0
	low  = 0;
	high = 0;
#endif

	// combine the two bytes
	return (high << 8) | low;
}

I pin analogici, sul ATmega328P corrispondono ai pin digitali dal 14 in poi.

Guglielmo