Electricity consumption meter - again

lbenson

Senior Member
> more than a pulse a second

Since a picaxe at 4mHz can execute about 2000 instructions per second, you shouldn't have any trouble keeping up with your original scheme of interrupting with each pulse and recording the time (perhaps in tens or hundreds of milliseconds) since the previous pulse. This assumes that you have some place to log the data quickly, and some way to record the time (using a timer and accounting for rollovers if necessary). If the ticks came too fast, you could up the speed.

Your main loop (which gets interrupted) could be one which keeps the time and occasionally sends the data off to your main recording and logging PC or other device.
 

hippy

Technical Support
Staff member
An 'instantaneous energy used' meter would be a good starting point. That should be relatively straight forward with quite simple maths but would need some thinking about to actually do that maths.

I'd aim for a very simple system; whenever a new pulse arrives, note the time ( 't' seconds ) since last pulse, reset and start the timer going again. The instantaneous power is ...

kWh = 3600 / t

So if t=0.24s that's 15kWh, t=3.6s that's 1kWh, t=3600s is 1Wh, and so on.

At high power the pulses will be coming thick and fast ( well, not that fast ) so nothing to do other than to display the value calculated as above. But you don't always want to wait for the next pulse as it'll continue show whatever was used last even if that was so high it's blown the fuse !

As long as the previous 't' has been stored, every second that 't' can have a second added to it and the kWh=3600/t calculation done again. That way the usage will decay which will be more realistic. With only 1000 pulses per kWh it's just not possible to quickly tell what a low power is accurately, just something one has to live with and it's the same issue with bike speedo's when just crawling along.
 

bpowell

Senior Member
An 'instantaneous energy used' meter would be a good starting point. That should be relatively straight forward with quite simple maths but would need some thinking about to actually do that maths.

I'd aim for a very simple system; whenever a new pulse arrives, note the time ( 't' seconds ) since last pulse, reset and start the timer going again. The instantaneous power is ...

kWh = 3600 / t

So if t=0.24s that's 15kWh, t=3.6s that's 1kWh, t=3600s is 1Wh, and so on.

At high power the pulses will be coming thick and fast ( well, not that fast ) so nothing to do other than to display the value calculated as above. But you don't always want to wait for the next pulse as it'll continue show whatever was used last even if that was so high it's blown the fuse !

As long as the previous 't' has been stored, every second that 't' can have a second added to it and the kWh=3600/t calculation done again. That way the usage will decay which will be more realistic. With only 1000 pulses per kWh it's just not possible to quickly tell what a low power is accurately, just something one has to live with and it's the same issue with bike speedo's when just crawling along.
Hi Hippy,

Thanks for these formulas and ideas...already, you've found a more graceful way to solve the problem than I was thinking!

I'm sitting up late trying to work out the math...since Picaxe doesn't do 3600 / .24...I'm trying to figure out an alternative.

I'm also establishing to realistic windows, so I don't have to go too crazy with the code....I'm okay with a resolution of 10th of seconds...(Frankly, I'm okay with a resolution of "seconds" but I can see that at times, the flashes come in faster than that...so I figure dividing a second into 10's would make it easier.

However, I need to make sure the value I send does not exceed 65,500 (the size of a word), and I need to be able to do some simple math on the receiving side to figure out "real time" kw/h usage...and maybe even plug in my electric companies kw/h cost...and have the picaxe say, "You're spending..."

So, it's a work in progress.

I've moved the hardware for the IR Led sensor from breadboard to circuit board...still works. That's a start!
 

Dippy

Moderator
Why don't you constantly measure time between pulses and use an interrupt to pop out and deal with request.
Then you can send the previous time-between-pulses as he reply.
Therefore it will give a near-instant reply.
 

hippy

Technical Support
Staff member
If you keep the 2.4s readings in milliseconds you get 2400ms and the maths becomes -

Wh = 3600000 / t

which, to keep within PICAXE limits is the same as -

Wh = ( 36000 / t ) * 100

You may lose seme accuracy that way but it can be clawed back, say multiply 't' and 3600 by 1.5 -

t = ( t / 2 ) + t
Wh = ( 54000 / t ) * 100

Or multiply by 1.75, better as you want the top value as close to 65535 as you can get it -

t = ( ( t / 2 ) + t ) / 2 ) + t
Wh = ( 63000 / t ) * 100

The resolution you want is really as large as possible, because only a small change in time can make a quite big difference in kWh consumption. I would expect milliseconds is good enugh but haven't looked at the numbers. You can store the number in the best unit which doesn't cause overflow and have a scaling factor to apply after doing the maths.

Once you have some hardware and some basic maths implemented it's just a case of thinking on 'how to' and trying things out, and you can observe the results.
 

bpowell

Senior Member
Update

Hi Gang,

Here's an update on how I'm coming with this project...the hardware is built and working (no RF just yet, but that's down the road)...the software is built and in testing...still a few quirks to work out.

I'm measuring 10 ms at a time, and incrementing a variable every 10ms by one...when a pulse triggers, I take that variable and send it out via serial...Haven't built the receiver yet...but it'll have code along the lines of:

Receive 240 (2.4 seconds)
w/h = (36000 / 240) * 10 = 1500 (1.5 kw/h)

This gives me a resolution of about 10 w/h...which I think is okay.
Receive 241 (2.41 seconds)
w/h = 1490 (1.49 kw/h)

What I'm trying to work in now is a delay...even though I'm saying "real-time", in actuality, I imagine after a few days of "real time" monitoring, I'd probably like to throttle back to an update every ten seconds or so...no need hogging up the 433 mhz band with an update or two every second! however, whenever I sneak a delay anywhere in my code; I get a real odd reading...I have another Picaxe blinking an IR led every 350 ms or so...so I'll get "35, 34, 35, 34," which is okay...but then when I add a delay, I get, "35, 8, 34, 8, 35, 8"...so I'm still trying to figure that out.

So far though, so good!

Code is attached:

Code:
' Real Time Power Meter LED detector / Counter
' This will go on our power meter, and hopefully send data in the house for
' Real-time monitoring of power consumption
' 
' First, need a circuit to detect the IR LED and send clear logic signals
' To the Picaxe...may be onto something...
' Using a varient of a circuit found here: http://ciseco.co.uk/forum/viewtopic.php?f=15&t=59
' Will use INPUT 2 on the picaxe 8m, as it's a Schmitt Trigger level input
' Input is normally high, goes low on a pulse
' 
' Built for Picaxe 08M
' March 2010


' A Standard Picaxe 08M          
'                                       __________
'                           5V VCC   1- |        |- 8  0V GND
'                        Serial In   2- |        |- 7  Out 0 / Serial Out / Infraout
'             ADC 4 / Out 4 / In 4   3- |  08M   |- 6  In 1 / Out 1 / ADC 1
'                   Infrain / In 3   4- |        |- 5  In 2 / Out 2 / ADC 2 / pwm 2 / tune
'                                       ---------- 
' 

'  The LED Detector / Counter / Transmitter
'                                       __________
'                           5V VCC   1- |        |- 8  0V GND
'                        Serial In   2- |        |- 7  Serial Out
'                       LED Status   3- |  08M   |- 6   
'                                    4- |        |- 5  LED Flashing Trigger input
'                                       ---------- 
'
' Available Bytes: b0 - b13
' Available Words: w0 - w6
'
' Currently 168 Bytes out of 256




#Picaxe08m ' Instruct Compiler to use a Picaxe 08M Chip

' *** Declare Variables

Symbol LEDin = pin2	' Using input 2 as it's a Schmitt Trigger input, which has the logic
				' levels I need to make this work
Symbol LEDout = 4		' Something to blink and help develop circuit
Symbol ElapsedTime = w6	' b12 and b13 now unavailable due to w6
Symbol Countdown = w5	' b10 and b11 now unavailable due to w5
Symbol PreviousTime = w4	' Previous elapsedTime b8 & b9 now unavailable

' *** End Declare Section


' *** Start Init Section / set up variables

Low LEDout
ElapsedTime = 0
Countdown = ElapsedTime + 1500 	' Countdown is 15 seconds (give or take)

setint %00000000, %00000100 ' Set interrupt on input 2, going low (first #=input, Second #=mask)

' *** End Init Section



main:		' The Main program
	
		' Want to send an updaet every 15 seconds regardless of value change

	do while ElapsedTime < Countdown
		pause 10 ' wait 10 ms (may adjust for fine tuning later)
		inc ElapsedTime	'ElapsedTime = ElapsedTimei + 1
	loop


	gosub Update	' loop complete; so 15 seconds has elapsed with no pulse (or same freq)

	goto main	' Start over


interrupt:


	' ToDo: In here, need to take elapsed time, compare with previous value (to see if changed)
	' If changed, then transmit new elapsed time between pulses to serial (RF later)
	' If not changed, reset ElapsedTime counter and
	' And jump back to program
	If ElapsedTime = PreviousTime Then
		ElapsedTime = 0
	'	There's a little bug here; if for some reason, the flashes come in the same frequency
	'	(exactly) then there will be no updates until the frequency changes. As resetting
	' 	ElapsedTime means it will never be = or > Countdown 
	'	Will look and see if this is an issue down the road; initial testing indicates
	' 	it won't be a problem; value should always be changing...
	Else
		Gosub Update	' Send the new time...
		PreviousTime = ElapsedTime	'Reset the compare variable
		ElapsedTime = 0	' Reset Elapsed Time
	Endif
	
	do while LEDin <> 1	' Wait for interrupt condition to clear before re-arming
	loop

	setint %00000000, %00000100 ' Set interrupt on input 2, going low (first #=input, Second #=mask)
	
Return



Update:	' Here is where we transmit the time between pulses on serial

	high LEDout

	Setint OFF	' Turn the interrupt off to prevent it from triggering during x-mit

	sertxd("Elapsed Time Between Pulses: ",#ElapsedTime," centi-seconds",13,10)
	Gosub Reset_Countdown	' may be able to remove this later for space...


	do while LEDin <> 1	' Wait for interrupt condition to clear before re-arming
	loop
	
	setint %00000000, %00000100 ' Set interrupt on input 2, going low (first #=input, Second #=mask)

	low LEDout

Return


Reset_Countdown:	'This sets the 15 second count down timer...system should update every
			' 15 seconds even if no pulse is detected...elapsedtime will continue to
			' increment, so this will show decaying power consumption 
			' Until 11 minutes...where the counter rolls over...then the universe explodes

	Countdown = ElapsedTime + 1500
		if Countdown < ElapsedTime Then
			' What do do if roll-over? 65535
			' Roll-over means nearly 11 minutes have elapsed without a flash...
			' Either a power out, or I've gone crazy and unplugged EVERYTHING
			' Let's assume I'm crazy
		ElapsedTime = 0	' For the moment, just reset and start over...unlikely to see this event
		Countdown = ElapsedTime + 1500
	endif
	
Return


end
 

hippy

Technical Support
Staff member
What I'm trying to work in now is a delay... whenever I sneak a delay anywhere in my code; I get a real odd reading...I have another Picaxe blinking an IR led every 350 ms or so...so I'll get "35, 34, 35, 34," which is okay...but then when I add a delay, I get, "35, 8, 34, 8, 35, 8"...so I'm still trying to figure that out.
I haven't examined the code but did note you are using interrupts. If the PICAXE is in a PAUSE when the interrupt occurs it will prematurely abort the PAUSE. Something which follows that interrupted PAUSE and assumes it was as long as it was expected to be will be incorrect.

One simple solution to that is to have not one large PAUSE but a FOR-NEXT loop of shorter PAUSE which amount to the same. One of the PAUSE may get shortened but that is the most time you will lose.

Alternatively you need to use a mechanism which either does not interrupt or timing which is not affected by interrupts. As the pulses are so slow you should be able to get away without using interrupts, just use polling.
 

bpowell

Senior Member
I haven't examined the code but did note you are using interrupts. If the PICAXE is in a PAUSE when the interrupt occurs it will prematurely abort the PAUSE. Something which follows that interrupted PAUSE and assumes it was as long as it was expected to be will be incorrect.

One simple solution to that is to have not one large PAUSE but a FOR-NEXT loop of shorter PAUSE which amount to the same. One of the PAUSE may get shortened but that is the most time you will lose.

Alternatively you need to use a mechanism which either does not interrupt or timing which is not affected by interrupts. As the pulses are so slow you should be able to get away without using interrupts, just use polling.
Hi Hippy,

I'm off to work; but will hopefully have time to play around with code (sans hardware) at lunch.

This was my first go at using Interrupts...I really like the concept, but if they're not right for this application, then I can go to a for-next loop.

My understanding from the manual is if an interrupt triggers in a pause, when the interrupt returns, the pause will be completed regardless of the time remaining...my pauses are only 10ms...and the difference I was seeing in numbers (35 to 8 equals 350ms to 80ms...) 270 ms are lost...this is more than just one pause being shortened...so that's what was confusing me.

Last night, as I tossed and turned worrying about this project...(Well, really, I just fell asleep, but I wanted to be more dramatic)...I had a thought. pulses are coming in every 350 ms...which the sensor is recording well...however, when I add that 1000 second pause (or 15 seconds, whatever). when I release out of the pause, the system is dumped into "start counting" mode again, right in front of an incoming pulse...hence the small number....the next number is accurate, then the pause, then the short number again....maybe that's what's happening.

I had a couple of ideas...do the pause, then a do/loop waiting for a pulse before releasing back into the code...this would "sync" the pulses back up...or, having a pulse trigger the interrupt, then have the interrupt start the timer, and wait for another pulse...(meaning 2 pulses are needed for a measurement).

All of the above, as well as looking at a for/next loop will give me something to do at lunch and back at home!

Thanks again!

Brendan
 

SAborn

Senior Member
The easy solution is to put the project on hold till the 18mx2 hits the market as a multi tasking chip would do this job nicely.

I am currently building a amp/voltage data logger for a wind generator using a CT and get good enough results from the CT.
I also use the CT to generate a square wave to the line frequency to calculate the alternator rpm.

I had the Ct on my mains line to test it out on a known frequency and consumption and all works very well so far.

The problem with the meters is they are often not in the best location to record data from and then there is the problem with using a CT that it needs to be placed around the main neutral line so it will read all phases and all power used.

The CT is read with a opamp and 08m and my data is logged to a 12v computer that dose all the number crunching down to what ever decimal point you want.
I think there will be errors in any system but they will average out, and any log of power useage is far better than none at all.
 

MartinM57

Moderator
The easy solution is to put the project on hold till the 18mx2 hits the market as a multi tasking chip would do this job nicely.
Interesting. Where have you found what the multi-tasking abilities of the 18M2 are (and any limitations from what an ideal multi-tasking environment might be considered to have)?
 

hippy

Technical Support
Staff member
@ bpowell : I've had a better look at the code and it's far too complicated for me to work through so I expect that is maybe where the problem lies.

I think you need to greatly simplify what you have. Don't worry about lack of pulse timeouts to start with, have something simple which interrupts, records elapsed time, resets the timer and returns. Set a flag to say new data is ready, print out the recorded elapsed time.

I'd even go as far as saying drop the sensor and use a push button to get it all to work to start with. The following is what I'd start with and should work with either a button or your sensor to Pin 2 ( leg 5 ) of an 08M so should be compatible with your hardware. It looks for a rising edge interrupt to record elapsed time, ignores the falling edge though that is still handled through the interrupt. That can be changed to work the otehr way if needs be. It's not perfect, can lose up to 5ms on every interrupt and isn't a calibrated time loop but a good place to start -

Code:
#Picaxe 08M
#Terminal 4800

Symbol elapsedTime    = w0 ' b1:b0
Symbol recordedTime   = w1 ' b3:b2
Symbol interruptLevel = b4
       
interruptLevel = %000100
SetInt interruptLevel, %00100

Do 
  Do
    Pause 5
    elapsedTime = elapsedTime + 5
  Loop Until recordedTime <> 0 
  SerTxd( "Interval = ", #recordedTime, "ms", CR, LF)
  recordedTime = 0
Loop

Interrupt:
  If interruptLevel <> 0 Then
    recordedTime = elapsedTime
    elapsedTime = 0
  End If
  interruptLevel = interruptLevel ^ %00100
  SetInt interruptLevel, %00100
  Return
 

bpowell

Senior Member
@Hippy:

Wow! Very nice (and efficent code!) I'll download that tonight and do some playing! Thank you!

Taking an objective look, I can see how my program was a little elaborate...first things first; get it working!

I do have a question in your code though...maybe you can help me?

First you set the interrupt up:
interruptLevel = %000100
SetInt interruptLevel, %00100

So, if I'm reading this right, pin 2 will interrupt if it goes high.

Then, in the interrupt you have:
interruptLevel = interruptLevel ^ %00100
SetInt interruptLevel, %00100

Oh wait...I think I just figured it out while I typed...however, in the interest of full disclosure, I'll not delete my question, but explain what I think the answer is:

You are flipping the interruptLevel from 1 to 0 (so every other interrupt will be on the signal going positive...and only the positive interrupts are the ones the program uses to calculate duration. The level then gets flipped from 0 to 1 on the next pass.

The XOR threw me for a bit, but as I walked through it (3rd or 4th time) I got it!

Thanks Hippy and everyboty else! I'm new to this stuff, but it's sure a lot of fun to learn!

Brendan
 
Last edited:

hippy

Technical Support
Staff member
Yes - Spot on with the toggling of interrupt level ...

SetInt %00100, %00100 to look for a high, then
SetInt %00000, %00100 to look for the low, then repeats forever
 

davidwf

Senior Member
As the nights are getting longer again so my thoughts are turning to digging out the PICAXE stuff :rolleyes: ...... anyone progressed with this and got a working design up and running yet ?
 

Azza

New Member
I just came across your post, I have a completed and working Electricity Monitor, it uses a Picaxe 20x2 and results are sent by wireless (xbee) to my server. I have also just completed a stand alone receiver for the electricity monitor using Maximite and Xbee. Details of both these projects are available on my web page http://codenquilts.com.au/?page_id=97

Mike.
 
Top