Sodele. Der Sharp läuft, und zeigt auch _brauchbare_ Werte an, aber:
Es gibt ein neues Problem.
Offenbar verträgt sich _diese_ ADC-Routine nicht mit der, die mir die Akkuspannung ermittelt.
Konkret sieht es so aus, dass beim "hochfahren" so ziemlich als erstes mal die Akkuspannung ermittelt wird, wenn der einen bestimmten Wert unterschreitet, machts keinen Sinn, weiterzumachen.
So weit klappt das auch, dann wird das Schwenkservo mal kurz getestet und dann der Sharp abgefragt.
Keinerlei Probleme, bis dahin.
Nun will ich aber, Timergesteuert, von Zeit zu Zeit den Akku immer wieder mal prüfen, und _dann_ hängt _diese_ Routine sich auf.
Code:
//----------------------------------------- Sharp-IR-Sensor ---------------------------------------
int Sharp(void)
{
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);// Frequenzvorteiler: setzen auf 128 (16 MHz / 128kHz = 125 kHz) und ADC aktivieren
ADMUX = 0x03; // Kanal waehlen (ADC3)
ADMUX |= (1<<REFS1); // interne Referenzspannung nutzen
ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
while ( ADCSRA & (1<<ADSC) ); // auf Abschluss der Konvertierung warten
sharpResult = ADCW; // Wert abholen
lcd_setCursor(0,1); // Ausgabe ADC-Wert
printf("Sharp: %4d",sharpResult);
return 0;
}
//----------------------------------------- Spannungsüberwachung ----------------------------------
int Batterie(void)
{
led_set(LED_L_RD,1); // blitzt bei jeder Messung kurz auf
unsigned char temp1,temp2;
while ((ADMUX & 0x07) != 0x04);
cli();
while (!(ADCSRA & (1 << ADIF))); // wait for conversion complete
ADCSRA |= (1 << ADIF); // clear ADCIF
temp1 = ADCSRA; // Registerinhalte retten
temp2 = ADMUX;
ADMUX = (1 << REFS0) | (1 << REFS1) | ANALOG_VOLT; //interne Referenzspannung m. externem Kondensator
// ADCSRA löschen und neu setzen
ADCSRA = 0;
ADCSRA |= ((1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0)); // ADC clock = Clock/128
ADCSRA |= (1 << ADEN); // Enable ADC (das aktiviert die 2.56V Referenz)
// Warten bis Kondensator an ARef = 2.56V hat
// Messung an ARef ergab 1,2msec
delay(6); // = ca. 5*Tau
// 1. ADC Wandlung starten und Ergebnis ignorieren
ADCSRA |= (1 << ADSC); // Start conversion
while (!(ADCSRA & (1 << ADIF))); // wait for conversion complete
ADCSRA |= (1 << ADIF); // clear ADCIF
// 2. ADC Wandlung starten und Ergebnis übernehmen
ADCSRA |= (1 << ADSC); // Start conversion
while (!(ADCSRA & (1 << ADIF))); // wait for conversion complete
ADCSRA |= (1 << ADIF); // clear ADCIF
akkuResult = ADCL + (ADCH << 8);
// Registerinhalte wiederherstellen
ADMUX = temp2;
ADCSRA = temp1 & ~(1 << ADSC);
// Warten bis Kondensator an ARef = AVcc hat
// Messung ergab sehr steile Flanke
delay(2); // nicht notwendig, nur zur Sicherheit
ADCSRA |= (1 << ADSC); // Start conversion
sei();
.....hier kommt noch ein bisschen Rechnerei und die Displayausgabe
Lasse ich den periodischen Aufruf von Batterie() weg, klappt alles hervorragend.
Die Routine Sharp() wird im Hauptprogramm in einer Endlosschleife praktisch ununterbrochen aufgerufen, nebenbei zählt ein Timer hoch und löst, bei einem bestimmten Wert (so alle 15s) die Routine Batterie() auf.
Die LED (sie wird später, während der Umrechnung des ADC-Wertes in brauchbares wieder ausgeschalten) bleibt an, daher _muss_ der Punkt, an dem sich das Programm aufhängt, irgendwo in Batterie() liegen.
Alleine (wenn ich Sharp() _nicht_ aufrufe) funktioniert Batterie() einwandfrei.
Weiss jemand Rat?
Lesezeichen