For the past two years, I’ve wanted to make a fully open source brushless gimbal controller. Essentially, this is a circuit board and software that can drive a 2 or 3 axis brushless camera gimbal to perform stabilization, motion, tracking, etc. I’m not happy with existing solutions like the STorM32 - closed source firmware, somewhat buggy/hard to use. Most other open source gimbal projects are a decade old and abandoned, and run on horrendously old hardware. I haven’t tried the AlexMos/SimpleBGC, but it’s rather expensive (and also closed source). There are also commercial gimbals, but other than the fact that they are all very proprietary in how they work and have bad interfaces with open standards (like UAVCAN and MAVLink), they are also really expensive and only work on the packaged gimbal.
So I’ve been researching now and then on how to design a gimbal controller. It took a while, but I think I’ve figured out enough of the steps to start prototyping a project. If this works out, I’ll post more about the development project, and if it does end up working, it’ll be open source :). However, this article is a collection of all the materials and information I’ve found along the way, and an overview of all the components required.
Closed source. Looks more expensive than it needs to be, although not entirely unreasonable. Haven’t tried, but can’t use as a starting point since it’s proprietary. Seems to be well designed/built though, and has an (optional upgrade to) a distributed controller using CAN to communicate with an external IMU and motor controller board. This is useful for reasons mentioned later on.
Open source hardware, which has been useful during research. Unfortunately, the firmware is closed source, which annoys me. I have one of the pre-NT hardware modules, which means I have to run older firmware as well. I hope the firmware has improved since then, because the old firmware is really horrible, buggy, and the configurator only works on Windows. Ugh. Newer versions use a distributed controller design, which is good, but use an in-house (proprietary) bus and protocol called “NT”.
Despite the firmware being proprietary, the STorM32 has the best open standard integration of all the gimbal controllers I’ve seen. It supports UAVCANv0 (although not v1 at time of writing), and MAVLink Gimbal protocol v1 and v2. In fact, I believe OlliW played a big part in the design of the MAVLink Gimbal v2 standard.
I reached out to OlliW, the creator of the STorM32, but he was not interested in helping out, other than giving me a couple of broad pointers (thanks anyway, OlliW). Please don’t bother him about this, it’s his choice to make the firmware proprietary.
Appears to be unmaintained for many years now. Fully open source (HW + SW). Using an AVR ATMega328P chip as the controller, which is IMO hardly adequate for a high performance gimbal. However, it does seem to have worked. Monolithic controller board design. Appears to be the original design basis for the hardware of the STorM32, as is mentioned on the STorM32 V1.1 board silkscreen.
Found this while browsing the ArduPilot docs for gimbal controller information. Fully open source (HW + SW). Port of the BruGi to an STM32F103. Not a very fast chip (and no FPU), but better than a 328P. Unfortunately also unmaintained. Monolithic controller board design.
Appears to be built for STM32F103. Unmaintained for almost a decade as of time of writing. Fully open source (HW + SW). Monolithic controller board design.
Other articles/resources I found
https://www.youtube.com/watch?v=UxABxSADZ6U. Servo gimbal, not as performant, and doesn’t help with a lot of the difficulty in building a brushless controller (3 phase motor control, rotor angle sensing).
https://www.instructables.com/DIY-Brushless-Gimbal-with-Arduino. This person seems to have designed something that works, but wasn’t actually very good at explaining what they did. The problems were outlined, but the final solution had a pretty mediocre explanation. Some source code is provided.
OlliW has a lot of articles on his blog regarding the mathematics behind gimbal and motor control. It’s a great resource, but very math heavy.
After a lot of googling about motor control, reading through existing source code, etc, I’ve come up with a design that I think should work. This is described below.
Brushless motors need to be used. They have much better response characteristics than servos. Steppers are far too bulky. However, controlling 3 phase brushless motors (BLDC) to specific angles without torque ripple is not trivial, requiring methods like sinusoidal or field oriented control. This is explained below.
Any gimbal needs at least one inertial measurement unit. This is a sensor consisting of a 3DOF accelerometer and 3DOF gyroscope (and optionally, a 3DOF magnetometer) which is used to calculate the attitude of a body. In our case, we need to find the attitude of the camera itself so we can move the gimbal motors to make the attitude what we want (level, or pointing down/sideways/whereever the user wants).
One of the most classic IMUs used in the hobby world is the TDK Invensense MPU6050. It’s cheap and widely used. Unfortunately, its also old and not very performant. There are much newer MEMS sensors from TDK and others now. Newer sensors are more sensitive, which also means they require more filtering to make sure attitude data is accurate and not noisy. However, please use a new sensor. It’s a good idea in the long run. Sometimes they are more expensive. Don’t get the cheapest sensor you can find.
IMUs output 6DOF raw sensor output regarding acceleration and angular velocity of the sensor, which has to be processed to obtain an (accurate) state estimation. This is a huge topic of its own, with a lot of literature on the web about it. The simplest such algorithm is the complementary filter, which combines a low pass filter on the accelerometer data with a high pass filter on the gyro data to produce a value (why this is the case is explained in other articles). More advanced filters include Mahony, which uses a PI controller to remove gyro drift by tracking the gyro estimate towards the accelerometer value, the Madgwick filter, and the Kalman filter.
If this is going to be on a drone or other vehicle, you should implement some vibration filter mechanism on the state estimation. This could range from a simple low pass filter or band stop/notch filter to something dynamic and FFT based like PX4 uses (although that’s probably overkill). Gimbals are supposed to be slow moving and smooth. Because they don’t have to respond quickly to sharp setpoint changes, the negative effects (response time/sensitivity loss) of aggressive low pass filtering probably won’t cause much issue.
Motor Position Estimation
Now that we know the attitude of the camera, the motors need to be turned correctly to point the camera forward. However, to do this accurately, we need to know the current rotation of all the motors (angle of the rotor compared to the stator). This is necessary because accurately driving a BLDC motor using sinusoidal or field oriented control requires knowing the current angle of the rotor to correctly choose phase voltages that will apply torque.
There are two main ways to do this. The more expensive, but more reliable way, is to use an encoder, like a magnetic encoder. This consists of installing a permanent magnet on the rotor, and using a magnetic encoder sensor like the TLE5012B to read the orientation of that magnetic field to determine the angle of the rotor. This method requires installing a magnet and an encoder per motor, or buying motors with encoders preinstalled. However, it’s the most robust solution.
The cheaper way is to use two IMUs. Remember that we previously installed an IMU on the camera to determine its attitude. If we also install a second IMU in location such as the gimbal controller board, which is NOT rotated by any of the gimbal arms, we get the attitude of the external body connected to the gimbal. By subtracting these two attitudes, we get the orientation of each of the rotors, since the rotor has to be angled that much to “transform” or rotate the body attitude into the camera attitude. This has some limitations, and is less accurate than encoders. However, it also works out of the box without installing anything on the motor, and is usually much cheaper.
Now that we know the angle of the rotor, we can drive the motor. On a 3 phase BLDC, this involves driving a certain voltage to each of the 3 phases of the motor, which creates a electromagnetic field on the stator which interacts with the permanent magnet on the rotor, inducing a torque on the rotor.
Motors need to be “commutated”, which means to periodically switch the polarity of the voltages applied to the stator to make the rotor continue spinning as it passes through different segments of a full revolution. Brushless motors don’t have brushes - mechanical devices that commutate the phases - so this has to be done by a microcontroller.
Brushless control electronics use 6 transistors, as shown below. Each phase can be connected either to battery voltage or to ground.
When only high speed drive is necessary, a simple “6 step” commutation scheme is used, either with encoder feedback or with Back EMF sensing. I won’t go into the details here, but 6 step commutation involves connecting 1 phase to battery voltage (or through PWM to vary the total voltage), another to ground, and leaving the third disconnected. The order of which one is which is cycled through 6 steps in one revolution. However, this drive technique causes torque ripple - the rotor snaps to each coil on the stator, and the torque produced varies throughout the revolution. This is not good for a brushless gimbal, which needs very low RPM (basically 0), but needs to smoothly move to and hold any arbitrary angle.
So, we need a different drive solution. Two solutions that work are sinusoidal control and field oriented control. Sinusoidal control is the simpler solution, which involves charging all 3 phases at different voltages based on a sinusoidal lookup table, which creates a magnetic field in the stator at whatever angle you want. By changing this “target” the angle, the rotor can be moved to any desired angle.
An even better solution is to use field oriented control. FOC is similar to sinusoidal, but instead of trying to act on the phase voltages directly, it tries to maintain a certain amount of torque at maximum possible efficiency by keeping the stator and rotor magnetic fields perpendicular. I have written an article about FOC here. Using FOC isn’t strictly necessary, but will likely improve performance over plain sinusoidal. However, it’s also more complex to implement. One important addition to the article I wrote is that a technique called “space vector PWM” should be used, which will improve torque output at the same energy usage/battery voltage input. This is important for maximizing performance.
When first looking at the STorM32 schematics, I found that the design uses a TC4452 MOSFET driver as opposed to just transistors. While usually used to drive transistors, these drivers essentially connect an output to either battery voltage (if input signal is high) or ground (if input signal is low). Hence, they act as 2 transistors in one chip. Note that this removes the ability to disconnect a phase entirely, as is done in 6 step control. However, since sinusoidal or field oriented control mechanisms are used, which always energize all three coils (just at different levels using PWM), this isn’t a problem.
The gimbal controller includes a microcontroller, optionally an inertial measurement unit (required if using the IMU based motor position estimation method), and input circuitry to read input from external controls (RC receiver, flight controller, Serial/MAVLink, CAN bus, USB configuration). You also need the battery input and power management electronics, transistors (unless you’re using a distributed design, which as explained below, has many benefits), and other assorted accompanying hardware. However, it’s mostly self explanatory - you just need to go through the effort of laying everything out on a PCB.
You should be able to use standard PID control to command the motors to stabilize the camera. This is straight forward to implement. The only thing to note here is that you should probably tune your PID to maximize disturbance rejection rather than tracking performance like you may be used to. This is because the primary objective of a gimbal is not to accurately track a moving target angle, but rather to ignore outside influences such as quick body movement/acceleration and vibration.
Wiring is easy, right? The difficulty comes from the fact that the inertial measurement unit mounted to the camera needs to send data back to the gimbal controller. IMUs use the I2C or SPI communication protocols, which are both not resistant to electromagnetic interference, and suffer from signal integrity issues. This is bad because the IMU wires are usually close to the gimbal motors. I came across this issue a lot on the STorM32, which is why newer versions of that board use an NT bus.
The solution here is to increase the cost and complexity of the design slightly by installing a microcontroller on the circuit board with the camera IMU on it. The MCU reads the I2C/SPI data, processes it, and transmits data to the main controller over a more robust bus, like CAN(FD) or RS-485. These are differential signals, which in short mean they are more resistant to “common mode noise” and external electromagnetic interference. Since you have the IMU on a separate board now, you can also choose to split motors onto their own PCBs with dedicated MCUs. This allows you to improve wiring significantly, add encoder support without more I2C/SPI errors, and makes the design more modular. However, it also increases cost.
There you have it! I think I’ve covered everything you need to create a brushless gimbal controller. I’m currently in the early stages of designing one, along with my teammates at AmadorUAVs. If it works out, it will be published as open source (both the hardware and firmware). The goal is to make a distributed design with CAN, use new hardware (STM32G4/G0 and newer TDK ICM IMUs), and priotize interoperation with open standards (UAVCAN v0/v1 and MAVLink). If you have any questions, feel free to email me at