Irgendwie versteh ich das mit dem ADC und dem Sleep noch nicht ganz. Ich möchte zyklisch aufwachen und die Versorgungsspannung (mit der Bandgap Referenz), da Batteriebetrieben, messen. Ohne den Sleep Modus geht es wunderbar, mit Sleep bekomme ich komische Werte als Spannung. Ich mache Folgendes: //einmalig void ADC_Init() { ADMUX |= ((1 << MUX3) | (1 << MUX2) | (1 << MUX1)); /* 1.1V (VBG) */ ADCSRA |= ( (1 << ADEN) | (1 << ADSC)); /* hit it */ } //zyklisch //Aufwachen void ADC_GetVccVoltage() { ADCSRA |= (1 << ADEN) ; ADCSRA |= ( (1 << ADSC)); /* enable ADC to get VCC */ while ((ADCSRA & (1<<ADSC))) {} u16_voltage = (ADC >> 2); if(u16_voltage != 0) { u16_voltage = (uint16_t) ((((11 * 2550)) / (u16_voltage))); } ADCSRA &= (~(1 << ADEN)); /* disable ADC to save power */ } //gehe nach sleep -> SLEEP_MODE_PWR_SAVE Ich hab auch schon überall _delays_ms() eingebaut, ohne Erfolg, da ja das enable auch einige Zeit dauern soll. Habt Ihr noch einen Tip für mich? Vielen Dank und Grüße!!!
:
Bearbeitet durch User
Habe gelesen, dass beim Atmega8(8) nach aktivieren des ADC eine Probemessung gemacht werden muss, um den ADC zu initialisieren. Bei der 2. Messung sollte also alles ok sein.
Habe ich auch schon probiert, und die Messung mehrmals im zyklischen Task gemacht. Also so: //wakeup //enable ADC ... ADCSRA |= ( (1 << ADSC)); /* enable ADC to get VCC */ while ((ADCSRA & (1<<ADSC))) {} (void)ADC; /* read value to get the next updated */ ADCSRA |= ( (1 << ADSC)); /* enable ADC to get VCC */ while ((ADCSRA & (1<<ADSC))) {} ... //disable ADC //sleep Hat aber nix gebracht, ich bekomme immer falsche Messwerte. Es müssten für 5V 500 rauskommen und für 4.5V 450. Aktuell ist der erste messwert 500 und alle nachfolgenden 230-250. Mein Gefühl ist, das ich irgendwo noch etwas auf den ADC warten muss, aber hab schon fast alle Stellen durchprobiert. Kruzifix ;-)
Sebastian H. schrieb: > Habe gelesen, dass beim Atmega8(8) nach aktivieren des ADC eine > Probemessung gemacht werden muss, um den ADC zu initialisieren. > > Bei der 2. Messung sollte also alles ok sein. genau. zum einen nach dem aktivieren eine Messung machen und verwerfen, zum andren warten bis BG gestartet ist. Bandgap reference start-up time max.70µ
ach ja, es kann auch an der gesamten startroutine liegen. warum machst das nicht wie im tutorial? http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Analoge_Ein-_und_Ausgabe das klappt auf alle fälle.
Ich habs mal folgendermassen modifieziert aber ich kann keine Verbesserung bemerken. //einmalig void ADC_Init() { ADMUX |= ((1 << MUX3) | (1 << MUX2) | (1 << MUX1)); /* 1.1V (VBG) */ ADCSRA |= ( (1 << ADEN) | (1 << ADSC)); /* hit it */ } //zyklisch //Aufwachen void ADC_GetVccVoltage() { ADCSRA |= (1 << ADEN) ; _delay_us(70); ADCSRA |= ( (1 << ADSC)); /* enable ADC to get VCC */ while ((ADCSRA & (1<<ADSC))) {} (void)ADC; /* read value to get the next updated */ ADCSRA |= ( (1 << ADSC)); /* enable ADC to get VCC */ while ((ADCSRA & (1<<ADSC))) {} u16_voltage = (ADC >> 2); if(u16_voltage != 0) { u16_voltage = (uint16_t) ((((11 * 2550)) / (u16_voltage))); } ADCSRA &= (~(1 << ADEN)); /* disable ADC to save power */ }
Steffen schrieb: > ach ja, es kann auch an der gesamten startroutine liegen. warum machst > das nicht wie im tutorial? > > http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Analoge_Ein-_und_Ausgabe > > das klappt auf alle fälle. Weil das Tutorial nicht zu meiner Anwendung passt. Ich hab das schon gelesen, und so ähnlich mach ich das ja auch. Ich hab einen Externen Quarz welcher den atmega weckt und ab und zu genau diesen Task ausführt. Die Init wird nach Reset aufgerufen. Ander Aufgaben hat der ADC bis jetzt nicht.
:
Bearbeitet durch User
das dachte ich schon... nur irgendwie ist das komisch: u16_voltage = (ADC >> 2); hier ist ne klammer zu viel ;-) u16_voltage = (uint16_t) ((((11 * 2550)) / (u16_voltage)));
Hehe, die Klammer... Ich hab das ADCSRA |= ( (1 << ADSC)); /* enable ADC to get VCC */ while ((ADCSRA & (1<<ADSC))){} (void) ADC; nun 5mal nacheinander drin. Damit gehts. Aber ich versteh nicht warum!??
:
Bearbeitet durch User
ja die klammern ;-) while (ADCSRA & (1<<ADSC)) {} das reicht auch ;-) hab dir mal eine main.c von mir angehangen, da mess ich die spannung und sende die per rfm12 raus. das geht 100%. der uc ist im sleep und wird durch den wdog aufgeweckt.
Vielen Dank dir! Ich habs gerad auch empirisch ermittelt. Scheinbar muss der ADC Wert gelesen werden, und danach passiert noch was anderes bevor der start conversion wieder durchstartet. Mit 70us funktioniert es nicht, aber mit längeren Wartezeiten... //zyklisch //Aufwachen void ADC_GetVccVoltage() { ADCSRA |= (1 << ADEN) ; ADCSRA |= ( (1 << ADSC)); /* enable ADC to get VCC */ while ((ADCSRA & (1<<ADSC))) {} (void)ADC; /* read value to get the next updated */ _delay_us(500); ADCSRA |= ( (1 << ADSC)); /* enable ADC to get VCC */ while ((ADCSRA & (1<<ADSC))) {} u16_voltage = (ADC >> 2); if(u16_voltage != 0) { u16_voltage = (uint16_t) (((11 * 2550) / (u16_voltage))); } ADCSRA &= (~(1 << ADEN)); /* disable ADC to save power */ } Dann kann ich ja nun beruhigt ins Bette gehen. Danke Dir Steffen!
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.