20M2: PULSIN crashes with clock frequency below 2MHz.

AllyCat

Senior Member
Hi,

For part of my "project" I need to measure quite accurately the width of a pulse which occurs once every 48 seconds. Power consumption is very critical as it must run 24/7 on a pair of AA cells.

So, using PULSIN (and subsequently PULSOUT or COUNT) with a clock frequency of 31kHz, for the period between the pulses, seemed the obvious solution (since Sleep and Nap have such terrible tolerance timing errors). However, the code runs fine on the simulator and with a clock frequency of 2MHz and above, but crashes (repeatedly resets to the start address) at 1MHz and below.

Code:
#picaxe 20m2
begin:
	sertxd ("**START** ")
measure:
	do
	sertxd ("Loop ")
	setfreq m1
	pulsin b.7,0,delay
	setfreq m4
	sertxd (#delay," @m1 ")	
	loop

Gives an Output:    **START** Loop **START** Loop **START** Loop 2503 @m1 Loop **START**
    but at 2MHz:    **START** Loop 0 @m2 Loop 0 @m2 Loop 0 @m2 Loop 5025 @m2 Loop
I've found a couple of old threads which suggest that the watchdog timer is responsible. In those threads the terms "underclocked" and "hacked speed" are used, but 31kHz is a completely "legitimate" clock speed for the M2 series. I do see that the manual only explicitly refers to "Effect of Increased Clock Speed" for PULSIN, but I would have expected at least a comment if the command is flawed at lower frequencies.

Is it the Watchdog Timer that is responsible and are there any workarounds?

Thanks,

Alan.
 

Technical

Technical Support
Staff member
Yes, the watchdog will reset the chip after about 2.1 seconds or so. That is by design, it is not a 'flaw', that is actually the whole purpose of the watchdog. So if your pulsin command lasts longer than 2.1 s before the pulse starts it will timeout. So the main problem, as shown by your 2MHz results, is that your pulsin is often timing out (value 0 = timeout). Ideally you want a program, at any speed, that never replies with a pulsin value of 0.

However if the pulses are always 48s apart you will be far better off sleeping anyway, the accuracy of sleep is not as bad as you seem to think. Sleep for, say, 46 seconds (try 'sleep 22' as a starter) and then start waiting for the pulse via pulsin. This will prevent the timeout that is the main root of the problem. You will be able to do this at various different clock speeds.
 

AllyCat

Senior Member
Hi,

Thanks for your reply, although sadly not what I wanted to hear. Normally the user can disable or "feed" the watchdog hardware, but as I understand it, the watchdog is not part of the User Environment but only under the control of the operating system. So IMHO it is a "flaw" (I refrained from using the term bug) if it activates when using only documented commands and parameters.

My information on the "Sleep" tolerance was based on the PICaxe User Manual which says (for Nap) "this time is subject to -50 to +100% tolerance. The external temperature affects these tolerances and so no design that requires an accurate time base should use this command." The 48 seconds period is absolutely accurate (crystal controlled) so the "calibration" is actually for the PICaxe clock(s), because my application may encounter large variations of temperature and voltage. The pulse itself is between a few and a few hundred ms and needs to be read to within a few percent accuracy (where ideally each "few" means two).

I had actually hoped to use COUNT (with a 31kHz clock, as the signal in question has a maximum frequency of a few tens of Hz) during the normal "waiting" period, and this (according to the manual) doesn't appear to suffer the same problem? But in any case, my code above was a "third attempt", after abandoning the first two trials which were based on "Sleep/Nap":

Code:
	w2 = 0
	w4 = 50			; About 30 seconds nominal delay (Nap 5)
main:
	PULSIN b.7 , 0 , w3          ;  Measure the required pulse
	inc w2			; Count the number of timeouts
	if w3 = 0 then main          ; Loop back if no pulse detected
	if w2 > 3 then inc w4 	; Increase delay if the wait was too long
	else if w2 < 3 then dec w4 
	endif
	....                                 ; Process the pulse data
	w2 = 0
	for b1 = 0 to w4
	nap 5                               ; About 600ms delay per loop
	next b1
	goto main
The issue with the above code is that if the leading edge of the pulse occurs during the inc w2 or loop back, then the pulse will be either incorrectly measured, or more likely missed altogether. Another issue with 24/7 operation is that if there are any "trap doors" like this in the code then they will surface sooner or later.

My second attempt reduces the possible dead (undetected) interval, but I doubt if it completely closes the trap door (unless PULSIN has been very carefully encoded)? :

Code:
main:
	PULSIN b.7 , 0 , w2            ;  Measure pulse if it's early
	PULSIN b.7 , 0 , w3            ;  Measure pulse if it's correct
	PULSIN b.7 , 0 , w5            ;  Measure pulse if it's late
	if w2 > 0 then dec w4            ;  Decrease delay if pulse was early
	else if w3 > 0 then
	w2 = w3                           ; Required pulse time into w2  
	else if w5 > 0 then 
	inc w4 	                        ;  Increase delay if pulse was late
	w2 = w5
	else goto calibrate              ; Try to work out what delay IS required ! 
	endif
	for b1 = 0 to w4
	nap 5                               ; About 600ms delay per loop
	next b1
	goto main
calibrate:    
	?????
What I really need to do is measure the time interval from the "end of delay" to the leading edge of the pulse (so that the delay can be trimmed), and then measure the width of the pulse itself (using pulsin), but as far as I can see that's not possible with an M2. The 20M2 is my development tool, but I'd expect the "final" device to be a 14M2 or even 8M2, so an X series would be a step too far.

Any other ideas?

Thanks,

Alan.
 

Buzby

Senior Member
Hi Allycat,

Another idea is 'wake on interrupt'. ( This works on X2, but I'm not sure about M2. Edit : Sorry, I missed the bit about you not wanting to use an X2 )

If all you need to measure is the width of the pulses, and not the time inbeteween, then you can sleep the whole time between pulses.

Cheers,

Buzby
 

hippy

Ex-Staff (retired)
The key here seems to be to ensure the PICAXE is awake and ready to see the pulse when it occurs and be in low-power mode unless measuring the pulse and subsequently processing, or to find a means of reading the pulse while not having the watchdog cause a hardware timeout and a subsequent reset. It should be possible to combine both for lowest power operation.

The internal hardware counters of the PICAXE can be accessed via PEEKSFR and POKESFR and it should be possible to use those in the background to measure a pulse, while running at 31kHz, and keep the watchdog from firing, adding NAP or SLEEP commands used between intervening pulses to reduce power consumption.

All the M2 devices have Timer Gate Control which will help in pulse timing so, though one would have to check which pins hardware signals are brought out to ensure suitability, the M2's should be able to do the job envisaged. I'm not sure how being a negative-going pulse will affect things, and that would have to be checked in a datasheet.

Being a negative going pulse; what is its voltage and how much current can the signal itself supply ? There might be an opportunity to use the signal itself to power the PICAXE or float charge the batteries.
 

hippy

Ex-Staff (retired)
Using the internal Timer1 seems to be the way to go. With a gated pulse and internal 31kHz clock that's timing a 0 to 2 second pulse to around 32us resolution.

Proof of concept code attached. Most of the time it's at 31kHz waiting for the pulse to have happened, only at 4MHz to output the result and set up for the next. Didn't measure current consumption and that can be lowered by turning the timer off, adding SLEEP or NAP after receiving the pulse.The timer and gate control set up should be done better but it's good enough for proving the concept.

There are some neat tricks with gate control I haven't previously explored; having it time a single pulse then stopping the timer automatically, being able to time both the low and high parts of a waveform consecutively.
 

Attachments

AllyCat

Senior Member
Hi Hippy,

That's much more encouraging. I must admit that one of my reasons for using a PICaxe was to avoid having to wade through pages of SFR bit-tables, but beggars can't be choosers and it doesn't seem that I'll need to peek (and maybe poke) much deeper than Bank 0 for Timer 1 and maybe Bank 1 for the Watchdog.

You almost seem to be a mind reader. There are actually several pulses in the complete system but the primary one is indeed "high" for > 99% of the time and I do intend to steal some of the power to run the PICaxe. Consumption appears to be about 25uA at 31kHz which meets my target. I guess the PICaxe Manual must be out of date as I see that the Sleep/Nap timer is driven from the 31kHz clock, which I hope isn't as bad as -50% to +100%.

Thanks for the proof of concept code, perhaps in exchange I should explain the background to the project. It's intended as an "add on" to overcome some of the limitations of the external sensors of a mass-produced wireless "weather station". Hence the potential wide temperature range, limited power availability and non-negotiable data/pulse format. 48 seconds is the period between radio transmissions and the "background" counter is for revolutions of the windspeed cups. The variable width pulses are from a very simple A/D converter (ramp on a capacitor converting current to a timer count) for temperature (a NTC thermsitor) and wind direction (variable resistance).

Cheers,

Alan.
 

AllyCat

Senior Member
Hi,

Well, the simple solution to the original problem seems to be to switch off or extend the WD timer during the (slow clocked) PULSIN command. Either decrement the WatchDog Timer CONtrol SFR to disable it, or add 2 to double the timeout (or more):

Code:
symbol    WDTCON = $37			; Watchdog Control (SFR 97h,bank 1)
	.....
	peeksfr WDTCON,b4
	b5 = b4 + 2			; Double WDT/sleep to 4 secs  OR:
;;	b5 = b4 - 1			; Disable WDT/sleep (bit0=Enable)
	pokesfr WDTCON,b5
	setfreq m1	
	pulsin b.7,0,delay
	setfreq m4
	pokesfr WDTCON,b4		; Restore to 2 secs
Incidentally, both the "examples" for calculating M2 peek/poke SFR addresses in the User Manual appear to be wrong.

However, for my longer term aims the Gated Timer, or even the Timer Capture registers, approach looks more interesting. The issue is which PICaxe commands potentially reset or corrupt the Timer1 registers? Is there any documentation?

So far I believe I have ascertained that PAUSE, SLEEP and NAP don't corrupt Timer 1 (may stop it) but that PULSOUT and COUNT do. However, what surprised me is that SERTXD does appear to corrupt/reset Timer 1, but only if there is a # in the formatting. :confused:

Any comments?

Thanks, Alan.
 

hippy

Ex-Staff (retired)
Incidentally, both the "examples" for calculating M2 peek/poke SFR addresses in the User Manual appear to be wrong.
In what way ? They both look correct to me ...

As location can only take the value 0-255 the value for M2 locations taken from the Microchip datasheet are created as follows:
Bit 7-5 Memory Bank $00-$07
Bit4-0 Addresses $0C to $1F on this bank
WDTCON is register $17 of bank 1, so bit 7-5 is 001 and bit 4-0 is 10111, concatenated that is %00110111 or $37
 

Technical

Technical Support
Staff member
However, for my longer term aims the Gated Timer, or even the Timer Capture registers, approach looks more interesting. The issue is which PICaxe commands potentially reset or corrupt the Timer1 registers? Is there any documentation?

So far I believe I have ascertained that PAUSE, SLEEP and NAP don't corrupt Timer 1 (may stop it) but that PULSOUT and COUNT do. However, what surprised me is that SERTXD does appear to corrupt/reset Timer 1, but only if there is a # in the formatting. :confused:
It looks like your tests may be flawed, what are you doing to test this?

The main internal purpose of timer1 on M2 parts is to maintain a 20ms background tick which is used by both the incrementing 'time' variable and 'servo' command pulses. Internal features like this are generally designed to be used exclusively by the PICAXE firmware. But the first step to hack it for your own use would be to issue a 'disabletime' command to ensure the background 'time' feature is not trying to use it.
 

AllyCat

Senior Member
In what way ? They both look correct to me ...
Hi Hippy/Technical,

Maybe I have an out-of-date manual (2) but mine says (under peeksfr/pokesfr):

"e.g. BAUDCON, address 01Fh on bank 3, becomes %011 11111
Example:
peeksfr $9B,b1 ; Read OSCTUNE into variable b1"


IMHO the BAUDCON address should be %0111 1111 (sorry it looks as if I was being pedantic, I thought I had only seen 4 '1's in the second "nibble")
and OSCTUNE is the address "above" the WDCON, i.e. at $38 (098h in bank 1).

You could be correct Technical, it was quite a "quick and dirty" test. I started just peeking the Timer 1 SFRs and reporting via SERTXD in a loop but always got the same value. So I tried peeking twice with a variable delay and a "test command" between them. If the time between the two peeksfrs changed then I assumed the sample instruction was OK, if I always got the same delay then I assumed the instruction was "corrupting" the Tmer 1 registers.

Code:
	for delay = 1 to 5
	peeksfr TMR1L,b10,b11	; Read w5
	for b2 = 0 to delay
	next b2
	pause 100				; Sample Instruction under test
	peeksfr TMR1L,b12,b13	; Read w6
	w6 = w6 - w5
	sertxd ("Delta= ",#w6,cr,lf)
	next delay
Maybe it depends if a "tick" occurs during the test (but the results seemed consistent). I'll try some more when I next have a PICaxe connected to my PC.

Thanks, Alan.
 
Top