Measuring low RPM

Vmax

Member
I have a set up that sends a +5V pulse to a Picaxe 28X1 for every revolution of a wheel on an axel. I would like to measure Revolutions Per minute (RPM), in the 30 to 600 range (i.e. 0.5 Hz to 10 Hz). I was hoping to use Pulsin, but that has a maximum of 0.65535 secs. I figure this command can’t be used to reliably measure anything under 3 Hz or 180 RPM. The only other option I can think of is to use Count. This should be able to measure between 5 and 100 pulses in a 10 second interval to give 30 to 600 RPM. My problem is that I don’t really want to tie up the Picaxe for 10 seconds to measure RPM with the Count command. Do I have any other options?
 

BeanieBots

Moderator
The 28X1 has an internal timer that you can read.
Have the incomming pulse trigger an interrupt and measure the time difference.
I've not looked at what sort of values would be returned so I may have given you a duff steer but certainly worth investigating.
Other options would include using different clock speeds to change the range of pulsin to suit your signal.
 

womai

Senior Member
Using the timer is probably the most elegant solution. You can even set up an interrupt the gets called when the signal from your sensor arrives. But depending on your level of programming experience underclocking may be easier to implement. The 28X1 is VERY easy to underclock (no need for an 08M or for any Poke's) - just use the setfreq command. Lower frequencies will increase the max. pulsin timeout accordingly (the 0.65535 secs number is for the default clock frequency of 4 MHz, so 2 MHz will yield 2*0.65535 secs, and so on).

Wolfgang
 

Vmax

Member
I know you can speed up a Picaxe but I didn’t realize you can slow one down. The PIC16F886 datasheet (i.e. 28X1) has an OSCCON register at $8F. Bits 6-4 can change the Internal Oscillator Frequency to:

111 = 8 MHz
110 = 4 MHz (default)
101 = 2 MHz
100 = 1 MHz
011 = 500 kHz
010 = 250 kHz
001 = 125 kHz
000 = 31 kHz

So I could:

Poke $8F, %00110000 ; decrease speed to 500 kHz
Pulsin to read low RPM
Poke $8F, %01100000 ; reset speed to default 4 MHz

I would probably need to adjust the RPM value (i.e. * 8). I’m not certain how this would affect other timing functions like "timer" and "PWM". It seems that after a Reset, the IRCF<2:0> bits of the OSCCON register are set to "110" and the frequency selection is set to 4 MHz. So I should not muck things up if I make a mistake. Hitting the reset should change the oscillator back to default 4 MHz.

It makes me nervous poking about.

I just realized that the 28X1 has a setfreq command that can be used to set the frequency. No need to poke about.

setfreq k500 should put the picaxe at 500kHz.
 
Last edited:

hippy

Ex-Staff (retired)
I would like to measure Revolutions Per minute (RPM), in the 30 to 600 range (i.e. 0.5 Hz to 10 Hz). I was hoping to use Pulsin, but that has a maximum of 0.65535 secs. I figure this command can’t be used to reliably measure anything under 3 Hz or 180 RPM.
Alternatively you could measure the period of the pulse, not the period between pulses.You can switch between measuring the pulse or gap between depending upon the RPM you are getting.
 

maitchy

Member
for the small range of frequencies where the pulsin won't measure half the period: if you don't have an X1 chip with a timer you can still zero a word variable, put the picaxe in a tight loop waiting for the 0-to-1 transition, then increment the word counter in another tight loop until the next 0-to-1 transition. It means you have to calibrate it for the timing of the loop, but that is reasonably easy to do... just a matter of getting the right scale factor.
 

maitchy

Member
--Another thought, if you don't have an X1, but want good accuracy without having to work out the timing of the loop I suggested: with something like a 14M there is a good 16-bit Timer1 that you can access with PEEKs to the word at $0E before and after the period (after setting it up with something like:

Code:
poke $10,%00110001 ' timer1 on and internal clock,1:8 prescaler
or maybe something to give a different prescaler option? You'd have to keep reading it and spotting when the counter wraps around, but you wouldn't need to allow for the millisec or so in instructions at the start and end that make less than 1% error in the timing.
 

Vmax

Member
setfreq test

I tried to use “setfreq” to measure low RPM, but I seem to be having problems with time.

To test the idea, I first tried to get baseline data at 4 MHz. I compared the “timer” variable with an external clock. It was fairly good, only losing a few seconds after about 5 minutes. I think playing with “settimer” and changing the preload around “t1s_4” may improve things, but I’m not really that interested in time (other than RPM).

Next, I sent the Picaxe a pulse about once a second. This should give an RPM of around 60. If my math is ok (??), then I should be able to measure RPM from the time between pulses (PulseTime) using the pulsin function:

Time (in secs) = PulseTime / 100000
RPM = 60 / Time(in secs)

so

RPM = 6000000 / PulseTime

Here’s the code I used:

SYMBOL RPM = w4
SYMBOL PulseTime = w5
SYMBOL PulseCount = W13

settimer t1s_4 ; timer = seconds at 4MHz
PulseCount = 0

rpmtest:

pulsin 5, 0, PulseTime ; PulseTime = time between pulses.
If PulseTime > 0 then ; is PulseTime valid (i.e. >0)
PulseCount = PulseCount + 1
endif
w0=PulseTime/100 ; I only need 3 digits for RPM
RPM = 60000/w0
if timer >= 60 then ; reset timer if >60 secs.
timer = timer - 60
endif
sertxd(13,10, #PulseTime, " ",#RPM, " ",#PulseCount," ",#timer)
goto rpmtest

A sample of my results:

PulseTime, RPM, PulseCount,Seconds
-----------------------------------------------
42812 140 2 2
41979 143 3 3
48176 124 4 4
47459 126 5 5
48332 124 6 6
42072 142 7 7
53686 111 8 8
41980 143 9 9
42981 139 10 10
39694 151 11 11
50256 119 12 12
45632 131 13 13

The measured RPM is about 2.2 times higher than I expected at 4 MHz. If I add the line

RPM = RPM * 10 / 22

then RPM hovers around 60, what I expected. Am I missing something here (i.e. math, software, circuit, …), or do I need to calibrate the “pulsin” function?
 

womai

Senior Member
Pulsin measures the width of the pulse, not the time from one pulse to the next. So assuming your signal spends about the same time high as low, the pulse width will be half of the period and you'll calculate an RPM that is too high by a factor of 2 - exactly what you see.

If you are sure the duty cycle is exactly 50% (or you know the number, e.g. 2.2 in your case, and it won't change when the RPM change), then simply divide the result by that number. Otherwise you could add a simple divide-by-2 circuit in front, and measure the resulting pulse width (which will be equal to the original period): take a standard 74HCxx series D-flip-flop, e.g. 74HC74:

http://www.ortodoxism.ro/datasheets/philips/74HC_HCT74_CNV_2.pdf

Connect the signal to the clock (CP), and connect the inverted output (/Q) to the data input (D) as well as to the Picaxe input. Set (S) and Reset (R) must be tied to +5V.

Wolfgang
 

Vmax

Member
Does “Pulsin” measure the width of a pulse, and not time between pulses? That could explain discrepancy. Not obvious from the manual. If “Pulsin” measures the width of a pulse, then I would need to know the time between high to low and low to high. Do I need two “pulsin” commands, one to measure pulse width and one to measure pulse lag? I think I need “technical” advice.
 

moxhamj

New Member
Well both, depending on how you set it up. Consider a wheel going around and say the wheel is 30cm in circumference and you attach a strip of metal 1cm wide going through an optoswitch, or you drill a 1cm hole and shine a led through it to a photodetector. Once you have cleaned up the signal you will have a pulse that is high 1/30th of the time. The pulse could be a high pulse or a low pulse - it doesn't matter but lets say it is a high pulse. You want to start measuring when on the positive edge, ie when the pulse goes high and you want to stop measuring on the negative edge, ie when it goes low again. Reading the instructions for pulsin, this means the state value should be 1 - a low to high transition starts the timing.

We could just as easily have measured the low time, ie the other 29/30ths of the circle and used the state value of 0.

You don't need two pulsin commands. If a pulse is 1/30th the circumference and you know that width (measure it with a ruler) compared with the circumference then you can do the maths and work out the speed. Let us know if you need help with that maths.

There is another scenario where you don't have access to the width of the pulses - say you have a pulse that happens once per revolution and the width of the pulse is a bit erratic. You get a positive edge, then a high for a while, then a negative edge. You want to measure the time between two positive edges. Pulsin won't do that directly but you can feed the signal through a flip flop first and then measure the width of the pulse using pulsin. A flip flop goes high when the first positive edge arrives then goes low when the second one arrives.
 
Last edited:

Vmax

Member
Arg. This looks like it’s going to be a bit more complicated than I originally thought. I measure RPM from an opto sensor. The signal will be high about 1/3 of a revolution, and low about 2/3 of a revolution.

Ok, so after banging my head, how does this sound? If ton is the amount of time the signal is high and toff is the amount of time the signal is low, then I can measure RPM from T = ton + toff. So I can measure ton from:

pulsin 5, 1, ton

and toff from

pulsin 5, 0, toff

But I don’t need to know both. The ratio of toff to ton should be constant:

X = toff / ton

because that ratio will depend on the setup and will not change with RPM. So,

toff = X * ton

and

T = ton + X * ton = ton * (1 + X)

For my setup

X = (2/3) / (1/3) = 2

So T = 3 * ton

I should probably measure X directly by calibrating using two pulsin commands, one for ton and one for toff, and storing results in eeprom. Then I could use that stored value and only one pulsin to measure RPM.

Am I close?
 

hippy

Ex-Staff (retired)
The problem with consecutively measuring Ton and Toff is that it takes a full three revolutions to read both, and if the revs change slightly during that time the numbers don't add up. You can't read the Ton immediatly after the Toff ( and vice-versa ) because the Ton will already have started so it waits for the next one to come round.

The easiest solution is as already mentioned to run the pulse through a flip-flop and that will give a 50-50 high low-time which is accurate ( much simpler maths ) and takes two revolutions per reading.
 

Rickharris

Senior Member
You could increase the number of pulses by putting a slotted disc or a printed graticule on the shaft - This will give potentially many on/off transitions for each revolution. If you count then and have a single master start marker you can know exactly where the shaft is in any single revolution as well.

Graticule's are easy to make by printing onto acetate with a laser printer and there are many examples available on the web at various robotic sites.
 

moxhamj

New Member
Re "so T=3*T(on)", this would work. For calibration maybe there are other ways - ie do the maths in the picaxe, give a reading (eg 1000Rpm) that the picaxe has calculated and compare with the real reading obtained another way. I suppose the next question is whether you can determine the revs in other ways? If this doesn't have to be accurate then I guess picking 1/3 would be close enough, and if it does have to be really accurate then you may be looking at strobes or other calibration systems.
 

Vmax

Member
I tested the idea of calibrating for X=toff / ton. First, I froze my buns off (it’s getting cold in Canada) checking the opto sensor (the picaxe is indoors). I loaded the picaxe with the “one off” program:

Symbol toff = w0
symbol ton = w1
symbol x1 = w2

calib1:
pulsin 5, 0, toff
pulsin 5, 1, ton
w3 = ton / 100
x1 = toff/w3
sertxd(13,10," toff=", #toff, " ton=",#ton, " X=",#x1)
goto calib1

Next, I spun the hub to try and get a constant RPM. This is the output:

(accelerating)
toff=0 ton=0 X=0
toff=0 ton=41988 X=0
toff=52852 ton=28657 X=184 73.6 81.2
toff=41856 ton=24895 X=168 89.8 93.4
toff=38410 ton=23262 X=165 97.2 99.9
(constant RPM)
toff=36134 ton=22449 X=161 102.4 103.6
toff=35552 ton=22433 X=158 103.4 103.7
toff=35442 ton=22000 X=161 104.4 105.7
toff=34514 ton=21628 X=159 106.8 107.5
toff=34834 ton=22348 X=156 104.9 104.1
toff=35612 ton=22432 X=158 103.3 103.7
toff=36036 ton=23067 X=156 101.5 100.8
toff=37024 ton=23314 X=158 99.4 99.8
toff=37088 ton=23367 X=159 99.2 99.5
toff=37200 ton=23620 X=157 98.6 98.4
toff=37800 ton=23839 X=158 97.3 97.6
toff=37848 ton=24057 X=157 96.9 96.7
toff=38042 ton=23996 X=159 96.7 96.9
toff=37916 ton=24013 X=157 96.8 96.8
toff=37900 ton=24046 X=157 96.8 96.7
toff=38446 ton=24618 X=156 95.1 94.5
(decelerating)
toff=39800 ton=27332 X=145 89.3 85.1
toff=49224 ton=35873 X=137 70.5 64.8
toff=0 ton=47114 X=0
toff=0 ton=57241 X=0
toff=0 ton=0 X=0
(stopped)

I added the last two columns. The first added column is RPM calculated from toff + ton and the last column is RPM calculated from (1 + 1.58) * ton (i.e. X = 1.58). There are limitations here. As hippy pointed out, toff is measured from one rev and ton from the next one. Everything should work out ok, provided RPM is constant. Things go amuck when accelerating/decelerating.

What gets me is that I tried to get X from physical dimensions of the sensor, but got a different result. I have a skirt at the base of the hub between an LED and LSR. Light goes directly to the LSR for part of a rev and is blocked for the rest of the rev. I measured the total circumference as 18.9 cm. The gap in the skirt is 6.2 cm long and blocks light for 12.7 cm. From these dimensions, I would guess X to be 12.7 / 6.2 = 2.05, but it doesn’t seem to be. Go figure.
 

hippy

Ex-Staff (retired)
It would probably be worth seeing what results you get with (Ton+Toff)/N. You might need to divide Ton, Toff and N by two to keep the maths from overflowing. A +/-3% range of constant RPM readings might be improved upon that way, although we have no idea how accuare constant RPM is anyway.
 
Top