April 15, 2021

New motor drive firmware

 Over a year ago I started porting my motor control firmware away from mbed.  I've been working on it in spurts every few months and and ended up re-doing a lot of things from scratch, so it took much longer than I originally planned.  Find it here:


The core motor control math hasn't changed (foc.c is nearly identical to the old version).  Lots of features have been improved though:

  • Encoder calibration/linearization is now current-mode, not voltage mode, and the calibration current can be configured from the serial terminal interface
  • Lots more parameters are configurable from the serial interface
  • Hardware setup is done with the Cube auto-generated setup code.  Linking between the hardware and motor control code is all done in hw_config.h so it should be pretty easy to port to different micros (someday I'll switch to using G4's instead of F446's....)
It's certainly not completely polished, but I think everything's working - I've been using this firmware for the espresso machine pump.  I don't have any Mini Cheetah hardware other than the motor drives any more, so I haven't been able to confirm backwards-compatibility.  Let me know if you try it and have problems.


  1. Ben, you are pure angel! I don't really like mbed either, so I recently started moving your FW to STM Cube/HAL based environment by myself, but as it's rather my side hobby, the progress was awfully non-existent. Today something in the back of my head told me to check your blog, then... BAM! YOU DID THIS! HOLY SHIT! Right now I'm throwing all my crappy code to trash :D Thank You so much! Good luck with all your projects!

  2. Great stuff! Ended up doing much the same last fall - transitioning away from the HAL libs and to LL - but ended up doing it _again_ a month and a half ago porting the entire thing to Rust; no more ST code anywhere! Glad to see you're still able to explore motor control outside your day job.

    Side note: Rust is *spectacular*; I'll never write a line of C++ again if I can help it. If you end up starting another embedded project I'd whole-heartedly recommend kicking the tires (great ARM and ST support in the cortex-m, cortex-m-rt, and stm32-rs crates).

    1. Interesting, do you have pointers towards good resources/documentation?

      The motor control is simple enough that it's reasonable to just read the reference manual and do all the setup from scratch, but for more complicated peripherals I wonder how it'd work out. Doing USB stuff recently, I don't think I could have done it (certainly not in a reasonable time frame) without the ST libraries. But maybe there are good alternatives for that stuff too?

    2. Sure! After spending too much time trying to write the appropriate C++ wrappers around ST's code, I took a break and stumbled on this blog post with the contentious title "Prefer Rust to C/C++ for new code" [1]. This was written by Cliff Biffle, the guy who somehow managed to make an stm32f403 output 800x600@60FPS full color VGA; to put that in perspective, the RAM capacity of the f403 is incapable of storing a single 800x600 frame, much less double-buffered. Oh, and it has no video hardware (!). What's more is that he originally wrote it in C++ back in '15, but recently re-wrote it in Rust [2], and it's both faster and fewer LoC than the C implementation. The icing on the cake is that his m4vga-rs repo is _staggeringly_ well documented [3]; it's been my go-to for learning embedded Rust.

      As far as implementing peripherals from bare metal, it's not exactly straightforward, but if you're comfortable poking around the reference manual I doubt you'd have much of a problem. Heck I learned most of my EE/embedded from you, and I managed to get the FDCAN peripheral up and running in bare-metal Rust in under a week [4]. If I can do it, I'm sure you could :D

      [1] http://cliffle.com/blog/prefer-rust/ (This was written back in '19 as well, and Rust has come a long way since then)
      [2] http://cliffle.com/blog/m4vga-in-rust/
      [3] https://github.com/cbiffle/m4vga-rs/
      [4] https://github.com/timblakely/pino-rs/tree/master/bldc/src/comms

  3. Ben, a big fan of your work here.

    Thank you for sharing all this work.
    I spend almost a week trying to get working all your firmware from mbed repository (mbed-dev library is to big now to work on the online compiler). At the end, I upload manually the library from my computer and finally work (maybe is useful for somebody trying the previous version).

    One again, thank you for sharing your work (save me a lot of time in my thesis :) another quadruped robot).
    Greetings from Colombia.

  4. Hi Ben,
    how were you picking gains for PI current regulators? I've tried plugging the resistance and inductance values for your motor into equations from your thesis (as well as into equation in 'Teaching Your PI Controller to Behave' series) but got widely different results.

    1. I'm using the same equations as always - put the PI zero close to the LR pole, then calculate the gain for the crossover frequency you want. Careful with units/loop structure. I write the PI controller in the form:
      u = kp*(error + ki*error_integral)

      whereas most people do:
      u = kp*error + ki*error_integral.

      The reason I do this is because then the frequency of the PI zero is independent of the loop gain KP

  5. Dear Ben,
    I'm a newer motor learner. I try to understand your motor driver (foc.c) file,but I really do not know some constants in the code. Can you give me some reference(papers,books.etc.)? Thank you very much.

    1. Check out James Mevey's thesis for a good intro to field oriented control:

      Happy to answer any longer-form questions if you email through my contact form as well.

    2. Thanks Ben,and thanks your genius work. I am a big fans for your work, wanna to
      learn more with you.

  6. Hi Ben,
    Love the motor controller project and very excited for this port.

    Just though I should mention that I'm slowly working on a basic port to the B-G431B-ESC1. It's a low cost ~$20 motor driver that has all the feature need to run the the above firmware.
    Currently the motor dose spin but the current monitroing/controller are partically broken, it uses an incremental encoder and eeprom/CAM are a work in progress.
    Will update when it's more fully featured

  7. one of you many brilliant posts, thanks for sharing this