Saturday, May 7, 2016

ARM STM32F10x GCC: Connect a volume control encoder

Volume control is nowadays commonly done using rotary encoders rather than traditional potentiometers. They would make nice input devices in DIY projects. This example shows how you can connect such an encoder to STM32F103. As in my other projcts, plain ARM GCC toolsuite is used with no GUI.

Roraty volume encoders output a quadrature signal, and represent the rotation angle and direction using two square wave signals A and B generated in + or  - 90 degree phase shift with respect to each other. They are easy to read in practice; detect the rising edge of signal A, and check the level of signal B; if it is high, encoder is turning in one direction, else in the other direction.

Typical rotary volume encoder.

In real life, it can be a bit more difficult using the cheap encoders which are based on mechanical switch contact. There can be a lot of contact bounce which can be mistaken as switch rotation and poor user experience.

This project shows an example of how such an encoder can be connected to the STM32F103 processor. It reads the encoder and sends '1' or '0' over UART1 as the encoder is turned.

The  source code can be downloaded here. The project is built using GCC ARM Embedded, the installation of which is  shown here. It contains several files to divide  the functionality neatly so that it can be re-used easily. The source also contains Elm-ChaN's xprintf and xuart files which allow using regular printf over serial port, and are greatly helpful in debugging simple applications (but the latency is large and depends on the displayed value).

The encoder device produces a quadrature signal generating two square wave signals which are + or - 90 degrees out of phase depending on the direction of rotation. The signal is decoded using software (not the hardware quadrature counter of STM32F103) because of the low pulse rate. Encoder pins are connected to ordinary GPIO pins. Since many of these encoders come from Chinese manufacturers with low quality, they may have a lot of noise and bounce during rotation. To eliminate this noise, a debounce method is implemented using a DSP lowpass filter (1st order, IIR, 1kHz sampling frequency). The result is nice and smooth action without missing or extra counts.

I built the circuit around a Flip32 flight controller which makes a great STM32 prototyping board. It already has LEDS, 0.1" headers, voltage regulator, USB serial converter and several inertial and barometric sensors. The best is, all of that costs only about $15-20 depending on the configuration. Besides it is nicely compact and easy to carry around. The only gripe is that the Vbat pin is not brought out. Here is a photo of one of the prototypes:

Rotary volume encoder connected to a STM32F103 board, the Flip32 (Naze32 clone).


 I also took a video of operation. The board is connected through a USB-Serial converter to a Linux computer running Kermit. Each time the encoder is pressed and turned, a '1' or '0' is displayed on the screen, depending on the direction. No data is displayed if encoder is turned without pressing (this is a safety feature for the altimeter application this functionality was built for). The press-and-turn can be easily disabled in the source.






To run the program on your board, edit endcoder.h file to change the GPIO pins that are actually used. The SysTick should be set for 1kHz operation and the encoder pins are scanned at each interrupt.

The encoder code was used in another project of mine、aviation altimeter, that you can reach through this link.

1 comment: