Batteriemonitor mit Dual Slope Wandler

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche

H.Stockhoff

Dieser Artikel nimmt am Artikelwettbewerb 2012/2013 teil.

Abbildung 1: Batteriemonitor mit Dual Slope Wandler in Gehäuse


Der Dual Slope Wandler wird häufig in Vielfachmessgeräten eingesetzt, da dieser kostengünstig in der Fertigung ist, und eine relativ hohe Auflösung bietet. Ein Beispiel für ein IC nach dem Dual Slope Wandler Prinzip ist der ICL7107 der Firma Intersil. Das Verfahren basiert auf dem Vergleich zwischen einer integrierten Mess- und Referenzspannung. Es arbeitet also mit zwei Rampen. Daher wird dieses Verfahren auch Zweirampenverfahren oder Dual Slope genannt.

Ich möchte in diesem Artikel ein Batteriemonitor zur Spannungs- und Strommessung vorstellen. Das Messgerät kann später an einem 12V Akku betrieben werden und zeigt den aktuellen Stromfluss, die Spannung und die entnommene Ladung sowie die Laufzeit an. Mit entsprechender Bauteildimensionierung (Glättungskondensator und Spannungsteiler für die Betriebsspannungsmessung sowie Spannungsregler) kann das Gerät auch an Spannungen bis zu 28V betrieben werden.


Features

  • Messung der entnommenen Ladung Q
  • Auflösung: 0,001A
  • max. I: 6A
  • UBetrieb: 8-14V/DC
  • Automatischer Nullabgleich
  • einfache Bedienung
  • Stromaufnahme
    • Mit eingeschalteter Beleuchtung: 39mA
    • Mit ausgeschalteter Beleuchtung: 15mA

Blockschaltbild

Abbildung 2: Blockschaltbild des Batteriemonitors

Allgemeines zum Dual Slope Wandler Prinzip

Der Dual Slope Wandler setzt sich grundlegend aus einem Integrator und einem nachfolgenden Komparator zusammen. Eine Steuerlogik legt die entsprechenden Signale an den Eingang des Integrators. Ein Zähler, der mithilfe des Komparators gestartet und gestoppt wird, misst die am Integrator angelegten Messsignale aus und stellt dann einen Wert in Form eines Zählerstandes zur Verfügung. Der Wert des Timers ist der Mittelwert der angelegten Messspannung über die Messzeit. Daher werden Störungen kompensiert und es können mit diesem Wandler Genauigkeiten von bis zu 0,01% erreicht werden.

Abbildung 3 : Dual Slope Wandler

Anhand der nebenstehenden Schaltung kann die Funktion des Wandlers noch einmal verdeutlicht werden (Abbildung 3).



Funktionsprinzip

Zu Beginn sind die Schalter S1 und S2 geöffnet. Schalter S3 ist geschlossen(siehe Abbildung 3). So wird der Integrationskondensator kurzgeschlossen und entladen. Im nächsten Schritt wird der Schalter S3 geöffnet und der Schalter S1 geschlossen. Es wird nun die zu messende Spannung am Integrator angelegt und aufsummiert. Der Vorteil des Integrators ist, dass der Integrationskondensator mit einem konstanten Strom geladen wird. Dadurch ergibt sich eine lineare Aufladung des Kondensators C. Die Spannung am Ausgang des Integrators besitzt eine umgekehrte Polarität, da die Eingangsspannung an den invertierenden Eingang des Operationsverstärkers gelegt wird. Da die Spannung am invertierenden Eingang des Komparators nun kleiner als 0V ist, gibt er das Tor frei(UND-Gatter). Das Signal wird nun so lange integriert, bis der Zähler einmal übergelaufen ist. Anschließend wird die Referenzspannung (umgekehrtes Vorzeichen zur Messspannung) an den invertierenden Eingang des Integrators angelegt. Dazu wird der Schalter S1 geöffnet und der Schalter S2 geschlossen. Die Spannung am Kondensator C des Integrators wird abintegriert. Sie sinkt linear, da auch hier der Kondensator C mit einem konstanten Strom geladen bzw. in diesem Fall entladen wird. Zu diesem Zeitpunkt gibt der Komparator das Tor noch frei, da die Spannung am invertierenden Eingang über ein Potential kleiner als 0V verfügt. Wenn der Kondensator nun so weit entladen bzw. aufgeladen ist und er das 0V Potential überschreitet, sperrt der Komparator das Tor. Er gibt dann ein negatives Signal am Ausgang aus. Somit ist die Messung beendet. Anschließend wird durch die Steuerschaltung der Schalter S2 wieder geöffnet. Um eine gleiche Anfangsbedienung vor jeder Messung zu bekommen, wird der Kondensator C wieder entladen. Dazu wird der Schalter S3 geschlossen. Der Kondensator C ist kurzgeschlossen.

Im nächsten Schritt kann mithilfe des Wertes des Zählers die gemessene Spannung Ue ermittelt werden. Dazu bediene ich mich der Formel für die Aufladung des Integrators über die Zeit t1:

[math]\displaystyle{ U_I(t_1)= -\tfrac{1}{\tau} \int_0^{t_1} U_e dt = -\tfrac{1}{RC} \int_0^{t_1} U_e dt }[/math]


mit [math]\displaystyle{ \tau }[/math] = R∙C

UI  : Spannung am Integrator
t1 : Zeit der Integration der Eingangsspannung
Ue : Eingangsspannung des Integrators

Das Prinzip des Dual Slope Wandlers besteht darin, die Mess- und Referenzspannung (Ue, Uref) zu integrieren. Die Referenzspannung wird mit der Anfangsbedingung UI0 integriert, da sie nach dem Anlegen der Messspannung aufsummiert wird. Da ich eine zeitlich konstante Spannung integriere, gilt der Sonderfall für die Berechnung der Spannung UI des Integrators:

[math]\displaystyle{ U_I = -\tfrac{U_e}{\tau} \cdot t + U_{I0} }[/math]

mit [math]\displaystyle{ \tau }[/math] = R∙C


Ue : Eingangsspannung des Integrators
UI : Spannung am Integrator
UI0 : Anfangsbedingung des Integrators (Anfangsspannung an UI)
t : Zeit der Integration

Die Zeit t setzt sich zusammen aus dem maximalen Zählerstand Nmax und der Periode T.

[math]\displaystyle{ t = (N_{max} + 1) \cdot T }[/math]

Somit ist

[math]\displaystyle{ U_I = -\tfrac{U_e}{\tau} \cdot (N_{max} + 1) \cdot T + U_{I0} }[/math]

mit [math]\displaystyle{ \tau }[/math] = R∙C

Da beide zu integrierenden Spannungen entgegengesetzte Vorzeichen besitzen, ist die Summe beider Spannungen null. Es gilt:

[math]\displaystyle{ 0 = - \tfrac{U_e}{\tau} \cdot (N_{max} + 1) \cdot T + \tfrac {U_{ref}}{\tau} \cdot N \cdot T }[/math]
             Integration	       Integration
             der Messspannung          der Referenzspannung

Wird diese Gleichung vereinfacht erhält man:


[math]\displaystyle{ 0 = - \tfrac{U_e}{\tau} \cdot (N_{max} + 1) \cdot T + \tfrac {U_{ref}}{\tau} \cdot N \cdot T \quad | -(- \tfrac{U_e}{\tau} \cdot (N_{max} + 1) \cdot T) }[/math]
[math]\displaystyle{ \Leftrightarrow \tfrac{U_e}{\tau} \cdot (N_{max} + 1) \cdot T = \tfrac {U_{ref}}{\tau} \cdot N \cdot T \quad | \cdot \tau }[/math]
[math]\displaystyle{ \Leftrightarrow \tfrac{U_e}{\cancel{\tau}} \cdot (N_{max} + 1) \cdot T = \tfrac {U_{ref}}{\cancel{\tau}} \cdot N \cdot T \quad | : T }[/math]
[math]\displaystyle{ \Leftrightarrow U_e \cdot (N_{max} + 1) \cdot \cancel{T} = U_{ref} \cdot N \cdot \cancel {T}\quad | :N_{max}+1 }[/math]
[math]\displaystyle{ \Leftrightarrow U_e= \tfrac{N \cdot U_{ref}}{N_{max}+1} }[/math]


Durch diese Gleichung kann mithilfe des aus dem Zähler erhaltenen Wertes die Eingangsspannung des Integrators berechnet werden. Dazu ist die Gleichung nach Ue aufzulösen:

[math]\displaystyle{ U_e = \tfrac {N \cdot U_{ref}}{N_{max} + 1} }[/math]

Gut zu sehen ist, dass weder die Periode T bzw. die Taktfrequenz [math]\displaystyle{ f = \tfrac {1}{T} }[/math] , noch die Zeitkonstante [math]\displaystyle{ \tau }[/math] des RC-Gliedes mit in die Rechnung einfließen. Dies ist ein spezielles Merkmal des Dual Slope Wandlers. Wird ein Dual Slope Wandler aufgebaut, ist auf den Typ des Operationsverstärkers zu achten. OPs, aufgebaut aus bipolaren Transistoren, besitzen meist hohe Bias Ströme. Diese führen dazu, dass die Aufladung des Kondensators beeinflusst wird. So werden sich die Bias Ströme auf den Kondensator durch die lange Aufladung aufsummieren und das Messergebnis verfälschen. Es sollte daher ein Operationsverstärker mit geringen Bias Strömen gewählt werden, damit die Aufladung des Kondensators nicht beeinflusst oder gar verfälscht wird. Dazu eignen sich meistens OPs mit einem internen FET-Aufbau. Sie besitzen oft kleine Bias Ströme von wenigen Pikoampere (Diese können dann vernachlässigt werden). Somit müssen bei FET-Operationsverstärkern lediglich die Offsetspannungen kompensiert werden, um ein korrektes Ergebnis zu erhalten.


Hardware

Nun zur Hardware. Das Messgerät besteht aus einem Dual Slope Wandler, an den über ein Multiplexer (4051) die verschiedenen Messsignale angelegt werden. Gesteuert wird der Multiplexer mit einem ATmega168 der Firma Atmel. Auf dem Display können die aktuelle Spannung und der Strom eines Verbrauchers abgelesen werden.

Die Schaltung des Messgeräts besteht aus drei Teilen: der Spannungsversorgung, dem Analogteil (AD-Wandler) und dem Digitalteil (Mikrocontroller und Display).


Spannungsversorgung

Abbildung 4: Spannungsversorgung

Die Spannungsversorgung besteht aus einem Festspannungsregler und einer Ladungspumpe, sowie einer Diode zur Erzeugung der Referenzspannung von -2,5V (Abbildung 4). Als Festspannungsregler ist ein 7805 vorgesehen. Er stellt die Versorgungsspannung für den Mikrocontroller, das Display und den Analogteil zur Verfügung. Um einen höheren Wirkungsgrad zu erzielen, kann er aber auch gegen einen Schaltregler(TSR 1-2450) ersetzt werden, damit die Schaltung auch mit Spannungen größer als 14V versorgt werden kann. Der 7805 würde zwar die Eingangsspannung von 14V auf 5V herunter regeln; dies würde aber zu einer erhöhten Verlustleistung führen, was zur Folge hat, das sich der Festspannungsregler erwärmt und mit einem Kühlkörper ausgestattet werden müsste. Bei 14V Eingangsspannung und einer Stromaufnahme von 0,2A würde die Verlustleistung 1,8W betragen. Diese muss dann über die Kühlfläche in Abwärme umgesetzt werden. Die Ladungspumpe wurde mit einem ICL7660 realisiert. Sie stellt die negative Versorgungsspannung für die Operationsverstärker, die Referenzspannung und den Multiplexer her. Das einzige Problem bei dieser gewählten Ladungspumpe ist seine Belastbarkeit. Die Ausgangsspannung des ICL7660 kann mit nur wenigen Milliampere belastet werden, bevor sie einbricht. Daher wurden die Ladungskondensatoren etwas größer gewählt und die Ein- und Ausgangsspannung gepuffert. Ein zweites wichtiges Kriterium ist eine stabile Eingangsspannung. Diese ist, da die Ladungspumpe am Ausgang des Festspannungsreglers 7805 angeschlossen ist, gewährleistet.

Mithilfe kleiner 100nF Kondensatoren in den Eingangsleitungen beider Regler werden Spannungstransienten (Spannungsspitzen) sicher abgeleitet und so die nachfolgenden Bauteile geschützt.

Die Diode LM385 ist so konzipiert, dass sie eine Spannung von -2,5V erzeugt. Gespeist wird sie durch den ICL7660. Der Widerstand R9 begrenzt den Strom auf 0,5mA. Ein nachfolgender Kondensator fängt noch einmal Spannungsspitzen ab.

Analogteil

Abbildung 5: Analogteil


Der Analogteil der Schaltung besteht aus einem Differenz- (INA117) und Vierfachoperationsverstärker (TLC274) sowie einem Multiplexer (CD4051). Grundlegend kann der Analogteil auch noch einmal in den Wandlerteil und in den Strommessteil gespalten werden. Beginnen möchte ich mit dem Strommessteil. Dieser besteht aus einem INA117, einem Tiefpassfilter und einem Verstärker. Die Messung des Stroms wird mithilfe eines Shunts realisiert. Genannt wird diese Methode auch indirekte Strommessung, da lediglich der Spannungsfall am Shunt betrachtet wird. Daher wird die Spannung nach dem Shunt von der Spannung vor dem Shunt subtrahiert. Über das ohmsche Gesetz kann anschließend der Strom resultierend aus dem Spannungsfall errechnet werden. In meinem Fall sind der Widerstand (R2 = 0,01Ω) und der gemessene Spannungsfall über dem Widerstand R2 bekannt. Um das ganze jetzt auch messen und digitalisieren zu können, wurde ein Differenzverstärker vom Typ INA117 ausgewählt. Der Differenzverstärker(INA117) besitzt die Eigenschaft, dass er zwei anliegende Signale voneinander subtrahieren kann. Es wird dann der Spannungsfall über dem Shunt(R2) gemessen (Abbildung 5). Die Verstärkung des Ausgangssignals ist 1:1. Ausgewählt wurde der INA117, da er im HIGH-Side Anschluss der Schaltung messen kann. Er ist durch den internen Spannungsteiler im Eingang bis zu Spannungen von 500V abgesichert. Für den Zweck in dieser Anwendung ist es ausreichend, da maximal Spannungen von 14V herrschen. Die Teilungen der Eingangsspannungen belaufen sich auf jeweils 1:20.

Da das Signal am Ausgang des INA117 einen hohen Rauschpegel besitzt, wird es im nächsten Schritt durch ein RC-Glied gefiltert und anschließend mithilfe des 4-fach Operationsverstärkers auf das gewünschte Maximum, der Referenzspannung, verstärkt. In der Verstärkerstufe wird das Signal ebenfalls noch einmal gefiltert, um eine bessere Stabilität zu erlangen. Dies geschieht einerseits durch den Verstärker selber, da er ein geringeres Rauschen als der INA117 am Ausgang ausgibt und andererseits durch das Filter C in der Rückkopplung parallel zum Rückkoppelwiderstand. Hier wurde der Wert 68nF gewählt(siehe dazu auch noch einmal die nachfolgende Rechnung). Dies ergibt dann bei einer Frequenz von 100Hz einen Blindwiderstand XC von 24kΩ.

f = 100HZ
XC = 24000Ohm
[math]\displaystyle{ X_C = \tfrac{1}{2 \cdot \pi \cdot f \cdot C} }[/math]
[math]\displaystyle{ \Leftrightarrow 24000Ohm = \tfrac{1}{2 \cdot \pi \cdot 100Hz \cdot C} \quad | \cdot 2 \cdot \pi \cdot 100Hz }[/math]
[math]\displaystyle{ \Leftrightarrow 24000Ohm \cdot 2 \cdot \pi \cdot 100Hz= \tfrac{1}{C} \quad | (.)^{-1} }[/math]
[math]\displaystyle{ \Leftrightarrow 0,000000066F = C }[/math]
[math]\displaystyle{ \Leftrightarrow 66nF = C }[/math]

Es wird der nächst größere Kondensator gewählt. Somit 68nF.

Der Verstärker dient im genaueren hinsehen dazu, dass Messsignal auf das Maximum der Referenzspannung zu normieren. Die Referenzspannung beträgt, wie oben schon erwähnt, -2,5V. Das bedeutet, dass das Messsignal den Betrag dieser Spannung nicht überschreiten darf.

Um nun den kompletten Messbereich von |-2,5V| auszunutzen, wird das Signal des INA117 mit dem Faktor 25 verstärkt. Anschließend wird es über einen Eingangswiderstand auf den Multiplexer gelegt.

Weitere Eingangssignale des Multiplexers sind neben der zum Strom äquivalenten Spannung auch die Referenzspannung, die aktuelle Spannung vor dem Shunt und die Spannung des Integrationskondensators (Kurzschluss des Kondensators). Die aktuelle Spannung vor dem Shunt dient später dazu, wie weit der Akku bereits entladen ist. Bei einer gewissen Grenze soll der Controller ein Alarmsignal ausgeben, damit der Akku nicht tiefentladen wird oder die angeschlossenen Geräte sich dann plötzlich wegen zu geringer Spannung abschalten. Dies könnte dann über den externen Anschluss (PB1) erfolgen. Derweil ist dies im Programm aber noch nicht vorgesehen.

Digitalteil

Abbildung 6: Digitalteil

Als Mikrocontroller wird ein ATmega168 eingesetzt. Er bietet einen Timer, bei dem der Zählerstand über einen Hardwareeingang gesichert und im nächsten Schritt softwareseitig verarbeitet werden kann. Dies ist besonders bei dieser Anwendung von Vorteil, da genaue Zeitmessungen mit schneller Umschaltung und Auswertung nötig sind, um exakt gewandelte Werte zu erhalten. Da auch die Zählerfrequenz auf den kleinsten Strom abgeglichen werden muss, wurde ein Quarz mit einer Frequenz von f = 16MHz gewählt. Hierdurch werden ausreichend große Zählerstände und Auflösungen erreicht. Des weiteren ist an den Mikrocontroller das Display zur Anzeige der ausgerechneten Werte an PORTC angeschlossen. Die Beleuchtung des Displays kann wahlweise softwaremäßig über den OC2-Ausgang des Mikrocontrollers gedimmt oder auf konstante Helligkeit eingestellt werden. Der Kontrast kann Hardwareseitig mit einem Potentiometer eingestellt werden. Anderweitig verfügt der Mikrocontroller über einen zweiten externen PIN, an den über eine Stiftleiste ein Piezosummer angesteuert werden kann. Er dient zur akustischen Warnmeldung bei Unterschreitung der Akkuspannung, um ein zu tiefes Entladen zu verhindern.


Funktion der Schaltung

Der eigentliche Dual Slope Wandler ist im Gegensatz zur obigen Erläuterung etwas anders aufgebaut (siehe Funktionsprinzip und Abbildung 3). Das Integrationsglied ist in dieser Anwendung schon ein wenig negativ Vorgespannt, um einen definierten Umschaltpunkt zu erhalten. Dadurch ist gesichert, dass der Komparator nicht bei kleineren Masseschleifen umschaltet. Die Vorspannung beläuft sich auf -0.025V. Dadurch, dass der Operationsverstärker immer versucht, zwischen seinen beiden Eingängen (PIN 12 u. 13, IC3D) einen virtuellen Nullpunkt zu erzeugen, ist die Vorspannung auch an PIN 13 anzutreffen. Sie gibt nun, wie oben schon gesagt, die Schaltschwelle des Komparators an PIN 2 vor. Sobald nun die Messspannung an den Eingang des Integrators angelegt wird, lädt sich der Kondensator negativ auf. Dies geschieht über einen fest vom Mikrocontroller vorgegebenen Zeitraum. Ist die fest vorgegebene Zeit verstrichen, wird die Referenzspannung an den Integrator angelegt. Der Integrationskondensator wird nun mit positiver Spannug aufgeladen. Wird jetzt der definierte Schaltpunkt überschritten, also ist die Spannung des Integrationskondensators größer als -0.025V, kippt der Komparator um. Es gilt:

Komparator mit logischem Ausgang:

y = 1 für U1 > U2
U1 : Eingangsspannung nichtinvertierender Eingang
U2 : Eingangsspannung invertierender Eingang
y : logisches Ausgangssignal

Der Komparator gibt den Transistor am Ausgang frei. Der Transistor legt ein High-Signal an den ICP-Pin des Mikrocontrollers. Nachdem nun die Referenzspannung erfolgreich Integriert wurde, der Komparator den Transistor freigegeben hat, wird der Integrationskondensator durch den Multiplexer kurzgeschlossen. Dadurch wird der Kondensator auf das Potential der Vorspannung aufgeladen (UI0 = -0,025V). Zur Erläuterung sei hier nochmal ein Oszillogramm dargestellt, dass die Spannungen an den Messpunkten MP1, MP2, MP3 und MP4 zeigt (Abbildung 7 und 8).


Abbildung 7: Ausschnitt Analogteil mit MP1, MP2, MP3 und MP4
Abbildung 8: Oszillogramm zur Erläuterung der Spannungen in den Messpunkten MP1, MP2, MP3 und MP4



Das Platinenlayout

Die Platine des Messgerätes ist zweiseitig aufgebaut (es ist aber auch möglich, diese einseitig zu fertigen, da alle Drahtbrücken dementsprechend ausgelegt sind). Sie beläuft sich auf eine Größe von 71,11mm x 107,3mm.

Auf der Lötseite, bzw. auf der Unterseite, wurden die SMD-Bauteile, wie der Mikrocontroller, Operationsverstärker und Multiplexer untergebracht. Auf der Oberseite befinden sich neben den konventionellen Bauteilen (Spannungsversorgung und Display) auch noch Drahtbrücken, die eine sichere Verbindung zwischen der Unterseite und der Oberseite herstellen. Zusätzlich wurde auf der Oberseite noch eine Beschriftung zur Anschlussbelegung des Messgerätes eingefügt. Das Layout des Messgerätes wurde speziell darauf ausgelegt, möglichst keine Masseschleifen zu erzeugen. Daher besitzt jeder Schaltungsteil (Spannungs-, Analog- und Digitalteil) seine eigene Masseleitung. Es wurde kein Polygon als Massefläche gewählt, da dort nicht explizit der Stromfluss ermittelt werden kann. Zusätzlich wurden die Leiterbahnlängen im Analogteil möglichst kurz gehalten, um einem eventuellen Spannungsfall vorzubeugen.

Im rechten Bereich wurde der ISP-Stecker zur Programmierung des Mikrocontrollers ATmega168 herausgeführt. Das Display wird später mit ausreichend langen Abstandsbolzen über die Elektronik gesetzt. Dabei muss die Länge der Abstandsbolzen entsprechend der Bauhöhe der Kondensatoren und des Shunts gewählt werden. Für die Befestigung der Abstandsbolzen sind bereits vier Bohrungen hervorgesehen. Die 16-polige Stiftleiste verbindet die Platine mit dem Display. Außerdem kann später die Beleuchtung mithilfe des Mikrocontrollers gedimmt bzw. ein- und ausgeschaltet werden. Ein Trimmer für die Kontrastspannung ist auch vorgesehen. Da das Display auf die Top-Seite der Platine befestigt wird, musste die Anschlussklemme für die Spannungsversorgung (X1, X2) etwas nach links versetzt werden, um auch noch ein nachträgliches anbringen der Versorgungskabel zu ermöglichen. So muss bei einem Anschlusswechsel nicht jedes Mal das Display demontiert werden, um an die Schrauben der Anschlussklemme zu gelangen. Des weiteren wurden auch die vier Kurzhubtaster etwas unterhalb des Displays positioniert.

Abbildung 9: Platinenlayout Batteriemonitor

Software

Die Software für das Messgerät ist in der Programmiersprache C geschrieben. Der Mikrocontroller übernimmt das Zeitmanagement für die Umschaltung der zu integrierenden Spannungen sowie die darauf folgende Auswertung und Umrechnung der Zählerstände. Schließlich wird der ermittelte umgerechnete Wert auf dem LCD-Display angezeigt.

Das Programm des Batteriemonitors ist so aufgebaut, dass zuerst eine Spannungsmessung durchgeführt wird. Anschließend wird die Strommessung bei nicht angeschlossener Last initialisiert. Dieser Stromwert dient dann als relativer Nullpunkt für die späteren Messungen. Im nächsten Schritt wird der Timer2 initialisiert. Er dient zur Zeitmessung. Dabei wurde der Top-Wert so gewählt, dass er alle 500µs ein Überlauf auftritt. Dadurch kann leichter eine volle Sekunde errechnet werden. Nachdem nun die Zeitmessung gestartet wurde, betritt das Programm eine Endlossschleife, in der eine kontinuierliche Spannungs- und Strommessung durchgeführt werden. Die gewandelten Werte werden dann umgerechnet auf dem Display angezeigt. Innerhalb der kontinuierlichen Spannungs- und Strommessung kann über die Bedientaster die Errechnung der Ladung Q gestartet, gestoppt und zurückgesetzt werden. Eine nachträgliches abgleichen des relativen Nullpunktes für die Strommessung ist auch möglich. Dieser Vorgang soll als nächstes noch einmal etwas detaillierter erläutert werden.

AD-Wandlung

Die AD-Wandler-Routine habe ich in der Software so gestaltet, dass sie schnell auf einen anderen Mikrocontroller übertragen werden kann. Es müssen lediglich die entsprechenden Umschaltung zur Anlegung der Spannungen am Multiplexer verändert werden. In der Headerdatei wird zunächst festgelegt, an welchem Port der Multiplexer angeschlossen ist und an welchem Port sich Hardwaremäßig der ICP-Pin des Mikrocontrollers befindet. Dazu einmal ein kleiner Ausschnitt aus dem Programm:

// Steuerbits des Multiplexers
#define A PD0
#define B PD1
#define C PD2

// PORT des Multiplexers
#define Multi_PORTx PORTD

// DDR des Multiplexers
#define Multi_DDRx DDRD

#define ICP_PINx PINB
#define ICP_Px	PB0

Hier sind auf einem Blick die wichtigen Anschlüsse des Multiplexers einsehbar und können schnell an den jeweiligen Mikrocontroller angepasst werden.

Damit das Signal auch gemessen werden kann, muss ein Timer eingesetzt werden, der die Aufladungszeiten in Form von Zählerständen ermitteln kann. Dazu eignet sich am Besten der 16-Bit Timer1 des ATmega168. Er verfügt zudem über einen Capture-Betrieb, bei dem der Zählerstand hardwaremäßig über einen Flankenwechsel am ICP-Pin im ICR1-Register gespeichert werden kann. Der Timer1 wird folgendermaßen initialisiert:

	TCCR1B |= (1<<WGM12);
	TCCR1B |= (1<<ICES1) | (1<<ICNC1); // Trigger auf steigender Flanke und Noise Canceler eingeschaltet
	TCCR1B |= (1<<CS10) | (1<<CS11); // Vorteiler 64
	OCR1A = 0xFFFF; 
	
	TIMSK1 |= (1<<ICIE1); // Input Capture Interrupt einschalten
        sei();

Im nächste Teil kommt nun die eigentliche Wandler-Routine. Dort wird über eine switch-case Anweisung differenziert, ob der Strom oder die Spannung gemessen werden soll. Der spätere Zählerstand wird in der Variablen ad_wert abgespeichert. Welcher Steuereingang des Multiplexers zum Anlegen der korrekten Spannung eingeschaltet werden muss, wurde anhand einer Wahrheitstabelle aus dessen Datenblatt ermittelt. Es wird nun zuerst die zu messende Spannung an den Integrator angelegt. Im nächsten Schritt wird solange gewartet, bis der Komparator ein Low-Signal ausgibt. Erst danach wird der Zählerstand des Timer1 zurückgesetzt. Es wird nun das Messsignal über einen festen Zeitraum integriert. Festgelegt ist die Zeit durch die Variable timer_max. Nachdem das Register TCNT1 größer ist als die Variable timer_max, wird die Referenzspannung an den Integrator angelegt. Das Timer/Counter Daten-Register(TCNT1) wird zurückgesetzt. Der nun folgende Zählerstand ist der Entscheidende. Es wird so lange die Referenzspannung an den Integrator angelegt bzw. gewartet (while), bis die Schaltschwelle von -0,025V durchlaufen ist. Ist dies geschehen, erzeugt der Komparator eine steigende Flanke und der Zählerstand des Timer1 wird in dem ICR1-Register gespeichert. In der Interrupt-Routine für den Capture-Betrieb wird anschließend der Wert des ICR1-Registers in die Variable ad_wert kopiert. Nachdem die Interrupt-Routine beendet ist, wird der Integrator kurzgeschlossen und wieder entladen, um eine gleiche Anfangsbedingung für die nächste Wandlung zu erhalten. Nachfolgend ist dieser Vorgang nochmal in Form des Sourcecodes dargestellt (siehe auch Abbildung 10):

<avr/io.h>
<avr/interrupt.h>

unsigned int timer_max = 50000; // entspricht einer Aufladung von 0,2s

// gewandelter Analogwert in Form eines Zählerstandes
unsigned int ad_wert = 0;

ISR (TIMER1_CAPT_vect)
{
	ad_wert = 0;
	ad_wert = ICR1;
}



// Analog-Digital-Wandlungen
void ad_wandlung(unsigned char wert) {

	// Anlegen von:
        // 'i' : Strom
	// 'u' : Spannung
	
	switch (wert) {
		case 'i': Multi_PORTx &=~ (1<<B); break;
		
		case 'u': Multi_PORTx &=~ ((1<<B) | (1<<A)); break; 
		}
        // Warte, solange der ICP-Pin noch High ist
	while (ICP_PINx & (1<<ICP_Px));
	TCNT1 = 0; // Timer zurücksetzen

	while (TCNT1 < timer_max); 

	// Anlegen der Referenzspannung
	switch (wert) {
		case 'i': {
			Multi_PORTx &=~ (1<<C);
			Multi_PORTx |= (1<<B);
			}
			break;
		
		case 'u': {
			Multi_PORTx &=~ (1<<C);
			Multi_PORTx |= (1<<B) | (1<<A);
			}
			break;
		}

	TCNT1 = 0;
	while(!(ICP_PINx & (1<<ICP_Px)));

	// Multiplexer kurzschließen		
	Multi_PORTx |= (1<<C); 

}
Abbildung 10: Oszillogramm zur Verdeutlichung der AD-Wandlungsroutine

Korrektur Gleichtaktunterdrückung

Mit obiger Software ist es jetzt möglich, den Strom bei konstanter Spannung zu messen. Da das Messgerät jedoch durch einen Akku betrieben wird, sinkt die Spannung nach einer gewissen Zeit zwangsläufig. Es muss jetzt festgestellt werden, ob der zuvor initialisierte relative Nullpunkt auch bei sinkender Spannung gleich bleibt bzw. der gemessene Wert größer ist als der relative Nullpunkt. Um dies zu überprüfen, wird das Messgerät so programmiert und eingeschaltet, dass der Zählerstand und der umgerechnete Zählerstand gleichzeitig auf dem Display angezeigt werden.

Es wurde nun folgende Messreihe für den maximalen Aufladungsbereich von timer_max = 50000 aufgenommen:

Betriebsspannung U in V Betriebsspannung U in Zähler Strom I in A Strom I in Zähler
14 2251 0 543
13 2088 -0,005 517
12 1931 -0,009 497
11 1773 -0,013 473
10 1622 -0,018 450
9 1468 -0,023 427

Messreihe bei timer_max = 30000:

Betriebsspannung U in V Betriebsspannung U in Zähler Strom I in A Strom I in Zähler
14 2251 0 319
13 2088 -0,005 308
12 1931 -0,009 295
11 1773 -0,013 282
10 1622 -0,017 268
9 1468 -0,022 256

Anhand der Messwerte kann man gut erkennen, dass die Abweichungen bei beiden Messreihen annähernd linear sind. Somit können daraus folgende lineare Gleichungen erstellt werden:

Gleichung 1 für timer_max = 50000:

[math]\displaystyle{ y = 0,1471 \cdot x+211,5 }[/math]
y : Strom I in Zähler
x :Betriebsspannung U in Zähler


Gleichung 2 für timer_max = 30000:

[math]\displaystyle{ y = 0,0856 \cdot x+129,86 }[/math]
y : Strom I in Zähler
x :Betriebsspannung U in Zähler

Die linearen Gleichungen korrigieren die relativen Nullpunkt in Abhängigkeit von der Eingangsspannung. Die y-Achsenabschnitte n = 211,5 und n = 129,86 werden später noch durch eventuelle weitere Abweichungen im Programm automatisch abgeglichen. Im Sourcecode sieht die Korrektur mit Gleichung 1 und vorangegangener Wandlung folgendermaßen aus:

Definieren von Konstanten und Variablen:

// Betrag der Referenzspannung in V
#define ref 2.44375

float null_wert_r = 0; 

signed int nach_null = 0; // Nachträglicher Nullableich 

float mittel_i = 0; // Zählerstand Strom
float mittel_u = 0; // Zählerstand Spannung

float i = 0; //Strom
float korrekt = 1; 

// Speicherarrays für Spannung und Strom
unsigned int speicher_i[5];
unsigned int speicher_u[5];


Wandlung mit anschließender Korrektur durch lineare Gleichung:

// Strommessung

for (unsigned char z=0; z<3; z++) {
	ad_wandlung('i');
	speicher_i[z] = ad_wert;
	}	
		
for (unsigned char z=1; z<=2; z++) {
	mittel_i += speicher_i[z];			
	}
		
mittel_i /= 2;			
	
	
// Spannungsmessung		
		
timer_max_zwischen = timer_max; 
		
timer_max = timer_max_u;

for (unsigned char z=0; z<4; z++) {
	ad_wandlung('u');
	speicher_u[z] = ad_wert;
	}
		
for (unsigned char z=1; z<=3; z++) {
	mittel_u += speicher_u[z];
	}
mittel_u /= 3;
		
timer_max = timer_max_zwischen;

null_wert_r = 0.1471*mittel_u+211.5;

// Umrechnung von Zählerstand nach Strom
i = (((((((float)mittel_i-null_wert_r+nach_null) * ref) / timer_max))/25)*100)*korrekt;


Bei den Wandlungen werden die Zählerstände in einem Array gespeichert. Der erste gewandelte Wert wird jeweils verworfen, da dort noch Differenzen durch eventuelle Vorspannungen auf dem Integrationskondensator vorhanden sein können. Anschließend wird der Mittelwert aus den restlichen Messwerten gebildet und in der zugehörigen Variable (mittel_i, mittel_u) gespeichert.

Zeitmessung

Die Zeitmessung wurde, wie oben schon kurz erwähnt, mit dem Timer2 des ATmega168 realisiert. Initialisiert wird der Timer2 im CTC-Mode. Hier kann die Obergrenze durch das Register OCR2A festgelegt und so die Periode T der Überläufe variabel gestaltet werden. Es wurde hier der Wert 250 bei einem Timer Vorteiler von 32 gewählt. Begründung:

f = 16000000Hz

[math]\displaystyle{ f_{vorteiler} = \tfrac {16000000Hz}{32} }[/math]
[math]\displaystyle{ \Leftrightarrow f_{vorteiler} = 500000Hz }[/math]


[math]\displaystyle{ T = \tfrac{1}{f_{vorteiler}} }[/math]
[math]\displaystyle{ \Leftrightarrow T = \tfrac{1}{500000Hz} }[/math]
[math]\displaystyle{ \Leftrightarrow T = 0,000002s }[/math]


Überläufe bei einem Top-Wert von 250:

[math]\displaystyle{ T = 0,000002s \cdot 250 }[/math]
[math]\displaystyle{ \Leftrightarrow T = 0,0005s }[/math]
[math]\displaystyle{ \Leftrightarrow T = 500\mu s }[/math]

Um jetzt auf eine volle Sekunde zu gelangen, müssen demnach 2000 Überläufe erfolgt sein. Die Zeitroutine ist im Sourcecode folgend aufgebaut:

Timer2 Initialisierung

void timer2_init() 
{
	TCCR2A |= (1<<WGM21);
	TCCR2B |= (1<<CS21) | (1<<CS20);

	OCR2A = 0xFA;

	TIMSK2 |= (1<<OCIE2A);
	sei();
}

Timer Compare Match Interrupt Service Routine:

// Zeit
volatile unsigned int t = 0;
volatile unsigned char sek = 0;
volatile unsigned char min = 0;
volatile unsigned char h = 0;

ISR (TIMER2_COMPA_vect) 
{
	if (t >= 1999 ) {
		t = 0;
		if (sek >= 59) {
			sek = 0;
			if (min >= 59) {
				min = 0;
				if (h >= 23) {
					h = 0;
					}
				else {
					h++;
					}
				}
			else {
				min++;
				}
			}
		else {
                     sek++;
			}
		}
	else {
		t++;
		}
}

Automatische Messbereichsumschaltung

Da der Integrationskondensator nur eine gewisse Menge an Ladung aufnehmen kann, darf das Eingangssignal ein gewisses Maximum bei gleich bleibender Aufladungszeit nicht überschreiten. Dies ist jedoch nicht sehr vorteilhaft, da so nicht der vollständige Zählerbereich der maximalen Aufladung ausgenutzt wird. Außerdem wären bei kleiner Aufladungszeit die Zählerstände zu gering, was eine kleinere Auflösung zur Folge hat. Daher wird bei dem Batteriemonitor eine automatische Messbereichsumschaltung durchgeführt. Es wird bei großen Strömen, die große Spannungsfälle am Shunt bewirken und verstärkt werden, die maximale Aufladungszeit herunter gesetzt. Hierfür dient der zweite Aufladungswert timer_max = 30000. Die Aufladung ist folgendermaßen gestaffelt:

  • es gibt zwei Messbereiche
    • Messbereich 1: timer_max1 = 50000. Die Aufladung beträgt umgerechnet 0,2s. Der Bereich gilt von 0 < I < 3,5A.
    • Messbereich 2: timer_max2 = 30000. Die Aufladung beträgt umgerechnet 0,12s. Der Bereich gilt von I ≥ 3,5A.

Die Messbereichsumschaltung erfolgt nach der Umrechnung des Zählerstandes in einen Stromwert. Zusätzlich werden in der Messbereichsumschaltungsroutine noch die entsprechenden relativen Nullpunkte durch die lineare Gleichung der Gleichtaktunterdrückung berechnet. In der Variablen nach_null stehen Abweichungen von dem Nullpunkt null_wert_r.

// Messbereichsumschaltung

if (i < 3.5) {
        // Messbereich 1
	timer_max = timer_max1;
	null_wert_r = 0.1471*mittel_u+211.5;
	korrekt = korrekt_max1;
	nach_null = nach_null1;
	}
else {
	if (i >= 3.5) {
                // Messbereich 2
		timer_max = timer_max2;
		null_wert_r = 0.0856*mittel_u+129.86;
		korrekt = korrekt_max2;
		nach_null = nach_null2;
		}
	}

Nullabgleich

Der erste Nullabgleich des Displays ist komplett automatisiert. Es muss lediglich über die Taster (Taster 4) der Fortschritt bestätigt werden. Das heißt, es muss bestätigt werden, das keine Last am Batteriemonitor angeschlossen ist. Andernfalls kann der Nullpunkt nicht korrekt initialisiert werden. Um den Nullpunkt null_wert_r mit Abweichung in nach_null zu setzen, wird mit der Ermittlung der Betriebsspannung begonnen. Hierfür werden 4 gewandelte Spannungswerte in Form von Zählerständen in ein Array (speicher_u[4]) geladen. Im nächsten Schritt wird der Mittelwert aus den letzten drei Werten gebildet. Nun kann mit der Spannung der relative Nullpunkt null_wert_r berechnet werden. Die Aufladungszeit timer_max_u beträgt timer_max_u = 5000. Also 0,2s. Im Sourcecode wurde es so realisiert:

Zugehörige Variable:

float mittel_i = 0; // Zählerstand Strom
float mittel_u = 0; // Zählerstand Spannung

float null_wert_r = 0; // relativer Nullpunkt

// Korrektur Nullpunkt
signed int nach_null = 0;
signed int nach_null1 = 0; // Korrektur Nullpunkt timer_max1
signed int nach_null2 = 0; // Korrektur Nullpunkt timer_max2

unsigned int timer_max_zwischen = 0; // Zwischenspeicher für timer_max
unsigned int timer_max = 0;
// Speicherarrays für Spannung und Strom
unsigned int speicher_i[5];
unsigned int speicher_u[5];

Programmcode:

// Spannungsmessung	Initialisierung	
timer_max_zwischen = timer_max; // Zwischenspeicherung des timer_max
		
timer_max = timer_max_u;
	
for (unsigned char z=0; z<4; z++) {
	ad_wandlung('u');
	speicher_u[z] = ad_wert;
	}
		
for (unsigned char z=1; z<=3; z++) {
	mittel_u += speicher_u[z];
	}
mittel_u /= 3;
		
timer_max = timer_max_zwischen; // Laden des zwischengespeicherten Wertes zurück in timer_max

// Strommessung Initialisierung

// Bereich 1
null_wert_r = 0.1471*mittel_u+211.5;

timer_max = timer_max1;

for (unsigned char z=0; z<4; z++) {
	ad_wandlung('i');
	speicher_i[z] = ad_wert;
	}	
	
for (unsigned char z=1; z<=3; z++) {
	mittel_i += speicher_i[z];			
	}
	
mittel_i /= 3;

nach_null1 = 0;
nach_null1 = null_wert_r-mittel_i;

// Bereich 2
null_wert_r = 0.0856*mittel_u+129.86;
	
timer_max = timer_max2;

mittel_i = 0;
for (unsigned char z=0; z<4; z++) {
	ad_wandlung('i');
	speicher_i[z] = ad_wert;
	}	
	
for (unsigned char z=1; z<=3; z++) {
	mittel_i += speicher_i[z];			
	}
	
mittel_i /= 3;

nach_null2 = 0;
nach_null2 = null_wert_r-mittel_i;

Es wird also die Differenz des durch die lineare Gleichung ermittelten relativen Nullpunktes und dem ersten ohne angeschlossene Last gemessenen Zählerstandes gebildet. Dieser Wert nennt sich hier nach_null. Auch er muss für beide Messbereiche (timer_max1 und timer_max2) separat bestimmt werden.

Kontinuierliche Wandlung

Die kontinuierliche Wandlung befindet sich bereits in der while(1)-Schleife des Programms. Es wird dauerhaft die Spannung und der Strom gemessen. Im Sourcecode ist dies folgendermaßen programmiert:

// Strommessung
for (unsigned char z=0; z<3; z++) {
	ad_wandlung('i');
	speicher_i[z] = ad_wert;
	}	

for (unsigned char z=1; z<=2; z++) {
        mittel_i += speicher_i[z];			
	}
		
mittel_i /= 2;	
		
		
// Spannungsmessung		
	
timer_max_zwischen = timer_max; 

timer_max = timer_max_u;

for (unsigned char z=0; z<4; z++) {
	ad_wandlung('u');
	speicher_u[z] = ad_wert;
	}
		
for (unsigned char z=1; z<=3; z++) {
	mittel_u += speicher_u[z];
	}
mittel_u /= 3;
	
timer_max = timer_max_zwischen;

Zum besseren Verständnis dient das nachfolgende Oszillogramm. Es zeigt die Eingangsspannungen und die Spannung UI des Integrators (siehe dazu auch Abbildung 3 und Abbildung 10).

Abbildung 11: Eingangsspannungen und AD-Wandlung


Bedienung

Abbildung 12: Technologieschema
Pin Belegung
1 Input Batterie+
2 Input Batterie-
3 Output -
4 Output +
Abbildung 13: Programm­ablaufplan

Zu beachten ist, dass der Batteriemonitor nur mit Spannungen von 8V/DC < UBetrieb < 14V/DC betrieben werden darf!

Die maximale Belastung beträgt 6A.

Der Batteriemonitor wird über die 4 Taster bedient. Taster 1 dient zum Starten und Stoppen der Ladungsermittlung. Taster 2 setzt die Zeit und die Ladungsermittlung im "Stop"-Zustand zurück. Mit Taster 3 kann bei gestoppter Ladungsermittlung ein erneuter Stromabgleich vorgenommen werden. Es wird dann der neue Nullpunkt gesetzt. Taster 4 wird nur während der Initialisierung benötigt. Mit ihm werden Bestätigungen ausgeführt.



Probleme bei der Entwicklung

Die Entwicklung des Gerätes hat doch sehr viel Zeit in Anspruch genommen. So wurde zuerst der Wandler auf einem Breadboard getestet, um das Verhalten zu untersuchen. Als Operationsverstärker haben dort OP07 gedient, die keinen internen CMOS-Aufbau haben. Dadurch wurde das Ergebnis aus der Wandlung immer wieder verfälscht. Hinzu kamen noch Masseschleifen durch die langen Steckleitungen, die das Ergebnis des Differenzverstärkers immer wieder zunichte machten. Außerdem war zu diesem Zeitpunkt auch nicht klar, dass der Kondensator nicht bis zur Sättigung aufgeladen werden darf(wird in der Fachliteratur meist nicht so deutlich). Erst nach einigen Versuchen, konnte festgestellt werden, dass nur ein kleiner aber dennoch ausreichender Bereich der linearen Aufladungskurve des Integrationskondensators nötig ist, um ein gutes Ergebnis zu erzielen. Kurz darauf wurde dann die erste Testplatine entworfen und gefertigt. Dort konnten, durch gezieltes Routen der Leiterbahnen, Masseschleifen vermieden werden. Das Projekt konnte nun gezielt verbessert und Störungen beseitigt werden. Eine zweite Testplatine mit konventionellen Bauteilen und einem CMOS-OP wurde auch noch hergestellt, um dessen Verhalten zu untersuchen. Wie oben in dem Funktionsprinzip schon dargestellt wurde, bestätigte sich die These, das CMOS-OPs für diesen Typ von Integratorschaltung am Besten geeignet sind. Zum Schluss wurde dann das Endprodukt (Abbildung 1) hergestellt. An ihm wurden die Aufladungszeiten angepasst und die Bedienung durch Taster noch hinzugefügt.


Bilder zum Projekt

Fazit

Als Fazit zu diesem Projekt kann ich sagen: Es hat mir sehr viel Spaß gemacht, dieses Gerät zu entwickeln. Es war zwar manchmal etwas knifflig, doch mit viel Zeit, Ausdauer und Recherchen bin ich dann zum Ziel gelangt. Hinzu kommt auch noch, dass ich viele Objekte auf ihre Funktion hin untersuchen konnte, um besser zu verstehen, wie sie eigentlich funktionieren. Meistens wird es nur theoretisch im Lehrbuch behandelt, wo man das Verhalten verschiedener Schaltungen durch mathematische Gleichungen und Formeln berechnen kann. Doch dies ist dem oft nicht so, da Bauteiltoleranzen und andere Umgebungsfaktoren die praktische Schaltung ungewollt beeinflussen.

Downloads

Siehe auch

  • Tietze, U./ Schenk, Ch.: Halbleiterschaltungstechnik. Berlin-Heidelberg-New York3 1976
  • Tietze, U./ Schenk, Ch.: Halbleiterschaltungstechnik. Berlin-Heidelberg-New York10 1993
  • Schmitt, G.: Mikrocomputertechnik mit Controllern der Atmel AVR-RISC-Familie. Oldenbourg4 2008