DirectServo is a microcontroller that drives BLDC motors as servo. It was tested on gimbal motors but can technically drive any motor that has magnet attached to its rotor.

I initially intended it as a servo for humanoid robot but it turned out to not be strong enough (just). However the design is successful and can be used for less demanding applications. It was designed to apply constant torque in stall situation or when spinning slowly. No matter what resistance the rotor experiences, controller will measure its electric angular position and apply SIN PWM at +-90 degrees.

Power supply: 10…40 volt
Max current: unknown but MOSFETs are rated 100Amp
MCU: STSPIN32 from STMicroelectronics, 4K RAM, 32K Flash, 48Mhz
Protocol: RS485 @ 115200 baud


Both software and PCB design is opensource and can be found here:



Controller has to be calibrated before it can be used. Calibration will establish the number of poles of the motor and the angle of the magnet relative to the sensor. Once controller knows this, it can calculate +- 90 electric degrees based on physical degrees read by sensor.

When calibrating, please make sure the rotor does not touch anything and that nothing interferes with its free motion or else calibration will be distorted. Please see video for explanation.

Controller IDs

Because all the controllers are attached to the same RS485 bus, each controller can hear all the commands that are sent on the bus. To address each individual controller, all the commands start with the target ID. There must never be two controllers with the same ID on the bus. ID=0 is reserved for the mainboard. ID=FF is broadcast, it will be accepted by all controllers.


Every command starts with 2 chars that represent the target controller’s ID. If controller has ID=0 it considers itself not-calibrated and will be blinking. ID=0 os reserved for the mainboard. Then a command letter follows (or several commands) with its command-specific parameters. Every command must be ended with ‘\n’ or ‘\r\n’. Command with ID=FF is a broadcast and will be accepted by all controllers on the bus.


Set Identity

Letter: I
Parameters: the desired ID
Example: 01I03\n – this will tell controller with ID=01 that its ID is now 03. FFI02\n – this will tell all the controllers attached regardless of its ID that its ID is now 02. You would typically use it if there is only one controller attached.
Response: OK or Error



Letter: C
Parameters: none
Example: 01C\n – calibarate controller with ID=01
Response: OK or Error

Read back angle

Letter: a
Parameters: none
Example: 05a\n – read current angle of the controller 05. Can be used together with “T” torque command: 05T+40a\n in which case torque will be set to 40 in positive direction and angle will be reported back.
Response: 8-digit HEX values. First two chars are always 00 indicating that the target of this command is the mainboard. Next two chars is HEX ID of the controller that sends the response. Next 4 chars are 16-bit angle. For example: 0001346A\r – means that the destination is the mainboard (00), the controller that reports angle has ID=01 and the angle value is 346A.

Set Torque

Letter: T
Parameters: +- followed by HEX value from 00 to FF
Example: 01T+FF\n will set 01 controller’s torque to maximum in positive direction. 05T-80\n tells controller with ID=5 that its torque is 80 in negative direction.
Response: none. Can be used with “a” command in which case angle will be returned.