Period of time between two rising edges

Thread Starter

donnje

Joined Dec 2, 2020
6
Hello guys!
I am a beginner in microcontrollers and I need some help with a personal project.
I have a Hall Sensor which is generating 2000 pulses for every km.
I am interfacing with a PIC18F46. How could I calculate the speed from this sensor or how can I find period of time for every km or meter?
I know that I can use an interrupt for every rising or falling edge but I am a beginner in software and have no idea how to do.
 

jpanhalt

Joined Jan 18, 2008
11,088
Welcome to AAC.

Is that the complete chip number ? Is it maybe an 18F46J50 or something. If so, you need to learn how to use the timers. There are 5 of them. Timer0 can be configured as a 16-it counter and can create an interrupt. Timer1 is a 16 bit counter or timer. One approach would be to use Timer0 to create an interrupt or flag every 2000 clicks, then time between them. You can also reverse the roles, but Timer1 can have its own oscillator (say 32.768 kHz), which makes timing much simpler. That is, 16-bits at 32.768 kHz = 2 seconds.

I suspect you do not want a speed update only second or two, or every km. Since you know there are 2000 clicks per km, you could actually time between every click, i.e., rising edge (leave Timer1 run continuously -- don't start and stop it), then calculate the speed much more frequently. I would do the latter for a speedometer.
 

Thread Starter

donnje

Joined Dec 2, 2020
6
I find it easier to count every two rising edge. This means every meter. Then speed will be 1/time. I can start a timer, but do I need to reset after every 2 clicks? I need a separate counter to number every 2 clicks? Then, I can do an average on the last, let’s say 100 measurements of speed and show the result.
 

jpanhalt

Joined Jan 18, 2008
11,088
Starting and stopping a timer may lose a little time or miss a click. Just capture the times for your rising edges and let the MCU do the calculation.
 

jpanhalt

Joined Jan 18, 2008
11,088
I find it easier to count every two rising edge. This means every meter. Then speed will be 1/time. I can start a timer, but do I need to reset after every 2 clicks? I need a separate counter to number every 2 clicks? Then, I can do an average on the last, let’s say 100 measurements of speed and show the result.
donnje said:
I have a Hall Sensor which is generating 2000 pulses for every km.
There is some not so hidden ambiguity there. To put it simply, are you counting fence posts or spaces?

Example: |___|___|___|___| There are 5 rising edges, but only 4 spaces. Your prior conversion of 2000 clicks per km to 2 clicks per meter leads me to wonder how your counter is set up. That is, are you sure a km is not just 1001 rising edges?
 

Thread Starter

donnje

Joined Dec 2, 2020
6
I know only that there are 2000 pulses per km, so I suppose to count 2001 rising edges for every km. My question is, how can I number these pulses? I was thinking at Entering in a interruption for every pulse and increase a variable, then when variable is equal with 2000, stop the counter and reinitialize all. Or to do this for every 2 pulses. For this I will need to configure a DIO as interrupt pin and a timer only I think. I am using a PIC18F64K22, and I do not know to configure the timer because depending on the speed it need to number from seconds to minutes. The interval for 2000 pulses can be found very different. So, I was thinking it is better to number duration for only 2 pulses, starting the counter at first rising edge and stoping and third.
 

jpanhalt

Joined Jan 18, 2008
11,088
I know only that there are 2000 pulses per km, so I suppose to count 2001 rising edges for every km. My question is, how can I number these pulses? I was thinking at Entering in a interruption for every pulse and increase a variable, then when variable is equal with 2000, stop the counter and reinitialize all. Or to do this for every 2 pulses. For this I will need to configure a DIO as interrupt pin and a timer only I think. I am using a PIC18F64K22, and I do not know to configure the timer because depending on the speed it need to number from seconds to minutes. The interval for 2000 pulses can be found very different. So, I was thinking it is better to number duration for only 2 pulses, starting the counter at first rising edge and stoping and third.
Those pulses are so slow compared to the speed and accuracy of your MCU, why do you want to "count" 2000 or 2001 pulses per km? For the last time:
1) Let the counter run. No need to start and stop it.
2) Determine the time between pulses and calculate the speed accordingly. I hope you realize that the second pulse is also the start of the next period.

Even if I were driving 180 mph (3 miles/min), I would not want my speedometer to update only every 20 seconds! You need to THINK about this and sketch it out on paper. The fact it has taken you 10 days to respond is not a good sign. Have you thought about it in the interim? Maybe you should just use a calendar for your speedometer.

Why is this still in microcontrollers instead of "Homework?"
 

Thread Starter

donnje

Joined Dec 2, 2020
6
The PCB is almost finished in these 10 days. Now, I start with software.
I want to count 2 pulses per meter. I understand your idea. To do the difference between current moment and last saved moment when the counter reachesa multiplier of 2, right?
 

Papabravo

Joined Feb 24, 2006
16,509
If you record time stamps for a sequence of rising edges, then you can easily compute the difference between any combination of rising edges.
 

MrChips

Joined Oct 2, 2009
23,959
Ignore any multiplier by 2 thingy for now.

Run the timer continuously, never stopping. There is something called input capture. Read up about it.
On every pulse from the Hall sensor, capture the value of the counter.
So you have T1, T2, T3, ... Tn, Tn+1

All you need to do is take the difference between two consecutive values = Tn+1 - Tn.
If you get a negative result, add 65536 if it is a 16-bit timer.

Convert this value to speed.

You have to figure out a scheme to detect if the speed is too low or zero, i.e. a pulse has not been received within a given time period.
 

jpanhalt

Joined Jan 18, 2008
11,088
The PCB is almost finished in these 10 days. Now, I start with software.
I want to count 2 pulses per meter. I understand your idea. To do the difference between current moment and last saved moment when the counter reachesa multiplier of 2, right?
You don't understand. No multiplier is involved. Look at the picture I drew for you. 1 meter = 2 counts; 2 meters = 3 counts; n meters = n +1 counts. You are not "counting" edges per se. You are measuring the time (aka period, clock ticks) between counts.

Ten days to make a PCB? Why so long? I hope your PCB turns out better than your understanding.
 

Thread Starter

donnje

Joined Dec 2, 2020
6
Thank you for help and little jokes.
I try using CCP module as MrChips said to find the period between two consecutive pulses. Then the speed will be 1/period.
 

Phil-S

Joined Dec 4, 2015
220
Take a look at Nick Gammon's website (Gammon.au) where he covers timing and interrupts.
I know it's Arduino, but you might be able to see how interrupts work.
He has one example for timing RC cars.
There is generally more support for Atmel chips (Arduino) than PIC in community forums.
Personally, I would have got a prototype going before designing and buying PCBs
As for your motorbike not having a display for speed, I hope you aren't using it on public roads.
 

vanderghast

Joined Jun 14, 2018
55
If you are using a microcontroller, you can play with the soft without any hardware. You could use an interrupt each time you get a pulse (servicing the interrupt take some CPU-clock time) and read "a" time counter (assuming that the microcontroller allows you to define one precise enough for your purpose) after a given numer of pulse that you got (ie, each 2 pulse, or as you wish). and unless you get a counter roll over (as example, 1+( 2^16 -1) may be not 2^16 but ... 0; some microcontroller raises a flag when that occurs). just subtract from the previous reading (and add the rollover period if the result is negative: if you get after the subtraction -2^15, the new reading is close to 0 while the previous one was close to 2^16 -1, well, the result, here ssumed to be -2^15 then indicates one (or more) roll-over occured between the two readings, so add 2^16 to the -2^15 that you just got to get the right elapsed number of clock-tics). No hardware implied, implicitly, since it is all internal to the microcontroller.
If you wish to minimize the interruption delay, you can add a diviser by 2, in hardware, as example, so only one pulse each two pulses will reach the microcontroller GPIO pin. But that implies a hardware modification.
 

andrewmm

Joined Feb 25, 2011
1,641
Doing the famous step back.

we know now its a motor bike
Assuming you do say 60 Km / hour,
then thats 1Km per 60 seconds, during which you will get 2000 pulses
that s a pulse every 30 ms.

Depending upon your processor speed, 30 ms is a long time.
and if your going slower than 60 Km/h, the time between pulses is going to lengthen.

As has been said before,
what you need to do is measure the time between pulses,
Which as you go faster, the period will decrease.

As has been said,
simple method is to have counter constantly running of a fixed clock,
and on every pulse rising edge, read the counter.
an interrupt would be the ideal way , but keep the interrupt routine to the minimum
( just read the counter in the interrupt )

then in your main loop, you need to process the counter.
which is where the "fun" starts.

The count values are for a start at some point , as has been said, over flow,
and the counter wrap. You need to detect this , and account as has been shown.

Then the pulses are going to have a fair amount of variation on them, even if you keep a constant speed,
so you will need some sort of smoothing code, may be an exponential smoother.
new speed = (old speed *( 1-A )) + ( news speed * A )

Then, what happens as you slow down / stop.
With no pulses coming in ,
then there will be no speed update , so if yo go from 10 KM/h to a quick stop, the speedo will show the same speed.

I'd suggest a big think about your algorithm
then start looking at how you can code it.
 

MIS42N

Joined Jan 25, 2013
17
A way to deal with this:
Set up a capture on event (the Hall sensor) for one of the 16 bit counters. The capture is done in hardware so you don't need to read the counter, just the captured value.
Allow an interrupt for when the 16-bit counter overflows. Each time it overflows, increment a 16-bit software counter. This effectively gives you a 32 bit counter Soft+real*65536. Even if you run the 16 bit hardware counter full speed this takes many seconds to wrap around. It has to be longer than the rate you update the speedo.
Allow an interrupt for the capture event. In the interrupt routine copy the software counter and the captured value, and increment a count of events (unsigned, allowed to wrap around).
The mainline loops at whatever rate you want to update the speedo - say every 500 milliseconds. The procedure is disable interrupts (you need to do this so the values don't get updated while you are reading them) , get the current values as last captured by the capture interrupt. If this is the first time they become the previous values. In subsequent loops, the current values become the previous values and the captured values become the current values. Enable interrupts.
Use unsigned arithmetic to subtract the previous count of events from the current count of events (unsigned arithmetic ignores the fact the counters wrap around). If the result is zero then no event occurred in 500 milliseconds so assume a speed of zero. If not zero, subtract the previous 32 bit capture from the current 32 bit capture (unsigned again) and divide it by the number of events. The result is average period between events in whatever clock speed the timer is using, convert this to speed.
There is one gotcha. The order and timing of the two interrupts. The capture interrupt should go first, and should check if the captured value is small (testing the most significant bit is 0 is good enough). It is possible the timer overflow hasn't updated the soft counter yet. That can be tested by looking at the timer interrupt flag. Normally it is cleared by the overflow interrupt but if it is set then the soft counter hasn't been updated so the captured value should be incremented (don't touch the soft counter, it will be updated by the overflow interrupt as soon as this interrupt is serviced).
I've left the initial setup to you. It needs careful reading of the Data Sheet. I didn't read it carefully because I haven't used this particular processor, but it looks like most PICs.
Hope this helps.
 
Top