SETFREQ/PULSIN crash

Further to the very helpful discussion in my previous thread "Interrupt advice please?", I've been trying to get some lower speed measurements as well as the (apparently) accurate measurements I'm getting which range from about 23 rpm to 999 rpm.

I've been using PULSIN with the standard 4 MHz clock on an 8M2 which gives the above range if the pulses are less than 0.65536 secs.

In order to get some slower measurements from 9 to 22 rpm, I assumed it would work to just slow the clock rate down, e.g.
Code:
SETFREQ k250			; Slow the clock by a factor of 16 to take a
					; longer measurement of any pulses present.
					; This will take 10.48576 seconds.
PULSIN Count_in , 1 , puls_ln ; Measure the positive part of the square
					; wave which represents 1/4 of a revolution.
SETFREQ m4  			; Restore the clock to the default 4MHz.
where the pulse length (puls_ln) comes out with a viable measurement.

This seems to work fine until the pulses stop and (according to the manual) puls_ln should get a zero value which I test for, but in practice this doesn't seem to happen and the program crashes and restarts (I see an output from the init: sequence).

Just discovered that SETFREQ k500 & SETFREQ m1 also crash but not SETFREQ m2 (or of course m4).

Can anyone help please?
 
Last edited:

hippy

Technical Support
Staff member
The PICAXE has an in-built watchdog which restarts the chip should program execution 'disappear into oblivion'.

Unfortunately there is no way to disable the watchdog and, when you have a very low system frequency and nothing happening - such as waiting for a long period as here - the watchdog timeout can trigger and restart the program. This is probably what you are experiencing.

For measuring long pulses it would be appropriate to use polling ...

Code:
  w0 = 0
  Do : Loop Until pinX.Y = 0
  Do : Loop Until pinX.Y = 1
  Do While pinX.Y = 1
     w0 = w0 + 1
     PauseUs 1000
  Loop
  SerTxd( "Pulse time = ", #w0, "ms", CR, LF )
You can tweak the PAUSEUS for more accurate time measurements.
 
Ah, that would explain it. Many thanks. It's nice to understand why something isn't working as expected.

I'll have a go with your helpful suggestion and see if I can work that into the program instead.
 

hippy

Technical Support
Staff member
IIRC the watchdog timer can be switched off or extended.
You seem to be right. At least works with a physical 18M2.

The C.3 pin is Serial Out so always reads as zero, never gets a pulse in. With watchdog enabled it timesout and resets every 4 seconds or so ( only gives "start" reports ), with the watchdog disabled it reports "tick" every 5.2 seconds, which is 8 x 650ms ...

Code:
#Picaxe 18M2
#Terminal 4800
#No_Data

Symbol WDTCON = $37

PeekSfr WDTCON,b0
bit0 = 0 ; Disable WDT
PokeSfr WDTCON,b0

Pause 2000
SerTxd( "Start " )
Do
  SetFreq k500
  PulsIn C.3, 0, w0
  SetFreq M4
  SerTxd( "Tick " )
Loop
Can probably reduce disabling to a one-liner "PokeSfr $37,0".

I recall it might not work on non-M2 because they have different silicon, different configuration fuse options.
 
For measuring long pulses it would be appropriate to use polling ...

Code:
  w0 = 0
  Do : Loop Until pinX.Y = 0
  Do : Loop Until pinX.Y = 1
  Do While pinX.Y = 1
     w0 = w0 + 1
     PauseUs 1000
  Loop
  SerTxd( "Pulse time = ", #w0, "ms", CR, LF )
You can tweak the PAUSEUS for more accurate time measurements.
Indeed, the PAUSEUS isn't sufficiently accurate with the given value, presumably due to the overhead of the instructions around it.

After quite a lot of tweaking I've come up with this:
Code:
init:
PAUSE 1000  			; It needs this for the RF to be ready.
SETFREQ m16
; --------------------------------------------------------------------------------
main:
;
puls_ln = 0
  Do : Loop Until pinC.4 = 0
 SerTxd( "Pin now low", CR, LF )
  Do : Loop Until pinC.4 = 1
 SerTxd( "Pin now high", CR, LF )
  Do While pinC.4 = 1 OR puls_ln > 32000
     puls_ln = puls_ln + 1
     PauseUs 40000
  Loop
BINTOASCII puls_ln,b1,b2,hundreds,tens,units    
					; Convert the byte value into three characters
SerTxd( "Pulse time = ", hundreds,tens,".",units, " secs", CR, LF )
GOTO main
Speeding up the clock minimises the overhead and using 40,000 x 2.5 us periods to achieve 0.1 second resolution seems to be a reasonable compromise as it can now measure very long periods if necessary.

This PDF from the DPscope output shows the relevant signal on C4 when the SerTxd quoted a 9.3 second pulse: View attachment PauseUs fast.pdf

So that looks pretty good to me and should do what I need. Many thanks Hippy.
 

hippy

Technical Support
Staff member
After quite a lot of tweaking ...
One way to minimise tweaking is to set a PICAXE so it generates the best 10 second pulse you can and then leave a program running which determines what PAUSEUS times give a 10 second reading and use the mid value. Untested ...

Code:
Symbol pauseUsTime    = w0
Symbol result         = w1
Symbol minPauseUsTime = w2
Symbol maxPauseUsTime = w3

Symbol IN_PIN         = pinC.0

Goto Main:

MeasureThePulse:
  result = 0
  Do : Loop Until IN_PIN = 0
  Do : Loop Until IN_PIN = 1
  Do While IN_PIN = 1
     result = result + 1
     PauseUs pauseUsTime
  Loop
  Return

Main:
  Do
    pauseUsTime = 1100
    Do
      pauseUsTime = pauseUsTime + 10
      Gosub MeasureThePulse
    Loop Until result < 10000
    maxPauseUsTime = pauseUsTime
    SerTxd( "Max", TAB, #maxPauseUsTime, CR, LF )
    Do
      pauseUsTime = pauseUsTime - 10
      Gosub MeasureThePulse
    Loop Until result > 10000
    minPauseUsTime = pauseUsTime
    SerTxd( "Min", TAB, #minPauseUsTime, CR, LF )
    pauseUsTime = maxPauseUsTime - minPauseUsTime / 2 + minPauseUsTime
    SerTxd( "Use", TAB, #pauseUsTime, CR, LF, CR, LF )
  Loop
You will need to tweak that for chosen SETFREQ, time periods being measured, and resolution required.
 
Top