During building my pedals, I decided to make my own pedal controller using cheep and affordable components. Already having some experience with Arduino boards, I know their capabilities and decided to route a STM32 way this time (mostly to learn something new though).
Here is the comparision of Arduino Leonardo (which is a most likely candidate for our goal) and STM32F103C8T6 (which I used)
|Architecture||8-bit ATMEL AVR||32-bit ARM CORTEX-M3|
|Frequency||16MHz||up to 72MHz|
|Timers||1x 16-bit, 2x 8-bit||3x 16-bit, 1x pwm|
|Peripheral||10-bit ADC (6 channels)
|2 x 12-bit, 1 μs A/D converters (7 channels)
7-channel DMA controller
As you can see, specs for stm32f103c8 are not so bad. And it’s cheaper than Leonardo!
One big drawback is that you need additional external programmer. But its not expensive also, total price for mini board + programmer is still comparable with Arduino clones.
I bought both items on aliexpress.com, search for «STM32F103C8T6 Minimum System Development Board» and «ST-Link v2 mini», for example this and this. Also there is another version of the board called BlackPill — link. It has less available pins, but has mounting holes.
Schematics for the dev board:
Pinout in pdf — The-Generic-STM32F103-Pinout-Diagram
So, after some time, I programmed simracing-oriented firmware for the device.
Device capabilities are:
- 6x 12-bit (4096 steps) axises
- rotary encoders support
- rotary switches support
- matrix buttons support
- single buttons support
- axises calibration
- analog inputs as buttons
- 1kHz exchange rate with PC, which means 1ms maximum latency for axises
It can be used for DIY buttons boxes, button rim plates, pedals, hand brakes, gear shifters, etc, etc — everywhere you need joystick/gamepad interface with PC.
Here is pinout you get after flashing the firmware first time:
STM32F103C8T6 ------------------- - |3VB +3.3V| - - |C13 GND| - COL1 - |C14 +5V| - COL2 - |C15 B9| - ROW6 ADC0 - |A0 B8| - ROW5 ADC1 - |A1 B7| - ROW4 ADC2 - |A2 B6| - ROW3 ADC3 - |A3 B5| - ROW2 ADC4 - |A4 B4| - ROW1 ADC5 - |A5 B3| - COL4 ADC6 - |A6 A15| - ROT11 COL5 - |A7 A12| - ROT1 - |B0 A11| - ROT2 - |B1 A10| - ROT8 ROTA - |B10 A9| - ROT7 ROTB - |B11 A8| - ROT6 - |R B15| - ROT5 - |+3.3V B14| - ROT4 - |GND B13| - ROT3 - |GND B12| - COL3 -------------------
Also I programmed small PC-based app named OSHStudio, which allows you to choose a function for each pin. Pins’ functions can be selected in the «Pins Configuration» tab, also here you can choose your board type. Here is how the initial pinout looks in OSHStudio, when you click «Get Config from Device»:
When buttons wired in matrix, columns have to be connected to Button Matrix COLUMNS pins, rows — to Button Matrix ROWS pins. Single separate buttons (not matrix), can be connect to «Single Button +3,3V» or «Single Button GND». If you connect button to «Single Button +3.3V» than connect the other side of button to +3.3V, if you connect button to «Single Button GND» than connect it to GND. Here is an example of matrix wiring:
You can test your buttons in the «Buttons» tab of OSHStudio:
In this tab you can also configure POV Hat switches. When activated first Hat Switch used first 4 buttons of matrix, 2nd Hat Switch — from 2nd 4 buttons and so on.
The firmware supports full step, half step and quarter step encoders. Rotary encoders can be wired in «chained» or «single» configuration. Chained config means you wire side encoders’ pins (PINA & PINB) together and central pin become «control» pin. Central pin identified your encoder type — 1/1 (full step), 1/2 (half step) or 1/4 (quarter step). You can wire different type encoders in one chain.
Also encoders can be connected in single configuration. In this case you should configure side pins according to the type of encoder and central pin have to be connected to +3.3V.
If necessary you can remap encoders pins on the «Single Encoders Config» tab.
Encoders can also be tested in the «Buttons» tab.
Virtual button is «clicked» when shaft is changing position.
Analog pins ADC0 — ADC6 used to connect potentiometers or other analog inputs. Also you can calibrate axises in OSHStudio, and calibration values in this case will be stored in MCU itself. After calibration an axis is «expanded» by the controller, so PC always sees axis as 4096 steps. There is also a possibility of AutoCalibration of axes.
As you can see, there is also «Combined axis» function. It means you can combine 2 analog inputs in one axis. The function is mainly intended for rims with 2 clutch paddles. There are 2 possible modes:
- cooperative work — in this mode results from both analog inputs are summarized. You can choose weight of each input by slider.
- each on his own — each analog input works independently but for one axis. For example you can short calibrate an one input (paddle) for fast gear changes and an other calibrate as normal axis — for starting.
Beginning with 0.15 version there is a more advanced possibility to map analog iinputs to buttons. You can configure up to 10 analog inputs and each of them can be mapped up to 10 buttons (keep in mind though total number of buttons is still 64). You can define it in the Analog2Buttons tab
You can tune such parameters as:
- «Your identifier for the device» — unique identifier for the board, if you have for example few boards, you can assign different idetigiers to them — «pedals», «buttonsbox», etc
- «USB polling interval» — means interval between USB packets, i.e. 1ms means 1kHz USB exchange frequency. For high performance devices you can try decrease this down to 1ms, for anything else default 16ms probably is enough.
- «Amount of time a button will be pressed when Rotary Encoder position changed» — virtual button will appear as pressed during this time, for encoders
- «Amount of time a button will be pressed when Rotary Switch position changed» -virtual button will appear as pressed during this time, for rotary switches
- «Amount of time a button will be pressed when Analog Input position changed» -virtual button will appear as pressed during this time, for analog2buttons inputs
- «Time since previous Rotary Switch change» — if you change rotary switch position in less time than the parameter then buttons presses will not be registered. So if you rotate switch fast enough then intermediate positions will not be registered.
- «Time since previous Analog Input position change» — same as previous one, but for Analog2Buttons types
- «Debounce time for Rotary Encoders» and «Debounce time for Buttons» — try to increase it if you have problem with phantom presses
I recommend set to «Not used» all unused pins 🙂
Source code in my github project.
Available firmware + OSHStudio app:
If you wonder how to flash firmware to the board you can check this post — How to flash firmware to STM32Fx