General

How the project started

In year 2012 I had the idea to build a quadcopter from scratch. The idea was to begin with the drive. Back then I have had some knowledge about electronics already due to my part-time job in an electronics repair shop and a completed training as a programmer. At this time I began studying computer science at a university close to my hometown.
I soon had noticed that most quadcopters use so-called electroncal speed controllers (ESC) to run the motors. Then I learned that this was the superior way to run brushless dc motors (BLDC). For me it was clear: I want to build the ESC's myself.
I understood the theory of the typical trapezoidal bldc control relatively quickly, which is used in almost all common ESCs. Nevertheless, I haven't had much experience with pulse wide modulation, control algorithms, position observers, microcontrollers and low level programming like timers, ADC (analog to digital converter), hardware triggering, interrupts, DMA (direct memory access) and so on.

First rotation

As a first step I bought a small 8 Bit Atmel controller, a breadboard, a handful of mosfets and bipolar transistors. As an first exercise I’ve built a simple dc motor controller. Since I didn’t own a lab power supply, I modified an old ATX computer power supply. (Luckily it was very robust!) Luckily, I was allowed to the use the same tools I used during my part-time job. Nevertheless, I quickly realized that I would not get very far without my own oscilloscope. I found a bargain: a good old Tekronix TDS 210 for less than 200 bucks. And it was the same device as the one I’ve used at my part-time job!
After the dc motor controller was working well (more or less …) I started to build a three-phase controller required for BLDCs. It took me quite some time to understand how a half-bridge works, the meaning of bootstrapping and so on. I had to understand how a sensorless trapezoidal bldc commutation is working and that I also needed a comparator for zero crossing detection as well. The first three-phase design consisted of discrete parts. The gate drivers were made of separate bipolar transistors. The whole thing was soldered on a stripboard. TO-220 mosfets where used. It took a lot of time until I was able to run a BLDC motor. My first BLDC motor was an old 3.5" HDD. It didn’t run stably, lost track when applying load and was noisy. Trapezoidal BLDC controllers (and most back emf based controllers) need some kind of start-up strategy. I wanted to see the motor spinning, so my start-up strategy was to start the motor by hand :D.

First touch with Field Oriented Control

Before my trapezoidal controller has worked properly, I’ve realized that I didn’t like the trapezoidal control: it seemed unnatural to me because the back emf shape of most BLDC motors is sinusoidal, not trapezoidal. I wanted to feed the motor with sinusoidal signals and started to search for these kinds of controlling methods. I soon came across FOC: field oriented control. After reading some application notes, I realized that I needed a more powerful microcontroller. I’m sure there are some 8 Bit FOC controllers out there but I didn’t want to have to worry about fixed point arithmetic, low memory and slow CPU back then. My primary goal was to run the motor. The choice fell on STM32. I bought a STM32F4 discovery board and have had to learn to work with this new microcontroller first. During this time, I decided to go for real half bridge drivers like IRS2101.
The new powerstage was made again on a stripboard. It was connected to the STM32 discovery board. For field oriented control one needs phase current measurement: I decided to use shunt measurement combined with some special operational amplifiers designed for motor control applications (however, I had to deal with discrete OpAmps soon afterwards).


(Unfortunatley, there are some parts missing now)
This construction didn’t work well: there was too much noise in the current measurement, PWM signals and so on.

First PCB (hardware rev. 1.0)

Because of the drawbacks of the stripboard construction, I decided to design my very first PCB! Back then I didn’t dare for designing my own PCB for a microcontroller. Instead, I’ve created a 150x100mm PCB with a footprint matching the STM32F4 discovery board. This could be plugged onto the PCB. This time I wanted to place the phase current measurement into the LOW side of the halfbridges. It was a good time to learn how to use operational amplifiers. Furthermore, I’ve placed a breaking chopper circuit on this PCB. A breaking chopper is required - especially when you power the controller by a power supply. When the motor is recuperating energy, electrical power is flowing back into the power source. Most lab power supplies don’t like that: they either turn off or die. In this case the breaking chopper is turned on. In fact, it is just a resistor which eats the recuperated energy.
At this point I’ve realized that it would not be that easy to implement a sensorless FOC algorithm. So I’ve provided connectors for the hall sensors and optical rotor position resolvers on the new PCB.
This is how the first PCB looks like:

I was very proud there were no mistakes on my first PCB :-)
(the modifications have been done afterwards to try some particular things).

A few words on the long way to Field Oriented Control

Now I’ve had a working platform for developing the FOC controller firmware. It took me a very long time until the motor was running on field oriented control. I’ve had to understand clarke and park transformations, the inverses of them, space vector modulations, PID (proportional integral derivative) controllers… I’ve had to learn how to implement anti-windup circuits for PID controllers, integrations, derivations and lots of other mathematical stuff. I’ve received a lot of help from a mikrocontrollner.net member. Big thanks to Alexander! He has answered tons of my questions. After around three years of having put almost all of my spare time into this project, I was able to run a BLDC sensorless using a BEMF (back electromotive force) based position observer. The used BEMF based observer is stable enough to start the motor from standstill at partial, acceptable torque. I would estimate that this kind of observer, if tuned well, is able to start a motor with 25 to 50% of its maximum torque.

At this point the controller firmware was more than good enough for my original goal to run a BLDC for a quadcopter. The big advantages over a conventional sensorless ESC was FOC:
  • quieter
  • better throttle response
  • better startup behavior
  • current control: no motor overheat or overload
  • less motor heating because of sinusoidal current wave instead of trapezoidal
  • when used with position sensors:
    • 100% torque at standstill
    • position control like a sensored stepper motor

Disadvantages (at this time):
  • expensive, due to the additional computing power required because of FOC
  • large
  • parameters must be tuned for every new motor model individually

First size and price optimizations (hardware rev. 2.0)

My next goal was to design a more compact PCB and to make the thing a bit cheaper. I decided to use the following components
  • Processor: STM32F303CCT6
  • Gate Driver, Step Down, Operational Amplifier: DRV8302
  • Mosfets: D2PAK-7

The STM32F303CC6 has less than half of the computing power of the used STM32F4 before. I had optimized the former firmware (e.g. by using own sine and cosine functions) so it required only about ~30% of the computing power of the STM32F4 when running the program 20000 times per second (@20kHz PWM frequency). I was confident it would run on the slower and cheaper STM32F303CCT6. The STM32F303 costs around half of STM32F4.

The DRV8302 has the advantage of having integrated mosfet drivers, a step down voltage regulator down from up to 60v and suitable operational amplifiers for low side current measurement. It also offers a lot of integrated hardware protection stuff. All these features for around 6 dollars - nice!

The D2PAK-7 mosfets should offer nice and low Drain to Source resistance (Rdson) and enough surface for a good heat sink.

This was the result:



Dimensions: 60x40mm

My hopes were fulfilled: there were no problems porting the firmware from STM32F4 to the cheaper STM32F3 processor and there was still enough computing power left. As one can see the board has a lot of different interfaces, but I’ve never really used them all. The board is able to run true continuous 30A without any cooling.

Simplify assembly (hardware rev. 3.0)

The 60x40mm board was still too large to put it on a quadcopter, so I soon started designing a new one. Goals: smaller, cheaper and easier to assemble.

Result:



For the processor I chose STM32F303K8T6 in a LQFP32 package this time.
Advantages:

  • even cheaper than the previously used STM32F303CCT6
  • 0.8mm instead of 0.5mm pitch (pin center to pin center distance): easier to solder by hand

Disadvantages: less pins, flash- and ram memory, periphery like only 2 analog to digital converters

This time I decided to even omit the external oscillator to keep price, assembly and place on PCB low. That’s why this time I had even less computing power than before:

  • first board: STM32F4 run at 168MHz
  • second board: STM32F303CCT6 at 72MHz
  • this board: STM32F303K8T6 with internal oscillator at only 64MHz

For the mosfets I created a custom footprint to be able to fit

  • Toshiba’s SOP Advance
  • SOP-Advance-8
  • Nexperia’s LFPAK

and some other different packages to be more flexible and to try some different parts. For the gate drivers, step down and operational amplifiers I continued to use the DRV8302.

What I have learned from the last PCB: for better looks and practicality, I placed all connectors to the edge of the PCB this time. On the whole, I was pretty happy with this board and used it for a while to continue the development of my firmware.

Avoid complicated parts & ease assembly further (hardware rev. 4.0)

What did I not like about the rev. 3.0 hw?

The DRV8302 drawbacks for me are:

  • a little more complicated handsoldering due to the large powerpad below the chip
  • non common values of the required external parts (I always try to use common values like 1k Ohm, 1uF and so on to make the assembly by hand more comfortable)
  • limited gate drive current

I wanted the PCB to be narrower (width under 20mm) and to try attaching the heat sink underneath the mosfets, on the other side of the PCB. Furthermore, I wanted to play around with different mosfet gate rising edges, so I required some more powerful gate drivers: IRS2186. This little guy is able to source and sink at 4A!
I also wanted to play around with USB (still not done xD), so I had to provide an external crystal oscillator again. By not using the DRV8302 I had to use a standalone step down converter, operational amplifiers and a charging pump for the gate drivers.

For the required charging pump you have to calculate the average current load of the gate drivers. The following equation can be used:

total number of mosfets x total gate charge x switching frequency = averate gate drive current

Good mosfets in this small package with low Rdson have a total gate charge Qg of 50 to 100nC. Mostly I use a switching frequency of 20kHz and had planed to use 6 mosfets.

6 [mosfets] x 100 x 10^-9 [C] x 20000 [Hz] = 0.012 [A]

So I required a charging pump which can provide 12mA. I decided to use the common MAX1683 which can deliver up to 30mA. On this PCB I paid attention to place all the same components next to each other to simplify the assembly. (of course with taking into account the clean current and signal paths)
It also was my first 4 layer PCB design.

This is how the PCB looks like:



Because there were no parts behind the mosfets this time, I was able to make a very good cooling connection. For test purposes I screwed the board to a large aluminum plate for cooling. I was able to draw up to 40A as long as the large aluminum plate was being kept cool. Beyond 40A the DC bus voltage ripple rose very rapidly. Probably because of not having enough ceramic capacitors and a relatively distant electrolytic capacitor. However, this was more than sufficient. The goal was to draw about 20A without cooling and that was fulfilled.

I was very happy with this PCB. I was able to optimize my algorithms, position observers and so on. I also improved the motor parameter measure algorithms for measuring the resistance, inductance and flux linkage. I’ve also created a controlling and debugging app which communicates with my motor controller over serial interface. I’ve called it serialmonitor. I will make a separate page for this.

Sensorless at standstill

Overall, the project seemed to be slowly transitioning to completion. There was only one thing: the sensorless position observer! For now only BEMF based observer was used. Meanwhile, the developed sensorless observer was very good: it is able to startup the motor with good torque and is able to run it down to about 20-50 rpm (depending on the motor).
But one thing is and will remain: a BEMF based position observer will never be able to provide full torque from standstill. When using BEMF based observers only, one will never be able to implement a sensorless position controller which runs sinusoidal currents and runs the motor as efficiently as possible without position sensors. The reason is that BEMF is only present while the motor is spinning. At standstill, you have no BEMF information that you need to calculate the rotor position.

I think many of motor control interested people have heard about the INFORM method. It stands for Indirect Flux detection by Online Reactance Measurements. In short, the field oriented control of the motor is periodically interrupted to inject a special signal pattern. This signal pattern produces changing currents within the motor. By derivation of the current changes, it is possible to calculate current inductances in different directions of the motor coil. The relation between the measured inductances depends on the current rotor position and can be used to calculate the position at standstill. There are countless other methods beside INFORM to obtain the rotor position. They are often called “HFI” - high frequency injection. For the simplest of these methods one does not need any special controller hardware. It is even possible to run INFORM method using a single low side shunt resistor.
The general drawback of these kinds of sensorless algorithms at standstill is audible noise generated by the motor due to signal injection.

Frankenstein (hardware rev. 5.0)

After having played around with different signal injections, I noticed that I would get better results when using in-phase current sensors. The reason for that is that one can measure the currents at any time and not only when all low side mosfets are conductive. In this way I’m able to measure the currents much more often than ‘only’ 20000 times per second (synchronized to PWM frequency). All of my PCBs had only low side current sensors, so I’ve built this Frankenstein:

This is how it looks like:


Because of signal injection it was a major change within my firmware and because of my firmware version number policy this frankenstein build had to get an own major rev. number (so don’t wonder about the transition from revision 4.0 to 5.0).

I’ve added three shunts into the power rails and connected them to three external AD8418 current sense amplifiers. The output of the amplifiers is fed back to the main motor controller PCB. Of course the measurement precision of this crude construction was pretty bad, so I had to inject a very high signal into the motor to be able to calculate the rotor position. This leads to even more audible noise. There is a way to increase the precision, especially if you want to measure current derivations: measure the signal much more often and draw a line through the sample points. This is also called linear regression.
https://en.wikipedia.org/wiki/Linear_regression
The more sample points the higher the precision, the lower the required signal injection amplitude and the quieter the audible noise. The computing of linear regression requires a high amount of computing power. A pretty hard job for the small STM32F303, if you have e.g. 3x 80000 sample points per second. I had to do some handstands in the firmware to optimize the linear regression calculation and to make it run on this processor. Overall, it was not a nice solution and I wanted to experiment with some other things for which there was no computing power left. Furthermore, I wanted to experiment with higher PWM frequencies. I decided to design a new hardware again.

Powerpath Boy (hardware rev. 6.0)

The new hardware requirements:

  • STM32F405 for more computing power to continue experimenting with linear regression and other things
  • In-phase current measurement on every phase
  • standalone gate drivers
  • strong power stage
  • well accessable power supply and motor connecting pads
  • electrolytic capacitors on PCB
  • a bunch of ceramic capacitors
  • PWM capability up to 40kHz

This is how the result looks like:




100x50mm

This time I’ve decided to use 24 mosfets instead of regular 6. For every power path I now have 4 mosfets in parallel. The advantage is sinking resistance and thus sinking heat development. Moreover, we get more surface for heat dessipasion. It took me literally a few months to find the best way to place the mosfets and to route the power paths to achieve the lowest electrical resistance. I want to avoid copper bars as much as possible. Soldering them by hand is pretty unpleasant and unsoldering even more so in case you want to reuse them. This time I finally have proper mounting holes for a big heatsink. Moreover, there is a fan for better cooling. I control it within the firmware depending on the mosfet temperature measured by a NTC resistor.

Because of the 24 mosfets this time, I have a lot of gate capacity to be driven. Luckily there are strong enough gate drivers like the IRS2186.

Average current load of the gate drivers for the 24 mosfet PCB:

total number of mosfets x total gate charge x switching frequency = averate gate drive current
24 [mosfets] x 100 x 10^-9 [C] x 40000 [Hz] = 0.096 [A]

That is a lot! That’s why I’ve had to use three charging pumps (3x MAX1683) instead of one. I like using charging pumps instead of step up converters because of the easier hand-soldering and less different parts.

Pin assignment

This time I’ve assigned the pins of the microcontroller like the VESC. Maybe there are some guys with a VESC or VESC clone hardware out there who want to try my firmware. Just ask me.

Current measurement

For the amplifiers I’ve used the AD8418 again. This time I’ve had to use two shunt resistors in parallel for every phase. The most inexpensive shunts in my favourite package 2512 can take 6 watts at maximum.

For the selection of the shunt resistor values, we do some math:
Let’s assume you want to drive a motor at a maximum of 150A. To measure the current in both directions using the analog to digital converters of the STM32F4 at 3.3 volts, at 150A the output of an operational amplifier must be 1.65 volts (the half of 3.3v because of both directions) to use the whole bandwidth of the ADCs (for field oriented control the current must be measured in both directions).
The gain factor of the used AD8418 is 20.
So at 150A at one phase shunt pair the voltage drop must be 1.65v / 20 = 0.0825v. To drop 0.0825v at 150A we need the following resistance:

U / I = R
0.0825[v] / 150[A] = 0.00055[Ohm]

To achieve 0.00055R as accurately as possible we use two 0.001R shunts in parallel. We get a combined resistance of 0.0005R.

Recalculate ADC bandwidth usage with the selected shunts:

R * I = U
0.00005[R] * 150[A] = 0.075[v]
0.075[v] * 20[gain] = 1.5[v]

So at 150A the operational amplifier feeds 1.5v to microcontroller (instead of 1.65v). In this way about 91% of the ADC bandwidth is used.

Recalculate power dissipation of the selected shunts:

I * I * R = P
150[A] * 150[A] * 0.0005[Ohm] = 11.25[watt per shunt pair]

->

11.25[watt] / 2 [shunts] = 5.625[watt per shunt]

The selected shunt allows a maximum power of 6 watt.

Using two 0.001R shunts in parallel seems to have pretty good ADC bandwidth usage and the power dissipation is also OK.

However, the most powerful BLDC I have here is a Turnigy Aerodrive SK3 6354 260kv. It is rated for 70A. Unfortunately, at least without active cooling, the motor gets very hot already at 50A after 20 seconds. I think it would do better when driving a propeller, so it would cool itself. This motor is designed to be built on a rc plane or some other flying stuff. I will soon write a blog entry about my motor load bench. Because of the lack of a bigger motor, I can’t really stress out this controller for now.

Progress at sensorless standstill control

In the end, I had a stable hardware to continue developing the sensorless algorithm at standstill. Since then, I have made huge progress in developing the sensorless standstill position observer. The firmware is finally able to run the motor at standstill at full torque sensorless. Just like sensored stepper motors or sensored servos, but without needing sensors or resolvers. The firmware can run the motor seamlessly from zero to max rpm and beyond using field weakening. I’ve also managed to make the stillstand/low-speed position observer not audible. There is no noise coming from the injection and the position is calculated at every PWM cycle at e.g. 20kHz. This was by the end of 2019. Since then, I have been working on extended automated motor parameter detection, especially for the additional parameters required for the new standstill/low-speed sensorless position observer.

Ratio between software and hardware development

All in all, for now I have spent a total of about 1.5 years on hardware development and around 1 year on serialmonitor. The rest of the time since 2012 I have spent on the firmware development.


5 Kommentare:

  1. Hi ! I am very interested of this project. How to contact you ?

    AntwortenLöschen
  2. Das sieht sehr interessant aus!
    Ich starte aktuell ein Projekt in dem ich deinen Controller gebrauchen könnte.
    Falls du Interesse hast melde dich gerne bei mir unter: https://human-ascension.com/contact-us/
    Dann können wir alles weitere per mail klären.

    MfG
    Luca

    AntwortenLöschen
  3. Hello
    congratulations for your amazing work !
    Is it possible to try your software ?
    regards
    Fred

    AntwortenLöschen
  4. how can buy pcb? my email hoanghaieast@gmail.com

    AntwortenLöschen