Regel 6: | Regel 6: | ||
|Samenvatting=Electriciteitsverbruik volgens de 'slimme meter' opvangen en omzetten in grafieken | |Samenvatting=Electriciteitsverbruik volgens de 'slimme meter' opvangen en omzetten in grafieken | ||
}} | }} | ||
+ | |||
+ | == Meten is weten == | ||
Ik ben geïnteresseerd in het terugbrengen van mijn energieverbruik. | Ik ben geïnteresseerd in het terugbrengen van mijn energieverbruik. | ||
Maar daarvoor wil je meten wat er verbruikt wordt. | Maar daarvoor wil je meten wat er verbruikt wordt. | ||
Regel 28: | Regel 30: | ||
Ik gebruik een gekloonde Arduino Nano. | Ik gebruik een gekloonde Arduino Nano. | ||
Dit is de kleinste Arduino die ook een USB poort aan boord heeft. | Dit is de kleinste Arduino die ook een USB poort aan boord heeft. | ||
− | + | De Arduino detecteert en telt de lichtflitsjes. | |
Met wat proefcode bleken de flitsjes 9-12ms te duren; hij telt een puls als een flitsje tussen de 5 en 20ms duurt. | Met wat proefcode bleken de flitsjes 9-12ms te duren; hij telt een puls als een flitsje tussen de 5 en 20ms duurt. | ||
Voor de compleetheid zit er wat fout-detectie in de pulsdetector: Korter dan 5ms, dan telt hij geen puls maar een storing ('fluke') en langer dan 20, dan telt hij geen puls maar 'teveel omgevingslicht'. | Voor de compleetheid zit er wat fout-detectie in de pulsdetector: Korter dan 5ms, dan telt hij geen puls maar een storing ('fluke') en langer dan 20, dan telt hij geen puls maar 'teveel omgevingslicht'. | ||
=== Rapportage === | === Rapportage === | ||
− | De Arduino rekent het vermogen als volgt uit: 1000 pulsen per KWh, dat is 1 puls per 1Wh, is 1 puls per 3600 Joule. Elke puls is dus 3600 Joule verbruikt. | + | De Arduino rekent het vermogen als volgt uit: De meter geeft 1000 pulsen per KWh, dat is 1 puls per 1Wh, is 1 puls per 3600 Joule. Elke puls is dus 3600 Joule verbruikt. |
− | Dus (aantal pulsen) x 3600 Joule / (tijdsinterval 5 minuten) = vermogen | + | Dus (aantal pulsen) x 3600 Joule / (tijdsinterval 5 minuten) = vermogen. |
De Arduino rapporteert via de seriële poort wat het verbruikte vermogen is, een truc die ik van de Space heb afgekeken. | De Arduino rapporteert via de seriële poort wat het verbruikte vermogen is, een truc die ik van de Space heb afgekeken. | ||
Dit doet hij één keer per 5 minuten. | Dit doet hij één keer per 5 minuten. | ||
Regel 46: | Regel 48: | ||
=== Seriële verbinding === | === Seriële verbinding === | ||
De volgende pakketten zijn geinstalleerd om het mogelijk te maken: | De volgende pakketten zijn geinstalleerd om het mogelijk te maken: | ||
− | kmod-usb-acm | + | * kmod-usb-acm |
− | kmod-usb-ftdi | + | * kmod-usb-ftdi |
− | kmod-usb-ohci | + | * kmod-usb-ohci |
− | Ik kwam er achter dat een Arduino Uno de module kmod-usb-acm nodig heeft, maar de Arduino Nano een andere seriële chip heeft; die heeft kmod-usb-ftdi nodig. | + | Ik kwam er achter dat een Arduino Uno de module '''kmod-usb-acm''' nodig heeft, maar de Arduino Nano een andere seriële chip heeft; die heeft '''kmod-usb-ftdi''' nodig. |
− | Als je de juiste module hebt geïnstalleerd, | + | Als je de juiste module hebt geïnstalleerd, kun je in de /dev de Arduino zien: |
+ | * /dev/ACM0 (Arduino Uno) of | ||
+ | * /dev/ttyUSB0 (Arduino Nano). | ||
+ | Als dit device ontbreekt is de juiste kernelmodule nog niet geïnstalleerd. | ||
=== Grafieken: === | === Grafieken: === | ||
− | Hiervoor ga ik RRDTOOL gebruiken. Dit is in progress. | + | Hiervoor ga ik RRDTOOL gebruiken. Dit is ''in progress''. |
Een grafiek van 600 pixels met één meetpunt per pixel gaat 600x5 = 3000 minuten omvatten. Da's genoeg voor ruim twee dagen. | Een grafiek van 600 pixels met één meetpunt per pixel gaat 600x5 = 3000 minuten omvatten. Da's genoeg voor ruim twee dagen. | ||
+ | De grafieken worden weggeschreven in de /tmp in de router. | ||
+ | Deze directory is gemount in RAM, dus dat vergt geen flash-wear&tear. | ||
+ | De grafieken moeten dan nog geserveerd worden. Mogelijk kan dat met rrdtool-cgi. Ook dat is ''in progress''. | ||
+ | |||
+ | == Software == | ||
+ | De software kan ik hier posten, ter leering ende vermaeck. | ||
+ | Algemene problemen die moesten worden opgelost zijn: | ||
+ | * RRDTOOL moet op vaste tijdstippen een meting ontvangen. | ||
+ | * pulsdetectie | ||
+ | |||
+ | === Vaste tijdstippen: tijd-interrupt? Delay? === | ||
+ | De Arduino staat 99% van zijn tijd maar één ding te doen: Heel hard op een puls te wachten. | ||
+ | Toch moet hij om de 5 minuten (instelbaar) rapporteren, ongeacht of hij even op een puls staat te wachten. | ||
+ | |||
+ | Een delay kan in elk geval niet worden gebruikt omdat de arduino echt naar de output van de sensor moet kijken. | ||
+ | Een Interrupt heeft twee nadelen: | ||
+ | * de code is complex; De interrupt-tijd is veel korter dan 5 minuten. In plaats daarvan moet de interruptcode bij elke aanroep checken of hij al moet rapporteren | ||
+ | * het is niet te controleren wanneer een interrupt wordt aangeroepen, terwijl je liever niet wilt dat hij net tijdens een puls-detectie valt. De puls kan dan mogelijk niet goed gedetecteerd worden en deze situatie is bovendien zeer moeilijk te testen. | ||
+ | |||
+ | De oplossing is simpel en als volgt: De 5 minuten heet een rapportage-interval. | ||
+ | De starttijd van een interval wordt onthouden. | ||
+ | Tijdens het wachten op een puls wordt gechecked of dit interval al is verstreken. | ||
+ | |||
+ | === Pulsedetectie === | ||
+ | Een puls duurt kort en de lichtflits is niet heel fel. | ||
+ | Eerst is experimenteel vastgesteld hoe lang hij duurt en welke waarde op de analoge pin krijgt tijdens een lichtflits. | ||
+ | De code om de puls te detecteren wordt dan: | ||
+ | |||
+ | * Markeer starttijd | ||
+ | * loopje: while (Waarde op analoge pin zegt: lampje is aan, EN de verstreken tijd is niet langer dan de maximale pulstijd) | ||
+ | * bepaal pulslengte = huidige tijd - starttijd. | ||
+ | |||
+ | Bepalen van de tijd gebeurt met millis(). De gebruikte berekening heft de wraparound van 2^32 op. | ||
+ | Let op de bepaling die de while-loop onderbreekt na 20 milliseconden (maximale pulsduur). | ||
+ | Als de sensor wordt blootgesteld aan omgevingslicht blijft de software dus niet hangen. | ||
+ | |||
+ | Wat hij ''niet'' doet is dynamisch bepalen wat de grenswaarden zijn voor wel of geen puls, rekeninghoudend met omgevinslicht. Dat zou extreem cool zijn, en de huidige oplossing is goed genoeg. | ||
+ | De waarden zijn experimenteel bepaald en daarna (met enige marge) hard gecodeerd. | ||
+ | Wie dit project dus overneemt doet er goed aan deze waarden zelf eerst te bepalen. |
Versie van 19 nov 2013 11:58
Project: Electriciteitsmeter loggen | |
---|---|
Naam | Electriciteitsmeter loggen |
Door | Erin |
Status | Uitvoer |
Madskillz | Arduino, Openwrt, grafieken genereren, rrdtool |
Doel / Omschrijving | |
Electriciteitsverbruik volgens de 'slimme meter' opvangen en omzetten in grafieken | |
Alle Projecten - Project Toevoegen |
Meten is weten
Ik ben geïnteresseerd in het terugbrengen van mijn energieverbruik. Maar daarvoor wil je meten wat er verbruikt wordt. Enige google-actie leert dat het mogelijk is om een grafiek te genereren die zó nauwkeurig is, dat je individuele apparaten aan- en uit kunt zien schakelen. Dit project gaat dus om het meten van het totale verbruik via de electriciteitsmeter en wel zeer nauwkeurig.
Onderdelen
Huis electriciteitsmeter
Ik gebruik de digitale meter die in Arnhem als proef is geïnstalleerd toen je nog naar de gevangenis kon worden gestuurd als je het ding weigerde. De meter heeft twee lampjes die een korte puls geven: 1000 impulsen per kilowattuur. Het ene lampje meet reactief vermogen, het andere het echte vermogen. Ik ben geinteresseerd in het echte vermogen. Ik wil dus lichtflitsjes tellen.
Sensor op de meter
Ik wilde zeker weten dat de sensor snel genoeg was. Ik heb deze fotodiode gebruikt: http://dx.com/p/diy-photosensitive-diode-module-blue-black-200148 Er is een digitale en een anloge uitgang. De digitale klapt om als de sensor een - met de blauwe potmeter - instelbare waarde overschrijdt. Ik gebruik echter de analoge output, en ik detecteer de puls in de Arduino. Het lichtje brandt zwak, maar deze sensor pikt het goed op. Donker geeft waarde 1023; en tijdens een puls gaat de waarde omlaag tot rond de 740. In fel licht daalt hij tot vlak boven de 20.
De Arduino
Ik gebruik een gekloonde Arduino Nano. Dit is de kleinste Arduino die ook een USB poort aan boord heeft. De Arduino detecteert en telt de lichtflitsjes. Met wat proefcode bleken de flitsjes 9-12ms te duren; hij telt een puls als een flitsje tussen de 5 en 20ms duurt. Voor de compleetheid zit er wat fout-detectie in de pulsdetector: Korter dan 5ms, dan telt hij geen puls maar een storing ('fluke') en langer dan 20, dan telt hij geen puls maar 'teveel omgevingslicht'.
Rapportage
De Arduino rekent het vermogen als volgt uit: De meter geeft 1000 pulsen per KWh, dat is 1 puls per 1Wh, is 1 puls per 3600 Joule. Elke puls is dus 3600 Joule verbruikt. Dus (aantal pulsen) x 3600 Joule / (tijdsinterval 5 minuten) = vermogen. De Arduino rapporteert via de seriële poort wat het verbruikte vermogen is, een truc die ik van de Space heb afgekeken. Dit doet hij één keer per 5 minuten.
OpenWRT Router
De Arduino kan aan een miniPC gekoppeld worden maar die kost me veel te veel stroom. In de meterkast bevindt zich ook mijn router, die een USB poort heeft én OpenWRT draait. Die blijkt naar de Arduino te kunnen luisteren. De router draait OpenWRT 12.09.
Seriële verbinding
De volgende pakketten zijn geinstalleerd om het mogelijk te maken:
- kmod-usb-acm
- kmod-usb-ftdi
- kmod-usb-ohci
Ik kwam er achter dat een Arduino Uno de module kmod-usb-acm nodig heeft, maar de Arduino Nano een andere seriële chip heeft; die heeft kmod-usb-ftdi nodig. Als je de juiste module hebt geïnstalleerd, kun je in de /dev de Arduino zien:
- /dev/ACM0 (Arduino Uno) of
- /dev/ttyUSB0 (Arduino Nano).
Als dit device ontbreekt is de juiste kernelmodule nog niet geïnstalleerd.
Grafieken:
Hiervoor ga ik RRDTOOL gebruiken. Dit is in progress. Een grafiek van 600 pixels met één meetpunt per pixel gaat 600x5 = 3000 minuten omvatten. Da's genoeg voor ruim twee dagen. De grafieken worden weggeschreven in de /tmp in de router. Deze directory is gemount in RAM, dus dat vergt geen flash-wear&tear. De grafieken moeten dan nog geserveerd worden. Mogelijk kan dat met rrdtool-cgi. Ook dat is in progress.
Software
De software kan ik hier posten, ter leering ende vermaeck. Algemene problemen die moesten worden opgelost zijn:
- RRDTOOL moet op vaste tijdstippen een meting ontvangen.
- pulsdetectie
Vaste tijdstippen: tijd-interrupt? Delay?
De Arduino staat 99% van zijn tijd maar één ding te doen: Heel hard op een puls te wachten. Toch moet hij om de 5 minuten (instelbaar) rapporteren, ongeacht of hij even op een puls staat te wachten.
Een delay kan in elk geval niet worden gebruikt omdat de arduino echt naar de output van de sensor moet kijken. Een Interrupt heeft twee nadelen:
- de code is complex; De interrupt-tijd is veel korter dan 5 minuten. In plaats daarvan moet de interruptcode bij elke aanroep checken of hij al moet rapporteren
- het is niet te controleren wanneer een interrupt wordt aangeroepen, terwijl je liever niet wilt dat hij net tijdens een puls-detectie valt. De puls kan dan mogelijk niet goed gedetecteerd worden en deze situatie is bovendien zeer moeilijk te testen.
De oplossing is simpel en als volgt: De 5 minuten heet een rapportage-interval. De starttijd van een interval wordt onthouden. Tijdens het wachten op een puls wordt gechecked of dit interval al is verstreken.
Pulsedetectie
Een puls duurt kort en de lichtflits is niet heel fel. Eerst is experimenteel vastgesteld hoe lang hij duurt en welke waarde op de analoge pin krijgt tijdens een lichtflits. De code om de puls te detecteren wordt dan:
- Markeer starttijd
- loopje: while (Waarde op analoge pin zegt: lampje is aan, EN de verstreken tijd is niet langer dan de maximale pulstijd)
- bepaal pulslengte = huidige tijd - starttijd.
Bepalen van de tijd gebeurt met millis(). De gebruikte berekening heft de wraparound van 2^32 op. Let op de bepaling die de while-loop onderbreekt na 20 milliseconden (maximale pulsduur). Als de sensor wordt blootgesteld aan omgevingslicht blijft de software dus niet hangen.
Wat hij niet doet is dynamisch bepalen wat de grenswaarden zijn voor wel of geen puls, rekeninghoudend met omgevinslicht. Dat zou extreem cool zijn, en de huidige oplossing is goed genoeg. De waarden zijn experimenteel bepaald en daarna (met enige marge) hard gecodeerd. Wie dit project dus overneemt doet er goed aan deze waarden zelf eerst te bepalen.