Calculating motor RPM without using optical sensor

Hi folks,

I have a brushed DC motor (12v, 4000 RPM) which I want to drive at a specific RPM.

The motor is being driven by a Pololu motor driver breakout board[1], and I am using a PWM pin from my ATMEGA328P to control the driver board.

Currently I am using an open-loop setup whereby I drive the PWM and assume the motor will spin at a given speed (i.e. assuming constant load). This mostly works in practice, however under longer-term testing I find the motor may spin at slightly different rates depending on the environment.

So I want to monitor the motor RPM and use that to develop a closed-loop control system (i.e. drive PWM to achieve required RPM rather than assuming a constant relationship between the two).

I think the easiest approach is probably to use some sort of opto-coupler. But I'd prefer to avoid this as my physical motor housing won't easily accommodate the sensor.

As such I wanted to ask for a steer on calculating/detecting RPM using other means. I think it should be possible using measurement of back-emf, but I'm a little bit uncertain as to how to approach this, or whether it's even a good/workable idea in the first place for my configuration.

Any advice welcome :slight_smile:

[1] Pololu - BD65496MUV Single Brushed DC Motor Driver Carrier

You need optical or magnetic feedback (a magnet and a hall-effect sensor). Optical is usually easier on a small motor.

Thanks DVDdoug.

So back-emf type approach not possible?

How are you going to measure the back EMF? Voltage drop across a known resistance? A slightly varying voltage only tells you varying torque, which would make the constant load assumption suspect.

BackEMF is proportional to the motor speed, not torque. Torque is proportional to current. With constant voltage power source backEMF and current are related but when OP let the motor coast briefly it should be possible to measure the back-EMF quite precisely. The backEMF should give some estimate of the motor speed but I am not sure how accurate - and how repeatable.
Included is some app note you may find interesting. I did not try this (or any other approach to be honest) and I think it is too complicated to be really useful.
Sensorless rotation counting brushed motors.pdf (314.7 KB)

2 Likes

Sounds reasonable.

Yes, the methods I have read about involve briefly removing the driving voltage to the motor, and then measuring the voltage at the motor terminals using the MCU's ADC.

It does feel quite involved :-), which is why I am wondering whether anyone has actually done it or had good results with this approach.

Thanks @Smajdalf for the app note -- I will read that in more depth but skimming it I think it might be a bit complicated for implementation in the ATMEGA328p. For me at least :smiley:

Well, I guess there is no such thing as a free lunch, perhaps I have to resign myself to an optical sensor.

Unlike the method described in the app note removing the power (which is part of PWM anyway) and measuring voltage should be relatively simple. Without tricks the resolution will be poor - 1/1000 (4 RPM) of max speed at most, probably much less.

With a driver like the Pololu - BD65496MUV Single Brushed DC Motor Driver Carrier it looks like the PS pin could do the disconnection easily:

So then you'd need to condition the motor terminal voltages for the ADC pins.

What have you seen?

Yeah, I think I could use PS as you describe.

I need to do some calculations around what level of accuracy I need: I'm going to be limited by ADC resolution if nothing else. That might be "good enough" for my use case though.

There's always Why You Need an Analog Front End and How to Set It Up | Nuts & Volts Magazine

Power down, even briefly and motor will slow down. Amount depends on load...not a good idea...use hall effect and small magnet as suggested earlier......can't get much smaller than that.

That could be a good idea: If you can sample a few times and record the decay, it would be a way to determine the load.

Briefly powering down a motor is principle of operation of PWM control. One voltage measurement takes only a short time. Of course the load is very important here. If it has a high momentum and low friction (i.e. rotating disk, fan) it will take looong time for the motor to slow down when coasting.

A common PWM frequency is less than 1 kHz. How long does it take to make an ADC measurement? Should be perfectly easy, nothing to do with letting the motor slow down. :roll_eyes:

Thanks all for the extra input.

For reference I am using digital pin 11 for the PWM signal to the motor driver, from effectively an Uno, which I think by default runs that pin at just under 500Hz.

I have done a bit of prototyping, with the following methodology:

  • I connected the motor driver PS pin to a digitial IO pin on the ATMega. If I drive PS LOW the driver chip should enter a "power save" mode, which the datasheet says will tristate the output pins which supply voltage to the motor.
  • I connected the motor +ve voltage rail (i.e. after the motor driver) through a potential divider to ATMega ADC pin A0. The potential divider resistor values are chosen such that a full 12V supply to the motor should present around 5v to the ATMega ADC pin.

So the idea here is that I can turn off the driver's output to the motor, and then sample the motor voltage to determine the back emf generated by the motor.

To make a measurement of back emf, I used this approach:

  • Drive PS on the motor driver LOW
  • Loop 15 times reading the ADC pin, discarding the first 5 readings, and averaging across the following 10 readings
  • Drive PS on the motor driver HIGH

So the idea here is to bin the first few ADC readings to allow any transients from powering off the driver to settle down, and then make a back emf measurement with some averaging to try to reject a bit of noise.

The Arduino docs say analogRead() on the Uno takes about 100us, so the whole operation takes something in the region of 15ms; so comparable to a PWM cycle.

This is just my starter for 10 to test the theory, I'm sure it could be refined somewhat.

The results so far show that I get an ADC reading which goes up with PWM, but which looks quite noisy[1]. I need to do a bit of maths to decide whether or not it is too noisy to be useful but it seems worth exploring some more.

[1]. By "quite noisy" I don't mean total garbage, more that if I take 10 readings for a given PWM speed, the ADC readings may vary by 20 or so.

1 Like

As a slight aside: I am aware that methods using sensors such as an optocoupler or hall effect sensor are perhaps more widely used.

The reasons I want to avoid these if I can include:

  • We have already designed the motor housing, and it doesn't account for additional sensors. If we respin the CAD for the housing and 3d print some more it's not the end of the world, but it'd be nicer not to have to.
  • The motor is physically separate from the control unit. Currently we're just running power wires to the motor. I am slightly concerned about running a sensor signal over a similar distance (maybe 50cm or so) since the environment has quite a lot of EM noise. We could maybe work around this with shielded cables, etc, but again if I don't have to deal with this that would be nice :slight_smile:

At the end of the day, I want the motor to spin at the right speed, so Plan B is an optocoupler at the moment, but if I can make something work well enough with back-emf measurements then that would be ideal.

1 Like

For those following along at home, here's a graph showing the measured back-emf for a range of PWM values.

Each of the back-emf points were manually requested (I have a basic CLI for the ATMega) at roughly 1s intervals. Each point represents an iteration of the measurement algorithm described above (i.e. each measurement is the average of 10 consecutive analogRead() samples).

I am not using the full range of the ADC, which is something to fix. I am also not providing an external reference for the ADC, which may be something else to fix.

1 Like

Do you have an oscilloscope? It would be very useful to see how the signal looks like.