I am building a 4 wheel rover and am using PID DC motor control for the back set of wheels. The feedback for the speed is provided by Hall effect sensors, with two pulses per rotation.

This means with the motor as 100% duty, the sensor returns a 240Hz signal (4.2ms between pulses) and at the lowest duty for when the wheels are turning 20% duty, the sensor returns a 14.33 Hz signal (74.2 ms between pulses).

I'm using a STM32 Cortex-M3 part for the controller and a timer to capture the hall effect input and convert this to frequency. This is done by comparing two capture samples through a ISR that triggers on each rising edge.

The issue I have is the PID loop is running at a rate of 50Hz, so when the motor is running at low speeds and a timer compare has not been done, it returns the last calculated value. This is fine, but I could also find myself in the situation where the motor has stopped spinning and I haven't been able to update the captured frequency due to the second pulse not having arrived.

Im just wonder if there is a sensible way of handling this ?


  • 1
    $\begingroup$ Two counts per revolution does seem small, but if you're getting 240Hz at 100% duty cycle, shouldn't you get 20% of that (48Hz) at a 20% duty cycle? You never explicitly state your speeds. $\endgroup$
    – Chuck
    Jul 16, 2017 at 9:33
  • $\begingroup$ Thanks Chuck. I don't know the speed, all I know is the Hall effect sensor is on the motor shaft with a simple magnet, which I assume to trigger the hall sensor for the north and south pole of the magnet (hence two per rotation). Also I assume the speed of the motor is not perfectly linear. So 20% duty for driving the motor will not be 20% of the full speed when the motor is flat out at 100% duty. $\endgroup$
    – Dibly
    Jul 17, 2017 at 10:25

1 Answer 1


I came up with a solution in the end.

  • Fire a periodic interrupt at a fixed rate (In my case, I configured the STM32 to fire a systick interrupt every 1ms
  • In the ISR for the 1ms timer, decrement a global variable down to zero (stopping at zero)
  • In the ISR for compare and capture timer that detects the pulse from the Hall effect sensor, set the same global variable above to a "time-out value" (In my case 100). This is the millisecond value to denote the maximum period for the pulses.
  • When polling for frequency of the hall effect sensor, I now check if the global variable is zero. If it is, I return zero (It would have decremented down to zero if no pulses have been received for 100ms) else I return the last measured frequency.

As I said above the slowest period I detect before the motor becomes stationary is 73.2ms, so the 100ms timeout gives me some buffer for example if the robot is moving down hill and can actually register a speed slower than this.

  • $\begingroup$ I'm glad you found a solution for your problem! Please accept your own answer by clicking the check mark to the left of your answer. This closes out the question on the site and helps future visitors find quality answers faster. $\endgroup$
    – Chuck
    Jul 31, 2017 at 13:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.