Go Down

Topic: Problema con analogRead (Read 2690 times) previous topic - next topic

d407336

Ho uno strano problema con analogRead() e non riesco a capire perchè mi succede.

Uso tre ingressi analogici e un lcd per vedere i valori letti.
Uno lo uso come un digitale, quindi nel setup() ho messo pinMode INPUT numerando il pin secondo i pin analogici ma da 14 a 19 anzichè da 0 a 5.
Agli altri due pin ho collegato dei potenziometri.
Con un analogRead() leggo il primo valore analogico dal potenziometro.
Il secondo valore analogico dell'altro potenziometro lo leggo solo quando vedo che il pin che uso come digitale è alto, per farlo uno digitalRead() e un interruttore.
Se lascio l'interruttore aperto vedo il primo valore analogico correttamente.
Se invece chiudo l'interruttore il secondo valore analogico lo vedo correttamente, ma il primo che continuo a leggere sale e scende da solo...
Non capisco perchè succeda, ho letto che servono almeno 100us per ricaricare il condensatore dell'analogRead(), ma anche mettendo 10 millisecondi di delay tra un analogRead() e l'altro non cambia...

m_ri

domanda banale: il primo ingresso analogico è collegato a qualcosa con tensione fissa,quando lo vedi flottare?

uwefed

Come hai collegato l'interuttore? usi una resistenza pullup/pulldown?
Ciao Uwe

d407336

dopo varie prove ho scoperto che se prima di leggere quello che mi serve metto un'analogRead() a vuoto funziona tutto correttamente.
Per esempio se invece di mettere
Code: [Select]
int a = analogRead(A0);
metto
Code: [Select]

analogRead(A0);
int a = analogRead(A0);

funziona.
Ma è normale che faccia così?

leo72

La prima volta che si usa l'ADC è bene fare una lettura a vuoto per calibrare il circuito S&H interno. Questo vale anche nel caso di ADC spento per motivi di sleep o altro.
Potresti postare lo sketch usato per capire cosa può succedere?

d407336

#5
Dec 13, 2012, 08:44 pm Last Edit: Dec 13, 2012, 08:51 pm by d407336 Reason: 1
Allora, ecco quello che ho scoperto:

Code: [Select]
#include "LiquidCrystal.h"
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  lcd.begin(16, 2);
}

void loop() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(analogRead(A0));
  lcd.setCursor(8, 0);
  lcd.print(analogRead(A2));
  lcd.setCursor(0, 1);
  lcd.print(analogRead(A1));
  lcd.setCursor(8, 1);
  lcd.print(analogRead(A3));
 
  delay(500);
}


Con questo codice stampo sull'lcd quello che leggo dai pin analogici 0, 1, 2 e 3.
Quello che c'è collegato ai pin A0 e A1 lo lascio fisso, mentre faccio variare quello collegato ai pin A2 e A3:

  • se alzo A3 cambia anche il valore di A0

  • se alzo A2 cambia anche il valore di A1


Quando alzo A2 o A3 vedo correttamente i valori di A2 e A3 (almeno sembra che salgano correttamente), mentre gli altri valori si alzano di un po' ma non in modo stabile, rimangono sempre più alti del normale ma un po' salgono e un po' scendono.


Se invece faccio:
Code: [Select]
#include "LiquidCrystal.h"
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  lcd.begin(16, 2);
}

void loop() {
  lcd.clear();
  lcd.setCursor(0, 0);
  analogRead(A0);
  lcd.print(analogRead(A0));
  lcd.setCursor(8, 0);
  lcd.print(analogRead(A2));
  lcd.setCursor(0, 1);
  analogRead(A1);
  lcd.print(analogRead(A1));
  lcd.setCursor(8, 1);
  lcd.print(analogRead(A3));
 
  delay(500);
}

funziona tutto correttamente.
Anche se non metto analogRead() a vuoto per i pin A2 e A3 funziona, forse perchè A0 e A1 rimangono sempre uguali?

Se invece degli analogRead() a vuoto metto un delay(10) i valori diventano instabili come all'inizio.

p.s. non ho collegato più nessun interruttore.

p.p.s.

La prima volta che si usa l'ADC è bene fare una lettura a vuoto per calibrare il circuito S&H interno. Questo vale anche nel caso di ADC spento per motivi di sleep o altro.

Intendi una lettura a vuoto all'inizio di tutto e poi basta o ogni volta prima di leggere da un pin analogico?
Perchè se metto una lettura a vuoto in setup() non funziona l'lcd.
edit: forse non si era resettato bene l'lcd ;) ho riprovato e funziona ma i valori sono instabili come all'inizio.

cyberhs

Non vedo nel setup l'assegnazione degli ingressi analogici.

Se non lo fai, è normale che tu debba effettuare una "lettura a vuoto", poiché con essa Arduino capisce che quell'ingresso è di input.

leo72


Non vedo nel setup l'assegnazione degli ingressi analogici.

Se non lo fai, è normale che tu debba effettuare una "lettura a vuoto", poiché con essa Arduino capisce che quell'ingresso è di input.

Se si usano i pin analogici come ingressi appunto analogici, non è necessario dichiarare i pin come input usando pinMode dato che questo controlla l'ingresso digitale del pin e non l'ADC, che viene agganciato al pin in oggetto dalla funzione analogRead.

leo72

@d407376:
esiste una modalità di lettura, descritta nel datasheet, detta "Free Running Mode", in cui si possono eseguire più letture una dietro l'altra. Se però in questa modalità si cambia canale (cioè pin letto), la prima lettura dopo il cambio di canale rispecchierà il canale precedente e solo quella successiva sarà riferita al nuovo canale.
Ora, analizzando l'analogRead dell'Arduino mi pare che sia impostata proprio questa modalità per cui il problema riscontrato potrebbe essere dato da questo. Quindi la lettura a vuoto per ricalibrare l'ADC è necessaria affinché esso cambi canale correttamente.

d407336

pinMode per i pin analogici sò che non va usato, come ha detto leo.


@d407376:
esiste una modalità di lettura, descritta nel datasheet, detta "Free Running Mode", in cui si possono eseguire più letture una dietro l'altra. Se però in questa modalità si cambia canale (cioè pin letto), la prima lettura dopo il cambio di canale rispecchierà il canale precedente e solo quella successiva sarà riferita al nuovo canale.
Ora, analizzando l'analogRead dell'Arduino mi pare che sia impostata proprio questa modalità per cui il problema riscontrato potrebbe essere dato da questo. Quindi la lettura a vuoto per ricalibrare l'ADC è necessaria affinché esso cambi canale correttamente.

Grazie, ho capito il perchè ;)
Mettendo un analogRead() a vuoto prima non è un grand problema, ma se si volesse mettere non in free running sarebbe possibile?
Questa modalità riguarda proprio l'altmega o come è scritta la funzione?

leo72


se si volesse mettere non in free running sarebbe possibile?
Questa modalità riguarda proprio l'altmega o come è scritta la funzione?

La risposta semplice è no. Devi cambiare il core dell'Arduino ed ovviamente poi tutto quello che fa uso dell'analogRead non funzionerebbe più per come era stato inizialmente pensato per cui lascia perdere.  ;)

d407336

ok
un'altra cosa, se all'interno del programma metto analogReference(INTERNAL) per leggere da un pin, poi rimetto analogReference(DEFAULT) per leggere da un altro pin e lo faccio in continuazione non ci sono problemi?

leo72


ok
un'altra cosa, se all'interno del programma metto analogReference(INTERNAL) per leggere da un pin, poi rimetto analogReference(DEFAULT) per leggere da un altro pin e lo faccio in continuazione non ci sono problemi?

Non collegare nulla al pin AREF, però.

d407336

no, non collego niente ;)
chiedevo solo per sapere se fare continuamente queste operazione è troppo "stressante" per l'atmega

cyberhs

Ha ragione Leo quando dice che non è indispensabile usare il pinmode per gli ingressi analogici, ma io lo uso lo stesso per attivare o disattivare il resistore interno.

Go Up