STM32 pwm test

Posted at 2016-01-11.

I needed a little speed controller for a DC motor, so I made a board to hold a switching transistor and set out to make a PWM controller for it. Naturally, the target of opportunity was again a Maple mini clone board.

Since this would be a simple module, I thought I'd test libopencm3.

New firmware project

I read some of the readme files and decided to pretty much follow the instructions and set up a GPL project using libopencm3. I don't want multiple projects to duplicate a repo or a library, so I didn't use a subrepo.

I wrote the code and only tested any of it on Debian with integrated gcc-arm-none-eabi and dfu-util. The results are on Github. (They may have been modified further since this was written.)


I looked up the closest FETs I could find. No surprise that they're on the IRF540 (pdf) and 640 line of things. Not logic level, so I thought I'd make a BJT driver. I have a bag of cheap transistors that should work. After some thinking and broad calculations, I had a KiCAD schematic and instead of building it on stripboard, I thought I'd revive my toner transfer kit. So I laid out a PWB in KiCAD as well.

I have misplaced all my heavier board stock or perhaps even used it all up (which seems unlikely), but I found some pieces of very old board and cleaned that up. My etchant solution could use some reviving as well, but I decided to try it as it is.

Also, my printer wasn't feeding properly. It's used very little, but has always worked flawlessly. After a few tries, the printer started to work. I manages a few poorly sticking or poorly detaching tries at first, but then I managed to get a tolerable transfer. Only it was a mirror image, since I was using through hole parts and mirrored the bottom layer. The usual story.

Yet another try, I took the opportunity to change some footprints for bigger ones and fatten traces as well. Drilling and suboptimal transfer still conspired to make some pads nearly disappear.

So, diversions had piled up again, but I managed a working board in the end. There's a low side FET that drives the motor. It's on by default, so if the controller is dead, I can still use the main power switch to turn the motor on and off just like before. If a controller is alive (3V3 line in the connector is up), the BJT pulls the FET down unless you pull (or pulse) the PWM input low. STM32 with open drain output was the plan, but there's no harm if the output is a totem pole pin as the weak pullup is to the controller 3V3.

I'm driving pin D27 which should be GPIOA, GPIO_TIM1_CH1 or PA8.


A small motor runs nicely and the PWM sweeps 0-100-0 %. There's more to do, such as tachometer and servo loops plus some kind of input and perhaps even a display.

Turns out I put an IRFZ20 (pdf) on the board instead of a 640, but that should work fine anyway. Both are overkill by a good margin. I should have placed a series resistor in the input as a just in case as a current limit. I'll probably put that on the wire, somewhere else, or make a new board sometime. While picking the right resistors I came across some logic level IRLS540 (pdf) FETs that would have just plugged in. Oh, well.

Once I got a suitable combination of timer lines copied in, the PWM just worked. That took a little while. Other than that, the firmware writing was uneventful. I should maybe write some kind of notes on configuring STM32 timers with this library. Maybe once I (re)do the code for the encoder or tachometer input capture.

While testing the code, I also configured output pins with OD and TP modes and the difference could be seen on scope. The board seemed to work fine with both.

Over all, a promising start.