Hallo,
über ein Potentiometer kann die Lage der Zündimpulse verstellt werden.
Bei schnellem Drehen des Potis treten Kurzschlüsse, siehe Bild, zwischen
den Zündimpulsen auf, allerdings nur, wenn man die Zündimpulse nach
links verschiebt, also die Spannung am Poti vergrößert. Beim Verschieben
der Zündimpulse nach rechts gibt es keinerlei Probleme, unabhängig wie
schnell man am Poti dreht.
Kann mir jemand sagen wie man an dieses Problem herangeht?
Mittelwertbildung des ADC-Ergebnisses hab ich schon versucht, das
Problem bleibt aber bestehen.
Dein Problem ist höchst wahrscheinlich nicht die Ermittlung der Spannung
(und damit der Potistellung), sondern wie du daraus die Zündimpulse
erzeugst.
Wie erzeugst du denn die Pulse?
Wenn das zb ein Timer im CTC Modus ist, dann hast du schon deinen
Übeltäter. Dessen Top Wert (OCR1A) wird 'immediate' upgedated und nicht
synchronisiert mit dem Erreichen des Top Wertes.
Und damit kann dir dann folgendes passieren:
Angenommen der Top Wert steht auf 200. Jetzt bestimmst du einen neuen
Wert, der sei 100.
Wie es der Zufall so will, hat der Timer zum Zeitpunkt der Zuweisung an
das OCR1A Register schon den Wert 150 erreicht. Was ja auch kein Problem
wäre, denn bei 200 würde ja die Aktion ausgelöst und der Timer wieder
auf 0 gesetzt.
Jetzt weißt du aber dem OCR1A einen neuen Wert von 100 zu. 150 ist
größer als 100. Nur: das interessiert keinen. Der Compare Match kommt
bei Gleichstand, und 150 ist nun mal kein Gleichstand mit 100. Auf der
anderen Seite wird der Timer weiterzählen, 151, 152, 153, ... usw. Bei
200 passiert nichts mehr, denn OCR1A ist ja nicht mehr 200 sondern 100.
Also wird der Timer weiterzählen 201, 202, 203, ... bis er irgendwann
dann auch mal die 65535 erreicht und es dann bei 0 weiter geht. Da zählt
der Timer dann 0, 1, 2, 3, ... 98, 99, 100. Und erst jetzt ist der
nächste Compare Match fällig, denn erst jetzt stimmen ja OCR1A und der
Zählerstand überein.
Durch das Verringern des OCR1A Wertes von 200 auf 100 bist du also bei
aktuellen Timer-Zählerständen zwischen 100 und 199 in der Situation,
dass der Timer weder bei 200, noch bei 100 den Compare Match auslöst,
sondern erst mal komplett 'rundum laufen' muss, ehe dann der Mechanismus
erneut in Gang kommt.
Das Problem ist die nicht synchronisierte Zuweisung eines neuen OCR1A
Wertes, der kleiner ist als der aktuelle Zählerstand des Timers zum
Zeitpunkt der Zuweisung.
Danke Karl-Heinz,
deine Erklärung ist sehr gut und nachvollziehbar!
Leider bin ich mir nicht sicher was du mit synchronisierter Zuweisung
eines neuen Vergleichswerts meinst. Auf was müsste die Zuweisung denn
synchronisiert werden?
Meine Zündimpulse erzeuge ich nach folgendem Schema:
Kannst du denn das ganze nicht so machen, dass die OCR Werte nicht fixe
Zahlenwerte sind, sondern sich in Bezug auf den jeweils letzten OCR Wert
errechnen und dafür der Timer dann einfach durch lauft?
Denn wenn ich etwas gelernt habe, dann das, das dieses Timer auf 0
setzen mehr Probleme mit sich bringt als es löst.
1
ISR(TIMER1_COMPA_vect)
2
{
3
....
4
5
6
OCR1B=OCR1A+ALPHA+Fixer_Offset;
7
OCR1C=OCR1A-1;// sicherheitshalber, damit der nicht im Weg ist
8
}
9
10
ISR(TIMER1_COMPB_vect)
11
{
12
....
13
14
OCR1C=OCR1B+ALPHA+Fixer_Offset;
15
OCR1A=OCR1B-1;// sicherheitshalber
16
}
17
18
ISR(TIMER1_COMPC_vect)
19
{
20
...
21
22
OCR1A=OCR1C+ALPHA+Fixer_Offset;
23
OCR1B=OCR1C-1;// sicherheitshalber, damit OCR1B nicht unbeabsichtigt auslöst
24
}
so ungefähr. Jetzt kannst du ALPHA verändern wie du lustig bist, die 3
Interrupts feuern nach wie vor reihum dahin und sobald ALPHA einen neuen
Wert kriegt wird die zeitliche 'Distanz' zwischen den 3 Interrupts
entsprechend verringert oder verkleinert.
Der Timer läuft durch und jede ISR rechnet aus, wenn die jeweils nächste
ISR drann ist zu feuern und setzt dann den entsprechenden OCR Wert ins
richtige Register (und sorgt dafür, dass dann auch wirklich die nächste
ISR drann kommt, indem sie den OCR Wert für den jeweils 3-ten ISR AUfruf
auf die maximal mögliche Zeit setzt. Man hätte statt dessen auch den
jeweils nicht benötigten Interrupt sperren können, muss dann aber wieder
auf die Interrupt Flags aufpassen).
Das einzige worauf du achten musst: Das der Ausdruck
1
Alpha + Fixer_Offset
nicht größer als der Zählbereich des Timers wird. Bei 16 Bit also nicht
größer als 65535.
Edit:
Mir fällt gerade auf, dass ich unter 'Lage der Zündpulse' eventuell
etwas anderes verstehe als du. Ich deute die Verschiebung der Zündpulse
als Mittel um die 'Drehzahl' der ABlauffolge der Zündpulse zu verändern.
Beschreibe doch am besten mal die Grundaufgabe, sprich Randbedingungen.
Was willst du genau tun bzw. wofür. Das würde schon einmal helfen, wie
der Programmablauf auszusehen hat und was du eigentlich willst. Alles
andere ist für mich im Moment noch etwas blindes Raten.
Ich denke ich habe nicht deutlich genug gemacht was ich mit dem
Verschieben der Zündimpulse bewirken will.
Realisiert wird damit eine Phasenanschnittsteuerung für eine
Gleichstrommaschine. Das heißt mit den Zündimpulsen werden Thyristoren
in den leitenden Zustand gebracht, die nach erfolgter Zündung die
Netzspannung angeschnitten auf den Motor gibt. Die Lage der Zündimpulse
wird dabei mit INT0 auf den Nulldurchgang der Netzspannung
synchronisiert.
OCR1B ist nur dafür zuständig, die Breite der Zündimpulse festzulegen
und muss daher einen festen Wert erhalten.
Die Reihenfolge der Vergleichswerte muss also immer die gleiche sein:
OCR1A(einschalten) -> OCR1B(ausschalten) -> OCR1C(einschalten) ->
OCR1B(ausschalten).
Karl Heinz Buchegger schrieb:> Angenommen der Top Wert steht auf 200. Jetzt bestimmst du einen neuen> Wert, der sei 100.> Wie es der Zufall so will, hat der Timer zum Zeitpunkt der Zuweisung an> das OCR1A Register schon den Wert 150 erreicht. Was ja auch kein Problem> wäre, denn bei 200 würde ja die Aktion ausgelöst und der Timer wieder> auf 0 gesetzt.> ...
Hier wurde alles gesagt, hier liegt der Fehler. Du darfst dein OCR1A nur
dann mit ALPHA updaten, wenn das OCR1A = 0 ist, also im Timeroverflow
oder bei einem Compare-Match. Ansonsten hast du diese überlangen Pulse,
das ist normal!
In dem Fall würde ich dann mal schätzen, dass sich bei bestimmten ALPHA
Werten eine 'Überlappung' oder gar 'Vertauschung' der Reihenfolge der
OCR Werte ergibt.
AUch erhebt sich die Frage, ob du während die ISR Sequenz abläuft, das
ALPHA überhaupt verändern darfst. Im Zweifelsfall mal so
1
volatileuint16_tAlphaToUse;
2
3
ISR(INT0_vect)
4
{
5
TCNT1=0;
6
AlphaToUse=ALPHA;
7
8
OCR1A=AlphaToUse;
9
}
10
11
ISR(....
12
13
14
mitAlphaToUseanstellevonALPHAarbeiten
somit ist sichergestellt, dass der Alpha Wert während eines kompletten
Zykluses konstant bleibt. Der nächste Zyklus kann dann wieder sein
eigenes neues Alpha haben. Aber für diesen einen Zyklus ist es auf einen
fixen Wert eingefroren.
Vielen Dank Karl Heinz,
jetzt funktioniert alles so wie es soll!
Ich kann am Poti so schnell drehen wie es nur geht und meine Zündimpulse
kommen immer sauber wie sie sollen.
Nochmals vielen Dank und schöne Grüße!