Quantcast
Channel: Benjamin – Benjamin's robotics
Viewing all 10 articles
Browse latest View live

A custom BLDC motor controller (a custom ESC)

$
0
0

================= 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.

=====================================================

Updated 2014-12-08

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…):

Front

This is the back:

Back

An image from the KiCad 3D-viewer

BLDC_4

I have tested the following (and more) motors in sensorless mode and achieved good startup torque:

tested_motors

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:

IMG_2551

for a multicopter, it might be a bit more convenient to put a capacitor on the cable like this:

IMG_2777_small

Hardware design

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):

BLDC_4_P1

BLDC_4_P2

The component positions and their values on the front:

BLDC_4-F_SilkS

On the back:

BLDC_4-B_SilkS

A BOM with mouser part numbers can be accessed via google docs:

BOM on 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.

PCB service

Software overview

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:

BLDC_Tool_FIR

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:

BLDC_Voltages

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.

Software set-up

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-sdk
qmake
make

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. Adjusting MCPWM_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.

Required steps

  1. 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.
  2. 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
  3. Install a toolchain for compiling and uploading the STM32F4 code. See this post for a tutorial.
  4. 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.
  5. Compile and upload the program to the motor controller. How to use a discovery board as a programmer can be seen here.
  6. Assemble the PCB. The component position sheets above are very useful for that.
  7. Connect the outrunner motor and a power supply to the BLDC controller.
  8. Download the STM32 code here. Set the path in the makefile to where you have extracted ChibiOS. Compile and upload the program.
  9. Compile and start the Qt BLDC tool as described above or on the github page here. A window like this one should appear:
    BLDC_Tool
  10. 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
  11. Connect to the BLDC controller with the connect button. The lower right corner of the GUI should say Connected.
  12. 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.
  13. Study the code and use/adapt the interfaces for your own application.


ChibiOS on my cc2520+stm32f4 boards

$
0
0

I have created a simple example where I use ChibiOS on my rf boards. You can download it here:

rfboard-chibios

In order to build it, you need ChibiOS with the ST libraries in the ext directory, which you can download here:

ChibiOS-RT-master

Update: The ST libraries are no longer required, but you can still use the ChibiOS-version above if you’d like. It should work just as well with the official version.

In this example, there are two threads that send and receive RF packets between two RF boards. If this program is uploaded to two RF boards, the red LED on each board should blink because the other board sends packets to switch it on and off and vice versa. The green LED is on as long as the board receives acks from the other board. Auto-ack can also be switched off – then the green LED should be on all the time.

This example also emulates an USB modem when the USB cable is plugged in, so you can use you favourite serial terminal to connect to it. The baudrate is ignored and does not matter. On Ubuntu, it will show up as something like /dev/ttyACM0 (or 1 or n) depending on whether you have other USB modems.

How to use it

  1. Open the makefile and make sure that the CHIBIOS variable is set to where the ChibiOS-RT-master directory is located. If it is in the parent directory relative to the project, it should be:
    CHIBIOS = ../ChibiOS-RT-master
  2. Build the project (to set up the required toolchain, see this post):
    make -j4
  3. Upload the program (requires a recent version of OpenOCD):
    make upload
  4. In order to test the CLI interface, make sure that your user is added to the dialout group as described here.
  5. Open /dev/ttyACM0 (or ttyACM1 or ttyACMn) in your favourite serial terminal, e.g. screen:
    screen /dev/ttyACM0
  6. You should see something like this:
    ChibiOS/RT Shell
    ch>

    In order to list all available shell commands, type help and press enter.

  7. In order to add new commands, create one like this:
    static void cmd_test(BaseSequentialStream *chp, int argc, char *argv[]) {
    	(void)argv;
    	(void)argc;
     
    	chprintf(chp, "This is a test command.\r\n");
    }

    and add it to the shell command list:

    static const ShellCommand commands[] = {
    		{"test", cmd_test}, // This line is for the command above
    		{"mem", cmd_mem},
    		{"threads", cmd_threads},
    		{NULL, NULL}
    };

Adding security support

In order to enable encryption of the data, add -DSECURITY_CCM to USE_COPT in the makefile. It should look like this:

# C specific options here (added to USE_OPT).
ifeq ($(USE_COPT),)
  USE_COPT = -DSECURITY_CCM
endif

Also, make sure that rf_security_key in main.c is the same for all the RF boards.

Testing my custom motor controller

$
0
0

I have been working more on my motor controller recently, and this is a brief update on the progress. One of my test rigs is my 1:8 RC car. With this one, I can test the startup torque, the braking and many of the safety functions, e.g. the transitions and currents when going from full forward to full reverse. Here is a video of the tests:


In order to use the motor controller with a servo input signal and a similar RC car, open the conf_general.h file and use these settings:

/*
* Select only one motor configuration
*/
//#define MCCONF_OUTRUNNER1
#define MCCONF_RCCAR1
//#define MCCONF_STEN
 
/*
* Select which application to use
*/
#define USE_APP_RCCAR
//#define USE_APP_STEN
//#define USE_APP_GURGALOF

On Sunday it is time for more interesting tests:

IMG_2545 IMG_2551 IMG_2554

This is a longboard that my friend makes for his bachelors thesis. It uses my motor controllers (of course :-) ) and these motors.

Startup torque on sensorless BLDC motors

$
0
0

One of the major challenges when working on my custom open source ESC was to get good startup torque and low-speed performance with sensorless motors. This challenge has been addressed in several places around the net:

Techniques I used

In order to get a smooth and quick startup without sensors I used several tricks, namely:

  • There are no hardware low-pass filters that introduce phase delay. Such filters can be avoided because the ADC samples are synchronized to the PWM timer and adjusted dynamically every time the duty cycle or switching frequency is changed.
  • After a zero crossing, the area under the voltage is integrated until a threshold for commutation based on the motor parameters. This integration is robust agaist acceleration and provides good SNR since an integrator is a low-pass filter.
  • There is a parameter that defines the voltage coupling between the windings when measuring the back-emf. This make a huge difference when running at low speeds with low duty cycle. This compensation has a RPM dependence though, which is something I tried to avoid where possible because the RPM estimation has a delay and thus causes problems during acceleration.
  • To get better voltage samples, the switching frequency is adaptive and proportional to the duty cycle. This is because the back-EMF only can be sampled during the ON-time of the PWM cycle and low duty cycles have short ON time. Since the motor is running slowly on low duty cycles, sampling and switching does not have to be as fast to keep up with the motor which makes this less of a problem. Lower switching frequency also decreases switching losses, which is a positive side-effect.
  • When the motor is un-driven, the back-emf on all phases is analysed to track the position, direction and speed of the motor. So when the motor is already spinning, the algorithm will begin in the exact state of the motor (position, duty-cycle, direction).
  • I have also used some hack-ish conditions based on trial and error to improve the startup.
  • Closed loop operation is used from the first commutation, since the measured values are clean enough when using these techniques.

This is a video where I demonstrate how this works on a scorpion outrunner and an electric longboard:

Some examples with plots

** Note that all the plots show the voltages samples captured by the motor controller, which are synchronized to the PWM timer. It would look different on an oscilloscope since the switching distorts the signal. **

This is what the phase voltage for a typical startup sequence looks like, where the duty cycle is set to 5%:

start_d5_almost_auto_voltage

Even though the duty cycle is only 5%, the waveform is clean. This is because the switching frequency is low at this speed and the on-time is long enough to get good samples. The first commutation is a bit off at first since the motor is not perfectly aligned, but the second commutation already looks perfect.

Here is another example with 35% duty cycle:

start_d32_voltage

And this is the measured current for the same startup:

start_d35_current

Here the phase voltage has some commutation spikes in the beginning because the current is quite high during acceleration, but even so the commutations are even and clean.

Here is an example where the duty cycle is ramped towards 100% rapidly:

start_d100_voltage

Again, because of the current, there are commutation spikes on the voltage. The voltage from my lab power supply is also dropping because of the load. Even so, the commutations are even and clean.

Here is one unusual case, for which I had to restart the motor 20 or 30 times to get it captured:

start_d20_auto_voltage

start_d20_auto_current

The first commutation happens to be exactly at a position where no torque is produced, which is as sub-optimal as it can get. On the current waveform, it can be seen that the current limit of 60A is applied. After 40 millisecond, the algorithm decides that nothing has happened for a too long time and adds an auto-commutation. After this, the motor is tracked right away and the commutations are nice and even. This works even though the motor was stalled with 60A for a while.

Here is one example where I start the motor, switch off power after a few commutations and then switch on power again:

start_release

It can be seen that the un-driven back-emf is tracked perfectly while the power is gone and no commutation is missed or distorted during the transitions.

Results

The electric longboard I have been working on starts perfectly smooth without sensors (see the video above).

I have also tested this on a 700w hub motor on an electric bicycle with extremely good results. Full throttle from a complete stop is smooth and no problem at all. I don’t miss hall sensors here one bit.

Chosing the right BLDC motor and battery setup for an electric skateboard

$
0
0

Recently, I have been involved with the electric skateboard community because of my custom ESC. I get many questions about motor kv, gear ratio, current, voltage and efficiency. In this post, I will try to explain how things are connected and how to chose the right setup. I will try to keep things simple and not involve too many equations to provide a good intuition for the DIY community. The assumption in this post is that we are using an 50mm-60mm hobby outrunner motor.

KV

First of all, I will try to make some things clear about the KV rating of these motors. Even if there are several versions of the same motor available with different KV, the properties of the motor are exactly the same but at different voltages/currents. The only difference the KV makes is how to choose an ESC and a battery pack, but I will explain more about that in the ESC section. For the same motor, the low KV versions have more windings with thinner wire, while the high KV versions have less windings with thicker wire. As long as they have the same mass of copper, they are exactly the same in regard to max power output, torque, efficiency, max RPM; but at different currents/voltages. If they don’t have the same mass of copper they are different, but it is always true that the more copper is squeezed into the stator, the better the motor is.

Let’s look at an example: Suppose an 8 turn motor has one ohm winding resistance. The winding resistance is proportional to the wire area times wire length. Making the same motor with 4 turns would allow twice as thick wire. Since that wire also is half as long, the resistance is four times lower: 0.25ohm. Further, since current times turns is proportional to torque, we need twice as high current with 4 turns to produce the same torque as with 8 turns. The copper losses are the voltage across the windings times the current: U*I. The voltage across them is R*I, so the losses are R*I*I. This square relation means that doubling the current will produce four times as much losses, however, since we got four times lower resistance the losses are the same for the 4t motor with double the current as for the 8t motor with half the current. Also note that the 4t motor will spin twice as fast as the 8t motor at the same voltage, so it will have double the kv. Putting this together, the 4t motor is equivalent to the 8t motor, but at half the voltage and double the current.

So, regarding KV: different KV versions of the same motor are fully equivalent. KV only affects the battery and ESC choice. Therefore, while comparing motors, lets talk about torque instead of current because torque is proportional to current / KV and, as explained above, the KV value can be changed freely with the amount of turns and copper thickness.

RPM/Losses/gear reduction

Now we know that copper losses are proportional to the square of the torque produced by the motor, and at low RPM and high load they are dominant. As RPM increases, other losses start to add up exponentially. In my experience, these losses start to get significant around 60k electrical RPM, which for a 14-pole motor is about 8570 mechanical rpm (most 50mm+ outrunners have 14 poles, some unusual ones have 18). Because of the square relation, it is desirable to run at as high speed and low torque as possible as long as we stay below 8.6k RPM. To express the square relation in some numbers, having double the RPM and half the torque at a certain power output will cause four times less losses. The lesson from this is that: make sure the top speed you design the skateboard for is at around 8.6k rpm on the motor if you are using an 50mm-60mm outrunner.

For my longboard with 84mm wheels, where I would like to design for a top speed of about 35km/h with a sing motor, I would need a gear ratio of about: (35 / (0.084 * pi * (8600 / 60) * 3.6) = 0.257 which is 1:(1/0.257) = 1:3.9. Note that this gear ratio is independent of battery voltage and motor kv. Keep in mind that 8.6k rpm is not an exact number, but a guideline that seems to apply quite well to all 50mm-60mm hobby outrunners I have tested so far.

Batteries/ESC/KV

As noted previously, we are designing for 8.6k rpm since we are using 14 pole motors and 60k electrical rpm seems to be a good value according to my experiments.

The resistive losses in the MOSFETs in an ESC are proportional to the square of the current, because the voltage across the MOSFETs is Ron*I and the power, which is U*I, in this case is Ron*I*I where Ron is the ON-resistance of the FETs. This means that for a given FET, doubling the current will produce four times the losses. Remember that current is directly proportional to motor torque. From the ESC perspective, we should run on as high voltage and low current as possible. Now, one interesting fact about MOSFETs is that the lower voltage they are designed for, the lower resistance they tend to have. So if I make an ESC for a lower voltage, the FETs will also have lower resistance. However, the PCB traces always have the same resistance and MOSFET resistance does not seem to decrease as fast as their voltage decreases, meaning that an ESC designed for higher voltage tends to be more efficient in general. When the voltage gets too high, handling it while switching fast starts to become problematic. I have discovered that a good trade-off is at around 60V (quite safe for 10s or 12s lipos), where the efficiency is good and the voltage is not too problematic to handle.

Going back to my longboard example with 84mm wheels and a top speed of 35 km/h at 8.6k RPM with a 1:3.9 gear reduction, let’s look at a good motor KV. At 12s, which seems good from the ESC perspective, and a moderate charge level, we have 3.8 * 12 = 45.6 volts. Since we want to run the motor at 8.6k RPM, we need a KV of 8600 / 45.6 = 188. Now, that is quite low. Since there are none or few 50mm outrunners with that KV available, we can do two things:

1. Run at 10s. Then we need a KV of 8600 / (10 * 3.8) = 226. Luckily, there happen to be 225 KV motors available on hobbyking :-)

2. Change the KV of the motor. Yes, this can be done quite easily without rewinding the motor. Almost all outrunners are connected using a delta-connection. By removing the heatshrink of the motor wires, they can be split up and reconnected in a star-connection. This reduces the KV by a factor of sqrt(3) = 1.73. For this modification, we can use a motor with a KV of 188 * sqrt(3) = 325. There are several hobby motors available close to that KV, so that is no problem. I have tested this modification on several motors and it works really well.

Open Source ESC Video Logging on Electric Longboard

$
0
0

In order to get an impression about what the load looks like while using my open source ESC on an electric longboard, I wrote a program using Qt and opencv to do real-time video overlay logging while testing. This is the first test I made in my basement:

Four threads are used:

  1. Capture images from the webcam (framegrabber.cpp).
  2. Overlay the images with real-time information and graphs (frameplotter.cpp).
  3. Encode a x264 video from the images (videocoder.cpp).
  4. Record audio, fetch data from the ESC and keep everything in sync (logger.cpp).

The source code and a small description on how to install and use it can be found on github;

https://github.com/vedderb/bldc-logger

Here is one indoor test in the V-building at Chalmers University test where the temperature is logged as well:

and this is one outdoor test with some uphills around chalmers:

I have been using my laptop with an external webcam for the tests in the videos, but it also works on my odroid u3 with lower resolution.

Connecting a programmer/debugger to my custom STM32 PCBs

$
0
0

When I make custom STM32 PCBs (such as my RF-mote or my ESC), I use an SWD connector for programming and debugging the microcontroller. The connector is a 6-pin micro-jst connector with 2mm pitch, which easily can be found by searching on ebay. An STM32 discovery board with stlinkv2 works perfectly for programming and debugging, and can be connected as shown here (click on the picture to get a larger version where the wire colors can be seen):

DiscoveryBoards_text

Notice that I have removed two jumpers on the discovery board to disconnect the SWD from the microcontroller. The pins in the jst connector are ordered in the same way as on the discovery board, but the outermost (green) cable is connected to 3V or VDD.

There are also some small and inexpensive stlinkv2 programmers available on ebay (just search for stlink v2), such as this one which I have soldered a micro-jst cable to:

EbayStlink_small

Update:

I had some problems with too long JST cables. If uploading the program does not work for you, try shortening the JST cable.

VESC – Open Source ESC

$
0
0

Post updated 2016-01-22

About this project

I have made many updates to my custom motor controller recently and the old post is getting confusing with notes and updates, I decided to write a new post about it that hopefully is more clear, more complete and easier to follow. This might sound a bit ambitions, but my goal is to make the best ESC available. I really enjoy sharing knowledge, so I want to keep all the hardware and software open.

This is an overview of the schematic (download a complete PDF here):

Schematic-1

This is the front of the PCB:

PCB_Front

The back:

pcb_back

3D render from KiCad:

3D

Some screenshots of the configuration GUI (BLDC Tool):

RT_Data

MCCONF_Limits

APP_PPM

Resources

All files are on github to keep them up to date, so check these links on a regular basis:

Related posts

Forums

Because information about the VESC is scattered all over the internet and a lot of information is in email conversations with me, I have created a forum dedicated to the VESC here.

Live Chat

I have created an IRC channel on freenode where you can live chat with me and other users about VESC and my other projects. Feel free to join: http://webchat.freenode.net/?channels=vedder

Features

  • The hardware and software is open source. Since there are plenty of CPU-resources left, the customization possibilities are almost endless.
  • STM32F4 microcontroller.
  • DRV8302 MOSFET driver / buck converter / current shunt amplifier.
  • IRFS7530 MOEFETs (other FETs in the same package also fit).
  • 5V 1A output for external electronics from the buck converter integrated on the DRV8302.
  • Voltage: 8V – 60V (Safe for 3S to 12S LiPo).
  • Current: Up to 240A for a couple of seconds or about 50A continuous depending on the temperature and air circulation around the PCB.
  • Sensored and sensorless FOC wich auto-detection of all motor parameters is implemented since FW 2.3.
  • Firmware based on ChibiOS/RT.
  • PCB size: slightly less than 40mm x 60mm.
  • Current and voltage measurement on all phases.
  • Regenerative braking.
  • DC motors are also supported.
  • Sensored or sensorless operation.
  • A GUI with lots of configuration parameters
  • Adaptive PWM frequency to get as good ADC measurements as possible.
  • RPM-based phase advance (or timing/field weakening).
  • 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: PPM signal (RC servo), analog, UART, I2C, USB  or CAN-bus.
  • Wireless wii nunchuk (Nyko Kama) control through the I2C port. This is convenient for electric skateboards.
  • Consumed and regenerated amp-hour and watt-hour counting.
  • Optional PPM signal output. Useful 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 an 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. If the current becomes way too high, the motor is switched off completely.
  • The RPM limit also has a soft back-off strategy.
  • 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. However, I’m not sure if FOC will have many benefits for low inductance high-speed motors besides running a bit quieter. Sensored and sensorless FOC is fully implemented since FW 2.3.

The is the ESC mounted on my electric longboard:

pcb_on_longboard

Sensorless startup and low-speed performance:

A short tutorial/demonstration on how to upload the firmware and get your motor running:

My electric longboard:

Video overlay logging (see a post about that here):


Hardware

The PCB is designed using KiCad. Have a look at the links under the Resources heading at the top of this page to find all files. Currently I have no assembled PCBs or kits to sell, but you can order bare PCBs from hackvana with these gerber files. Since hackvana got so many orders for my ESC, Mitch wrote a wiki page about how to order VESC boards from him. That makes it super easy to order the PCBs from him.

The components in the BOM can be ordered from mouser.com. Mouser numbers are included in the BOM as well. Make sure to order a bit extra of small capacitors and resistors in case you drop some of them and since the price doesn’t change much at all. Last I ordered, ordering 10 MOSFETs was cheaper than ordering 6 because there is a price break at 10, so have a look at the price breaks as well.

For assembling the PCBs, the following pictures are useful (the latest versions can be found on github):

B_Modules-1 F_Modules-1

Remember to put an electrolytic capacitor close to the ESC on the supply cable. How large it has to be depends on the length and inductance of the battery cables, but I usually use a 2200uF 63V capacitor.

Soldering Tips

This is the best tutorial I have seen so far. It really is as easy as it looks when done right.

  • Flux is essential. Without flux, it won’t work. I use a flux pen.
  • Lead-free solder is no good. It has more poisonous flux, requires more heat, gives lower quality and is difficult to handle. Don’t use lead-free solder.
  • Use a flat, screwdriver-shaped tip. Don’t use a cone tip, because putting solder on the top of it is almost impossible.
  • If you get bridges between smd pins, removing them is easy with a soldering wick.
  • Make sure to get the alignment right for the microcontroller when soldering the first corner. If you solder multiple corners and the chip is misaligned, you have to use hot air and remove it, then clean the pads and start over.

Here is a video on the technique I use to solder the pad under the DRV8302:

I just put solder on the pad and use a hot air soldering station. Again, using leaded solder makes it easier. When soldering the DRV8302, I first solder the pad using hot air and then I solder the pins with a soldering iron. Notice that the pad under the DRV8302 must be connected for it to work, since it is the ground connection.

Creative Commons License
VESC Hardware by Benjamin Vedder is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Software Installation and Configuration Tutorial

This a brief tutorial on how to get everything running using a fresh install of Ubuntu 14.04. Here is a video where I do everything live to demonstrate that it isn’t that difficult. Please read all the instructions carefully to avoid most problems.

So let’s open up a terminal and get started…

Preparations

Install a toolchain to compile the firmware (for more details, have a look at this page):

sudo apt-get remove binutils-arm-none-eabi gcc-arm-none-eabi
sudo add-apt-repository ppa:terry.guo/gcc-arm-embedded
sudo apt-get update
sudo apt-get install gcc-arm-none-eabi=4.9.3.2015q3-1trusty1

Install other dependencies

sudo apt-get install build-essential qt-sdk openocd git libudev-dev libqt5serialport5-dev

Add yourself to the dialout group to access the USB port of the ESC without being root:

sudo adduser $USER dialout

Uninstall modemmanager (unless you use it) to avoid a delay every time the ESC is plugged in to the USB port:

sudo apt-get remove modemmanager

Add udev rules to access the programmer without being root:

wget vedder.se/Temp/49-stlinkv2.rules
sudo mv 49-stlinkv2.rules /etc/udev/rules.d/
sudo reload udev

Log out and log back in. You should now be ready to compile the firmware, upload the firmware, compile BLDC Tool and run BLDC tool.

Download, Compile and Upload the Firmware

First, connect a programmer as described in this post. Then, download the latest firmware from github, compile and upload it:

mkdir BLDC
cd BLDC
git clone https://github.com/vedderb/bldc.git bldc-firmware
cd bldc-firmware
make upload
cd ..

Note: before running the make upload command, you should open conf_general.h and select which hardware version you are using. It is printed on the PCB. Also, 2015-01-22 I changed the voltage divider resistors to allow up to 60V to be measured by the ADC, so in that case you also have to override VIN_R1 to 39000.0 in conf_general.h.

Download, Compile and Upload the Bootloader

Again, connect a programmer as described in this post. Then, download the latest bootloader from github, compile and upload it:

mkdir BLDC
cd BLDC
git clone https://github.com/vedderb/bldc-bootloader.git bldc-bootloader
cd bldc-bootloader
make upload
cd ..

With the bootloader, BLDC Tool can be used to upgrade the firmware later.

Download, Compile and Start BLDC Tool

From the BLDC directory that you created in the previous step, type:

git clone https://github.com/vedderb/bldc-tool.git bldc-tool
cd bldc-tool
qmake -qt=qt5
make
./BLDC_Tool

You should see the following screen:

MCCONF_Limits

Connect the ESC to the USB port of your computer and click “Connect” in BLDC Tool. The lower right corner should now say “Connected”. If you have gotten this far, you should be ready to connect a motor and configure the ESC from BLDC Tool.

Note: If you have more than one usb-modem device in your computer (laptops often have built-in 3g modems), then you have to change ttyACM0 to the port of the ESC. To figure out which ttyACMx port the ESC got, open a terminal and type the following command right after plugging the USB cable in:

dmesg | tail

BLDC Tool can also be started by going to the bldc-tool directory with a file browser and double-clicking on “BLDC_Tool”.

Updating to the Latest Firmware

Updating to the latest firmware and the latest version of BLDC Tool is rather simple. From the bldc-firmware directory, type the following commands while the programming cable is connected to the ESC:

git pull
make upload

Note: Updating the firmware will delete the configuration of the ESC. To save it from BLDC Tool, use the “Read configuration” button and then “Save XML”. After updating the firmware, you can restore it with “Load XML” and “Write configuration”.

Also updating BLDC Tool is important and recommended at the same time as updating the firmware. In order to do that, go to the bldc-tool directory and type:

git pull
qmake
make

Now you have the latest version of the firmware and BLDC Tool. Remember to reconfigure the ESC after these changes.

Motor Configuration

Note: During the configuration, it is assumed that the USB cable is connected to the ESC and that the lower right corner of BLDC Tool says “Connected”.

The first thing to do in the “Motor Configuration” tab is to click “Read configuration” while the ESC is connected to get the current configuration. After that, click “Load XML” and look for a configuration that is the same as or similar to your motor in the “mc_configurations” folder included with BLDC Tool. If you find exactly your motor, you don’t have to change anything unless you want to tweak some parameters for your application.

Note: Even if you load an XML configuration file, use “Read configuration” first anyway because the XML might not contain all parameters. The missing parameters will become blank and can mess with things. Soon I will make sure that sane default parameters are loaded, but I haven’t done that yet.

Sensorless Motor Parameters

Since this ESC uses uncommon techniques to commutate the motor in order to get good low-speed performance without sensors, it is important to set correct motor-dependent parameters in the sensor(less) tab. Otherwise, the motor will run poorly or not at all.

This is what the Sensor(less) configuration page currently looks like (I will probably add more auto-detect options soon):

MCCONF_Sensorless

The important motor-dependent parameters are “Integrator limit” and “BEMF Coupling”, and they can be measured with the detection part. I will make a video showing this for several different motors soon, but until then you can try to follow these instructions:

  1. Connect the motor without any load and make sure that it can spin up freely.
  2. Make sure that no other input such as PPM is used. If it is, it will stop the motor immediately when the detection tries to start it and the detection will fail.
  3. Click the “Start detection” button. The motor should spin up, release throttle and then run slowly for a moment.
    1. If the motor doesn’t spin up properly, Adjust “Current” and “Min ERPM” until it does. In general, small motors should have lower current and higher ERPM and larger motors the other way around. Current usually is in the range 1A to 6A and min ERPM usually is in the range 300 to 1200.
    2. If spinning up works but running slowly afterwards doesn’t (the motor just stutters), try increasing “Low duty” to 0.1 or so. Increasing low duty will make it easier for the motor to run slowly during the test, but the result will become less accurate.
  4. Manually put the obtained values into the boxes. I usually round “integrator limit” down to the closest multiple of 5 and “BEMF Coupling” down to the closest multiple of 50. Having them slightly lower than the detection result is good in most cases, so that’s why I round them downwards like that. Getting these parameters perfectly right is not too critical though.
  5. The next parameters to adjust are “Min ERPM” and “Min ERPM for integrator limit”.
    1. What they should be depends on the application and is in most cases not too important, but in general lowering them will work better if the load has much inertia. I have Min ERPM around 200 and Min ERPM for integrator limit around 1000 for all my applications.
    2. You can probably keep the same parameters I have, but if you want to tweak your startup you can experiment with them.
    3. It is important that “Min ERPM” always is lower than “Max ERPM at full brake” and “Max ERPM at full brake in current control mode” on the “Limits” page.
  6. Commutation mode should always be “Integrate”.
  7. The other parameters are for RPM-based timing advance and some other things that aren’t necessary to adjust in the normal case, so I won’t explain them here yet.

For small low-inductance high-speed motors, the delay commutation mode can be used in case the integrate mode does not work. It does not require many parameters, just the minimum RPM which usually can be around 1500. I haven’t tested this mode much, but it is more or less how most hobby ESCs work (which is why it doesn’t require so many motor-specific parameters). Currently it does not support adjustable timing, but I will implement that in a few days since it is quite easy.

Phase advance (other terms: timing adjustment, field weakening)

To compensate for the current lagging behind the voltage at high speeds because of inductance or to get a bit higher top speed at the expense of some efficiency and torque, phase advance can be used. It is implemented in a speed-dependent way so that the motor gets more phase advance the faster it spins. It is implemented this way because having phase advance at low speeds does not give any improvements at all as far as I know, so the best way is to increase the effect as the motor increases its speed. BR ERPM is the electrical RPM of the motor at which the set phase advance is used, and Integrator limit scale at BR ERPM (will rename this option soon…) is the amount of phase advance to use. Setting it to 1.0 gives no phase advance and setting it to 0.0 gives 30 degrees (maximum) phase advance. The set phase advance will be mapped linearly between 0 ERPM and BR ERPM. If you don’t know what this is, you can leave the default options since it is not that important.

Motor

Current, temperature, RPM and voltage-limits can be configured depending on your application.

BLDC_Tool_motor_motor

Note: These limits are not foolproof. If you set them too high, you can damage the ESC and/or the motor.

  • Current
    • Separate limits for acceleration and braking current.
    • Separate limits for motor and battery currents.
    • “Absolute max” is checked in every PWM switching cycle and used in case the soft back-off strategy for the other limits doesn’t work. I usually set it way higher than the other limits because soft back-off is preferred rather than switching off the motor with a fault code, but it should never be higher than 150A.
    • The “Slow absolute max” box will make sure that a filtered version of the maximum current limit is used. This is useful if there is much noise and that fault code kicks in all the time. I usually have it ticked.
  • Temperature
    • At the “Start” temperature, the current will become more and more limited linearly until the “End” temperature, where the output is switched off completely. Setting them about 20 degrees apart will make the ESC slowly decrease the maximum output current as it gets too warm instead of abruptly switching everything off.
    • MOSFET temps (on the ESC) are implemented and working, but motor temps are not implemented yet. They will require an external temperature sensor in the motor. The software implementation is rather simple since I can just copy most of the MOSFET temperature limit code.
  • RPM
    • Max and Min ERPM are hard RPM limits. It is preferable to use the soft application RPM limits instead if possible.
    • “Max ERPM at full brake” (should change the name…) is the highest opposing RPM at which a direction change is allowed. Setting this too high will cause cogging when moving in one direction and giving high throttle in the other direction. On my longboard I have it at 300 and my RC car has it a bit higher.
    • “Max ERPM at full brake in CC mode” is the highest RPM at which applying full brake by shorting all the motor windings is allowed. Setting this value too high can cause much mechanical stress in some circumstances. I have it at 1500 for all my applications.
  • Voltage
    • The minimum and maximum input voltage.
    • NOTE: I changed the voltage dividers in hardware 2015-01-22. If you have built the PCB before that, the maximum voltage can’t be more than 52V. The difference is whether the PCB has 33k or 39k resistors. 33k means that maximum 52V can be measured. The latest PCBs (with 39k resistors) can measure 60V, but you should have some margin on your supply voltage to be safe. You can of course replace all 33k resistors with 39k and measure up to 60V.

Once the ESC is configured for your motor, you can use the up and down arrow keys to run the motor forwards or reverse in current control mote, or the right and left arrow keys to run the motor forwards and reverse in duty cycle mode. The buttons in the right-hand side of the GUI can also be used.

Misc

Here are the rest of the motor configuration parameters. You probably want to experiment with Startup boost if you are using current control. The rest of the parameters can be left as their default values unless you have some specific reason to change them.

BLDC_Tool_motor_misc

  • PWM mode
    • Synchronous is recommended and the best choice for a majority of all motors. If you have some weird motor, Bipolar could work better, but it probably won’t. Nonsynchronous is only for experimentation and can kill the ESC if you are unlucky.
  • Current control
    • Startup boost is the minimum duty cycle to use when using current control. If the motor is to weak when you are just starting, you can increase this parameter a bit until it feels right. The range is 0.0 to 1.0, where 1.0 is full throttle (which you shouldn’t use.). A sane range is up to 0.15 or so.
    • Min current is the minimum allowed current. There should be no reason to change this, so leave it at the default value.
    • Control gain is the gain used by the current controller. Increasing it makes the current response faster, but also increases the risk of getting an unstable system where the ESC can get damaged. Only change this if you know what you are doing.
  • Speed control
    • The PID parameters for the speed controller. Only change them if you know what you are doing.
  • Timeouts
    • Fault stop time is the amount of milliseconds that the ESC should be completely switched of when a fault code arises. After that time, it will switch on and try to listen for commands again.

Application Configuration

First, click “Read configuration” to get the current configuration from the ESC. After that, select which application to use and configure that application.

BLDC_Tool_app_general

  • Controller ID is the ID of this VESC. If multiple VESCs are connected over CAN-bus, they must have different IDs.
  • Send status over CAN has to be enabled to make other VESCs aware of this VESC and some of its current state. It should be enabled for all slave VESCs when connecting multiple VESCs over CAN-bus.
  • Changing application requires a reboot. There is a button for that. After a reboot, you have to click connect again.
  • Timeout is the amount of milliseconds after which the motor should be shut off in case the control signal is missing.
  • “Brake current to use…” can be set to make the motor brake with a certain current when a timeout occurs instead of just releasing it.

PPM

The signal that a normal RC receiver outputs is a PPM signal, so this can be used when connecting an RC receiver to the servo port.

Bldc_Tool_app_ppm

  • Control mode
    • Disabled: Nothing at all, motor is off.
    • Current: Torque control. This is what I prefer since it feels most natural. I haven’t seen hobby ESCs that have current control.
    • Current no reverse: Save as above, but no reverse function. Note that centring the now will give half throttle.
    • Current no reverse with brake: No reverse, but centre is zero torque. Reversing will brake, but not change motor direction.
    • Duty cycle: Duty cycle or voltage control. What most hobby ESCs use.
    • PID speed control: The throttle command is intepreted as a speed set command and closed-loop control is used to maintain that speed. “PID max ERPM” sets what max throttle should be interpreted as.
  • Settings
    • Deadband: how much span in the centre of the throttle should be ignored.
    • Minimum and maximum pulsewidth: The timing interpretation of the PPM signal can be adjusted in case your receiver doesn’t follow the specification or it you have some other reason to change it. Setting “Control mode” to “Disabled” and ticking display decoded PPM value is useful when adjusting these.
    • Use Median Filter enables a filter that is very useful when there are glitches on the PPM signal. If you have a quadcopter application, you should disable the filter and make sure that there are no glitches since a filter introduces some delay.
  • Soft RPM limit.
    • Speed limit that can be used in current control mode. Setting the start and end limits a bit apart will result in a soft torque decay when approaching the speed limit.
  • Multiple ESCs over CAN can be enabled to connect several VESCs over CAN bus. All VESCs must have different Controller ID and the slave VESCs must have Send status over CAN enabled (see the general tab under app configuration). The slave VESCs don’t need to have any application enabled since they will just be listening for CAN commands. Traction control can also be enabled, which reduces the torque on motors that spin faster than the slowest motor proportional to their speed difference. To connect VESCs over CAN-bus, connect the CANH and CANL signals between them. DO NOT connect 5v and GND because that is likely to cause ground loops which can reset and/or kill the VESCs.

Nunchuk

The Nyko Kama wireless nunchuk can also be used to control the ESC. Note that not all nunchuks for the nintendo wii will work, because they slightly differently.

BLDC_Tool_app_nunchuk

  • Control mode
    • Disabled or current control with or without reverse. If reverse is used, the Z button is used to toggle a direction change.
  • Settings
    • Deadband: The span in the centre of the throttle that should be ignored.
    • RPM limits: Limit the electrical RPM of the motor. The start value is the point where the torque should start decreasing and the end value is the point where the output will be switched off. Setting them slightly apart will give a soft RPM limit. Setting them very high will disable the RPM limit.
    • Ramping time constants: How fast the throttle command should be followed, in seconds.
  • Multiple ESCs over CAN can be enabled to connect several VESCs over CAN bus. All VESCs must have different Controller ID and the slave VESCs must have Send status over CAN enabled (see the general tab under app configuration). The slave VESCs don’t need to have any application enabled since they will just be listening for CAN commands. Traction control can also be enabled, which reduces the torque on motors that spin faster than the slowest motor proportional to their speed difference. To connect VESCs over CAN-bus, connect the CANH and CANL signals between them. DO NOT connect 5v and GND because that is likely to cause ground loops which can reset and/or kill the VESCs.

A video where I test this:

Realtime Data Display

Use the “Realtime Data” tab to display realtime information from the ESC. Make sure that the “Activate sampling” box is checked.

RT_Data

Common Problems and Solutions

As I encounter different problems, I will put them here together with possible solutions for reference.

Uploading the firmware does not work.

  • Make sure that you have followed all steps in the tutorial, including adding udev rules to access the programmer without being root.
  • Don’t use a too long cable for the SWD connector.
  • Make sure that you have a working programmer. I got one from ebay that didn’t work at all and one that died quickly. Otherwise they have been reliable though.

A DRV8302 fault code appears as soon as the motor starts.

  • Make sure that R16 is not mounted (see the comment in the schematic).

Connecting to VESC via BLDC Tool does not work.

  • Run dmesg to see which ttyACMx port gets assigned to VESC when plugging in the mini-usb cable.
  • Make sure that the mini-usb cable is plugged in and that power is connected to VESC. Connecting BLDC Tool is not done via the SWD programmer, but via the mini-usb port.
  • If you are using a different usb-connector than the one from the BOM, make sure that the order of the pins is correct. The connector in the BOM is upside-down, so a connector that isn’t will have all the pins mirrored.

My motor is not running properly.

  • Make sure that you have configured VESC for your motor as described above. VESC is not plug-and-play and needs an individual configuration for each motor. Without the configuration, the motor will run poorly or not at all. Read the instructions carefully.

Is there a way to “boost” the startup of my motor when using current control?

  • Yes, the Startup boost option under Motor Configuration > Misc tab in BLDC Tool can be adjusted as described above.

Update: I have ordered assembled VESCs, some of them are for sale

Update about this update: There are no assembled ESCs left. However, If you are interested in assembled VESCs you can still send me an email as described below so that I can put you on my extra list. If someone changes their mind or if there are other problems, I can send you VESCs that get left.

I have ordered 100 assembled VESCs and they will arrive this or next week. I don’t need all of them, so I will sell some of them for 115€ + shipping. Worldwide shipping with tracking is 20€ per order (which can contain more than one VESC). Shipping within Sweden is less expensive and I will update this post as soon as I know the price. You can contact me by email if you are interested (benjamin at vedder.se). Tell me how many VESCs you’d like and your address, and I will reply with an email that confirms that I have put you in my list. Later, when I have figured out how to accept payments, I will send another email with information about how to do that. As soon as I receive your payment, I will ship the VESC(s) to you and send an email with tracking information

I will update this information in the coming days, so make sure to check if there are updates.


VESC – Writing Custom Applications

$
0
0

Updated: 2016-01-22

The VESC has several extra ports and much extra computational power, so it can be used to run custom user code in addition to controlling a motor. This is convenient when there are space constraints and it is also the best way to implement real-time control applications where timing is critical. The code of the VESC is organized in such a way that it is easy to write and maintain custom applications while keeping the code up to date without having many conflicts when pulling updates using git. In this tutorial I will demonstrate how to make a custom application that will run a motor using speed control while a button is held with a speed proportional to the voltage on the ADC_EXT pin.

Preparation

Follow the tutorial in the VESC post and make sure that you can build and upload the firmware. When you can do that, you should be able to write and upload custom applications.

Connecting everything

This is the example that I’m going to use in this post. When the pushbutton is held down, the VESC will run the connected motor in a speed control loop with a speed proportional to the position of the potentiometer between 0 and 10k ERPM.

VESC_ADC_Button

 Create the custom application

Download the latest firmware from using git

mkdir BLDC
cd BLDC
git clone https://github.com/vedderb/bldc.git bldc-firmware
cd bldc-firmware

In the applications directory, create a file called app_example.c and put in the following content. This is your custom application that you can edit

#include "ch.h" // ChibiOS
#include "hal.h" // ChibiOS HAL
#include "mc_interface.h" // Motor control functions
#include "hw.h" // Pin mapping on this hardware
#include "timeout.h" // To reset the timeout
 
// Example thread
static THD_FUNCTION(example_thread, arg);
static THD_WORKING_AREA(example_thread_wa, 2048); // 2kb stack for this thread
 
void app_example_init(void) {
	// Set the UART TX pin as an input with pulldown
	palSetPadMode(HW_UART_TX_PORT, HW_UART_TX_PIN, PAL_MODE_INPUT_PULLDOWN);
 
	// Start the example thread
	chThdCreateStatic(example_thread_wa, sizeof(example_thread_wa),
		NORMALPRIO, example_thread, NULL);
}
 
static THD_FUNCTION(example_thread, arg) {
	(void)arg;
 
	chRegSetThreadName("APP_EXAMPLE");
 
	for(;;) {
		// Read the pot value and scale it to a number between 0 and 1 (see hw_46.h)
		float pot = (float)ADC_Value[ADC_IND_EXT];
		pot /= 4095.0;
 
		if (palReadPad(HW_UART_TX_PORT, HW_UART_TX_PIN)) {
			// If the button is pressed, run the motor with speed control
			// proportional to the POT position with a speed between 0 ERPM
			// and 10000 ERPM
			mc_interface_set_pid_speed(pot * 10000.0);
		} else {
			// If the button is not pressed, release the motor
			mc_interface_release_motor();
		}
 
		// Run this loop at 500Hz
		chThdSleepMilliseconds(2);
 
		// Reset the timeout
		timeout_reset();
	}
}

Open applications.mk and add your example application to the end of APPSRC

APPSRC =	applications/app.c \
		applications/app_ppm.c \
		applications/app_adc.c \
		applications/app_sten.c \
		applications/app_uartcomm.c \
		applications/app_nunchuk.c \
		applications/app_example.c

next open app.h and add a definition for your example application under Custom apps

// Custom apps
void app_gurgalof_init(void);
void app_sten_init(void);
void app_example_init(void); // Your application

now open app.c and add your app under the APP_CUSTOM case in the init function:

void app_init(app_configuration *conf) {
	app_set_configuration(conf);
 
	switch (appconf.app_to_use) {
	case APP_PPM:
		app_ppm_start();
		break;
 
	case APP_ADC:
		app_adc_start();
		break;
 
	case APP_UART:
		hw_stop_i2c();
		app_uartcomm_start();
		break;
 
	case APP_PPM_UART:
		hw_stop_i2c();
		app_ppm_start();
		app_uartcomm_start();
		break;
 
	case APP_ADC_UART:
		hw_stop_i2c();
		app_adc_start();
		app_uartcomm_start();
		break;
 
	case APP_NUNCHUK:
		app_nunchuk_start();
		break;
 
	case APP_NRF:
		nrf_driver_init();
		break;
 
	case APP_CUSTOM:
#ifdef USE_APP_STEN
		hw_stop_i2c();
		app_sten_init();
#endif
		app_example_init(); // Your example application
		break;
 
	default:
		break;
	}
}

After this you are done editing the source code, so connect a programmer to the VESC. Go to the terminal in the bldc-firmware directory and type make upload to build and upload the firmware.

make upload

Alternatively, you can just type make and upload the the firmware using BLDC Tool and the bootloader. The .bin file for the firmware will be created in the build directory under bldc-firmware.

Using your custom application

Configure the VESC as described in my other post as usual. In the app configuration, select custom user application

app_conf

and write the configuration. The next time the VESC boots, your custom example application will be loaded. Not too difficult, right?

Some tips

  • Have a look at the other applications for some inspiration.
  • mcpwm.h has all motor control functions and measurements that you can use.
  • The pin macros for the UART TX pin in this example are found in hwconf/hw_46.h. The ADC macros are also found there.
  • To print text for debugging in the BLDC Tool terminal, include commands.h and use the commands_printf function like the normal printf in C.
  • Include can.h and use the functions there to communicate with other VESCs over CAN bus. It is fairly easy and straight forward.
  • Have a look at the ChibiOS documentation which is very good. The testhal directory for this MCU has some good example applications that you can have a look at. Just be careful to not use drivers that are used by the VESC already, such as ADC. To read ADC values, use the macros and indexes found in hw_46.h that will use the existing implementation.
  • Eclipse is good for editing C source code. Just create a makefile project in eclipse and base it on the bldc-firmware directory. I will update this post or write a new one with how to make the indexing work in eclipse for C makefile projects, which is very useful.

Updates

  • 2016-01-22: Changed mcpwm to mc_interface for the FOC update.

Communicating with the VESC using UART

$
0
0

Many people have asked me how to communicate with the VESC using UART, but I did not have a good answer since I haven’t written any tutorial about that and the only thing I could refer to was the BLDC Tool code. Now I have created a project for the STM32F4 discovery board that implements UART communication with the VESC where the full interface is implemented. In this post I will try to explain how the code works and how to port it to other platforms.

Getting started

Start by downloading the code from github: https://github.com/vedderb/bldc_uart_comm_stm32f4_discovery

If you have a stm32f4 discovery board, you can upload the code to it and test it by following the tutorial in my VESC Post for installing the toolchain. After that, just connect both USB ports of the discovery board (one for the built in programmer and one for the serial terminal) and type make upload from the project directory. Don’t forget to connect rx (PB11), tx (PB10) and gnd from the discovery board to tx, rx and gnd on the VESC. The discovery board will show up as a USB-serial port and you can use a serial terminal such as screen or gtkterm to access a simple command line interface on it. Only a few commands are implemented for the command line interface (type help to list them), but a good exercise is to write more commands in the main file using the provided interface. Doing that with the bldc_interface code should be quite straight forward.

Understanding the implementation

The VESC communicates over UART using packets with the following format:

  • One Start byte (value 2 for short packets and 3 for long packets)
  • One or two bytes specifying the packet length
  • The payload of the packet
  • Two bytes with a CRC checksum on the payload
  • One stop byte (value 3)

The higher level of the VESC communication code is the same for the USB, UART and CAN ports, so everything that can be done from BLDC Tool can be done from the other ports as well. Therefore I have abstracted out the higher layer of the communication into separate files so that it can be reused for CAN-bus and USB without modifying the rest of the code later.

The important files in the project, which you can use for your implementation, are the following. They are plain C files and don’t have any hardware dependencies.

bldc_interface.c and bldc_interface.h

These files can assemble the payload for all the commands that the VESC supports. They can also interpret packets from the VESC and extract the data from them. Notice that only the payload is handled in these files, not the start, stop, length and checksum bytes since these are different for the CAN interface.

datatypes.h

The data structures used by the VESC.

buffer.c and buffer.h

Helper functions for for going between C types and byte arrays. These are used by the bldc_interface files.

crc.c and crc.h

For calculating the CRC checksum

packet.c and packet.h

For assembling the packets for the VESC with start, stop, length and checksum bytes. These files also have a state machine where one byte received from the VESC can be added at a time to assemble a packet and check the checksum correctness.

bldc_interface_uart.c and bldc_interface_uart.h

Connects packet and bldc_interface to provide a clean UART interface. This is where the user has to make the connection to the UART interface for the platform of choice.

All of these files rely heavily on function pointers. This might sound complicated at first, but it is actually quite convenient and easy to use. The connection between these files and the UART port is done in the file comm_uart.c, which is the file that you have to implement if you want to port this to a different platform. Also, if you decide to use some other port than UART such as CAN or USB, you only have to re-implement this file and the higher level implementation will work as before.

Making the platform-specific UART connection

This should be rather straight forward. The bldc_interface_uart files have three functions that have to be used:

bldc_interface_uart_init

This is the init function that takes a function pointer to a function that you provide for sending data on the UART. You can use it something like this:

/**
 * A function that will send the bytes in *data with length len on the UART
 */
static void send_packet(unsigned char *data, unsigned int len) {
	// Your implementation
}
 
// Your init function
void comm_uart_init(void) {
	// Initialize your UART...
 
	// Initialize the bldc interface and provide your send function
	bldc_interface_uart_init(send_packet);
}

bldc_interface_uart_process_byte

Call this function every time a byte is received on the UART with the received byte. It will run the state machine in the packet assembler and the callbacks in bldc interface will be called when the packets are ready.

bldc_interface_uart_run_timer

Call this function every millisecond to reset the packet state machine after a timeout in case data is lost.

Notice that bldc_interface_uart_process_byte and bldc_interface_uart_run_timer can be omitted it you only plan to send data to the VESC and not read anything.

In this example project this is implemented in comm_uart.c. This implementation is a bit more complicated than necessary because it uses threads to run the data processing to not block the UART while running the callbacks and to not run the callbacks from an interrupt scope, but a much simpler implementation can also be done if you don’t have an RTOS. You could call bldc_interface_uart_process_byte directly from an interrupt handler every time you receive a byte.

Using bldc_interface

After you are done with the hardware specific UART implementation, you can use bldc_interface in your application. To set the current, duty cycle etc. just call the corresponding function from the setters e.g.

// Run the motor in current control mode with 10A commanded current
bldc_interface_set_current(10.0);

You can do everything that BLDC Tool can do, including changing the configuration (you should read the old configuration before updating it though). Notice that you have to call these functions at regular intervals to not trigger the timeout in the VESC that will release the motor if no new commands have been received for longer than the configured time for safety reasons. This can be done either by calling the corresponding setters at regular intervals or by calling the bldc_interface_send_alive function.

Reading data

Reading data is done with getter functions and callback function pointers. For example, to get realtime data from the VESC, first set a callback to your function for handling the data using bldc_interface_set_rx_value_func and then request the data with bldc_interface_get_values. It can look something like this:

// Your callback function for the received data. In this case you simply
// print it using printf.
void bldc_val_received(mc_values *val) {
	printf("Input voltage: %.2f V\r\n", val->v_in);
	printf("Temp:          %.2f degC\r\n", val->temp_pcb);
	printf("Current motor: %.2f A\r\n", val->current_motor);
	printf("Current in:    %.2f A\r\n", val->current_in);
	printf("RPM:           %.1f RPM\r\n", val->rpm);
	printf("Duty cycle:    %.1f %%\r\n", val->duty_now * 100.0);
	printf("Ah Drawn:      %.4f Ah\r\n", val->amp_hours);
	printf("Ah Regen:      %.4f Ah\r\n", val->amp_hours_charged);
	printf("Wh Drawn:      %.4f Wh\r\n", val->watt_hours);
	printf("Wh Regen:      %.4f Wh\r\n", val->watt_hours_charged);
	printf("Tacho:         %i counts\r\n", val->tachometer);
	printf("Tacho ABS:     %i counts\r\n", val->tachometer_abs);
	printf("Fault Code:    %s\r\n", bldc_interface_fault_to_string(val->fault_code));
}
// Somewhere in your init code you can set your callback function(s).
bldc_interface_set_rx_value_func(bldc_val_received);
// Every time you want to read the realtime data you call the corresponding getter.
// This will send the get command to the VESC and return. When the data is received
// the callback will be called from the UART interface.
bldc_interface_get_values();

Have a look at main.c to see some examples of this.

That’s it! I hope this is enough to get started with UART communication to the VESC.

Viewing all 10 articles
Browse latest View live