Buongiorno,
ho necessità di leggere un pin analogico senza che la lettura analogica introduca un ritardo. Non ho necessità ne' di alte velocità di acquisizione e ne' di utilizzare i 10 bit, 8 bit sono sufficienti.
Non ho necessità nemmeno di usare l'interrupt.
Pensavo di usare questo codice
` /* The bit of code below was taken from:
* http://yaab-arduino.blogspot.it/p/oscope.html
*/
ADCSRA = 0; // clear ADCSRA register
ADCSRB = 0; // clear ADCSRB register
ADMUX |= (0 & 0x07); // set A0 analog input pin
ADMUX |= (1 << REFS0); // set reference voltage
ADMUX |= (1 << ADLAR); // left align ADC value to 8 bits from ADCH register
//ADCSRA |= (1 << ADPS2) | (1 << ADPS0); // 32 prescaler for 38.5 KHz
ADCSRA |= (1 << ADPS2); // 16 prescaler for 76.9 KHz
//ADCSRA |= (1 << ADPS1) | (1 << ADPS0); // 8 prescaler for 153.8 KHz
ADCSRA |= (1 << ADATE); // enable auto trigger
ADCSRA |= (1 << ADEN); // enable ADC
ADCSRA |= (1 << ADSC); // start ADC measurements`
per settare il convertitore e poi, nel loop, dove ne ho bisogno eseguire:
valoreAnalogico = ADCH;
Funziona? Lo chiedo perchè cercando in rete ho trovato molte cose diverse ma questa mi sembra semplice e funzionale e non introduce alcun ritardo nel loop da sembrare troppo bella.
Qualcuno potrebbe suggerirmi la configurazione per lasciare il prescaler a 128?
@fabio67 : in conformità al REGOLAMENTO , punto 7, cortesemente edita il tuo post qui sopra (quindi NON scrivendo un nuovo post, ma utilizzando il bottone a forma di piccola matita che si trova in basso del tuo post), seleziona TUTTA la parte di codice e premi l'icona </> nella barra degli strumenti per contrassegnarla come codice.
Per maggiori informazioni ... punto 17.2 del succitato regolamento. Grazie.
Guglielmo
P.S.: Ti ricordo che, purtroppo, fino a quando non sarà sistemato il codice, nel rispetto del suddetto regolamento nessuno ti risponderà, quindi ti consiglio di fare il tutto al più presto.
ma mi rimane un dubbio.
Mi sembra di capire che per far funzionare in maniera continua l'ADC ci sia bisogno di un segnale di trigger configurabile con il registro ADCSRB ma, nell'esempio che ho trovato e che ho riportato, il registro viene azzerato e non riconfigurato.
Può il convertitore essere triggerato dal segnale di EOC in modo da non essere necessario alcun altro segnale? O comunque funzionare in maniera continua senza una ben precisa frequenza di campinamento?
Prova a dara un'occhiata qui, nella sezione " Free running sampling" spiega come settare l'ADC per la lettura continua, leggendo il risultato con un interrupt.
Attenzione che nel codice è stata omessa la keyword "volatile" nella dichiarazione di aval, necessaria visto che si usa nell'interrupt.
A suo tempo avevo fatto anche io delle prove per ADC FreeRunning ed avevo verificato la lettura anche su due canali diversi (passaggio da A0 ed A1 e viceversa) ... magari questo programmino può essere utile :
#include <avr/sfr_defs.h>
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
void setup() {
delay ( 500 );
Serial.begin ( 115200 );
//
// Init ADC for freeRunning mode prescaler 32, VREF internal 5V, start on A0
ADCSRA = 0;
sbi ( ADCSRA, ADEN );
sbi ( ADCSRA, ADATE );
sbi ( ADCSRA, ADPS2 );
sbi ( ADCSRA, ADPS0 );
ADCSRB = 0;
ADMUX = 0x40;
sbi ( ADCSRA, ADSC );
}
void loop() {
int analog_A0, analog_A1;
unsigned long tStart_0, tEnd_0, tStart_1, tEnd_1;
//
// read 10 times A0 and then calculates the average of the values
tStart_0 = micros();
analog_A0 = 0;
for ( byte i = 0; i < 10; i++ ) {
loop_until_bit_is_set ( ADCSRA, ADIF );
analog_A0 += ADC;
cbi ( ADCSRA, ADIF );
}
tEnd_0 = micros();
analog_A0 /= 10;
//
// switch to analog port A1
tStart_1 = micros();
cbi ( ADCSRA, ADEN );
ADMUX = 0x41;
sbi ( ADCSRA, ADEN );
sbi ( ADCSRA, ADSC );
// read one time analog port A1
loop_until_bit_is_set ( ADCSRA, ADIF );
analog_A1 = ADC;
cbi ( ADCSRA, ADIF );
//
// switch back to analog port A0
cbi ( ADCSRA, ADEN );
ADMUX = 0x40;
sbi ( ADCSRA, ADEN );
sbi ( ADCSRA, ADSC );
tEnd_1 = micros();
//
// print the values
Serial.print ( "Valore A0 = " );
Serial.print ( analog_A0 );
Serial.print ( " - Elapsed time 0 = " );
Serial.println ( tEnd_0 - tStart_0 );
Serial.print ( "Valore A1 = " );
Serial.print ( analog_A1 );
Serial.print ( " - Elapsed time 1 = " );
Serial.println ( tEnd_1 - tStart_1 );
}
Grazie a entrambi per i suggerimenti.
Vi aggiorno comunque su dei test fatti : la porzione di codice, trovata su internet e ricondivisa, funziona senza interrupt e non introduce ritardo nel loop.