Loading...
Pages: [1]   Go Down
Author Topic: Lettura Potenziometro e Oversampling  (Read 300 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 15
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Carissimi, sono alle prese con la lettura di un potenziometro:

con il seguente codice ed un semplice potenziometro da 10K (nuovo di stecca), collegato correttamente alla porta analogica (0) di un Arduino Mega 2560 Rev.3, alimentato via USB dal PC, è CHIARO che, ruotando LENTAMENTE il potenziometro, (e aggiustandolo INTENZIONALMENTE), si arriva a quel SOTTILE PUNTO in cui il potenziometro genera QUEL VALORE DI TENSIONE che sarebbe in mezzo fra, ad esempio, 64 e 65, generando, sul serial monitor, una lettura instabile della variabile 'numero' (vedi codice esempio) (esso infatti fluttuerà fra 2 e 3).

Dal momento che vorrei realizzare una capillare lettura stabile di 1024/8=128 valori dati dal convertitore, è chiara la FITTA RETE di 'if else' (vedi codice esempio) che dovrò scrivere nel codice e quindi quanta confusione questo codice genererebbe sul serial monitor...
(più è fitta la rete, più spesso verrà lasciato il potenziometro a cavallo dei famosi due valori...)
L'unico modo che ho trovato per risolvere questo problema è il Sovracampionamento (con Vref di 5V) a 11 o addirittura a 12bit. Tuttavia NON so come applicare detta tecnica al codice che vi ho esposto.
Qualcuno può aiutarmi? Ovvero, come posso sovracampionare la lettura di questo potenziometro?
Grazie, Ruben

Code:
// Codice by Tonetta Ivan(Ruben) in data 19.03.2013
byte numero = 0;

void setup() { Serial.begin(9600); }
void loop() {
  int valore = (analogRead(0)/8); // Lettura del valore del potenziometro
  if (valore <= 32)                      { numero = 1; }
  else if (valore > 32 && valore <= 64)  { numero = 2; }
  else if (valore > 64 && valore <= 96)  { numero = 3; }
  else if (valore > 96 && valore <= 128) { numero = 4; }
  Serial.println(numero); // invio valori al serial monitor per la stampa
  delay(10); // attendi 10ms
}

Logged

ivrea (to)
Offline Offline
God Member
*****
Karma: 15
Posts: 896
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Se non ho capito male, ti risolve tutto una istruzione software, la map()
http://arduino.cc/en/Reference/Map

int val = analogRead(0);
val = map(val, 0, 1023, 0, 255);     // un valore tra 0-1023   trasformato in uno proporzionale 0-255

nel tuo caso: val=map(val,0,1023,1,4);
« Last Edit: March 19, 2013, 04:46:11 pm by nid69ita » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 15
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

carissimo, anche la funzione map arriva fino ad un certo punto...
E' PROPRIO UN LIMITE HARDWARE dato dal fatto che necessito di un paio di bit in piu rispetto ai 10 che offre arduino


grazie, Ruben
Logged

ivrea (to)
Offline Offline
God Member
*****
Karma: 15
Posts: 896
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ti riferisci a questo?
http://www.atmel.com/images/doc8003.pdf
Logged

Cagliari
Offline Offline
Faraday Member
**
Karma: 51
Posts: 3164
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

L'unico modo che ho trovato per risolvere questo problema è il Sovracampionamento (con Vref di 5V) a 11 o addirittura a 12bit. Tuttavia NON so come applicare detta tecnica al codice che vi ho esposto.
Qualcuno può aiutarmi? Ovvero, come posso sovracampionare la lettura di questo potenziometro?

Sostituisci
Code:
int valore = (analogRead(0)/8); // Lettura del valore del potenziometro

con

Code:
byte numerocampioni = 16;
unsigned long valore = 0;
for (byte j=0; j>numerocampioni; j++)
 {
  valore += (analogRead(0)/8); // Lettura del valore del potenziometro
  }
valore /= numerocampioni;

In questo modo fai una medi su n campioni, ma non stai sovracampionando.
« Last Edit: March 19, 2013, 05:48:01 pm by PaoloP » Logged


Forum Moderator
Italy
Online Online
Brattain Member
*****
Karma: 226
Posts: 16975
Don't know what I do
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Per l'oversampling ti passo questo doc:
http://www.atmel.com/images/doc8003.pdf

Per ogni bit in più di risoluzione devi campionare 22n volte in più. Quindi per 1 bit devi fare 4 letture, per 2 bit, 16 letture ecc. Riduci quindi la velocità di campionamento.

Potresti risolvere via software mettendo un controllo che ti memorizzi i precedenti 2 valori e se ti accorgi che il 3° è uguale al primo e differisce solo di 1 dal 2° allora vuol dire che il valore letto sta oscillando di 1 unità in su ed in giù.
es.
62-63-62-63....
Al 3° valore, non stampi la nuova unità ma replichi la 2a lettura.
Logged


Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 76
Posts: 7538
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Qualcuno può aiutarmi? Ovvero, come posso sovracampionare la lettura di questo potenziometro?

Non puoi usare l'oversampling con un potenziometro perché questa tecnica ha come prerequisito la presenza di rumore, con distribuzione uniforme, sul segnale.
In tutti i casi tutti gli ADC hanno sempre l'instabilità di +/- 1 count, indipendentemente dalla risoluzione avresti sempre dei punti dove la cifra, non importa se rappresenta una frazione della risoluzione, oscilla.
Unica soluzione possibile è fare una media mobile su almeno 16 campioni, in questo modo non elimini completamente il problema, però lo attenui moltissimo.
La media mobile si fa tramite un ring register, sopra scrivi continuamente tutti i campioni presi dal ADC partendo dalla prima posizione fino alla fine, poi riparti dalla prima posizione, ad ogni campionamento fai la media di tutti i valori del ring register, in questo modo ottieni l'andamento ideale del segnale pulendolo dal rumore e dalle fluttuazioni del ADC stesso.
Logged


ivrea (to)
Offline Offline
God Member
*****
Karma: 15
Posts: 896
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bel link Leo, sembra il mio  smiley-mr-green

Dal codice del primo post sembrava volessi fare semplicemente una map;
tra l'altro bastava un calcolo invece di quei if infiniti
val=int((valore_letto-1)/32)+1    // solo valore 0 da 0, perciò al max un if
Logged

Forum Moderator
Italy
Online Online
Brattain Member
*****
Karma: 226
Posts: 16975
Don't know what I do
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Bel link Leo, sembra il mio  smiley-mr-green
...azz....  smiley-sweat

Logged


0
Offline Offline
Newbie
*
Karma: 0
Posts: 15
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grazie a tutti voi. Appena posso provo il tutto e vi faccio sapere. Scusate il ritardo ma ho appena saputo di essere papà. ..

Impiego un po a scrivere anche perché non ho internet. ..
Grazie ancora. A presto
Logged

Pages: [1]   Go Up
Print
 
Jump to: