================= IMPORTANT UPDATE =================
I have written a new post about my open ESC on this page and also updated the hardware significantly. If you haven’t built it yet and if you are planning to order parts for it, please refer to that page. I will only leave this page for reference in case you have built it before I wrote the new post and updated the hardware. Also, If you have built the ESC before, the tutorial and software on the new page also applies to the old hardware.
For about three years I have been working on a custom BLDC motor controller (also known as an ESC). I have spent hundreds of hours on writing code and I have made many minor and four major revisions of the printed circuit board (PCB). Now I finally have something that I can publish. The code can still be cleaned up a lot, especially the latest parts that I wrote in a hurry, but I don’t want to delay the release forever.
The features of this BLDC controller are:
- The hardware and software is open source.
- A STM32F4 microcontroller.
- A DRV8302 MOSFET driver / buck converter / current shunt amplifier.
- IRFS3006 MOEFETs.
- 5V 1A output for external electronics from the buck converter integrated on the DRV8302.
- Voltage: 8V – 60V.
- Current: Up to 240A for a couple of seconds or about 50A continuous depending on the cooling.
- PCB size: slightly less than 40mm x 60mm.
- Current and voltage measurement on all phases.
- Regenerative braking.
- Sensored or sensorless commutation.
- Adaptive PWM frequency to get as good ADC measurements as possible.
- RPM-based phase advance.
- Good start-up torque in the sensorless mode (and obviously in the sensored mode as well).
- The motor is used as a tachometer, which is good for odometry on modified RC cars.
- Duty-cycle control, speed control or current control.
- Seamless 4-quadrant operation.
- Interface to control the motor: servo signal, analog, UART, I2C, USB or CAN (with a transceiver). Some of these modes need a bit more code to work, but not much.
- Servo signal output. Good when e.g. controlling an RC car from a raspberry pi or an android device.
- The USB port uses the modem profile, so an Android device can be connected to the motor controller without rooting. Because of the servo output, the odometry and the extra ADC inputs (that can be used for sensors), this is perfect for modifying a RC car to be controlled from Android (or raspberry pi).
- Adjustable protection against
- Low input voltage
- High input voltage
- High motor current
- High input current
- High regenerative braking current (separate limits for the motor and the input)
- Rapid duty cycle changes (ramping)
- High RPM (separate limits for each direction).
- When the current limits are hit, a soft back-off strategy is used while the motor keeps running.
- The RPM limit also has a soft back-off strategy.
- The commutation works perfectly even when the speed of the motor changes rapidly. This is due to the fact that the magnetic flux is integrated after the zero crossing instead of adding a delay based on the previous speed.
- When the motor is rotating while the controller is off, the commutations and the direction are tracked. The duty-cycle to get the same speed is also calculated. This is to get a smooth start when the motor is already spinning.
- All of the hardware is ready for sensorless field-oriented control (FOC). Writing the software is the remaining part.
This is a photo of the front of the assembled PCB (please ignore the soldering quality…):
This is the back:
An image from the KiCad 3D-viewer
I have tested the following (and more) motors in sensorless mode and achieved good startup torque:
Issues and updates
Before presenting the details of the hardware design, I will present some notes and updates that have come to my attention while testing the motor controller. There are also some people worldwide who have rebuilt my motor controller and got it working after I helped them a bit, so I have also added the issues they have encountered here.
* UPDATE * I replaced the 3.3V regulator with the TC2117-3.3VDBTR and got rid of a few problems. The dropout voltage on the other regulator was probably too close to the difference between 5V and 3.3V, so sometimes the 3.3V supply would drop.
* IMPORTANT UPDATE * Replace L2, L3 and L4 with 0 ohm resistors. Otherwise, the DRV8302 will keep dying randomly. NOTE: This is fixed in the latest hardware versions on github. I strongly suggest that you use one of them.
* UPDATE * If the motor controller resets when drawing large current spikes, the cause can be that the buck converter shuts down for a while. I noticed this on my RC car when I set the current limit to 150A. I solved that by removing C26 from the SS_TR pin on the DRV8302. This will disable the slow start feature of the buck converter, which makes it start up fast enough after shutting down for the microcontroller not to shut down. I don’t know if this is a proper solution, but it has been working for the few hours I tested the RC car without problems.
* NOTE * The pad under the DRV8302 has to be soldered. If it isn’t, the motor controller will not work for sure. The pad is not just for thermal cooling, it is also the only ground of the DRV8302.
* NOTE * There are no electrolytic capacitors on the PCB, only small ceramic ones to handle high frequency noise. However, there should be rather large electrolytic capacitors close to the motor controller on the DC bus. I chose not to put them on the PCB to make design a bit more flexible. For example, one can add capacitors like this:
for a multicopter, it might be a bit more convenient to put a capacitor on the cable like this:
IMPORTANT UPDATE: A new version of the hardware can be found here:https://github.com/vedderb/bldc-hardware I will write a new post about that and the large amount of recent updates soon. If you want to build this motor controller, please use the hardware from this github link since it has many important fixes and features. There is also a new BOM linked from github.
The PCB has four copper layers and is designed with KiCad. The size is slightly less than 40mm x 60mm. This is the schematic (a PDF can be downloaded here):
The component positions and their values on the front:
On the back:
A BOM with mouser part numbers can be accessed via google docs:
The KiCad-files can be downloaded here. If you are missing any KiCad libraries for this project, they can hopefully be found here.
- The PCB-service from Hackvana works well for this PCB. In this case, use the following gerber files: BLDC4_Hackvana_v1.2
- The PCB service from OSH park also works well. In that case, use these gerber files: BLDC4_OSH_Park
The software consists of a ChibiOS-project for the STM32F4 and a Qt-program to test and debug the hardware. This is what the FIR filter design part of the Qt program looks like:
It is possible to plot the currents, voltages and the duty cycle in real-time. This is useful when debugging how everything behaves when e.g. the software current limits are hit while loading the motor. Data can also be sampled and stored at a high rate internally and then sent to the Qt program for plotting high-speed processes such as the commutation timing. Here is a screenshot of the program displaying the commutation timing:
Note that the hall sensor position in the screenshot above is constant because there are no hall sensors connected. When adding custom hall sensors to BLDC motors, their position can be adjusted by comparing their output to the estimated rotor position in sensorless mode. Plotting the hall sensor position while running the motor in sensorless mode is therefore very useful.
The STM32 code for the BLDC controller can be downloaded here. In order to build and run it, ChibiOS with the ST libraries and a minor modification is required – you can download it here. To set up the required toolchain you can have a look at this post.
The Qt program can be downloaded here. To build it on Ubuntu (tested on 13.10), run:
sudo apt-get install qtcreator qt-sdkqmakemake
Now you should be able to start the program and connect to the motor controller.
A short tutorial to run a motor
In this section I will describe how to run an outrunner motor in sensorless mode from Ubuntu Linux. The reason for using an outrunner is that the parameters in the github project are tuned to work with most of my outrunners that I have at home. AdjustingMCPWM_CYCLE_INT_LIMIT in the mcconf file can affects the timing and should be tuned for each individual motor.
Note: The start-up torque in sensorless mode is higher than on most sensorless hobby ESCs, but the algorithm to start the motor will cause a delay before closed-loop commutation can be used. This delay is not desirable when e.g. building a sumo robot such as this one, so in such applications a sensored motor and the sensored mode is recommended.
- Add your user to the dialout group as described here. Log out and log back in. This is done in order to access the serial port emulated by the USB interface of the motor controller.
- If you don’t any 3g modem on your computer, remove the modemmanager package. This is because otherwise there will be many seconds delay before the Qt program can access the USB port since modemmanager is interfering (I’m sure that this can be solved in some other way).
benjamin@benjamin-UX31A:~$ sudo apt-get remove modemmanager
- Install a toolchain for compiling and uploading the STM32F4 code. See this post for a tutorial.
- Download the ChibiOS-version with a minor USB modification: ChibiOS-RT-master. This modification disables the voltage sensing on the VBUS pin because that pin is used for something else.
- Compile and upload the program to the motor controller. How to use a discovery board as a programmer can be seen here.
- Assemble the PCB. The component position sheets above are very useful for that.
- Connect the outrunner motor and a power supply to the BLDC controller.
- Download the STM32 code here. Set the path in the makefile to where you have extracted ChibiOS. Compile and upload the program.
- Compile and start the Qt BLDC tool as described above or on the github page here. A window like this one should appear:
- Make sure that the USB cable is connected and the correct port is chosen in the tool, e.g. /dev/ttyACM0. If you have other devices that show up as serial ports, the BLDC controller might get another one such as /dev/ttyACM3. See the dmesg output when connecting the USB cable to see which device is assigned to it:
benjamin@benjamin-P5K:~$ dmesg | tail[ 8198.248058] usb 1-5.3: new full-speed USB device number 6 using ehci-pci[ 8198.357182] usb 1-5.3: New USB device found, idVendor=0483, idProduct=5740[ 8198.357185] usb 1-5.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3[ 8198.357188] usb 1-5.3: Product: ChibiOS/RT Virtual COM Port[ 8198.357191] usb 1-5.3: Manufacturer: STMicroelectronics[ 8198.357193] usb 1-5.3: SerialNumber: 270[ 8198.395006] cdc_acm 1-5.3:1.0: This device cannot do calls on its own. It is not a modem.[ 8198.395038] cdc_acm 1-5.3:1.0: ttyACM0: USB ACM device[ 8198.395503] usbcore: registered new interface driver cdc_acm[ 8198.395506] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
- Connect to the BLDC controller with the connect button. The lower right corner of the GUI should say Connected.
- Use the right and left arrow keys or the buttons in the GUI to run the motor. Activate the real-time sampling (with the checkbox in the main tab) to see the currents etc. in real time.
- Study the code and use/adapt the interfaces for your own application.