For a Nottingham Hackspace project, I was asked if I could measure the RPM of a motor. “Sure!”, I said.
What was really needed was quickly bodging together a beam-break circuit and connecting it to an oscilloscope. This would have taken a couple of hours at the most. But like a proper software engineer, I decided to make the “generic” solution to the problem, which took ages.
There are actually two ways to measure RPM electronically
- Using a beam-break or reflective sensor and a counter, which provides a direct measurement.
- Using a strobe light and adjusting the frequency until the rotating object appears stationary.
I went with the second option – building a stroboscope.
At its heart, a stroboscope is just a rectangular wave generator hooked up to a light source. I wanted a few extra features to make it nice to use:
- Ability to set flash rate by either frequency or RPM
- Set duty cycle of output without affecting flash rate
- LCD display
- 2×16 for displaying RPM, frequency and duty (one per line, so one will be hidden at any time)
- Rotary encoder (with button) for main interface
- When button is not pressed, knob will increase/decrease the value of the selected digit
- When button is pressed, rotating knob will scroll through display digits
- Buttons for quickly halfing/doubling thirding/trebling the flash rate
- This is useful for checking that you haven’t hit on a multiple of the rotation rate
- Nice beefy output stage for switch big sets of LEDs
The system was prototyped on an Arduino Uno, and then a Nano was used for the actual board. The basic hardware diagram looks like this:
There were a few new software modules I had to write for this:
- A driver for the 16-bit timer in the ATmega
- I’d written a basic one of these before, but it needed a lot of fleshing out to support the fast PWM mode I was using
- A generic rotary encoder library
- This is the first project I’ve built using a rotary encoder – I took the code from the encoder library from PJRC and modified it for my own library.
- An LCD library
- Much the the encoder, this is the first project I’ve made using a 16×2 LCD – I took the code from the LCD library from Peter Fluery and modified it for my own library.
In addition, the application was split into UI, LCD and “strobe maths” modules. The application is takes responsibility for the encoder and passes encoder activity to either the strobe or UI modules (depending the state of the encoder button).
The strobe module keeps track of RPM, frequency and duty cycle, keeping them consistent and within limits. The application updates the timer and UI with the strobe data every 100ms.
This probably deserves a blog post of its own, but it was for this project that I developed my own software test harness specifically for my AVR projects.
I use the unity test suite for testing application level software, but it doesn’t play well with any libraries targeted at the AVR microcontrollers.
It’s still a work in progress, but I can now write a test harness alongside an application and run it with my actual AVR libraries.
Loosely, the process is:
- A “testing” makefile target calls a python script that parses the io.h file for the target microcontroller.
- That python script produces a C file with uint8_t variables representing the microcontroller registers and a “fake” io.h with these variables declared as extern.
- Test harness files for each peripheral, together with test functions in the library files, are able to perform limited “simulation” of external events by setting these “registers”.
- A test suite (called on each timer tick) sets up these events and tests the result.
I’m pretty happy with this setup. I developed the entire application code and libraries without ever once touching any hardware, and it worked first time. Test-driven development is pretty awesome.
Hardware is my downfall. I’m pretty bad at making good-looking boxes for things. For this project, I took an old modem-router and stripped out the innards. All the resulting holes were capped with lasercut plastic. It looks OK. Not great, just OK.
Here’s the wiring inside. I couldn’t be bothered to do a PCB for this one, despite vowing never to hand-wire anything ever again after the UNIX Clock.
Finally, here’s the stroboscope in action. The strobe light is a high-power green LED glued into an old microphone boom, screwed into a bit of metal rail. Once you’ve hit the frequency and the motor arm appears stationary, it’s fascinating to see it move as the motor speed slowly changes or the strobe frequency is changed.
We also tried measuring the speed of Rob’s electric skateboard wheels, with results that didn’t seem too stupid (7kph slow, 15kph fast).
All in all, this was a pretty nice project. Nothing went vastly wrong, although it took more time that I would have liked.