Hallo HP,
hatte mich auch damit beschäftigt.
Die erste Idee, dies im Freeflow-Modus des AD-Wandlers zu machen habe ich fallengelassen, nachdem ich die Dokumentation dazu gelesen hatte. Das Problem ist nämlich, dass man dann nicht mit 100%iger Sicherheit sagen kann, zu welchem Kanal die gerade anstehenden Daten gehören.
Das ist kein Problem. Die ADC Pipline braucht genau zwei Schritte (hier Interrupts) bis nach dem Setzen von ADMUX die passenden Daten fertig sind. Mit diesem Wissen konnte ich den nötigen Code vereinfachen.
Dein ADC_DATA[] heißt bei mir state[]. Hier meine zentrale Interruptroutine.
Code:
/**
* ADC_vect: handles all ADC and odometry ticking
*/
ISR(ADC_vect) {
static unsigned char flag[2], avg[2], toggle = 0, stable=0;
static unsigned int old;
static unsigned char mux[]={
(1 << ADLAR) | (1 << REFS0) | SWITCH,
(1 << ADLAR) | (1 << REFS0) | IR_LEFT, // AVCC reference with external capacitor
(1 << ADLAR) | (1 << REFS0) | IR_RIGHT, // AVCC reference with external capacitor
(1 << ADLAR) | (1 << REFS0) | (1 << REFS1) | BATTERY, // internal 2.56V reference with external capacitor
(1 << ADLAR) | (1 << REFS0) | WHEEL_LEFT, // AVCC reference with external capacitor
(1 << ADLAR) | (1 << REFS0) | WHEEL_RIGHT // AVCC reference with external capacitor
};
state[toggle]=ADCL + (ADCH << 8);
if(toggle<2) {
if(ADCH>avg[toggle]) avg[toggle]++; else avg[toggle]--;
if ( flag[toggle]? (ADCH < avg[toggle]-5) : (ADCH > avg[toggle]+5)) {
// if ( flag[toggle]? (ADCH < 180) : (ADCH > 190)) {
encoder[toggle]++;
flag[toggle] ^= 1;
}
}
if(toggle==2) {
stable++;
if(state[2][list=1]old) {
stable=0;
old=state[2];
}
if(stable>3) state[6]=old;
}
ADMUX = mux[toggle];
toggle=(toggle+1) % sizeof(mux);
}
Und dann z.B. für LineData()
Code:
/**
* reads out the phototransistors
* @param data pointer to the data destination. access: data[LEFT], data[RIGHT]
*/
void LineData(unsigned int *data)
{
data[0] = state[3];
data[1] = state[4];
}
Lesezeichen