k |
|||
Regel 19: | Regel 19: | ||
More information about the [[Power]] setup is at its own wiki page. | More information about the [[Power]] setup is at its own wiki page. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
+ | |||
== The code == | == The code == |
Versie van 7 mrt 2012 15:11
Project: Power Measurement | |
---|---|
Naam | Power Measurement |
Door | BugBlue |
Status | Uitvoer |
Madskillz | Cables, elektronics, code, rrdtool |
Doel / Omschrijving | |
Measure the power at the space. | |
Alle Projecten - Project Toevoegen |
The setup
We have a power meter which outputs 10 pulses per kWh. Contact closes for 60mS each pulse.
The meter is connected to an arduino:
- The meter switch contact is connected between pin 2 (interrupt 0) and ground.
- 100nF capacitor across meter switch, 1k pullup resistor on pin 2
at the moment that the power meter spits out an pulse we receive an interrupt, the capacitor makes sure it's only a real pulse (has some real length) and makes sure the arduino only gets 1 interrupt at the moment of a pulse instead of multiple due to noise while it switches.
More information about the Power setup is at its own wiki page.
The code
volatile unsigned long int0counter=0; void int0(); void readall(); long pulseCount = 0; unsigned long pulseTime,lastTime; double power; int dopulse; int ppwh = 10; // actually this gets kwH for our equipment ;) void setup() { int0counter=0; Serial.begin(19200); pinMode(2, INPUT); pinMode(3, INPUT); attachInterrupt(0,int0,RISING); interrupts(); } void readall() { Serial.print("Sensors "); Serial.print(power); Serial.print(" "); Serial.print("\r\n"); } void int0() { if(dopulse && millis() > pulseTime+500) { dopulse=0; lastTime = pulseTime; pulseTime = millis(); power = (3600000.0 / (pulseTime - lastTime))/ppwh; } } void loop() { dopulse=1; readall(); delay(1000); }
The output
The output is spits out over a serial (USB) line to a PC we happen to have very near our power meter (it has some other purposes too). The output lists the average usage of power measured at the moment in time. However due to the fact how we measure:
- we know the time (X seconds) between this interrupt and the previous.
- calculate the power usage in kWh because we used 1/10th kWh in X seconds.
you cannot store this number in rrd every second. That would mean that you store false data. If you assume that we use 1 for some time, and very shortly 3600 and again 1 for a long time we would save 3600 at the point in time we actually use 1.
However we want to have very detailed information at our fingertips (somebody already lost a lot of data in the past).
The solution is to create an rrd with a very long 'unknown' time. rrd will fill this part with the value you write later. We only update rrd at the point in time that we receive a new value.
Meanwhile it also collects temperature measurements which get stored every second, this means there is a very little shell script that does the trick:
#!/bin/bash OP="" stty -F /dev/ttyUSB0 19200 cat /dev/ttyUSB0 |grep --line-buffered ^Sensors|while read -r i xxxx w0 xxx crap; do if [ "X$OP" != "X$p0" ] ; then echo "update rrd2" rrdtool update power2.rrd N:$w0 OP="$p0" fi # some other stuff done
The rrd get's copied over to the internetz every 5 minutes if needed to ensure a very quick loading at the website.
Results: https://hack42.nl/spacestate/power/
Power meter reading
The (prediction) about the display of the power meter is very simple: At one point in time (2 march 2012 11:50) someone took a reading (22727.6), the rest is a simple calcutation of the average usage since then multiplied by the time. rrdtool needs at least 9 (real) lines of output to do this.
The oneliner:
#!/bin/bash rrdtool xport -s 1330685400 -e `rrdtool last power2.rrd` -m 10 DEF:p0=power2.rrd:p0:AVERAGE XPORT:p0:test|grep '<row>'|\ grep -v NaN|sed -e 's%</v></row>%%;s%.*<v>%%'|awk '{sum += $1} END { printf ("%.1f", 22727.6 + sum / '`\ rrdtool xport -s 1330685400 -e \`rrdtool last power2.rrd\` -m 10 DEF:p0=power2.rrd:p0:AVERAGE XPORT:p0:test|grep '<row>'|\ grep -v NaN|wc -l `' * ('`rrdtool last power2.rrd`'-1330685400 )/3600 ) }'