Vuurvliegjes
Een simpel project met de AVR ATtiny2313
Ik had nog een aantal oude tuinlampen met zonne-cellen
liggen; van die dingen met bovenin zonnecellen en een lichtdetector, onderin
een LED en van binnen twee oplaadbare NiCd cellen. Was ik op uitgekeken, kan ik
daar niet iets anders mee? Wat me leuk leek in de tuin waren 'vuurvliegjes',
subtiele oplichtende LEDjes die in een willekeurig patroon aan en uit gingen.
En dan niet hard knipperend, maar vloeiend aan en uit.
Zonne-energieHoeveel zonne-energie krijgen we eigenlijk hier in Nederland? Ongeveer 1000 kWh/m² per jaar, in de zomer ongeveer 10x zo veel als in de winter. Gemiddeld dus zo'n 2.7 kWh per dag, bij 10 uur/dag dus 270 W/m². Voor een cel van 10 cm², een rendement van 10% en een spanning van 3V is dat zo'n 100 mAh in de zomer, en maar 10 mAh in de winter... Van belang is natuurlijk het energiegebruik. Zon is in Nederland schaars (zie kader Zonne-energie), dus zeker in ruststand moet het ultra low power zijn... In de hardware is er voor gezorgd dat in stand-by mode de onderdelen buiten de ATtiny uitgeschakeld zijn, alleen incidenteel wordt het lichtmeetcircuit een keer per seconde zo'n 20 microseconden van energie voorzien om te kijken of het al donker is. Totale energiegebruik is in rust daardoor slechts 50 µA (of slechts 25 µA als de batterijspanning te ver daalt, omdat de processor dan helemaal plat gaat via de 'brown-out detection op 1.8V). Het circuitDemo-opstelling op Hieronder de beschrijving van de delen van het schema (download het hele schema: vuurvlieg_schema.pdf): processor, laadcircuit, voltage booster, LED control, lichtmeting. De processorSchematic entry en PCBEen plezierig en gratis pakket om schema's en de bijhorende print-layouts te maken is Eagle Light (Easily Applicable Graphical Layout Editor) De processor is op de 'standaard' manier aangesloten. Het draait op de low-power interne 128 kHz RC oscillator, niet erg nauwkeurig en snel maar dat is voor deze toepassing ook niet nodig. De processor probeert zo veel mogelijk in sleep/idle mode te zijn, om energie te besparen. Na iedere actie schakelt hij naar idle-mode, om vervolgens bij een timer-interrupt weer wakker te worden, bijvoorbeeld een keer per seconde. De bron voor de klok en dergelijken worden op de ATtiny ingesteld door 'fuses', een soort elektrisch programmeerbare zekeringen. Deze fuses zijn geprogrammeerd op 128 kHz interne low-power RC oscillator, en BOD aan (brown-out detection; het resetten van de processor als de spanning te ver daalt) op 1.8 Volt. Dit laatste heeft tot gevolg dat de processor in ultra low power mode gaat als de spanning daalt (25 µA voor het hele circuit) en pas weer wakker wordt als de spanning weer boven de 1.8 Volt komt; extra batterij-bescherming. Het laadcircuitHet laadcircuit stuurt de stroom van de zonnecellen direct naar de NiMH batterijen. Wel met een diode ertussen; in het donker zou anders de batterij via een lekstroom door de zonnecellen weer ontladen. Door de beperkte capaciteit van de zonnecel ben ik in Nederland niet bang voor overladen (zie kader 'zonne-energie'), maar eventueel kan je in de zomer (tip: meet de lengte van de dag) de LEDs overdag inschakelen om het laden te beperken... De voltage boosterDe voltage booster is een variant op een geschakelde voeding, waarbij de schakelfrequentie door de ATtiny wordt verzorgt. Omdat de ATtiny op een lage klok loopt, is de schakelfrequentie voor de voeding ook relatief laag (64 kHz, hoogste waarde die ik uit de baudrate-generator kan krijgen met de CPU op 128 kHz). Als gevolg hiervan is er een relatief grote spoel nodig, die ik nog in een rommelbakje had liggen (type-nummer in het schema slaat nergens op, maar had de goede afmetingen voor de PCB, waarde was ongeveer 1 milli-Henry). Als de transistor ingeschakeld wordt gaat er een stroom door de spoel lopen. Wordt nu deze stroom onderbroken (transistor schakelt uit), dan ontstaat er een spanningspuls, die door de diode wordt gelijkgericht. En uiteraard: als er geen enkele LED voor langere periode aan is, dan schakelt de ATtiny ook de oscillator van de geschakelde voeding af om energie te besparen. Pas op: onbelast kan deze spanning behoorlijk oplopen (tientallen volts), en dus je circuit beschadigen! Daarom zit er een zenerdiode van 5.1 Volt op de uitgang. Is er geen enkele LED aan, dan beperkt deze de spanning. Zodra een LED aangeschakeld is zakt deze spanning tot de spanningsval over de LEDs (twee gele LEDs in serie geeft 2x2 = 4 Volt). Je moet de waarde van de zener aanpassen aan het type (kleur) en aantal LEDs. Pas op: als er geen LEDs aan zijn is de voeding onbelast, en laden de condensatoren tot de maximum spanning. Als je te grote condensatoren plaatst laden deze op tot 5.1 Volt, en bij het inschakelen van een LED ontladen ze zich in een keer tot 4 Volt, dit kan grote stromen geven... Daarom beperkt tot 2x 0.1 µF. Ik had oorspronkelijk geen 5.1V zener als bescherming, en een 33µF elco --> spanning liep op tot >15 Volt; zodra je dan een LED activeert brand'ie nog maar een keer... De elco op 15 Volt bevat een behoorlijke hoeveelheid energie! Oeps... had ik kunnen bedenken. Onbelast kan de piekspanning trouwens wel tot >60V oplopen! LED-besturingDe LEDs worden via een transistor aangesloten op de PWM-uitgang van de ATtiny geschakeld. De stroom door de LEDs is beperkt, en zou direct door de ATtiny geschakeld kunnen worden. Maar... de spanning (max 5.1 V) is hoger dan de voedingsspanning van de ATtiny (2..3V), en dat gaat niet samen (pinnen mogen max Vcc+0.5V hebben). Vandaar deze extra transistoren! De helderheid van de LEDs wordt door pulsbreedte modulatie aangestuurd (in phase correct mode), de frequentie hiervan is 128 kHz/512 = 250 Hz. Deze frequentie kan het menselijk oog niet meer als knipperen zien, we zien een mooi gelijkmatig gloeiende LED. De ATtiny heeft 4 PWM uitgangen, op iedere uitgang heb ik op het moment 2 LEDs in serie zitten. LichtmetingDe vuurvliegjes in de tuin De lichtmeting wordt gedaan met behulp van de analoge comparator in de ATtiny. Ik wil alleen maar weten of het donker danwel licht is, dus ik bepaal niet de waarde maar kijk alleen of het meer of minder is dan een ingestelde waarde. De LDR (lichtgevoelige weerstand) vormt samen met een weerstand R5 een spanningsdeler, de spanning hier wordt vergeleken met een vaste spanning uit de deler R6 en R7. Door deze delers loopt normaal stroom, wat weer jammer is voor het energiegebruik; daarom schakel ik dit circuit uit met Q6 (aangesloten op uitgang PD6) als er niet gemeten wordt. Alleen tijdens een meting staat het circuit enkele tientallen microseconden aan. Ik maak geen gebruik van de ingebouwde spanningsreferentie; omdat de batterijspanning varieert ook de spanning in de deler verandert; door twee delers te gebruiken veranderen deze op dezelfde manier en wordt de invloed van de batterijspanning weggewerkt. Achteraf gezien had ik die transistor Q6 ook wel kunnen weglaten, en het circuit direct aan de output-pin van de tiny kunnen hangen, om op die manier de slaapstand te implementeren. Ach. De bijhorende code is vrij simpel, maar leuk is hier het software filter: je wilt niet de zaak verstoren omdat er een vogel overvliegt die de sensor triggert. Daarom wordt er steeds een groepje van 8 metingen bekeken (bij een meting per seconde) en pas als deze 8 keer hetzelfde is vind er een statuswijziging plaats. uint8_t light_samples = 1; // 8 latest light samples; all equal? De montageHet geheel is op een stukje ouderwets gaatjesprint (een gat per eiland) gemonteerd. Het voordeel hiervan is dat je SMD onderdelen (met name de weerstanden) direct op de onderkant kunt solderen, een '0805' smd component (0.8 x 0.5 tiende inch, dus ongeveer 2 bij 1 mm) past netjes tussen twee eilandjes in, en is nog goed hanteerbaar. Het geheel is met zelfstrippend draad gesoldeerd. Op de foto bovenaan deze pagina zit de print nog 'ondersteboven', normaal is deze omgedraaid gemonteerd zodat de componenten in de ruimte tussen de batterijen vallen. Ziet er mooi uit (en past dan in de gesloten behuizing), alleen zit de programmeer-connector daarmee op een onhandige plaats... Had beter een haaks type kunnen nemen. Omdat het geheel buiten in een boom zit, moet de zaak tegen weersomstandigheden kunnen: ik heb de print met een heldere plastic-lak bespoten, om een beschermlaag aan te brengen. De eerste winter heeft het al buiten overleeft. De softwareDownload source file: vuurvlieg.c Op hoog niveau bestaat de software uit een state machine met drie toestanden: slapen, spelen en laden. In de slaap- en laad-stand is de processor meestal in idle mode; slechts een keer per seconde wordt er gekeken of het licht veranderd is. Hiermee wordt het stroomgebruik geminimaliseerd. Tijdens het spelen is de processor vaker actief; maar wordt nog het meest gedaan door de peripherals als de hardware pulsbreedte-modulatoren. Deze draaien op 250 Hz; de frequentie waarmee ook de processor uit idle wordt gehaald (timer overflow interrupt). Meestal valt deze vervolgens weer snel in slaap, maar twee keer per seconde wordt er per LED gecheckt of de LED state machine moet worden bijgewerkt. Op dit moment gaat'ie na drie uur spelen via een time-out in nachtmode; dit zou in de zomer wat langer kunnen (meer zon, dus meer lading). Iets voor de volgende software revisie... Dit wordt misschien nog eens uitgewerkt: details LED state machine, lichtmeting, PWM-gebruik, etc; maar bekijk anders maar de source file. Alvast enkele fragmenten code: om de processor in void timer_xxx_sec(int secs) //
program timer to wake up from idle En het fragment dat de helderheid van de LEDs regelt. Het 'echte werk' gebeurt in de TIMER1 interrupt routine, die 250 keer per seconde wordt aangeroepen. Omdat de processor slechts op 128 kHz loopt zijn er in totaal dus maar 512 klokcycles per periode, waarin je 4 LEDs moet bijwerken: de routines moeten dus wel efficiënt zijn! Een aantal trucks van mijn software pagina zijn dan ook toegepast; waarmee het aantal cycli in de interrupt routine naar ongeveer 90 is teruggebracht, ongeveer 40% van de beschikbare hoeveelheid. De rest is voor het hoofdprogramma. Ik heb per LED twee vlaggen: up en down, die aangeven of de helderheid
omhoog gaat danwel naar beneden. Voor de 4 LEDS heb ik deze in een byte
gepackt, zie de definitie van // ######################### Interrupt
support ############################# Stroomgebruik in de werkelijke schakelingIn mijn vuurvlieg-project, een batterij- en zonnecel-gevoed ontwerp, heb ik
de stroom gemeten. Wordt tenslotte gevoed door 2 NiMH batterijen en geladen
door een kleine zonnecel, en de datasheets zeggen ook niet altijd alles... Dat
viel dus reuze mee (stroomgebruik is van de hele schakeling):
Als de LEDs uit staan gaan de batterijen dus wel een tijdje mee (batterij van 1000 mAh bij een stroom van 50 µA --> 20000 uur = 2¼ jaar; tegen die tijd is de NiMH batterij al leeg door zelfontlading). |
op mijn site |