Pages: [1] 2   Go Down
Author Topic: [Risolto] ADC in Running Free Mode - Leggere 2 Ingressi  (Read 1977 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao a tutti,
sono Marco e questo è il mio primo post sul forum.
Stò facendo il mio primo progetto con Arduino, e si tratta di ricostruire con componenti Thought Hole questo spelndido orologio:
http://www.vonnieda.org/tc18
e aggiungere funzionalità. Arrivo dalla programmazione PIC, ma questo è il mio primo progetto con arduino e processori AMTEL.
Ho questo problema. Il circuito dell'orologio, ha un Booster che trasforma i 9 Volt di alimentazione in 30-60 Volt per alimentare il display. Questa tensione, viene generata da un circuito Booster L-C ( qua il princicpio http://www.ladyada.net/library/diyboostcalc.html).
La tensione generata viene re-inmessa dento all'Arduino tramite un partitore sul Pin ADC0, e poi elaborata per mantenere l'alta tensione stabile.
Ho preso il codice originale dell'orologio e lo sto riadattando, ma non riesco a fare una cosa. Vorrei mettere sul pin ADC2 una fotoresistenza e poi avere anche la regolazione automatica della luminosità, ma per come l'autore ha scritto il codice non riesco a fare 2 letture diverse dall'ADC.

Posto il codice di impostazione dell'ADC:
Code:
 // Internal 1.1V Voltage Reference, Single Ended Input on ADC0
  ADMUX = _BV(REFS1) | _BV(REFS0);
  // ADC Enable, ADC Auto Trigger Enable, ADC Interrupt Enable
  // ADC Prescaler 128
  ADCSRA |= _BV(ADEN) | _BV(ADATE) | _BV(ADIE)
    | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);
  // ADC Start Conversion (starts free running mode)
  ADCSRA |= _BV(ADSC);

Il codice è commentato bene e per quello che capisco, fa partitr l'ADC in Free Running. Mi sono documento e ho capito che si tratta di una modalità che permette all'ADC di effettuare letture continue, e scatenare un Interrupt, quando una lettura è discponibile.
Infatti vi posto la routine di interrupt come l'ho modificata io, ma non funziona:

Code:
ISR(ADC_vect) {
  uint8_t tmp;            // temp register for storage of misc data
  tmp = ADMUX;            // read the value of ADMUX register
  tmp &= 0x0F;            // AND the first 4 bits (value of ADC pin being used)

    low = ADCL;
    high = ADCH;
 
  if (tmp == 0){
    if (voltage_sample++ > 20) {
      voltage_sample = 0;
     int adc = (high << 8) | low;
      voltage = 1.066f / (0x3ff - 1) * adc * 112.344;
      // We don't let the boost generator go below 10 or above 230
      // Those equate to roughly VCC and 60v so allowing it to
      // go too high can start blowing up components.
      if (voltage > voltage_target + voltage_drift && OCR2B > 10) {
        OCR2B--;
      }
      else if (voltage < voltage_target - voltage_drift && OCR2B < 230) {
        OCR2B++;
      }
    }
    ADMUX = ADMUX+2;            // add 1 to ADMUX to go to the next sensor
  }
  else if (tmp == 2){
        // put ADCvalue into whatever register you use for ADC2 sensor
        //ADMUX &= 0xF6;      // clear the last 4 bits to reset the mux to ADC0
        light = (high << 8) | low;
        ADMUX &= 0xF8;
        //Serial.println(light);
  }

}

A quanto ho capito devo leggere gli ultimi 4 bit del registro ADMUX per capire che porta dell'ADC sto leggendo, fare la lettura di ADCL e ADCH, e poi a seconda di ADMUX ho il valore della porta che mi interessa.
Invece non è così, se eseguo questo codice sull'orologio, sembra che la fotoresistenza collegata al pin ADC2 prenda il sopravvento, e mi regoli la luminosità del display entrando nella routine quando tmp==0. Ho provato anche con altri ingressi ma nulla cambia.
Ho cercato un po' in giro ma non ho trovato molto aiuto.

Grazie a tutti

PS è un Arduino UNO, quindi ATMEGA 328P
PSS Mi piace cominciare subito con qualcosa di difficile, altrimenti non c'è gusto  smiley
« Last Edit: February 05, 2013, 04:51:26 am by marcolino7 » Logged

Global Moderator
Offline Offline
Newbie
*****
Karma: 13
Posts: 14
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ho sbloccato il tread senó nessuno puó rispondere.
Ciao Uwe Federer
Logged

BZ (I)
Offline Offline
Brattain Member
*****
Karma: 249
Posts: 21183
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Per il tubo VLD mi manca il riscaldamento del filo emettitore elettroni.
Quello normalmente deve essere alimentato in alternata per garantire una luminositá uniforme. 
Ciao Uwe
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Per il tubo VLD mi manca il riscaldamento del filo emettitore elettroni.
Quello normalmente deve essere alimentato in alternata per garantire una luminositá uniforme. 
Ciao Uwe
Ciao Uwe,
grazie della risposta, ma questo step l'ho già passato. L'orologio funziona perfettamente e il tubo si accende e mostra i digit.
Ho il problema sull'ADC che ho scritto. In effetti sto rielaborando un progetto funzionante che utilizza un MAX6921 per pilotare i tubi.
Marco
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ho sbloccato il tread senó nessuno puó rispondere.
Ciao Uwe Federer
Ciao scusa,
ma posso sbloccarlo io o deve farlo un moderatore?
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Spiegami meglio.
Vuoi fare 2 letture dall'ADC, una fatta in automatico in free running mode ed una usando un'analogRead dal codice?
Se è così, non ti può funzionare perché nel momento in cui usi l'analogRead, l'ADC viene reimpostato. Inoltre l'ADC è multiplexato, quindi per fare 2 letture da 2 pin diversi viene cambiato canale ma l'ADC è sempre quello.
E' questo il problema o non ho capito io?
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Spiegami meglio.
Vuoi fare 2 letture dall'ADC, una fatta in automatico in free running mode ed una usando un'analogRead dal codice?
Se è così, non ti può funzionare perché nel momento in cui usi l'analogRead, l'ADC viene reimpostato. Inoltre l'ADC è multiplexato, quindi per fare 2 letture da 2 pin diversi viene cambiato canale ma l'ADC è sempre quello.
E' questo il problema o non ho capito io?
Ciao leo72,
no io voglio fare 2 letture da due pin diversi in Running Free Mode....
grazie
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 325
Posts: 22498
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Vabbè, vuoi fare comunque 2 letture.
Però hai il problema che ti ho menzionato. Cambiando canale, il multiplexer viene reinizializzato e quindi ci sono alcune precauzioni da prendere.
Leggi il datasheet cap. 23.5.1 Il 2° paragrafo parla proprio del cambio di canale in free running.
Logged


0
Offline Offline
Shannon Member
****
Karma: 129
Posts: 10441
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

se ricordo bene l'interrupt è lanciato anche in lettura singola.
In generale la prima lettura dopo il cambio pin va buttata via.
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Vabbè, vuoi fare comunque 2 letture.
Però hai il problema che ti ho menzionato. Cambiando canale, il multiplexer viene reinizializzato e quindi ci sono alcune precauzioni da prendere.
Leggi il datasheet cap. 23.5.1 Il 2° paragrafo parla proprio del cambio di canale in free running.

se ricordo bene l'interrupt è lanciato anche in lettura singola.
In generale la prima lettura dopo il cambio pin va buttata via.
Grazie leo72, lesto,
mi leggo il datasheet stasera, però a quanto dici lesto una cosa del genere?

Code:
ISR(ADC_vect) {

  volatile byte low = 0;
  volatile byte high = 0;
  volatile byte low1 = 0;
  volatile byte high1 = 0;

  uint8_t tmp;            // temp register for storage of misc data
  tmp = ADMUX;            // read the value of ADMUX register
  tmp &= 0x0F;            // AND the first 4 bits (value of ADC pin being used)

    low = ADCL;
    high = ADCH;
 
  if (tmp == 0){
      voltage = 1.066f / (0x3ff - 1) * adc * 112.344;
    ADMUX = ADMUX+2;            // add 1 to ADMUX to go to the next sensor
  }
  else if (tmp == 2){
        low1 = ADCL;
        high1 = ADCH;
        light = (high1 << 8) | low1;
        ADMUX &= 0xF8;
  }

}

dovrebbe funzionare?

Grazie
Logged

0
Offline Offline
Shannon Member
****
Karma: 129
Posts: 10441
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

se il problema è quello di "scartare" la prima lettura in realtà credo che basti invertirle...

per il codice che hai scritto mi pare solo mancare la parte relativa a OCR2B, che non capisco a cosa serva (non ho il datasheet sotto mano)
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

se il problema è quello di "scartare" la prima lettura in realtà credo che basti invertirle...

per il codice che hai scritto mi pare solo mancare la parte relativa a OCR2B, che non capisco a cosa serva (non ho il datasheet sotto mano)
Grazie lesto, stasera provo.
Per OCR2B non so esattamente, il codice non è mio, lo sto studianto ed adattando.
Il datasheet dice:

The Timer/Counter (TCNT2) and Output Compare Register (OCR2A and OCR2B) are 8-bit registers.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Vabbè, vuoi fare comunque 2 letture.
Però hai il problema che ti ho menzionato. Cambiando canale, il multiplexer viene reinizializzato e quindi ci sono alcune precauzioni da prendere.
Leggi il datasheet cap. 23.5.1 Il 2° paragrafo parla proprio del cambio di canale in free running.
ciao leo, nel datasheet del 328P non c'è il paragrafo 23.5.1, si ferma al 23.3.3  smiley
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

se il problema è quello di "scartare" la prima lettura in realtà credo che basti invertirle...

per il codice che hai scritto mi pare solo mancare la parte relativa a OCR2B, che non capisco a cosa serva (non ho il datasheet sotto mano)

Ciao lesto,
grazie per il suggerimento, ho invertitole letture nella routine di interrupt e adesso funziona perfettamente.
Giusto per capire io come funziona, e se avessi 3 sonde da leggere, diciamo A, B, e C, mi troverei nei valori ADCH e ADCL B, C e poi A?

Grazie Ancora.

Marco
Logged

0
Offline Offline
Shannon Member
****
Karma: 129
Posts: 10441
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

l'ADC di default "pensa" a 10bit, i reguistri sono a 8 bit, da quì la necessita di usare 2 registri, uno tiene 8bit e l'altro gli alti 2

di solito ADCL tiene gli 8 bit più a destra (i meno sisgnificativi) e ADCH i 2 più significativi, ma con un flag li puoi invertire

se imposti l'ADC a lavorare a 8 bit userai solo ADCL
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Pages: [1] 2   Go Up
Jump to: