Hallo,
ich habe ein Problem mit der AD-Wandlung beim ATtiny13 bzw. spielen
meine zwei Funktionen errückt, wenn ich den ADC mitlaufen lasse.
Ich möchte an PB3 (ADMUX=11) die Batteriespannung messen. Leider bekomme
ich das nicht mehr hin. Ich hatte eine erste Messung auf einem ATmega8
hinbekommen und ich bin auch der Meinung, dass es bei dem ATtiny als DIP
Version auch schon funktionierte.
Jetzt habe ich eine Platine angefertigt und den Quelltext angepasst.
Jedoch funktioniert die Messung nicht mehr richtig.
Beide Funktionen (Lauflicht und Blicklicht) funktionieren einzelt, wenn
diese aufgerufen werden (die Andere auskommentieren oder wenn ich für
result einen Wert einsetze), jedoch wenn diese zusammen über dem ADC
ausgewählt werden sollen (Größer / Kleiner als 410), dann laufen beide
Funktionen in einander ab.
while(!(ADCSRA&(1<<ADIF)));// auf Abschluss der Konvertierung warten (ADIF-bit)
86
result=ADC;// ADC muss einmal gelesen werden,
87
// sonst wird Ergebnis der nächsten Wandlung
88
// nicht übernommen.
89
90
//ADC-Messung mit arithmetischen Mittel aus 4 Messungen
91
result=0;
92
for(i=0;i<4;i++)
93
{
94
ADCSRA|=(1<<ADSC);// Messung ausfuehren
95
while(ADCSRA&(1<<ADSC));// Konvertierung abwarten
96
result+=ADC;// aufaddieren zur Mittelwertbildung (ADC auslesen der zwei Bits
97
}
98
ADCSRA&=~(1<<ADEN);// ADC ausschalten
99
100
result/=4;//
101
102
}
103
104
105
106
//call this routine to initialize all peripherals
107
voidmain(void)
108
{
109
//stop errant interrupts until set up
110
CLI();//disable all interrupts
111
port_init();
112
timer0_init();
113
adc_init();
114
115
MCUCR=0x00;
116
TIMSK0=0x02;//timer interrupt sources
117
GIMSK=0x00;//interrupt sources
118
SEI();//re-enable interrupts
119
//all peripherals are now initialized
120
121
while(1);
122
}
Auch wenn ich
1
if(result<=410){Warning();}
2
else{rul();}
statt der zwei if-Abfragen einsetze spielen diese verrückt.
Habe ich bei der AD-Wandlung einen Gedankenfehler (läuft diese so
schnell ab, dass mehere Ergebnisse Zustande kommen)oder woran könnte das
liegen?
Vielen Dank für eure Tipps.
Im Timerinterrupt Wandlungen starten, mitteln und dann abhängig vom
Ergebnis noch ein Blink- oder Lauflicht. Alles im selben Interrupt. Und
das ganze ist schon mal in einem DIP-Gehäuse gelaufen. Hmmm.
Interessant.
Also, tut mir ja leid, aber das kann leider so nicht funktionieren.
Lies mal die Tutorials hier und fang mal mit einfachen Sachen an.
Dann erfährst Du u.A. folgendes:
Interrupts sind so kurz wie möglich. Volatile. Flags setzen. Aktionen in
main. AD-Wandlung läuft sowieso mit eigenem Interrupt. Auch
kontinuierlich.
> läuft diese so> schnell ab, dass mehere Ergebnisse Zustande kommen
Dein Timer-Interrupt kommt alle 10 ms. Mehr lässt sich zu diesem Punkt
nicht sagen, da Du den Source von Warning() und rul() nicht mitlieferst.
Weitere Punkte, ohne Anspruch auf Vollständigkeit:
In der ADC-Routine setzt Du ADIF nicht zurück, also wird es immer
gesetzt sein und das Ergebnis der Wandlung wird gar nie abgewartet.
Wieso wartest Du nicht auf das Rücksetzen von ADSC -- da musst Du nichts
von Hand zurücksetzen? Falls Du doch bei ADIF bleiben willst: mach Dich
kundig, wie es rückgesetzt wird. Nein, nicht indem man 0 reinschreibt.
Du erledigst viel zu viel im Interrupt, das ist keine sinnvolle
Programmstruktur. Setze im Interrupt maximal ein Flag, ob das Resultat
über der Schwelle liegt, und mache die weitere Verarbeitung im
Hauptprogramm.
Meine Tips zum Programm wären:
Den Timerinterrupt wegschmeißen.
ADC auf freerunning laufen lassen.
in nem ADC-Interrupt die Mittelbildung machen.
In der main einfach nur abfragen, ob der Mittelwert grad kleiner oder
größergleich 410 ist und dann in der main die funktionen aufrufen.
Vielen Dank erstmal. Ich habe zwar noch nicht die Lösung gefunden, weiß
aber schonmal, woran es liegen könnte.
Den Interrupt nutze ich um das Rundumlicht sowie das Blinklicht anzu
steuern. Diese sollen im 100ms bzw 200ms Takt durchlaufen.
Da die Funktionen rul() und Warning() gehen, hatte ich diese nicht
eingefügt.
zur Vollständigkeit bringe ich diese hier nochmal an.
Squat *** schrieb:> Vielen Dank erstmal. Ich habe zwar noch nicht die Lösung gefunden, weiß> aber schonmal, woran es liegen könnte.
Lass dir doch mal den ADC Wert direkt auf die LED ausgeben (die obersten
4 Bit werden wohl genügen).
Ich wette mit dir, dass du keinen stabilen Messwert hast, sondern das
deine LED mehr oder eniger zufällige Zahlen anzeigen werden.
Warum das so ist?
Dafür gibt es mehrere Möglichkeiten. Anfangen würde ich mit der
Referenzspannung.
So, ich habe den Fehler gefunden.
Es lag einfach an der Kanalauswahl. Bin ich gerade zufällig drauf
gestoßen, als ich mir ein anderes Programm angeschaut habe.
Richtig muss es
1
ADMUX=0x03;
lauten.
Vielen Dank an alle Beteiligten!!
Gerne würde ich noch mehr aus diesem Threat herausziehen.
Zum einen habe ich jetzt das Problem, dass in der Übergangsphase
zwischen Rundumlicht und Blicklicht die Spannung einbricht, sobald das
Blicklicht beginnt. Um dieses Problem zu umgehen ist entweder auf der
Hardwareseite ein Kondensator zu verbauen. Oder softwaremäßig die
Messung gezielt zwischen den Blinken anzusetzen.
Ich habe es vorerst mit dem ELko versucht, jedoch half das nicht.
Daraufhin habe ich mir gedacht, ich rufe die ADC nur solange auf, wie
die Rundumleuchte an ist. Sobald einmal die Spannung zu niedrig ist,
wird nur noch das Blicklicht ausgeführt. Das funktioniert soweit auch,
jedoch nach dem ersten Blicken bricht die Spannung soweit zusammen, dass
der ATtiny neustartet. Und so beginnt das Spiel wieder von vorne. Wenn
ich aber die Spannung weiter nach unten schraube, Blicken irgendwann die
Lämpchen, so wie geplan.
Es geht also um den Übergang.
In der Software hatte ich schonmal probiert die Mittelwertbildung zu
erweitern. Bis 50 geht dass gut. Bei Hundert klappt es nicht mehr und er
Blink nur noch (blinkt einmalig und dann startet der Prozessor neu egal
wie viel Spannung anliegt.
Ich weiß leider nicht, wie ich dieses Problem umgehen kann.
Und noch eine kleine Frage am Rande. Wie kann ich im Hauptprogramm
erfragen, ob der Timer übergelaufen ist.
Und nochmals besten Dank für die Tipps.