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!!!
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.
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!??
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!
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.