CH32V003 as a servo controller

Published on 2025-07-15 in Mite Servo.

We need to program a small, cheap microcontroller to act as an I2C device, and generate 50Hz PWM signals on at least eight pins. Can we do it with the CH32V003? A quick check reveals that we have two timers, with four channels each, and an I2C peripheral, so it should be just possible? But what about resolution? Servo signals are peculiar: yes, they repeat every 20ms, so they are 50Hz, but each impulse is only about 1-2ms long. So if you have an 8 bit timer, about 5 of those bits are wasted, because they are never going to be set. Even with 16 bit timer, you only have about 6-7 bits of effective use. The rest is just wasted.

But 20ms is a very long time for a microcontroller, and the pulses don’t have to happen all at the same time. In fact, it would be better to stagger them somewhat, to avoid current spikes (cheap servos tend to drive the motor when they receive the signal). So here’s another plan: use one clock to trigger an interrupt every 20ms (or more often, for staggered signals), and then in that interrupt trigger timers in one-shot mode to actually generate the pulses. Those one-shot timers can then have a much smaller range, and so better resolution.

Even better, since I can switch which pins a timer is connected to, I can use more than just the four channels for every timer – I can use every pin that has any timer connected to it, negated or normal, because I can reconfigure the timers in between the pulses. As long as it fits in the 18ms time in between the pulses, that is, but my initial experiments show that it will most likely work.

That means that after this 8-servo controller, I will probably take a stab at another version of my 16-servo controller for the D1 Mini compatible boards.