Uit Hack42
< Gebruiker:BugBlue(Doorverwezen vanaf Power Measurement)
Ga naar: navigatie, zoeken
Project: Power Measurement
Schroefje24.png
Schroefje24.png
Schroefje24.png
Schroefje24.png
Power Measurement Picture.jpg

Power Measurement

Naam Power Measurement
Door BugBlue
Status Afgerond
Madskillz Cables, elektronics, code, rrdtool
Doel / Omschrijving
Measure the power at the space.
Alle Projecten - Project Toevoegen
File:Power Measurement_Picture.jpg noez

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 ) }'