-
-
Neuer Benutzer
Öfters hier
Hallo Rabenauge,
um klarzustellen was da passiert, muss man etwas in den Eingeweiden der Nibobee wühlen.
Wird mit analog_init() der ADWandler gestartet, so arbeitet er "interrupt getrieben" vor sich hin. D.h. sobald die Wandlung abgeschlossen ist, löst er einen Interrupt aus. In der ADC-Interruptroutine (siehe unten den Teil des listing von analog.c) wird das Resultat abgeholt (analog_storeResult(analog_pos)), ein neuer Kanal eingestellt (++analog_pos...) und die nächste Wandlung gestartet (analog_setupNext(analog_pos)).
ISR(ADC_vect) {
analog_storeResult(analog_pos);
if (++analog_pos>10) {
analog_pos=0;
}
analog_setupNext(analog_pos);
}
Das macht er für 11 analoge Kanäle (Warum 11 kommt später).
Mit deiner neu Konfiguration von ADCSRA in deiner Sharp(void) bringst du diesen Automatismus zum Stehen. Dadurch funktioniert nun die Abfrage der Liniensensoren nicht mehr und "meine" Batteriespannungsmessung hängt sich auf, denn sie setzt auf die laufenden Interrupts.
Eigentlich brauchst du deine Sharp(void) nicht, denn das Resultat von ADC3 findest du auch im Array analog_samples[..] (siehe analog.c) als 3. Eintrag, denn ANALOG_EXT3 = 3 (siehe analog.h).
Also mit
sharpResult = analog_samples[3];
erhälst du den Wert von ADC3 ganz automatisch.
Das funktioniert für alle AD-Werte bis auf die Batteriespannung, für die ich dieses "workaround" geschrieben habe (detaillierte Erklärung siehe nibobee: Akkuspannung mit ADC messen).
Nun noch ein Wort zu den 11 analogen Kanälen. Eigentlich hat der ATMega16 nur 8 Kanäle. Die Liniensensoren (3 analoge Werte) werden jedoch 2 mal gelesen. Nämlich einmal mit eingeschalteten IR-LED und einmal mit ausgeschalteten IR-LED.
Die Werte bei abgeschalteten IR-LED sind hier zu finden
case 4: analog_samples[ANALOG_L0]=value; break;
case 5: analog_samples[ANALOG_C0]=value; break;
case 6: analog_samples[ANALOG_R0]=value; clear_output_bit(IO_LINE_EN); break;
Die Werte bei eingeschalteten IR-LED sind hier zu finden
case 8: analog_samples[ANALOG_L1]=value; break;
case 9: analog_samples[ANALOG_C1]=value; break;
case 10: analog_samples[ANALOG_R1]=value; set_output_bit(IO_LINE_EN); break;
Es gibt nun 2 Möglichkeiten.
1. Du benutzt sharpResult = analog_samples[3]; und lässt das ADCSRA in der Sharp(void) in Ruhe.
2. Du schreibst ebenfalls ein "workaround" das ungefähr so aussieht (nicht getestet, nur ein Beipiel)
int Sharp(void)
{
unsigned char temp1,temp2;
uint16_t sharpResult;
while ((ADMUX & 0x07) != 0x03); //warten bis ADC3 dran ist
cli();
while (!(ADCSRA & (1 << ADIF))); // wait for conversion complete
ADCSRA |= (1 << ADIF); // clear ADCIF
//Registerinhalte retten
temp1 = ADCSRA;
temp2 = ADMUX;
//hier müssen die Teile deiner Sharp(void) rein
sharpResult = ADCL + (ADCH << 0x0
;
//Registerinhalte wiederherstellen
ADMUX = temp2;
ADCSRA = temp1 & ~(1 << ADSC);
ADCSRA |= (1 << ADSC); // Start conversion
sei();
return sharpResult;
}
Viel Erfolg
Skroete
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- Anhänge hochladen: Nein
- Beiträge bearbeiten: Nein
-
Foren-Regeln
Lesezeichen