Hallo,
bin über den Wiki-Artikel zum Thema Rückstromladen gestolpert und
überlege mir, ob ich sowas nicht auch mit einem mega machen könnte.
Ich weiß, es gibt ICs, die speziell dafür entwickelt wurden und es
sicher besser können - aber das ist ein anderes Thema.
Wenn ich beim mega ne akzeptable PWM-Frequenz erreichen will, geht das
nur mit Vorteiler 1, was bedeutet, dass jede Anweisung in der
Interrupt-Routine einen PWM-Zähler-Schritt bedeutet.
Wenn ich das Datenblatt richtig verstanden habe, verbraucht der Sprung
zur Interrupt-Routine 4 Takte, genau wie der Rücksprung.
Wenn ich Timer 2 nehme, dann haben dessen Compare-Interrupts die höchste
Prio, können also nicht von anderen überstimmt werden.
Würde es reichen, wenn ich das Maximum für den Compare-Vergleich auf:
1
Top - 10 - Anweisungsschritte in der IR festlege?
... oder gibt es noch andere notwendige IR-Schritte, die Zeit
verschlingen?
Für den Rückstrom-Impuls habe ich mir vorgestellt, dass ich in der
Compare-IR diese Sequenz absetze:
1
nop
2
setze Pin auf 1
3
nop
4
setze Pin auf 0
5
nop
Idealerweise sollte der letzte nop fertig sein, bevor der PWM-Zähler Top
erreicht und den PWM-Pin wieder umschaltet.
akkunator schrieb:> Wenn ich beim mega ne akzeptable PWM-Frequenz erreichen will, geht das> nur mit Vorteiler 1,
Was für eine Frequenz strebst du hier denn an? Wenn ich die diversen
Artikel richtig verstehe, dann scheinen 50 Hz "üblich" zu sein. 50 Hz
sind für deinen AVR langsam.
Die Anzahl der Takte müsste so schon stimmen. Das findet sich aber alles
- wie du schon festgestellt hast - im Datenblatt ;). Du solltest nur
bedenken, dass bei der Verwendung von C (bzw. avr-libc) mit dem ISR()
Makro relativ viel Overhead erzeugt wird. Also entweder auf Assembler
ausweichen - was gerade bei solchen zeitkritischen Geschichten
vielleicht sowieso empfehlenswert ist - oder ISR_NAKED() verwenden.
akkunator schrieb:> Wenn ich Timer 2 nehme, dann haben dessen Compare-Interrupts die höchste> Prio, können also nicht von anderen überstimmt werden.
nein, die Megas kennen soche eine Prio nicht. Die einzigste Prio die
existiert ist dann wenn gleichzeitig 2 ISR aufgerufen werden, dann zählt
die Reihenfolge der ISR in der Spungtabelle. Aber wenn eine ISR einmal
läuft kann sie von keiner anderen unterbrochen werden, außer man gibt
selber die IRQ wieder frei.
akkunator schrieb:> Vorteiler 1, was bedeutet, dass jede Anweisung in der> Interrupt-Routine einen PWM-Zähler-Schritt bedeutet.
Nein. Jeder Takt in der Interruptroutine bedeutet dann einen
PWM-Schritt. Da es bekanntermaßen Anweisungen gibt, die mehr als einen
Takt brauchen, kann das von dir postulierte Gesetz also nicht gelten.
> Wenn ich das Datenblatt richtig verstanden habe, verbraucht der Sprung> zur Interrupt-Routine 4 Takte
Das gilt nur dann, wenn die ISR direkt im Bereich der Interruptvektoren
liegt. Üblicherweise tut sie das aber nicht, sondern es liegt hier nur
ein Sprungbefehl zur eigentlichen ISR. Je nachdem, ob es sich dabei um
einen relativen oder absoluten Sprungbefehl handelt, kommen also nochmal
2 oder gar 3 Takte hinzu.
> ... oder gibt es noch andere notwendige IR-Schritte, die Zeit> verschlingen?
Ja, natürlich. Zum einen kann ein Interrupt nicht zu einem beliebigen
Zeitpunkt ausgeführt werden, sondern frühestens mit dem Ende des aktuell
gerade ausgeführten Befehls. Da es, wie oben schon gesagt, Befehle gibt,
die mehr als einen Takt brauchen, muß man diese sog. variable
Interruptlatenz mindestens mit der Dauer des längsten Befehls (-1)
ansetzen, der im durch den Interrupt unterbrochenen Code vorkommt. Da
der Controller immer irgendwas machen muß, braucht man zwingend eine
Schleife (und damit einen Sprungbefehl), um ihn davor zu bewahren,
unkontrolliert abzustürzen. Der kürzeste Sprungbefehl ist rjmp, dauert
zwei Takte und beschert somit ein variable Interruptlatenz von einem
Takt. Weniger geht nicht.
Viel mehr aber natürlich schon.
Z.B. wenn auch noch cli/sei-Konstrukte im unterbrochenen Code
hinzukommen. Alles innerhalb eines solchen Konstruktes wirkt nämlich
bezüglich der variablen Interruptlatenz wie ein einziger großer
Befehl...
Dasselbe gilt, wenn es noch andere Interrupts gibt, auch welche mit
geringerer "Priorität". Deren gesamte Ausführungszeit von der
Interruptauslösung bis zu dem Moment, in dem (wie auch immer) das
globale Interrupt-Enable-Flag wieder gesetzt wird, wirkt sich ebenfalls
als zusätzliche variable Latenz für einen konkurrierenden Interrupt aus.
Die Priorität der Interrupts beim AVR ist nämlich keine echte
Interruptpriorität im üblichen Sinne, sondern regelt nur das Verhalten
bei gleichzeitiger Auslösung von Interrupts.
> Für den Rückstrom-Impuls habe ich mir vorgestellt, dass ich in der> Compare-IR diese Sequenz absetze:>
1
nop
2
> setze Pin auf 1
3
> nop
4
> setze Pin auf 0
5
> nop
Das ist aus den genannten Gründen absolut keine gute Idee.
akkunator schrieb:> Für den Rückstrom-Impuls habe ich mir vorgestellt, dass ich in der> Compare-IR diese Sequenz absetze:
Soo schnell kann eine normale Endstufe (und schon gar nicht Dein Akku)
reagieren.
Bei Üblichen ICs ist dieser Reflex-Impuls ca 5ms lang und wird alle
Sekunde wiederholt.
Gruß Anja
Ein PWM Signal erzeugt man wenn möglich direkt in Hardware, über die
Output Compare Einheiten. Software PWM ist eher etwas für langsames PWM,
so wie die 50 Hz, da kommt es auch ein paar Zyklen auf nicht an.
Beim Interrupt braucht es 4 Zyklen für den Einsprung, 4 Zyklen für den
Rücksprung per RTI und 2 Zyklen für den RJMP aus der Vektortablelle, die
man sich eventuell sparen kann wenn der Code direkt da steht. Dazu kommt
noch eine Verzögerung (0-3 Zyklen) für das beenden des laufenden ASM
Befehls.
In kommt dann noch einiges in Overhead für das Sichern an Registern
dazu. In Assembler kommt man meist auch nicht herum das Statusregister
zu sichern.
In purem Assembler kann ein Interrupt in 20..50 Zyklen schaffbar sein.
Da darf aber auch kein C drumrum sein, d.h. es müssen Register für den
Interrupt exklusiv reserviert sein (kein Push/Pop).
Jedes Push/Pop wären ja schon 4 Zyklen mehr.
In AVR-GCC sind 50 Zyklen das Minimum, eher 100..200 Zyklen.
Danke für die vielen Antworten!
> Soo schnell kann eine normale Endstufe (und schon gar nicht Dein Akku)> reagieren.> Bei Üblichen ICs ist dieser Reflex-Impuls ca 5ms lang und wird alle> Sekunde wiederholt.
Hm, wenn ich mir die Specs eines BQ24620 anschaue, dann läuft der mit
300 kHz. Die mit einem mega anzustreben ist Illusion, deshalb ging ich
davon aus, dass wenn ich 100 kHz schaffe, es ziemlich langsam wäre.
> In AVR-GCC sind 50 Zyklen das Minimum, eher 100..200 Zyklen.
Uff! Dann kann ich mir die 100 kHz abschminken.
Wie würdet Ihr das angehen?
... oder gleich sagen: geht nich?
Also wenn es ein 5ms Puls alle Sekunde sein soll, dann könnte ich die
PWM ja wie üblich in Abhängigkeit von Strom und Spannung mit 100-200 kHz
takten und dann alle Sekunde die PWM abschalten und den Rückpuls
ansetzen.
Wäre das ein besserer Weg?
... und ja - Assembler und ich - 2 Welten prallen aufeinander.
Insofern bleibt mir nur AVR-GCC.
akkunator schrieb:> Wie würdet Ihr das angehen?> ... oder gleich sagen: geht nich?
Was angehen?
Das Hauptproblem ist, daß niemand weiß, was Du eigentlich machen willst.
Bevor man was sagen kann, mußt Du also erstmal eine verständliche
Aufgabenstellung bringen. Niemand kann in Deinen Kopf schauen.
akkunator schrieb:> Uff! Dann kann ich mir die 100 kHz abschminken.
Wieso? Wie schon gesagt, lässt sich das über die Hardware direkt machen.
Ansonsten sind aber auch 100 kHz in Software machbar. Bei 100 kHz und
einer 100 Instruktionen "langen" ISR, komme ich auf 10 MHz.
Aber wie schon gesagt, wir wissen nach wie vor nicht was du vorhast. Und
100 kHz für einen Akku ist zu viel des Guten. Wie bereits gesagt sind 50
Hz "üblich".
> Das Hauptproblem ist, daß niemand weiß, was Du eigentlich machen willst.
Huch?
Dachte, das hätte ich im ersten Beitrag erläutert.
Dann muss ich wohl etwas ausholen.
Habe die Schaltung vom BQ24620 so angepasst, dass ich sie mit einem
mega88 bei 20 MHz betreiben könnte.
(Ein Wannenstecker entspricht einem halben Port auf meinem Testboard)
Dazu habe ich die ADC im "freerunning" Modus vorgesehen. Im ADC-complete
Interrupt wird der Messwert in eine C-Struktur eingetragen und der MUX
für die nächste Messung weiter geschaltet. Bei Überlauf des MUX wird
über einen unbelegten Pin ein Software-Interrupt ausgelöst, welcher die
Messwerte bewertet. Die Bewertung ergibt den Compare-Wert für die PWM,
die auch in der Struktur abgelegt wird.
Auf diese Weise wird Strom und Spannung gemessen.
Die PWM läuft auf einem 8-Bit Timer der im Fast-PWM-Modus mit 7-Bit
Höchstgrenze läuft, sodass sich eine Frequenz von ca. 156 kHz ergibt.
Im Überlauf-Interrupt wird der bewertete PWM-Vergleichswert aus besagter
C-Struktur in das Compare-Register des Timers übertragen.
Der 16-Bit Timer läuft auch im Fast-PWM-Modus mit Obergrenze von 19.999
was einen Systemtakt von 1ms ergibt. Im Überlauf-Interrupt (der
natürlich andere Interrupts zulässt) läuft alles "langweilige" ab, wie
Auswertung von Schaltern, Steuerung von Status-LEDs, LCD-Anzeige etc.
Über einen Zähler bekommen die Aufgaben ihre Zeitscheibe zugeteilt.
Schalter-Abfrage alle 200ms, etc.
Über den Zähler könnte ich auch einen Sekundentakt verwalten, der die
PWM abschaltet und den Rückladungspuls aktiviert. In dieser Zeit könnte
ich auch noch die Temperaturmessung integrieren.
Alles in Assembler zu machen traue ich mir nicht zu.
Allerdings könnte ich mir vorstellen, die zeitkritischen IRs in
Assembler zu machen.
Bliebe noch die Frage: kann ich die Adresse der C-Struktur so ablegen,
dass sie sowohl in C, alsauch in Assembler als Konstante zur Verfügung
steht (evtl. Vorladen in ein Register, welches von keiner Seite geändert
wird)?
akkunator schrieb:> Bei Überlauf des MUX wird> über einen unbelegten Pin ein Software-Interrupt ausgelöst, welcher die> Messwerte bewertet.
Und was hindert Dich daran, das gleich im ADC-Interrupt zu machen?
Wozu ein weiterer Interrupt mit weiterem Push/Pop Overhead?
akkunator schrieb:> Im Überlauf-Interrupt wird der bewertete PWM-Vergleichswert aus besagter> C-Struktur in das Compare-Register des Timers übertragen.
Das ist Oberquatsch, so schnell berechnest Du doch keinen neuen Wert. Du
lädst nur haufenweise immer den gleichen Wert, also lass es sein.
Es ist also überhaupt nichts zeitkritisches zu tun.
akkunator schrieb:> Dazu habe ich die ADC im "freerunning" Modus vorgesehen.
Besser nicht, das ist nur für einen Eingang sinnvoll. Sobald man den MUX
umschaltet, besteht die Gefahr, daß man die Synchronisation verliert.
Lies im Interrupt den ADC aus, schalte den MUX um und erst dann starte
die nächste Messung.
> Wozu ein weiterer Interrupt mit weiterem Push/Pop Overhead?
Guter Einwand. Danke!
> Das ist Oberquatsch, so schnell berechnest Du doch keinen neuen Wert.
Hm - die Ladephase kann man doch in 3 Zonen einteilen, die überschaubare
Regeln haben. Wenn ich dann mit Funktionszeigern arbeite, sollte das
Ergebnis in akzeptabler Zeit ermittelt werden können.
Zur Not kann man immer noch mit Tabellen arbeiten.
> Sobald man den MUX umschaltet, besteht die Gefahr, daß man die> Synchronisation verliert.
Hm, mit Vorteiler 128 läuft die AD-Wandlung mit gleicher Frequenz, wie
die PWM. So wie ich das Datenblatt (mega88) verstanden habe, wird der
MUX-Eingang für eine laufende Wandlung gepuffert. Daraus habe ich
gefolgert, dass bei Start der Interrupt-Routine zu einem fertigen
Messwert die neue Messung bereits im Gange ist. Die Änderung des
MUX-Einganges würde also nur die nächste anstehende Messung betreffen.
Zwischen den Messungen kann man den MUX-Eingang - laut DB - nach
Belieben verändern.
akkunator schrieb:> Dachte, das hätte ich im ersten Beitrag erläutert.>> Dann muss ich wohl etwas ausholen.> Habe die Schaltung vom BQ24620 so angepasst, dass ich sie mit einem> mega88 bei 20 MHz betreiben könnte.
Wie wäre es mit so einfachen einführenden Worten wie: "Ich möchte einen
µC-gesteuerten Laderegler bauen und habe dazu die Standardschaltung aus
dem Datenblatt vom BQ24620 (Fig. x) wie folgt angepasst, um den Regler
mit einem ATmega88 steuern zu können ..."
So schlimm ist das doch nicht ...
Der extra Interrupt für das Update der OCR Register von Timer 2 ist
nicht nötig. Im PWM-mode werden die Register in Hardware gepuffert. Der
neue PWM Wert wird also automatisch erst nach dem nächsten Überlauf
übernommen.
Den ADC als free running und laufendes umschalten des MUX kann man
durchaus machen. Man muss aber aufpassen mit dem Update des MUX
Registers: gleich nach dem Start des AD-Wander Interrupts (dem ersten
Zyklus des AD Kaktes) wirkt eine Änderung des MUX-Registers noch auf die
gerade gestartete Wandlung, danach gilt der neue wert erst für die
nächste Wandlung. Was man also vermeiden muss, ist das der neue
MUX-wert mal vor und mal nach 128 (oder was als Teiler für den AD
eingestellt ist) Zykeln nach dem Start der AD-wandlung geschrieben wird.
Am einfachsten wäre da eine kleine Wartezeit vor dem schreiben des MUX
Registers, so das es immer danach ist. Sonst muss man sicher sein, das
keine größere Verzögerung beim AD Interrupt auftreten kann.
Der ADC braucht ohnehin 13 der Zyklen des ADC Taktes, es macht also für
die Syncronisation mit dem PWM Signal keinen Unterschied ob man den ADC
free running laufen lässt oder jeweils von Hand startet. Von Hand werden
es in der Regel 14 oder ggf. auch mal 15 Zyklen des ADC-Taktes sein, es
bleibt aber synchron zum geteilten Takt, also bei vielfachen der 128 CPU
Zyklen.
akkunator schrieb:> Die Änderung des> MUX-Einganges würde also nur die nächste anstehende Messung betreffen.
Das Problem ist, daß ja gerade ein anderer Interrupt laufen kann. Und
der kann zufällig Deinen ADC-Interrupt solange verzögern, daß schon die
nächste Wandlung startet, bevor Du den MUX umschaltest. Du kriegst also
einen Meßwert für einen völlig anderen Eingang.
Es gibt auch keinen Grund, warum bei Dir der free running notwendig
wäre.
akkunator schrieb:> Wenn ich dann mit Funktionszeigern arbeite, sollte das> Ergebnis in akzeptabler Zeit ermittelt werden können.> Zur Not kann man immer noch mit Tabellen arbeiten.
Was sollen Funktionszeiger bringen?
Wo siehst Du überhaupt Zeitprobleme?
Kein Akku ändert seinen Ladezustand alle µs.
Viele Ladegeräte machen die Messungen nur alle 10s, das reicht völlig
aus.
Ein Ladegerät ist so ziemlich die langweiligste Sache für einen MC. Der
könnte nebenbei noch bequem Schach spielen.
akkunator schrieb:> Hm, wenn ich mir die Specs eines BQ24620 anschaue, dann läuft der mit> 300 kHz.
Da hast du das Datenblatt aber fehlinterpretiert. Das einzige was da mit
300kHz läuft ist der Buck Converter. Der liefert aber nur die Spannung
zum Laden und hat mit den Überwachungs- und Messfunktionen recht wenig
zu tun. Die laufen im ms-Bereich ab.
akkunator schrieb:> bin über den Wiki-Artikel zum Thema Rückstromladen gestolpert und
"Rückstromladen"?
<nachguck>
Aua!
Arbeiten jetzt ex-Siemens-Mitarbeiter bei der Wikipedia, die jeden
Fachbegriff zwingend eindeutschen müssen? Es geht also um das
Reflex-Ladeverfahren.
> überlege mir, ob ich sowas nicht auch mit einem mega machen könnte.
Klar. Warum nicht. OK, der ADC ist mit seinen 10 Bit nicht unbedingt der
Hammer, wenn man das Ladeende bei z.B. Mehrzellen-NiMH-Akkus erkennen
will.
> Für den Rückstrom-Impuls habe ich mir vorgestellt, dass ich in der> Compare-IR diese Sequenz absetze:
1
> nop
2
> setze Pin auf 1
3
> nop
4
> setze Pin auf 0
5
> nop
Wie albern. Hast du dir mal angeschaut, wie das Timing beim Reflexlader
ist? Typischerweise ist ein Zyklus eine Sekunde(!) lang. Davon dann
vielleicht 980ms Laden mit konstanten Strom. Dann Strom abschalten, 5ms
warten. Dann 5ms Entladeimpuls. Nochmal 5ms warten. Akkuspannung messen.
Nochmal 5ms warten. Und von vorn.
akkunator schrieb:> Hm, wenn ich mir die Specs eines BQ24620 anschaue, dann läuft der mit> 300 kHz.
Fast richtig. Der PWM-Controller für den Ladestrom läuft mit 300kHz.
Aber dieser Teil hat mit dem Reflex-Impuls natürlich überhaupt nichts
zu tun. Ganz davon zu schweigen, daß der BQ nicht das Reflex-Verfahren
implementiert (das wohl auch nur für NiCd bzw. NiMH empfohlen wird)
sondern lediglich je nach Ladephase als Strom- bzw. Spannungsquelle
fungiert. Aber wenn der das Reflex-Verfahren implementieren würde, dann
würde er die 300kHz-PWM natürlich für besagte 3x 5ms abschalten müssen.
Und genauso solltest du das auch tun.
Ob du die PWM für die Ladestromerzeugung mit dem µC machst, oder dafür
z.B. einen MC34063 verwendest, ist lediglich ein Detail. Für einen
Anfänger (der du angesichts deiner Fragen zweifellos bist) würde ich im
Interesse der Akku-Lebensdauer aber zu einem analogen PWM-Regler raten.
XL
> Es gibt auch keinen Grund, warum bei Dir der free running notwendig> wäre.
Hm, vielleicht habe ich ja was missinterpretiert.
Ich bin davon ausgegangen, dass freerunning Messungen in 13 Takten
erledigt sind, während single-shot-Messungen 25 Takte brauchen.
Weiterhin bin ich davon ausgegangen, dass die ADC mit dem Takt nach dem
Vorteiler läuft. Da hielt ich fast die doppelte Taktzahl für zu teuer.
Desweiteren ist es ja so, dass zum Einschalten der Messung an anderer
Stelle der Interrupt länger braucht. Auch eine Zeit, die ich für unnötig
hielt.
> Da hast du das Datenblatt aber fehlinterpretiert. Das einzige was da mit> 300kHz läuft ist der Buck Converter. Der liefert aber nur die Spannung> zum Laden und hat mit den Überwachungs- und Messfunktionen recht wenig> zu tun.
Hm, das ist doch bei mir nicht anders. Ich habe auch eine
Gleichspannung, die höher liegt, als es der Akku verträgt. Gerade bei
Lithium Akkus habe ich gelesen, dass die recht empfindlich auf
Spannungsfehler reagieren. Aber Ihr habt recht - es ist mein erster
Kontakt mit dem Thema Akkuladen, ich habe also keine Ahnung, was
sinnvoll ist.
>> bin über den Wiki-Artikel zum Thema Rückstromladen gestolpert ...> ... das wohl auch nur für NiCd bzw. NiMH empfohlen wird
Scheint als hätten wir unterschiedliche Quellen gelesen. Ich las, dass
die Vorteile besonders bei Blei- und Lithiumakkus zum Tragen kämen, da
sie die Bildung von Gas verhindern.
Ganz so trivial scheint das Laden von Akkus nicht zu sein, sonst gäbe es
sicher funktionierende Schaltungen auch bei den bezahlbaren Ladegeräten.
akkunator schrieb:> Aber Ihr habt recht - es ist mein erster> Kontakt mit dem Thema Akkuladen, ich habe also keine Ahnung, was> sinnvoll ist.
Eine Akku mit einer Frequenz von 300 kHz zu laden jedenfalls ist nicht
sinnvoll ;). Aber das willst du ja nicht wahrhaben - auch wenn es dir
mittlerweile von verschiedenen Personen nahe gelegt wurde.
> Eine Akku mit einer Frequenz von 300 kHz zu laden jedenfalls ist nicht> sinnvoll ;). Aber das willst du ja nicht wahrhaben
Hm, letzteres würde ich so nicht sagen.
Meiner Ansicht nach sind das 2 Paar Stiefel, die da zusammen kommen.
Einmal die Anpassung von Spannung und Strom an die zulässigen Werte für
den Akku (also das, was man gemeinhin als Step-Down oder Buck-Regler
bezeichnet) und dann den Ladevorgang des Akkus.
Zwischen FET und Akku gibt es ja noch ne Spule und
Glättungs-Kodensatoren, sodass der Akku von der PWM nix mit bekommt.
Da sich die Steuerung der Ladezyklen im (milli-)Sekundenbereich
abspielt, kann ich das in Software abhandeln und brauche keine HW-PWM
dazu.
Für Strom- und Spannungsregelung werde ich die HW-PWM aber beibehalten.
Damit hat sich mein "Problem" in Luft aufgelöst, denn mein
unsprüngliches Problem bestand darin, 2 FETs übereinander so
anzusteuern, dass es zu keinem Kurzschluss kommt.
Da dies in der Zeitspanne, in der ich es vorhatte, nicht sinnvoll ist,
habe ich auch kein Problem mehr ;)
akkunator schrieb:> Ganz so trivial scheint das Laden von Akkus nicht zu sein
So isses.
Die Profis lassen sich da auch nicht in die Karten gucken, schließlich
wollen sie ihre Entwicklungsjahre auch bezahlt haben.
Den Bastlergeräten ala Conrad traue ich nicht.
Ich hatte mir mal eins ausgeliehen, plötzlich ein riesen Krach, der
Lüfter war angesprungen.
Dann habe ich einen Akku kurz vor Ladeschluß angefaßt und mir fast die
Finger verbrannt. Die 4 Akkus waren danach alle hin.
Auch von irgendwelchen Voodoo Priestern, die wahre Wunder von ihren
geheimen Ladealgorithmen behaupten, Finger weg.
Ein normales Laderät mit Einzelzellenladung im mittleren Preissegment
tuts am besten.