While I had got a motor moving in MicroPython, I found I hit a wall with the garbage collector causing multi-millisecond pauses.
A BLDC controller needs to be updating its model at at least 1KHz (and preferably more) so a multi-ms pause at random times is out of the question. I tried a few approaches to avoid GC but, even using the “compile-to-machine code” options in MicroPython, I couldn’t seem to control it. Beyond that, you’re only one small mistake from reintroducing GC by allocating something on the heap accidentally…. If I’m going to be one small mistake away from blowing my foot off, I’d rather work in C, where that’s perfectly normal 🙂
Porting the code to C went very smoothly:
- The Pico C SDK is wonderful, with excellent documentation. Probably the smoothest C SDK bring-up that I’ve ever experienced. Along with copious examples, there’s even a GUI tool to generate a skeleton project that has a hello-world for each peripheral that you intend on using.
- I translated the PIO programs from Python syntax to native PIO assembler and the C SDK made it easy to build that into the project.
- Translating the driver code itself, I did a fairly straight port for the initial version, but I opted to roll my own fixed point arithmetic instead of defaulting to floating point. For example, rather than converting a raw PWM value (which ranges from 0-212-1) I stuck with 212 as my base for angles. That means that clamping to 0-360 degrees can be handled by bitwise AND with 212-1 rather than an expensive modulo operation.
And what was the end result? The C code was significantly faster. So fast that my trick of toggling a pin while the code was actively running didn’t seem to be working at first. I had to zoom in on the oscilloscope to catch it!
Once I started work on the C code, I created a Github repo, the initial commit of the C code is here. The initial commit was still a prototype, it
- Measured the angle of the motor.
- Multiplied up to get the angle relative to the magnetic poles in the motor.
- Added a offset, controlled by a pair of pushbuttons.
- Drove the motor PWMs with a sine wave at the offset phase.
Still, it was enough to prove that C was fast and that the motor could be driven efficiently by correctly controlling that phase angle.