Data Logger/ MiNH Tester
Het
probleem: hoe goed is mijn batterij?
Ook een stapeltje oplaadbare batterijen liggen, en afgevraagd welke nog goed
zijn (en vooral een lange levensduur hebben)? NiMH batterijen hebben een
beperkte levensduur, maar hoe ver zijn ze 'op'? Ik had deze vragen, en vond dit
een mooi projectje om de Butterfly voor in te
zetten.
Hoe gedraagt een NiMH-batterij zich bij gebruik? Net na het laden komt er
een spanning uit van 1.35 tot 1.4 Volt, die vrij snel wegzakt naar de normale
werkspanning van ongeveer 1.2 Volt. Dit wordt een tijd volgehouden, waarna de
spanning snel wegvalt: de batterij is leeg (zie het grafiekje hieronder). Hoe
lang het duurt voor de spanning wegvalt is afhankelijk van de 'capaciteit' van
de batterij, en deze neemt af met de leeftijd van de batterij. Op de batterij
staat bijvoorbeeld 2500 mAh, dit is de capaciteit bij aankoop, en dit wordt dus
minder over de jaren. Hoe snel? Hangt af van de temperatuur, het gebruik, het
aantal keren laden, en zo voort.

Wat betekent een capaciteit van 2500 mAh? Het is het product van de stroom
en de tijd; de batterij kan dus bijvoorbeeld 1 mA leveren over 2500 uur, of 250
mA gedurende 10 uur, of elke andere combinatie van stroom maal tijd die 2500
oplevert.
Met deze opzet heb ik enkele batterijen (3 sets van 2) doorgemeten (apart,
niet per set), allemaal van ongeveer 2500 mAh. In de praktijk bleken er grote
verschillen te zijn tussen verschillende sets van batterijen, ook al zullen ze
oorspronkelijk vergelijkbaar zijn geweest! Van een set (A1 en A2) zijn beide
batterijen al na 10 uur uitgeput, bij de beste set (C1 en C2) duurde dit zo'n
24 uur...
Bij het uitschakelen van de
belasting loopt de spanning weer op, en lijken ze weer in orde. Helaas, zodra
je er weer iets op aan sluit zakt de spanning weer snel (na zo'n 5 tot 10
minuten, zie grafiekje links) in; ze zijn toch echt leeg. Dat de spanning
daarna weer oploopt komt omdat mijn ontlader afschakelt zodra het denkt dat de
batterij weer leeg is; de batterijspanning loopt dan alweer op.
Hoe werkt
de tester?
Als gebruiker: Je stopt de batterijen er in (1 tot 4 stuks), kiest in
het menu de NiMH test, en het programma gaat lopen. Op iedere batterij wordt
een belasting aangesloten om hem leeg te trekken (met 100 mA). Elke seconde
wordt er van een van de batterijen de spanning gemeten en weergegeven (en elke
minuut worden de 4 waardes opgeslagen om later op de PC te kunnen bekijken).
Dit gaat door tot een batterij tot op 1 Volt leeg is; op dat moment hoor je een
piepje, wordt de belasting uitgeschakeld, en geeft vanaf dat moment op het
display voor die batterij aan na hoe lang de ontlading was (uren:minuten).
Stroombron
Hoe krijg je een constante stroom, onafhankelijk van de spanning? Een
transistor in een schakeling als schema 1 probeert een constant
spanningsverschil VBE tussen basis en emitter te houden, typisch in
de orde van 0.4..0.7 Volt (voor silicium-transistoren).
Door nu een constante spanning op de basis te zetten (van zeg 1.3V, de
spanningsval over de dubbeldiode D1) zal de transistor de stroom door R1
dusdanig regelen dat de spanning hierover 1.2V - VBE is, hier 1.2V -
0.75V dus 0.45V, onafhankelijk van de voedingsspanning. Een vaste spanning over
een weerstand resulteert in een vaste stroom door de transistor -> doel
bereikt.
Bij een weerstand van 4.5 Ohm en een spanning van 0.45 Volt resulteert een
stroom van 100 mA.
Op zich kan verdere ontlading dan 1 Volt bij een enkele NiMH-cel overigens
niet zo veel kwaad. Het probleem van over-ontlading is pas een probleem met
meerdere cellen: hier kan de spanning over de meest ontladen cel negatief kan
worden, en dit kan de batterij wel echt beschadigen.
Als ontwerper: De basis is een 'data logger' functie in software.
Deze meet regelmatig welke spanning uit de afzonderlijke batterijen komt, en
slaat dit op om later te bekijken. De data logger bestaat in software uit
verschillende delen:
- een hoofdprogramma (met menu's) die de timing
en het starten van metingen regelt; gebouwd op het framework van de Butterfly
menu-structuur
- De meetroutine, die de A/D convertor
aanstuurt (kiezen van de te meten batterij en zo) en de waarde teruggeeft
- de logroutine, die de data-waarden regelmatig
wegschrijft naar de seriële flash-chip (en de routine om die gegevens
vervolgens op verzoek naar een PC door te sturen, om bijvoorbeeld grafiekjes
mee te maken)
Daarnaast is er wat hardware toegevoegd, die de batterijen koppelt aan de
Butterfly, en die ook de 100 mA belasting per batterij maakt, met mogelijkheid
die vanuit de Butterfly aan en uit te schakelen (zoals gezegd: als de batterij
haast leeg is, wil je stoppen met verder ontladen).
De uitleg komt hier in de omgekeerde volgorde: eerst de hardware, dan de
simpele routines, dan het hoofdprogramma, en uiteindelijk de resultaten.
De
hardware
De extra hardware bestaat (naast de butterfly
natuurlijk) uit twee delen; het batterij-meet-circuit en een
spanningsreferentie.
Het
batterij-meet-circuit
Het circuit om de batterijen op te
meten bestaat uit:
- De spanningsmeting: niet meer dan een weerstand R8 en condensator
C5 (storingsonderdrukking en bescherming van de Butterfly) van de
batterijen naar de A/D converter inputs (PF4-PF7)
- De belasting met 100 mA: een constante stroombron, aan/uit te schakelen via
vrije pinnen op de Butterfly (onderdelen: transistor, een dubbele diode, en
twee weerstanden)
De ontlading van de batterij wordt gedaan met een constante stroom van 100
mA (zie kader 'Stroombron'). De spanning over de
dubbele diode D1 is via R7 en de pinnen van de processor aan en
uit te schakelen, daarmee is de belasting dus te schakelen: als de batterij tot
1 Volt ontladen is wordt door de software de belasting uitgeschakeld om te ver
ontladen te voorkomen.
Het hele circuit is vier keer uitgevoerd, om vier batterijen onafhankelijk
te meten (zie het plaatje links; een deel van de onderdelen zit als SMD-variant
op de onderkant). De batterij-houder had de vier cellen oorspronkelijk in serie
staan; ik heb ze losgeknipt om ze per stuk te kunnen ontladen/meten (met een
gezamenlijke massa-aansluiting, de extra dik uitgevoerde zwarte draad.
Is dit de ideale schakeling? Niet echt; zie aan het einde van deze pagina voor verdere ideeën...
De
referentiespanning
De on-board referentie is niet echt
bruikbaar (zie de Butterfly
pagina); dus ik besloot zelf een referentiespanningsblokje te maken, in een
geschikt spanningsbereik (hoger dan de batterijspanning, zodat ik geen
spanningsdelers bij de batterij hoef te hebben: de ADC kan geen spanningen
meten hoger dan de referentiespanning). Dit heb ik gedaan met wat onderdelen
die ik nog had liggen, een wat vreemde keuze hier en daar (zie schema
hiernaast)...
De basis is een LED (LED1): brandende LEDs hebben een vrij constante
spanning (gedraagt zich ruwweg als een zenerdiode), zo'n 1.8 Volt bij het type
rode LED dat ik nog had liggen, hoger bij bijvoorbeeld groen en blauw.
Door een LED met een constante stroom aan te sturen wordt deze spanning nog
stabieler, ook bij verschillen in de voedingsspanning. Hiervoor gebruik ik weer
een constante stroombron (zie eerder kader), al heb ik hem hier 'gespiegeld' en
een PNP-transistor gebruikt, om de LED aan aarde te kunnen leggen. De spanning
voor de stroombron komt uit LED2.
Op deze manier heb ik een referentie van 1.8 Volt, met behoorlijke
onafhankelijkheid van de voedingsspanning (tussen de 2.7 en 10 Volt, al mag
deze laatste waarde natuurlijk nooit voorkomen op een Butterfly), en ook een
heel behoorlijke temperatuurstabiliteit. 1.8 Volt is ook een mooi meetbereik;
minder dan 2x de maximum batterijspanning van 1.35 Volt, dus ik gebruik alle 10
bits van de ADC (al gebruikt de software er verder maar 8).
Software
download
De software is hier als zip-archive te downloaden: NiMHtester.zip. Dit is de
hele source, inclusief de (hier en daar aangepaste) standaard
Butterfly-code.
De schema's zijn binnenkort als een PDF te downloaden.
En hier mijn simpele logfile
naar spreadsheet (tab-separated ascii) converter geschreven in Perl.
De
software
Het loggen
van de data
Voor de datalogging gebruik ik de seriële flash chip AT45DB041B die
op de Butterfly zit. Deze heeft een opslagruimte van ruim 512 kByte, bij een
meting per seconde (4 kanalen, 8-bits opslag per kanaal) genoeg voor tientallen
dagen opslag.
In de butterfly software zitten al routines om het flash aan te spreken
(dataflash.c ), maar daar komt nog al wat bij kijken. Opgebouwd in
2048 pages van 264 bytes is optimaal gebruik lastig, maar ik heb voor het gemak
er nog een laagje overheen gelegd. De chip heeft een (eigenlijk zelfs twee)
on-chip buffer, waar ik de waardes in weg schrijf; en pas als de buffer 256
bytes bevat, wordt de buffer naar de flash geschreven (duurt 20 ms voor wissen
en programmeren). Dit bufferen beperkt het aantal schrijfacties naar de flash,
en vergroot daarmee de levensduur.
De logging-routines heb ik in een aparte file 'datalog.c '
gezet, zodat ze ook in andere projecten toegepast kunnen worden. Intern wordt
er in een 32-bit teller bijgehouden hoeveel bytes naar de flash zijn
geschreven, zodat de DataLogUpload() routine weet hoe veel
gegevens er naar de PC gestuurd moet worden. De datalogging routines doen
verder niets aan structuur, schrijven alleen maar bytes. De drie belangrijkste
routines:
- void DataLogInit(void); initialiseert de zaak en reset de
teller
- void DataLogWriteByte(uint8_t byte); schrijft een byte naar de
buffer (en de buffer naar flash, indien nodig)
- void DataLogUpload(void); zend de bewaarde bytes via de seriële
poort naar de PC via een simpel ASCII formaat
De
spanningsmeting
Om de spanning te meten gebruik ik een aangepaste versie van de standaard
Butterfly ADC.c . Ik maak gebruik van de analoge ingangen PF4..PF7,
die ook dienst doen voor JTAG debugging (waar ik toch geen gebruik van maak).
Dit houdt wel in dat bij initialisatie deze pinnen eerst als analoge ingangen
moeten worden geconfigureerd, en dat JTAG debugging uitgeschakeld moet worden.
Daarnaast moet bij elke conversie het goede kanaal gekozen worden, wordt er
eerst een dummy-conversie gedaan, en dan worden 8 metingen gedaan waarvan het
gemiddelde wordt teruggegeven. De routines (uit nimh_test.c ):
- void NiMH_init(void); doet de initialisatie (JTAG uit, extra
inputs configureren)
- uint16_t NiMH_read(uint8_t channel); leest het opgegeven
kanaal
Piepjes
Nog even een hulproutine: het maken van piepjes. In de oorspronkelijke
Butterfly zit een heel stuk software voor het afspelen van melodieën, maar dat
neemt me te veel geheugen in gebruik, en de file sound.c heb ik dus verwijderd.
In plaats daarvan een simpele routine die een piep kan afspelen (met
selecteerbare frequentie, maar vaste amplitude) als een batterij leeg is. In de
file 'beep.c ' twee routines:
- void BeepStart(uint16_t pitch); start een toon; frequenties
als in sound.c ; 478 is een C (C2)
- void BeepStop(void); stopt de toon (moet je dus zelf doen!)
Overigens, tussen toetsaanslagen gaat de Butterfly zo veel mogelijk slapen.
Dit is normaal geen probleem; behalve bij het afspelen van piepjes: deze
klinken dan nogal stotterend. Vandaar dat ik gedurende een piepje de processor
maar niet laat slapen.
Het
hoofdprogramma
De Butterfly heeft een main loop die continue loopt en toetsaanslagen via de
menu-structuur verwerkt. Er is dus geen gebruikersprogramma continue actief. In
plaats daarvan hangt de NiMH tester de routine NiMH_periphery() in
een timer-interrupt die elke 10 ms wordt geactiveerd (nou ja, ongeveer dan, de
timing in de Butterfly is niet zo precies behalve voor de real-time clock). In
deze routine wordt getest of er een nieuwe seconde begonnen is (via de
real-time-clock variabelen), en alleen dan wordt er gemeten. Een aanpak die in
real-time systemen overigens niet ongebruikelijk is. Wel oppassen: als de
Butterfly in zijn main loop een tijd geen toetsaanslagen detecteert gaat hij in
power-down; dit moet dus wel voorkomen worden (door de power-down timer te
resetten).
Elke seconde wordt dus werk verzet. In de routine
NiMH_periphery() wordt steeds één batterij doorgemeten, en de
waarde op het display weergegeven (batterij-nummer gevolgd door een spatie en
de gemeten spanning in drie cijfers, dus iets als '1 123 ' voor
batterij 1 met 1.23 Volt).
Als de waarde voor het eerst onder de 1 Volt
komt wordt een piepje gegeven en de tijd gelogd. Bovendien wordt vanaf dat
moment in het display niet meer de spanning weergegeven, maar de tijd (in uren
en minuten) waarop de batterij leeg was, gevolgd door het batterijnummer (dus
12:02: 2 ). Op die manier worden spanning en tijd niet snel
verwisseld.
Een keer per minuut worden de laatste 4 spanningen naar de flash geschreven,
voor latere analyse in bijvoorbeeld een spreadsheet: via de seriële poort kan
met DataLogUpload() de data naar een PC gezonden (vang ik op met
GtkTerm), en een simpel Perl script vertaalt vervolgens de data naar een
formaat dat in de meeste spread sheets wel gelezen kan worden. Zo heb ik ook de
grafiekjes op deze pagina gemaakt.
Om deze routines aan te roepen zijn er in het Butterfly-menu twee entries
toegevoegd, gebundeld in een NiMH-tester hoofdmenu:
- char NiMHStartFunc(char input); de functie die het meten
start
- char NiMHUploadFunc(char input); de functie die de upload naar
de PC start
En
verder
Ondertussen de Butterfly in een net kastje ingebouwd,
zodat het geheel wat minder kwetsbaar is, en voorzien van een
uitbreidingsconnector om bijvoorbeeld het meetcircuit van de batterijtester op
aan te sluiten. Kan het dus ook voor andere toepassingen gebruiken.
Zoals al aangegeven; het batterij-ontladingscircuit is niet echt ideaal. De
belangrijkste beperking is het gebruik van de BC549 als transistor: bij deze
lage spanningen en (relatief) hoge stromen houd deze het maar net bij (en
eigenlijk wil ik naar een hogere belastingsstroom,de meeste apparaten willen
wel meer dan 100 mA). Beter is met een goede MOSFET te schakelen, zoals ik ook
bij mijn RGB-controller doe (en dan de
LEDS weg laten, en R3 weglaten of verlagen), maar die had ik op het moment niet
liggen.
Belangrijk is hier een FET te kiezen met een lage schakelspanning (veel
MOSFETS hebben 5 Volt of hoger nodig om goed te schakelen) en een lage
aan-weerstand. De gebruikte IRL510 voldoet aardig; een meting geeft aan dat
deze al schakelt vanaf 3 Volt, en dan een weerstand heeft van 0.5 Ohm (bij 1
Ampere). De BC549C uit het RGB-controllerschema wordt hier gebruikt om de
stroomgrens aan te geven, waarbij die 350 mA een realistischer belasting is dan
de door mij gebruikte 100 mA.
Wel denk ik een kleinere FET (IRLML2502PBF, 20 cent bij Dick Best,
SMD-montage, schakelt al < 2.2 Volt?) te kiezen, zo veel vermogen hoeft er
toch ook weer niet weg (stel dat ik de weerstanden zo kies dat er 0.5 Volt over
de FET staat; met 350 mA is dat iets onder de 200 mW). Ach, toch ook niet
niets, zal toch wat koeling nodig hebben...
|