Go Down

Topic: [Risolto] ADC in Running Free Mode - Leggere 2 Ingressi (Read 2363 times) previous topic - next topic

marcolino7

Feb 03, 2013, 09:39 pm Last Edit: Feb 05, 2013, 10:51 am by marcolino7 Reason: 1
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: [Select]
 // 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: [Select]
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  :)

UweFederer

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

uwefed

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

marcolino7


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

marcolino7


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

Ciao scusa,
ma posso sbloccarlo io o deve farlo un moderatore?

leo72

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?

marcolino7


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

leo72

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.

lesto

se ricordo bene l'interrupt è lanciato anche in lettura singola.
In generale la prima lettura dopo il cambio pin va buttata via.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

marcolino7


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: [Select]
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

lesto

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)
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

marcolino7


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.

marcolino7


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  :)

marcolino7


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

lesto

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
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Go Up