diff --git a/README.md b/README.md index f413ed7010b7b00a63456b37c0be558e98bfca06..1e400889599f488f552bb126be5dc52f45f24210 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,15 @@ # MachineKit BLDC Driver -See: [Circuit Development](https://gitlab.cba.mit.edu/jakeread/mkbldcdriver/tree/master/circuit), and [Code Development](https://gitlab.cba.mit.edu/jakeread/mkbldcdriver/tree/master/embedded) +See: [Circuit Development](/circuit), [Code Development](/embedded), and [Education](/education) -## Background, Motivation +## What + +The MMKBLDC Project is my attempt at building a decent controller for Brushless Motors. BLDCs are excellent sources of mechatronic actuation: they're [power dense](https://jakeread.pages.cba.mit.edu/actuators/) and serve the motion control justice present in most state of the art robotics. However, controlling them is non-trivial, and requires the combination of some EE expertise, some control expertise, and some hardware know-how. + + + + +## Why This project is largely a follow-on to [my Teensy-Powered Brushless Motor Controller](https://github.com/jakeread/tesc), and with this new work, may the TESC project RIP. A moment of silence. @@ -13,143 +20,27 @@ Once around is never enough* Eulagies aside, I am still motivated to do this. Brushless motors are the go-to motive force for electromechanical systems. By that I mean that just about any time you see a robot-like thing, or machine, moving about, there's a big likelihood that the thing doing-the-moving has a brushless motor in it's guts - or some variant thereof (stepper motors count as BLDCs in my books). See [this characterization of actuators](https://jakeread.pages.cba.mit.edu/actuators/) to get a sense for why. -# An Overview of BLDC Drive - -### Electric Motors actuate with a rotating a magnetic field. - -In relation to [Ashby's fundamental actuator types](/papers/ashby-actuators.pdf), brushless or brushed electric motors are effectively continuously-rotating solenoids. - -We have something with magnets, and something else with electromagnets, we use the electromagnets to rotate the field, we pull the magnets along. Rotating the field is called *Commutating* the motor, and can be done mechanically or electrically. With mechanical commutation, we have Brushed DC Motors, with electrical, Brushless DC Motors. - - - -### Brushed Motors rotate the magnetic field using 'brushes' - -Brushes are mechanical switches that use the motor's own rotation to change the magnetic field. Super neat. [Here's a link to Sparkfun's explanation.](https://learn.sparkfun.com/tutorials/motors-and-selecting-the-right-one/dc-brush-motors---the-classic) - -And a GIF. While the rotor rotates, different switches are connected to current, and the coils - to - pads relationship is set up such that the current will cause the motor to rotate. Pardon my abbreviated explanation. - - - -Brushes make motors very simple. You just pump voltage (in time, current) through the rotor, and things happen. However, there are resistive losses at the brushes, as well as friction losses. - -#### Brushless Motors rotate the magnetic field with switches. - -Power transistor technology means that we can do this electronically - use a computer (or simple timer) to switch the phases. - -So we can make the coils stationary, and 'artificially' switch the direction and timing of current flowing through them. - -Here's an example of '6-step' commutation. This is incredibly common for speed control, and simpler devices, as it requires very little processor work. It can also be done in an open-loop fashion, where we blindly switch currents at a set rate to control for speed. - - - -Here's a nice GIF of sinusoidal commutation (where phase currents follow a nice, smooth wave). This is more ideal than 6-step commutation for a number of reasons, some of which are discussed in the next section. Mostly, we get to use more of each coil (we have all three on simultaneously) and we have finer control over the magnetic vector. - - - -We can see the three current vectors (that translate into a combined magnetic field vector). The permanent magnetic field of the rotor follows this electromagnetic field around. - -Digikey has a nice article on sinusoid control [here.](https://www.digikey.com/en/articles/techzone/2017/jan/why-and-how-to-sinusoidally-control-three-phase-brushless-dc-motors) - -### Control - -Control of Brushed DC motors is straightforward, we use one Full H-Bridge to drive current in both directions across the coils. - - - -However, a brushless motor requires a bit more thinking. We use three Half H-Bridges to source and sink current between the three coils, each having a common connnection to one another. - - - -### Gate Driving - -Driving those Half-Bridges also requires a bit of doing, and gets us into some intricacies of MOSFET selection and, well, gate driving. Namely, MOSFETS have 'gate charge' - a set charge we have to drive into the gate pin before the fet turns on. If you look at the [mosfet datasheet](/datasheet/Infineon-IRF6648-DS-v01_02-EN.pdf) from the FET I'm using in this circuit, you'll find the fets have a gate charge of 36nC. We have to drive this charge into the gate every time we turn it on, and we're doing so at 20kHZ or more. This adds up. While we can get away with driving a low-side MOSFET right out of a microcontroller pin, we might be limited at how fast we can do so due to that current. And we can't even begin to switch the high-side MOSFET with a microcontroller pin, as the V_gs (voltage between the gate and source) is above our source voltage, since in the case of a high-side fet, the source is our motor voltage. - -We can also use a P-doped fet on the high side, simplifying gate drive. See [this](http://files.mikrokopter.de/BL_Ctrl_V2_0_Doku.pdf) schematic for an example of that scheme. - -#### Commutation Schemes - -While it's possible to blindly drive the switches at a set frequency (determining rotor speed) it's really advantageous to drive the coils with some form of feedback on the rotor's relative electric position. There are a few ways to do so. - -**Hall Effect Sensors & Six Step** - -Hall effect sensors measure the position of the rotor's magnets: - - - -This is a straightforward and very popular method for commutation, and is always useful information, but only completely effective for motor control schemes using 6-step commutation. - -**Back EMF & Six Step** - -Hall sensors add complexity, so Back EMF has become popular, although it doesn't work at lower velocities. - -With Back EMF, we take advantage of the fact that at any given time one of the coils is not being driven. This means that we can measure it's voltage (it's acting like a generator) and use the zero-crossing point (when that voltage is 1/2 of the voltage driving the other two phases) to inform our commutation (which should happen shortly thereafter. - - - -Because we're driving the other two ends of the coil whose voltage we're measuring with a PWM signal, there's some complexity here. I won't get into it, now, but for jumping off try [this](https://www.digikey.com/en/articles/techzone/2013/jun/controlling-sensorless-bldc-motors-via-back-emf) or [this](http://www.ti.com/lit/an/sprabq7a/sprabq7a.pdf). - -**Field Oriented Control** - -aka FOC - -This is 'modern' motor control, and represents the state of the art. FOC uses a good deal of embedded computing, and has a control schematic that looks like this: - - - -We use rotor position to drive a sinusoid of phase currents, and do control over those currents to overcome inductive lag. - -Normally, position information comes from an encoder, but Sensorless FOC exists where a state estimator is used to guess at the rotor position. - -In order to jump off here, try [this](http://www.copleycontrols.com/Motion/pdf/Field-Oriented-Control.pdf), a brief overview, and [this](http://www.ti.com/lit/an/sprabq3/sprabq3.pdf), a monster, from TI, on sensorless FOC. - -#### Circuits - -A number of brushless motor controllers are available in the open-source world: - -[ODrive](https://odriverobotics.com/shop) -[VESC](http://vedder.se/2015/01/vesc-open-source-esc/) -[Ben Katz](http://build-its-inprogress.blogspot.com/search/label/Motor%20Control) -[MKBLDCDriver](https://gitlab.cba.mit.edu/jakeread/mkbldcdriver) - -Here's the schematic that I'm most familiar with: - - - -And the board, - - - -In each of these boards, we find a microcontroller, a gate driver, three half-bridges (6 MOSFETS), and current and voltage sensing circuitry. And a few BFCs never hurt. - -#### Typically Available: - -For motors, I am deeply in love with [Hobbyking](https://hobbyking.com/en_us/power-systems-1/electric-motors/size.html). - -'Outrunner' Motors (rotor wraps stator) are popularized by drone enthusiasts and have fairly high torque densities due to an increased gap radius. - - - - -[here](http://store-en.tmotor.com/goods.php?id=475) - -Inrunners (rotor inside stator) are great for speed. - - -To control these, look [here](https://hobbyking.com/en_us/power-systems-1/speed-controllers-esc.html) to start, but preferrably pick up one of the open-source ESC's mentioned above - or try building your own. With off the shelf ESCs, open loop speed control is the only thing you can do. +## How -### The State of the Art +We use an ATSAMD51 microcontroller to drive phase voltages through a gate driver, through half-bridge drivers, through motor phases. An encoder reads motor position back to the uc, and we use shunt resistors to measure current flowing through the motor coils. With this information, we can use maths to determine where the motor's magnetic field is, and control that to drive position and torque outputs. -The design of BLDCs is not changing radically - it's a good idea, and it works. +This controller runs with the assumtion you're using the [mkxmods](https://gitlab.cba.mit.edu/jakeread/mkxmods) infrastructure for controls. Over the network (see link) you will be able<sup>1</sup> to issue commands like: -**There is one exception to this** - [Thingap Motors](http://www.thingap.com/) use an ironless winding [(patent here)](https://www.google.com/patents/US20130300241) and have relatively high torque densities. The [performance is impressive](http://www.thingap.com/standard-products/) but they cost ~1k at the low end. +*Speed Control* + - use key 129, int32_t speed in rpm + - does closed loop PID control to set RPM for spindle control, mostly +*'Dumb' Torque Control* + - use key 130, int32_t torque val/(2^32) pwm duty + - applies this pwm value to the motor, under simple sinusoid control, to apply closed loop commutation to motor +*'Smart' Torque Control* + - will require some search for FOC implementation, and should reply with available torques, bandwidths, etc... here be dragons -What is interesting is where BLDCs are being used, controlled, and how they are being designed (shape, new densities). Take a look at [The Biomimetics Lab at MIT's](http://biomimetics.mit.edu/research/optimal-actuator-design) discussion on optimizing gap radius, etc. +## Building MKBLDC - +Mostly, contact me and I'll get you set and ready to programme and use the circuit to control bldc motors. -The MIT Cheetah team had their motors custom made to optimize for torque density (at a cost of total power density). Their discussion is really interesting, you can read [This Paper](/papers/mit-cheetah-actuator.pdf), a great intro to the state of the art in robotic control, of which Brushless Motors and their cousins play a large role. +In the [circuit dev page](/circuit) you'll find doc on the BOM for the MKBLDC, and in the [embedded dev page](/embedded) you'll find documentation and source code for the firmware to run it as (along with networking code to send messages over the mkxmods network). This is all under development. -As well, [Ben Katz'](/papers/katz-thesis.pdf) thesis contains an excellent review, and more intelligent discussion, on FOC, motor selection, etc. +# Footnotes -And [Simon Galouche's](/papers/kalouche-thesis.pdf) thesis contains a similar review on actuator selection for robotics. \ No newline at end of file +1. working on it \ No newline at end of file diff --git a/circuit/README.md b/circuit/README.md index c71a1686ecd0f7852688d7713258937c00c5e70c..790fa20193c3e44b6844dc57d05a2874bee7d38f 100644 --- a/circuit/README.md +++ b/circuit/README.md @@ -1,84 +1,3 @@ # Machine Kit BLDC Driver: Circuit Development -While I previously went through this with the [ATSAMS70](atsams70.md), I'm at it again with a new micro - the ATSAMD51, so I'm re working most of it. - -# Version 0.2 - -I have a laundry list of notes - below - for the next version of this. Overall, I'm interested in generally 'tightening it up' as well as fixing some circuit errors. I'm also moving away from the 'header / hardware' interface, and dropping an ATSAMD52 (the new hot chip on the block) and I'm going to treat it like a network endpoint. - -I fixed some stray, messy errors (i.e. I had some done some senseless things with the buck converter that caused it to not function) and added some filtering to my phase voltage sensing. I also added a voltage sense circuit for th VCC line so that I can figure out in software what the supply voltage is. This is useful when (later) I might end up trying to measure things like phase inductance ! - -I did a few little things (like trying to minimize the number of different capacitor sizes I had - simplicities like this are nice when I am placing components) and then was re-labelling pins for the ATSAMD51, and picking the peripherals I figured I will use. - -## New Schematicking - -This is my PWM module - Timer / Counter for Control. 'waveform extensions are featured for motor control ... deatime insertion' bam. - -I *think* I read the datasheet correctly on how hi/lo channels are multiplexed here. Or, at least, here's hoping that I did. Sorted that out in the schematic. - -I also added microcontroller input to a few lines: the gain selection on the drv8302 (controls current sense amp gain) and the fault line, and the pwm mode line (so that in worst case I can just send hi-side signals, the drv will do lo/hi deadtime insertion and complimenting for me). - -## New Routing - -But *holy dang* did I ever open up the ratsnest :| - - - -Time for some serious annealing. - -OK, I'm starting to feel satisfied with this. I've made a few big improvements - or at least they feel like nice changes. I suppose calling them big is a bit much. Besides, it was already working. *BUT* my groundplane now looks *much* better. Dang, look at that sheet of copper! - - - -Specifically, the DRV8302 used to be a bit choked out on the ground plane, and when I turned the gates on I would see that area quickly jump from 30c to 50 or 60c, still cold by power electronics standards but I was barely running any current. So this feels nice. - -I also got rid of the thermal relief on the directfet packages, so they'll sink more heat into the copper (which is now 2oz instead of 1oz) as well. AND I set up proper mounting holes right across the FETS so that I can wrap them with a big shiny piece of aluminum for when I go for the kilowatt of juice *sunglasses dude emoji* - -I left a big lineup of .1" pitch pins that will save me lots of time and pain when I'm debugging this as well, those take up a bunch of space, but I know I'll be thanking myself in a week's time. - -The last thing, routing all of the voltage sense lines, was a bit of a pain. I have to reach four traces all the way from the business end of the board back to the microcontroller... - -In any case, here it is - - - - - - - -And the full schematic - - - -## Fabricated - - - - - -## Another Run - -## MK Global Wants and board notes - -### BLDC: - -finishing: - - overall due dilligence - - verify you can SSI with those pins - - do ssi encoder board, with one cap, led option - -order: - - 2512 Shunts - - fancy h-bridges? - - thermistor - - AE10817-ND - - 493-1111-ND - - 296-48289-1-ND - - https://www.digikey.com/products/en/resistors/chip-resistor-surface-mount/52?k=&pkeyword=shunt+resistor&pv2=143&pv2=7&pv2=8&FV=mu1+mOhms%7C2085%2Cmu1.5+mOhms%7C2085%2Cmu2+mOhms%7C2085%2Cffe00034&quantity=0&ColumnSort=0&page=1&pageSize=25 - - https://www.digikey.com/catalog/en/partgroup/ncp21/10801?mpart=NCP21XV103J03RA&vendor=490 - - thermal tape for those hs's - -# Footnotes -1. Part Number. Searching Digikey (or octopart, or what have you) for bits is an art, kind of. It's intimidating, but offers much gold at the end of the rainbow. -2. This means that this is where the FET breaks down at the transistor level. The real constraint has more to do with heat - there is *some* resistive loss in any transistor (spec'd as RDS_on) - that resistance turns into heat, and if at 86A that can be a lot of heat, and if you aren't able to get it out of the package fast enough it will break down due to high temperature. THIS is why the directFET package is cool - rather than being wrapped in plastic (not conductive) it is wrapped in a metal tin (conductive) so it's easier to really suck the waste energy out of it. -3. Both are Ben. Both control BLDC. A coincidence? Consider that. \ No newline at end of file +Uses DRV8302 to drive fancy TI half-bridges, etc. Current sensing, voltage sensing, thermistor, search. \ No newline at end of file diff --git a/circuit/mkbldcdriver/eagle.epf b/circuit/mkbldcdriver/eagle.epf index 89d634419dc0ed5e8e986d70c5fa7f95abe045c4..d20f95943258087015e45fad044f7be8602fabd4 100644 --- a/circuit/mkbldcdriver/eagle.epf +++ b/circuit/mkbldcdriver/eagle.epf @@ -38,17 +38,17 @@ UsedLibrary="C:/EAGLE 8.3.2/lbr/ltspice/sym.lbr" UsedLibrary="D:/Dropbox (Personal)/CBA/doc/libraries_jake/eagle/sparkfun/SparkFun-DiscreteSemi.lbr" [Win_1] -Type="Board Editor" -Number=1 -File="mkbldcdriver.brd" -View="-4.57313 9.06348 129.433 62.9098" -WireWidths=" 0.0762 0.127 0.15 0.508 0.6096 0.8128 2.54 1.016 1.27 0.3048 0.254 0.2 0.4064 0.1524 0.2032 0.1016" +Type="Schematic Editor" +Number=2 +File="mkbldcdriver.sch" +View="-27.0067 -108.204 579.237 121.062" +WireWidths=" 0.0762 0.1016 0.127 0.15 0.2 0.2032 0.254 0.3048 0.4064 0.508 0.6096 0.8128 1.016 1.27 2.54 0.1524" PadDiameters=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0" -PadDrills=" 0.2 0.25 0.35 0.4 0.45 0.5 0.55 0.65 0.7 0.75 0.8 0.85 0.9 1 0.6 0.3" +PadDrills=" 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.65 0.7 0.75 0.8 0.85 0.9 1 0.6" ViaDiameters=" 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 0.95 1 1.05 1.1 1.15 1.2 1.3 0" -ViaDrills=" 0.2 0.4 0.45 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 1 0.5 0.25 0.3 0.35" -HoleDrills=" 0.2 0.25 0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 1 0.35 0.3" -TextSizes=" 0.254 0.3048 0.4064 0.8128 1.016 1.27 1.4224 1.6764 1.9304 2.1844 2.54 3.81 5.08 6.4516 1.778 0.6096" +ViaDrills=" 0.2 0.25 0.3 0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 1 0.35" +HoleDrills=" 0.2 0.25 0.3 0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 1 0.35" +TextSizes=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.9304 2.1844 2.54 3.81 5.08 6.4516 1.778" PolygonSpacings=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 5.08 6.4516 1.27" PolygonIsolates=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0" MiterRadiuss=" 0.254 0.3175 0.635 1.27 2.54 1 2 2.5 5 7.5 10 0" @@ -57,14 +57,14 @@ DimensionExtWidths=" 0.127 0.254 0.1 0.13 0.26 0" DimensionExtLengths=" 1.27 2.54 1 2 3 0" DimensionExtOffsets=" 1.27 2.54 1 2 3 0" SmdSizes=" 0.3048 0.1524 0.4064 0.2032 0.6096 0.3048 0.8128 0.4064 1.016 0.508 1.27 0.6604 1.4224 0.7112 1.6764 0.8128 1.778 0.9144 1.9304 0.9652 2.1844 1.0668 2.54 1.27 3.81 1.9304 5.08 2.54 6.4516 3.2512 1.27 0.635" -WireBend=1 -WireBendSet=0 +WireBend=0 +WireBendSet=31 WireCap=1 MiterStyle=0 PadShape=0 ViaShape=1 PolygonPour=0 -PolygonRank=3 +PolygonRank=0 PolygonThermals=1 PolygonOrphans=0 TextRatio=8 @@ -79,20 +79,22 @@ SwapLevel=0 ArcDirection=0 AddLevel=2 PadsSameType=0 -Layer=22 +Layer=91 +Views=" 1: -27.0067 -108.204 579.237 121.062" +Sheet="1" [Win_2] -Type="Schematic Editor" -Number=2 -File="mkbldcdriver.sch" -View="-118.98 -12.0573 84.0498 64.7235" -WireWidths=" 0.0762 0.1016 0.127 0.15 0.2 0.2032 0.254 0.3048 0.4064 0.508 0.6096 0.8128 1.016 1.27 2.54 0.1524" +Type="Board Editor" +Number=1 +File="mkbldcdriver.brd" +View="1.8203 9.22162 135.827 63.0681" +WireWidths=" 0.0762 0.127 0.15 0.508 0.6096 0.8128 2.54 1.016 1.27 0.3048 0.254 0.2 0.4064 0.1524 0.1016 0.2032" PadDiameters=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0" -PadDrills=" 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 0.65 0.7 0.75 0.8 0.85 0.9 1 0.6" +PadDrills=" 0.2 0.25 0.35 0.4 0.45 0.5 0.55 0.65 0.7 0.75 0.8 0.85 0.9 1 0.6 0.3" ViaDiameters=" 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 0.95 1 1.05 1.1 1.15 1.2 1.3 0" -ViaDrills=" 0.2 0.25 0.3 0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 1 0.35" -HoleDrills=" 0.2 0.25 0.3 0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 1 0.35" -TextSizes=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.9304 2.1844 2.54 3.81 5.08 6.4516 1.778" +ViaDrills=" 0.2 0.4 0.45 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 1 0.5 0.25 0.3 0.35" +HoleDrills=" 0.2 0.25 0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.75 0.8 0.85 0.9 1 0.35 0.3" +TextSizes=" 0.254 0.3048 0.4064 0.8128 1.016 1.27 1.4224 1.6764 1.9304 2.1844 2.54 3.81 5.08 6.4516 1.778 0.6096" PolygonSpacings=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 5.08 6.4516 1.27" PolygonIsolates=" 0.254 0.3048 0.4064 0.6096 0.8128 1.016 1.27 1.4224 1.6764 1.778 1.9304 2.1844 2.54 3.81 6.4516 0" MiterRadiuss=" 0.254 0.3175 0.635 1.27 2.54 1 2 2.5 5 7.5 10 0" @@ -101,14 +103,14 @@ DimensionExtWidths=" 0.127 0.254 0.1 0.13 0.26 0" DimensionExtLengths=" 1.27 2.54 1 2 3 0" DimensionExtOffsets=" 1.27 2.54 1 2 3 0" SmdSizes=" 0.3048 0.1524 0.4064 0.2032 0.6096 0.3048 0.8128 0.4064 1.016 0.508 1.27 0.6604 1.4224 0.7112 1.6764 0.8128 1.778 0.9144 1.9304 0.9652 2.1844 1.0668 2.54 1.27 3.81 1.9304 5.08 2.54 6.4516 3.2512 1.27 0.635" -WireBend=0 -WireBendSet=31 +WireBend=1 +WireBendSet=0 WireCap=1 MiterStyle=0 PadShape=0 ViaShape=1 PolygonPour=0 -PolygonRank=0 +PolygonRank=3 PolygonThermals=1 PolygonOrphans=0 TextRatio=8 @@ -123,9 +125,7 @@ SwapLevel=0 ArcDirection=0 AddLevel=2 PadsSameType=0 -Layer=91 -Views=" 1: -118.98 -12.0573 84.0498 64.7235" -Sheet="1" +Layer=16 [Win_3] Type="Control Panel" diff --git a/circuit/mkbldcdriver/mkbldcdriver-v0-4-fab.zip b/circuit/mkbldcdriver/mkbldcdriver-v0-4-fab.zip new file mode 100644 index 0000000000000000000000000000000000000000..0354d224878505e5db5e0d2bfef77de63607005e Binary files /dev/null and b/circuit/mkbldcdriver/mkbldcdriver-v0-4-fab.zip differ diff --git a/circuit/mkbldcdriver/mkbldcdriver.brd b/circuit/mkbldcdriver/mkbldcdriver.brd index 814ff4b15f5cd4472704d51ed92a9376adc59ad7..612fc061e3abe7347d16076043eaf925412a1af1 100644 --- a/circuit/mkbldcdriver/mkbldcdriver.brd +++ b/circuit/mkbldcdriver/mkbldcdriver.brd @@ -55,7 +55,7 @@ <layer number="45" name="Holes" color="7" fill="1" visible="yes" active="yes"/> <layer number="46" name="Milling" color="3" fill="1" visible="yes" active="yes"/> <layer number="47" name="Measures" color="7" fill="1" visible="no" active="yes"/> -<layer number="48" name="Document" color="7" fill="1" visible="no" active="yes"/> +<layer number="48" name="Document" color="7" fill="1" visible="yes" active="yes"/> <layer number="49" name="Reference" color="7" fill="1" visible="no" active="yes"/> <layer number="50" name="dxf" color="7" fill="1" visible="no" active="no"/> <layer number="51" name="tDocu" color="7" fill="1" visible="no" active="yes"/> @@ -228,6 +228,10 @@ <wire x1="86" y1="34.5" x2="86" y2="34.9" width="0.1016" layer="22"/> <wire x1="86" y1="34.9" x2="86.4" y2="34.5" width="0.1016" layer="22"/> <wire x1="86.4" y1="34.5" x2="86" y2="34.5" width="0.1016" layer="22"/> +<dimension x1="32" y1="62" x2="100.5" y2="62" x3="66.25" y3="64.5" textsize="0.6096" layer="48"/> +<dimension x1="32" y1="9.75" x2="32" y2="62" x3="28.6" y3="35.875" textsize="0.6096" layer="48"/> +<text x="60.822" y="51.9" size="0.8128" layer="22" font="vector" rot="MR270">since systems tend to leave unstable equilibria +they cannot often be in them</text> </plain> <libraries> <library name="fab"> @@ -1458,7 +1462,7 @@ design rules under a new name.</description> <contactref element="C13" pad="1"/> <wire x1="71.148003125" y1="47.583996875" x2="71.009" y2="47.723" width="0.2032" layer="1"/> <contactref element="U2" pad="P$44"/> -<via x="60" y="50.45" extent="1-16" drill="0.4"/> +<via x="60.4" y="50.1" extent="1-16" drill="0.35"/> <contactref element="C17" pad="1"/> <contactref element="C14" pad="1"/> <contactref element="U1" pad="7"/> @@ -1481,7 +1485,7 @@ design rules under a new name.</description> <contactref element="C1" pad="2"/> <contactref element="R3" pad="2"/> <contactref element="J3" pad="1"/> -<via x="60" y="48.7" extent="1-16" drill="0.35"/> +<via x="60.4" y="49" extent="1-16" drill="0.35"/> <wire x1="42.351" y1="50.834" x2="43.188" y2="50.834" width="0.2032" layer="1"/> <wire x1="43.188" y1="50.834" x2="43.295" y2="50.727" width="0.2032" layer="1"/> <via x="43.295" y="50.727" extent="1-16" drill="0.35"/> @@ -1498,7 +1502,7 @@ design rules under a new name.</description> <via x="41.55" y="55.25" extent="1-16" drill="0.35"/> <via x="46.6" y="42.2" extent="1-16" drill="0.35"/> <via x="44.7" y="41.9" extent="1-16" drill="0.35"/> -<via x="60.1" y="41.75" extent="1-16" drill="0.35"/> +<via x="60.5" y="42.15" extent="1-16" drill="0.35"/> <via x="55.66" y="61.086" extent="1-16" drill="0.3"/> <contactref element="S1" pad="P$4"/> <contactref element="R2" pad="1"/> @@ -1777,9 +1781,17 @@ design rules under a new name.</description> <via x="86.2" y="28.4" extent="1-16" drill="0.35"/> <via x="86.2" y="30.5" extent="1-16" drill="0.35"/> <via x="84" y="29.5" extent="1-16" drill="0.35"/> +<via x="59.7" y="42.15" extent="1-16" drill="0.35"/> +<via x="60.5" y="41.35" extent="1-16" drill="0.35"/> +<via x="59.7" y="41.35" extent="1-16" drill="0.35"/> +<via x="59.6" y="49" extent="1-16" drill="0.35"/> +<via x="59.6" y="50.1" extent="1-16" drill="0.35"/> <wire x1="81.1" y1="59.4" x2="81.45" y2="59.05" width="0" layer="19" extent="1-1"/> <wire x1="81.25" y1="49.05" x2="80.9" y2="48.7" width="0" layer="19" extent="1-1"/> -<wire x1="60.1" y1="40" x2="60.1" y2="41.75" width="0" layer="19" extent="1-1"/> +<wire x1="60" y1="48.7" x2="59.6" y2="49" width="0" layer="19" extent="1-1"/> +<wire x1="60" y1="50.45" x2="59.6" y2="50.1" width="0" layer="19" extent="1-1"/> +<wire x1="60.1" y1="41.75" x2="59.7" y2="41.35" width="0" layer="19" extent="1-1"/> +<wire x1="60.1" y1="40" x2="59.7" y2="41.35" width="0" layer="19" extent="1-1"/> </signal> <signal name="+3V3"> <contactref element="U2" pad="P$24"/> @@ -2244,7 +2256,7 @@ design rules under a new name.</description> <via x="88.5" y="52.5" extent="1-16" drill="0.35"/> <via x="89.9" y="52.5" extent="1-16" drill="0.35"/> <via x="89.2" y="51.9" extent="1-16" drill="0.35"/> -<via x="84.8" y="59.4" extent="1-16" drill="0.35"/> +<via x="84.7" y="59.1" extent="1-16" drill="0.35"/> <via x="83.4" y="60.9" extent="1-16" drill="0.35"/> </signal> <signal name="DRV-HI-U"> @@ -2673,14 +2685,14 @@ design rules under a new name.</description> <contactref element="R20" pad="1"/> <contactref element="R5" pad="SB"/> <via x="81.7" y="36.386" extent="1-16" drill="0.35"/> -<wire x1="81.7" y1="36.386" x2="78.086" y2="36.386" width="0.2032" layer="16"/> -<wire x1="78.086" y1="36.386" x2="77.9387375" y2="36.2387375" width="0.2032" layer="16"/> <wire x1="77.9387375" y1="30.7397875" x2="74.67335" y2="27.4744" width="0.2032" layer="16"/> <wire x1="70.7258" y1="27.4744" x2="70.5" y2="27.2486" width="0.2032" layer="16"/> <via x="70.5" y="27.2486" extent="1-16" drill="0.35"/> <wire x1="70.5" y1="27.2486" x2="70.5" y2="33.35" width="0.2032" layer="1"/> -<wire x1="77.9387375" y1="36.2387375" x2="77.9387375" y2="30.7397875" width="0.2032" layer="16"/> <wire x1="74.67335" y1="27.4744" x2="70.7258" y2="27.4744" width="0.2032" layer="16"/> +<wire x1="81.7" y1="36.386" x2="79.086" y2="36.386" width="0.2032" layer="16"/> +<wire x1="79.086" y1="36.386" x2="77.9387375" y2="35.2387375" width="0.2032" layer="16"/> +<wire x1="77.9387375" y1="35.2387375" x2="77.9387375" y2="30.7397875" width="0.2032" layer="16"/> </signal> <signal name="SHNT-W-LO"> <contactref element="R21" pad="1"/> @@ -2690,15 +2702,15 @@ design rules under a new name.</description> <wire x1="81.7" y1="33.9138625" x2="81.3936" y2="34.2202625" width="0.2032" layer="16"/> <wire x1="81.3936" y1="34.2202625" x2="81.3936" y2="34.686" width="0.2032" layer="16"/> <wire x1="81.3936" y1="34.686" x2="80.1" y2="35.9796" width="0.2032" layer="16"/> -<wire x1="80.1" y1="35.9796" x2="78.3451375" y2="35.9796" width="0.2032" layer="16"/> -<wire x1="78.3451375" y1="35.9796" x2="78.3451375" y2="35.17145" width="0.2032" layer="16"/> -<wire x1="78.3451375" y1="35.17145" x2="78.3451375" y2="30.57145" width="0.2032" layer="16"/> <wire x1="78.3451375" y1="30.57145" x2="74.8416875" y2="27.068" width="0.2032" layer="16"/> <wire x1="74.8416875" y1="27.068" x2="72.4" y2="27.068" width="0.2032" layer="16"/> <wire x1="72.4" y1="27.068" x2="72.2" y2="26.868" width="0.2032" layer="16"/> <wire x1="72.2" y1="26.868" x2="72.2" y2="26.8422" width="0.2032" layer="16"/> <via x="72.2" y="26.8422" extent="1-16" drill="0.35"/> <wire x1="72.2" y1="26.8422" x2="72.2" y2="33.35" width="0.2032" layer="1"/> +<wire x1="80.1" y1="35.9796" x2="79.2543375" y2="35.9796" width="0.2032" layer="16"/> +<wire x1="79.2543375" y1="35.9796" x2="78.3451375" y2="35.0704" width="0.2032" layer="16"/> +<wire x1="78.3451375" y1="35.0704" x2="78.3451375" y2="30.57145" width="0.2032" layer="16"/> </signal> <signal name="N$7"> <contactref element="U2" pad="P$38"/> @@ -3710,4 +3722,10 @@ design rules under a new name.</description> </signals> </board> </drawing> +<compatibility> +<note version="6.3" minversion="6.2.2" severity="warning"> +Since Version 6.2.2 text objects can contain more than one line, +which will not be processed correctly with this version. +</note> +</compatibility> </eagle> diff --git a/circuit/v03-1.md b/circuit/v03-1.md new file mode 100644 index 0000000000000000000000000000000000000000..fe0efe7dbe063be2a911d07da77b49938546f40c --- /dev/null +++ b/circuit/v03-1.md @@ -0,0 +1,84 @@ +# Machine Kit BLDC Driver: Circuit Development + +While I previously went through this with the [ATSAMS70](atsams70.md), I'm at it again with a new micro - the ATSAMD51, so I'm re working most of it. + +# Version 0.2 + +I have a laundry list of notes - below - for the next version of this. Overall, I'm interested in generally 'tightening it up' as well as fixing some circuit errors. I'm also moving away from the 'header / hardware' interface, and dropping an ATSAMD52 (the new hot chip on the block) and I'm going to treat it like a network endpoint. + +I fixed some stray, messy errors (i.e. I had some done some senseless things with the buck converter that caused it to not function) and added some filtering to my phase voltage sensing. I also added a voltage sense circuit for th VCC line so that I can figure out in software what the supply voltage is. This is useful when (later) I might end up trying to measure things like phase inductance ! + +I did a few little things (like trying to minimize the number of different capacitor sizes I had - simplicities like this are nice when I am placing components) and then was re-labelling pins for the ATSAMD51, and picking the peripherals I figured I will use. + +## New Schematicking + +This is my PWM module - Timer / Counter for Control. 'waveform extensions are featured for motor control ... deatime insertion' bam. + +I *think* I read the datasheet correctly on how hi/lo channels are multiplexed here. Or, at least, here's hoping that I did. Sorted that out in the schematic. + +I also added microcontroller input to a few lines: the gain selection on the drv8302 (controls current sense amp gain) and the fault line, and the pwm mode line (so that in worst case I can just send hi-side signals, the drv will do lo/hi deadtime insertion and complimenting for me). + +## New Routing + +But *holy dang* did I ever open up the ratsnest :| + + + +Time for some serious annealing. + +OK, I'm starting to feel satisfied with this. I've made a few big improvements - or at least they feel like nice changes. I suppose calling them big is a bit much. Besides, it was already working. *BUT* my groundplane now looks *much* better. Dang, look at that sheet of copper! + + + +Specifically, the DRV8302 used to be a bit choked out on the ground plane, and when I turned the gates on I would see that area quickly jump from 30c to 50 or 60c, still cold by power electronics standards but I was barely running any current. So this feels nice. + +I also got rid of the thermal relief on the directfet packages, so they'll sink more heat into the copper (which is now 2oz instead of 1oz) as well. AND I set up proper mounting holes right across the FETS so that I can wrap them with a big shiny piece of aluminum for when I go for the kilowatt of juice *sunglasses dude emoji* + +I left a big lineup of .1" pitch pins that will save me lots of time and pain when I'm debugging this as well, those take up a bunch of space, but I know I'll be thanking myself in a week's time. + +The last thing, routing all of the voltage sense lines, was a bit of a pain. I have to reach four traces all the way from the business end of the board back to the microcontroller... + +In any case, here it is + + + + + + + +And the full schematic + + + +## Fabricated + + + + + +## Another Run + +## MK Global Wants and board notes + +### BLDC: + +finishing: + - doc those, upload, upload fab, order + +order: + - AE10817-ND heatsink + - 345-1557-ND heat compound + - 1528-1698-ND small rotary heatsink + - 493-1111-ND capacitor + - 296-48289-1-ND h-bridge + - https://www.digikey.com/products/en/resistors/chip-resistor-surface-mount/52?k=&pkeyword=shunt+resistor&pv2=143&pv2=7&pv2=8&FV=mu1+mOhms%7C2085%2Cmu1.5+mOhms%7C2085%2Cmu2+mOhms%7C2085%2Cffe00034&quantity=0&ColumnSort=0&page=1&pageSize=25 2512 shunts + - https://www.digikey.com/catalog/en/partgroup/ncp21/10801?mpart=NCP21XV103J03RA&vendor=490 thermistor + + - mcmaster + - size 0 for lock + - size 2 for everywhere + +# Footnotes +1. Part Number. Searching Digikey (or octopart, or what have you) for bits is an art, kind of. It's intimidating, but offers much gold at the end of the rainbow. +2. This means that this is where the FET breaks down at the transistor level. The real constraint has more to do with heat - there is *some* resistive loss in any transistor (spec'd as RDS_on) - that resistance turns into heat, and if at 86A that can be a lot of heat, and if you aren't able to get it out of the package fast enough it will break down due to high temperature. THIS is why the directFET package is cool - rather than being wrapped in plastic (not conductive) it is wrapped in a metal tin (conductive) so it's easier to really suck the waste energy out of it. +3. Both are Ben. Both control BLDC. A coincidence? Consider that. \ No newline at end of file diff --git a/education/README.md b/education/README.md new file mode 100644 index 0000000000000000000000000000000000000000..79a635518c75ea4a5c2873e18e961ef4cc59e8d6 --- /dev/null +++ b/education/README.md @@ -0,0 +1,141 @@ + +# An Overview of BLDC Drive + +### Electric Motors actuate with a rotating a magnetic field. + +In relation to [Ashby's fundamental actuator types](/papers/ashby-actuators.pdf), brushless or brushed electric motors are effectively continuously-rotating solenoids. + +We have something with magnets, and something else with electromagnets, we use the electromagnets to rotate the field, we pull the magnets along. Rotating the field is called *Commutating* the motor, and can be done mechanically or electrically. With mechanical commutation, we have Brushed DC Motors, with electrical, Brushless DC Motors. + + + +### Brushed Motors rotate the magnetic field using 'brushes' + +Brushes are mechanical switches that use the motor's own rotation to change the magnetic field. Super neat. [Here's a link to Sparkfun's explanation.](https://learn.sparkfun.com/tutorials/motors-and-selecting-the-right-one/dc-brush-motors---the-classic) + +And a GIF. While the rotor rotates, different switches are connected to current, and the coils - to - pads relationship is set up such that the current will cause the motor to rotate. Pardon my abbreviated explanation. + + + +Brushes make motors very simple. You just pump voltage (in time, current) through the rotor, and things happen. However, there are resistive losses at the brushes, as well as friction losses. + +#### Brushless Motors rotate the magnetic field with switches. + +Power transistor technology means that we can do this electronically - use a computer (or simple timer) to switch the phases. + +So we can make the coils stationary, and 'artificially' switch the direction and timing of current flowing through them. + +Here's an example of '6-step' commutation. This is incredibly common for speed control, and simpler devices, as it requires very little processor work. It can also be done in an open-loop fashion, where we blindly switch currents at a set rate to control for speed. + + + +Here's a nice GIF of sinusoidal commutation (where phase currents follow a nice, smooth wave). This is more ideal than 6-step commutation for a number of reasons, some of which are discussed in the next section. Mostly, we get to use more of each coil (we have all three on simultaneously) and we have finer control over the magnetic vector. + + + +We can see the three current vectors (that translate into a combined magnetic field vector). The permanent magnetic field of the rotor follows this electromagnetic field around. + +Digikey has a nice article on sinusoid control [here.](https://www.digikey.com/en/articles/techzone/2017/jan/why-and-how-to-sinusoidally-control-three-phase-brushless-dc-motors) + +### Control + +Control of Brushed DC motors is straightforward, we use one Full H-Bridge to drive current in both directions across the coils. + + + +However, a brushless motor requires a bit more thinking. We use three Half H-Bridges to source and sink current between the three coils, each having a common connnection to one another. + + + +### Gate Driving + +Driving those Half-Bridges also requires a bit of doing, and gets us into some intricacies of MOSFET selection and, well, gate driving. Namely, MOSFETS have 'gate charge' - a set charge we have to drive into the gate pin before the fet turns on. If you look at the [mosfet datasheet](/datasheet/Infineon-IRF6648-DS-v01_02-EN.pdf) from the FET I'm using in this circuit, you'll find the fets have a gate charge of 36nC. We have to drive this charge into the gate every time we turn it on, and we're doing so at 20kHZ or more. This adds up. While we can get away with driving a low-side MOSFET right out of a microcontroller pin, we might be limited at how fast we can do so due to that current. And we can't even begin to switch the high-side MOSFET with a microcontroller pin, as the V_gs (voltage between the gate and source) is above our source voltage, since in the case of a high-side fet, the source is our motor voltage. + +We can also use a P-doped fet on the high side, simplifying gate drive. See [this](http://files.mikrokopter.de/BL_Ctrl_V2_0_Doku.pdf) schematic for an example of that scheme. + +#### Commutation Schemes + +While it's possible to blindly drive the switches at a set frequency (determining rotor speed) it's really advantageous to drive the coils with some form of feedback on the rotor's relative electric position. There are a few ways to do so. + +**Hall Effect Sensors & Six Step** + +Hall effect sensors measure the position of the rotor's magnets: + + + +This is a straightforward and very popular method for commutation, and is always useful information, but only completely effective for motor control schemes using 6-step commutation. + +**Back EMF & Six Step** + +Hall sensors add complexity, so Back EMF has become popular, although it doesn't work at lower velocities. + +With Back EMF, we take advantage of the fact that at any given time one of the coils is not being driven. This means that we can measure it's voltage (it's acting like a generator) and use the zero-crossing point (when that voltage is 1/2 of the voltage driving the other two phases) to inform our commutation (which should happen shortly thereafter. + + + +Because we're driving the other two ends of the coil whose voltage we're measuring with a PWM signal, there's some complexity here. I won't get into it, now, but for jumping off try [this](https://www.digikey.com/en/articles/techzone/2013/jun/controlling-sensorless-bldc-motors-via-back-emf) or [this](http://www.ti.com/lit/an/sprabq7a/sprabq7a.pdf). + +**Field Oriented Control** + +aka FOC + +This is 'modern' motor control, and represents the state of the art. FOC uses a good deal of embedded computing, and has a control schematic that looks like this: + + + +We use rotor position to drive a sinusoid of phase currents, and do control over those currents to overcome inductive lag. + +Normally, position information comes from an encoder, but Sensorless FOC exists where a state estimator is used to guess at the rotor position. + +In order to jump off here, try [this](http://www.copleycontrols.com/Motion/pdf/Field-Oriented-Control.pdf), a brief overview, and [this](http://www.ti.com/lit/an/sprabq3/sprabq3.pdf), a monster, from TI, on sensorless FOC. + +#### Circuits + +A number of brushless motor controllers are available in the open-source world: + +[ODrive](https://odriverobotics.com/shop) +[VESC](http://vedder.se/2015/01/vesc-open-source-esc/) +[Ben Katz](http://build-its-inprogress.blogspot.com/search/label/Motor%20Control) +[MKBLDCDriver](https://gitlab.cba.mit.edu/jakeread/mkbldcdriver) + +Here's the schematic that I'm most familiar with: + + + +And the board, + + + +In each of these boards, we find a microcontroller, a gate driver, three half-bridges (6 MOSFETS), and current and voltage sensing circuitry. And a few BFCs never hurt. + +#### Typically Available: + +For motors, I am deeply in love with [Hobbyking](https://hobbyking.com/en_us/power-systems-1/electric-motors/size.html). + +'Outrunner' Motors (rotor wraps stator) are popularized by drone enthusiasts and have fairly high torque densities due to an increased gap radius. + + + + +[here](http://store-en.tmotor.com/goods.php?id=475) + +Inrunners (rotor inside stator) are great for speed. + + +To control these, look [here](https://hobbyking.com/en_us/power-systems-1/speed-controllers-esc.html) to start, but preferrably pick up one of the open-source ESC's mentioned above - or try building your own. With off the shelf ESCs, open loop speed control is the only thing you can do. + +### The State of the Art + +The design of BLDCs is not changing radically - it's a good idea, and it works. + +**There is one exception to this** - [Thingap Motors](http://www.thingap.com/) use an ironless winding [(patent here)](https://www.google.com/patents/US20130300241) and have relatively high torque densities. The [performance is impressive](http://www.thingap.com/standard-products/) but they cost ~1k at the low end. + +What is interesting is where BLDCs are being used, controlled, and how they are being designed (shape, new densities). Take a look at [The Biomimetics Lab at MIT's](http://biomimetics.mit.edu/research/optimal-actuator-design) discussion on optimizing gap radius, etc. + + + +The MIT Cheetah team had their motors custom made to optimize for torque density (at a cost of total power density). Their discussion is really interesting, you can read [This Paper](/papers/mit-cheetah-actuator.pdf), a great intro to the state of the art in robotic control, of which Brushless Motors and their cousins play a large role. + +As well, [Ben Katz'](/papers/katz-thesis.pdf) thesis contains an excellent review, and more intelligent discussion, on FOC, motor selection, etc. + +And [Simon Galouche's](/papers/kalouche-thesis.pdf) thesis contains a similar review on actuator selection for robotics. \ No newline at end of file diff --git a/images/board.png b/images/board.png new file mode 100644 index 0000000000000000000000000000000000000000..5068bed306e248b5e47a284d8e79d79554d64f31 Binary files /dev/null and b/images/board.png differ diff --git a/images/schematic.png b/images/schematic.png index 8f75cff41f2502e6d88372ecb82dbadc6ad44eac..db424eb16675bc3f1a8dc161e716dd4080f3f0a8 100644 Binary files a/images/schematic.png and b/images/schematic.png differ