Controlling program iteration time on picaxe 08m2

Barry84

New Member
Hi,

I'm working on a project in which I measure two signals using the adc10 command and convert these to current in mA and voltage in mV. I then calculate a power in mW by multiplying voltage and current together.
What I'd like to do next is to integrate the power measurement using a known, constant time step to calculate energy in mWh. In order to do this correctly, I need to be able to control the program's iteration time so that it is equal to the constant value used in the calculation. I would like to be able to specify an iteration time with a resolution of say 10ms (so 10ms, 20ms or 110ms etc. would be possible iteration times). The time required for program execution shall then be some fraction of the iteration time, and the next iteration is not started until the time for the current iteration has elapsed i.e. having executed the entire program, the PicAxe waits for the remainder of the time before continuing with the next iteration. Below is my program, in which I assume for the moment that the iteration time is 1 second.

Code:
#Rem
################################################## #######
# Current, voltage, power and energy meter.
# B.Dolan July 2016.
################################################## #######

This module measures current and voltage, and from these
calculates power and energy.

#endrem

Start:
SYMBOL mAmp = W0
SYMBOL mVolt = W1
SYMBOL mWatt = W2
SYMBOL mWattSeconds = W3
SYMBOL mWattHours = W5
SYMBOL mWattHeadroom = W6
SYMBOL mWattHoursLessThan18 = W7

Main:
FVRSETUP FVR2048 'Set reference voltage to 2.048V for battery operation.
ADCCONFIG %011
readadc10 C.1, mAmp
readadc10 C.4, mVolt

#Rem
Current --------------------------------
Current (A) = 2.048*ADCin/1024 = ADCin/500.	
Current (mA) = 1000*ADCin/500 = ADCin*2.
Max current = 1024*2 = 2048 (mA).
Resolution = 2 (mA).
#endrem
mAmp = mAmp*2	  

#Rem
Voltage --------------------------------
R1 = 30kOhm, R2 = 5kOhm => Vin = Vout*7. 
Vout (V) = 2.048*ADCin/1024 = ADCin/500.
Vout (mV) = 1000*Vout = 1000*ADCin/500 = ADCin*2.
Vin (mV) = Vout*7 (mV) = ADCin*2*7 = ADCin*14.
Max voltage = 1024*14 = 14336 (mV).
Resolution = 14 (mV).
#endrem
mVolt = mVolt*14    

#Rem
Power = Voltage*Current ----------------
Credit to PicAxe forum member 'hippy' for this 
little trick here.
#endrem
mWatt = mAmp*34**63164
mWatt = mVolt*2**mWatt

#Rem
Energy meter --------------------------
Assume code executed with a cycle time of 1 second.
Assuming the power remained constant over the 1 second interval, this implies that
the instantaneous power measurement is also the accumulated 
energy over the past interval of 1 second, with units of mWs (milliWatt-seconds).
Energy in mWs will quickly become a huge number, so we want energy in mWh.
3600 is the number of seconds in one hour => mWh = mWs/3600.
64800 is the highest integer number less than 65536, which when divided by 3600, 
results in an integer value.
2^16 = 65536 -> 65536/3600 = 18.2 -> Round(18.2) = 18 -> 3600*18 = 64800.

Check how many more mWs we can count before exceeding our limit,
then compare this value to the current power (which is also energy in mWs) reading.
Note: mWattSeconds <= 64800 for all time.
#endrem

mWattHeadroom = 64800 - mWattSeconds
IF mWattHeadroom < mWatt THEN 
	'If we don't have enough 'headroom', then increment the counter (meaning we have
	'filled our quota of 64800 mWs, which equates to 18 mWh)...
	mWattHours = mWattHours + 18
	'..and store the amount of overflow in mWs.
	mWattSeconds = mWatt - mWattHeadroom
ELSE
	'If we do have enough 'headroom', then add the current power (which is also energy in mWs)
	'reading to the previously accumulated energy value to give the total.
	mWattSeconds = mWattSeconds + mWatt
ENDIF

'mWh = mWh + mWs/3600 = mWattHours + mWattSeconds/3600
mWattHoursLessThan18 = mWattSeconds/3600
mWattHours = mWattHours + mWattHoursLessThan18

sertxd("Current [mA]: ",#mAmp,CR,LF)
sertxd("Voltage [mV]: ",#mVolt,CR,LF)
sertxd("Power [mW]: ",#mWatt,CR,LF)
sertxd("Energy [mWh]: ",#mWattHours,CR,LF)

goto main
I've searched a lot on the forum and on the internet in general. It seems one way to achieve a fixed iteration time is to use a crystal oscillator or real time clock to trigger code execution using an external interrupt. There seems to also be another, less accurate way using the internal RC oscillator of the PicAxe itself and the Timer1 command. As simplicity is more important than accuracy for this project, I would prefer to use the latter method, if possible.

I found this thread on the topic http://www.picaxeforum.co.uk/showthread.php?5824-Timer1-a-possible-simple-use-for-it/page2 and tried the test example posted by forum member Jeremy Leach. The test program should output 'Paused = Xms. Measured = Yms.' where X and Y are approximately equal and increasing with each program iteration. However, when I ran it in the simulation mode of my PicAxe Editor V6.0.8.8, I only saw 'Paused = Xms. Measured = 0ms.' on the serial terminal, i.e. only X was increasing. When I downloaded the program to my PicAxe 08m2, the following was displayed on the serial terminal:
Unbenannt.PNG

Can someone please advise me as to why the test program didn't work for me?
Could the Timer1 method allow me to achieve a constant iteration time on an 08m2?

Hope someone can help. Thanks.
 

hippy

Technical Support
Staff member
Can someone please advise me as to why the test program didn't work for me?
That code came from 2006/2007, it is not clear which PICAXE chip it was intended for, so there is no guarantee it will work with any current PICAXE chip. The code uses PEEK and POKE commands for access to SFR where X2 and M2 chips would use PEEKSFR and POKESFR. Most direct on-chip hardware interaction has to be tailored for the specific PICAXE type or at least its family type.

Could the Timer1 method allow me to achieve a constant iteration time on an 08m2?
It may be possible but I do recall that there are issues with doing that on the M2 where the firmware uses the timer for its own purposes which causes some unwanted interactions. It may be possible to work round those issues but it would probably be easier to be able to avoid them.

It is possible with a 20X2 ...

http://www.picaxeforum.co.uk/showthread.php?13983-20X2-with-the-timing-accuracy-of-a-crystal

Note that PICAXE Simulation is a software simulation, not a hardware emulation, so simulation of code using on-chip timers will not give the results one would see with a physical chip.

And welcome to the PICAXE forum.
 

AllyCat

Senior Member
Hi,

Yes, welcome to the forum. Unfortunately, doing some things (particularly timing-related) with PICaxe are (IMHO) more difficult than using assembler! ;)

However, I believe that "synchonising" to a 20ms interval (or 10 ms with some higher clock rates) can be moderately easy. The internal clock is fairly accurate and can be "trimmed" to much better than 1% accuracy by using the CALIBFREQ command, if required. Most PICaxes (certainly the 08M2) operate the hardware "Timer 1" with an overflow every 20 ms (to drive servos and as a prescaler for the "time" variable).

What you could do is repeatedly PEEKSFR the Timer 1 (High Byte) until it overflows and then start your measurement event. The full 16 bits value overflows from 65535 to a "reload" value of 45536 (because it has a 1 MHz update rate when a 4 MHz master clock is used). You can find the SFR addresses (and perhaps more useful background information) in the code section of my post #12 in this thread. Just ask, if the method looks useful but you need more help/explanation.

Also, to endorse what hippy said: You MUST use a real PICaxe chip and not the Simulator for any timing-related testing.

Cheers, Alan.
 

BESQUEUT

Senior Member
I need to be able to control the program's iteration time so that it is equal to the constant value used in the calculation.
We need to think backwards : do not try to have a constant round value for the iteration time but instead think to measure this time and do the calculation from this value.
You can count iterations and measure time with the Time special variable. Use the greatest SetFreq for your Picaxe.
You also can use an interrupt to inc a counter every N ms, and read this counter in the main loop.
 
Last edited:

Barry84

New Member
Hey, I just want to thank you all for your replies on this. It's already a while ago, but I haven't had any time for the project since. Looking forward to trying out your suggestions, and will get back you when I make some progress.
 
Top