Archive for the 'Motor Controllers' Category


A Brief Interlude from BattleBots with Brushless RageBridge

Jul 26, 2016 in Motor Controllers

Brushless RageBridge alt. Brushless Rage (n): A magical piece of robot hardware that everyone wants to exist, and whose developer keeps promising “eventually”. Kind of like the Duke Nukem Forever or  Deadpool of motor controllers. “I’m going to use Brushless Rages in my robot when Charles releases them.”

in a world

My own brushless ESC design has been a bit of a white rabbit project for years. While it’s lead me into learning a lot about motor control and power converter design, I’ve not actually made a working one. Melontroller version 2 came close in 2010, and it actually did run Razer Revolution (version 1) for a short while before consuming itself enthusiastically and being retired. It also required the now-legendary Common-Mode Nut to work properly. My next attempt, Tinytroller, was basically a miserable failure all-around, but my discoveries made during the testing of RageBridge meant it might not have been a total loss design-wise, just hampered terminally by a connection error in the schematic (that story can be found here).

In the era beween that and the last time I talked about Brushless Rage in 2014, shortly before I had an unexpected robot pregnancy for BattleBots Season 1, I tended to make do with mass-market EV controllers and R/C motor controllers, like a regular person. I don’t like to talk about those times, trying they were. Man, that post was a while ago. BattleBots Season 1 also pushed back regular-old-RageBridge basically a full year.

where brushless ESCs all suck

With the few months prior to the BattleBots Season 2 build kicking off devoted to hacking up HobbyKing controllers, it basically rekindled the flame that I had with my own brushless ESC bloodline. After Season 2 action wound down, I spent some of the intervening period before the premiere thinking about the next steps of the Brushless Rage project.  I didn’t want to keep modifying hardware not designed to do something I wanted it to, in order to get something which mostly works. Having chopped up dozens of models of R/C controllers, I was getting sick of dealing with them. An ESC of my design would mean I can account for all the variables that were cost-optimized out of the bill of materials, and they could be tailored to my specific application of getting the shit whipped out of them every time they are powered on. I wouldn’t need to worry about the global supply chain for #season3 either.  Furthermore, the robot market is slowly shifting brushless basically as I’m typing. And with the discovery of SimonK and other firmwares by the community, suddenly the bar was significantly lowered for the part I hate: firmware development.

It seemed to me that it wasn’t very difficult to get a SimonK compatible basic Brushless Rage put together, and I was in fact about to pull the trigger on the original board design (with a few changes) a few weeks into the build when the Great DLUX Famine of 2016 occurred, a go-for-broke move that was one of the failure mode branch analysis decisions of last resort. Overhaul 2 was a trailblazer in many ways for #Season2 (No, these things will never come without hashtags), so since I’ve reached a point where I’ve stopped caring about R/C hardware, it’s time to move on.

one man

It’s also interesting to see that my desires for a brushless ESC haven’t really changed – something that performs well in roughly the 2 to 5 kW range typically 48V and up to 100 amps. This segment of the market is still poorly served for the casual roboticist or hobbyist. Most Inexpensive Chinese equipment for e-bikes are 1kW and under, otherwise you’re looking at unreliable R/C controllers or really expensive industrial ones. This is where I come in.

But first, let’s rewind all the way back before BattleBots ruined my life yet again and see where this first model of Brushless Rage ended up.

Recall that this was the “component splattering” I first put together in late 2014. I do a bunch of trial layouts without schematics just to see if there’s enough space to do what I want. The form factor is still “RageBridge”. This board is based off the Arduino Leonardo, which has since been discontinued anyway.

After the component splattering is established, I then make the schematic (not shown here, but plenty of other examples abound). This is the final layout I decided to use, since it provided a clean U-turn path for DC current and three straight traces for the motor phase current towards the right side of the board.  The gate drive passives have been arranged around the A4910 chip for its own local sanity checking, and otherwise the micrcontroller and logic power supply are already arranged (and basically identical to RageBridge 2′s known good setup)


I enjoy a good game of “detangle the gate drive traces” every once in a while. Brushless (3 phase) makes this more entertaining since there’s an extra set to route!

Here’s the hilarious way I ended up routing those traces. What’s with the little curly offramps?!  Well, the traces all had to turn 90 degrees, but 90 degree hard turns are less desirable than 45s or straight lines. I could have gone with simple 45′s, I suppose, but decided to get cute with things and use the spline routing method instead.

This is the bottom layer of the board, looking the most “circuit board” of anything I’ve ever designed. There’s 6 gate driver lines logic pins from the microcontroller (three high, three low) to detangle, plus numerous other control pins and feedback pins. It also showes the layout of the power traces.

Finally, this is the completed version 1 board as of December 2014 or so. I actually had several boards made along with the version 1 of the RageBridge2 boards, but never did anythng with them.  Knowing what I do now about RageBridge 2′s design though, there’s a few things I’d change about this board before populating and trying to use it.

but now

Fast forward to about two months ago, and my desires to try again were high. Seeing the HSOF-package FETs used in the Vex BB controller at Season 2 also spurred me to try that package, which I had only speculated out before and whose high price per unit in low quantity kept me from buying a rail to blow up. However, I found that other companies besides Infineon also made parts in the package, such as the Fairchild FDBL0150N80, which were priced much closer to my favorite D2PAK-7s.

The HSOF package has very short legs, which enabled tighter packing than the D2PAK-7 devices. This was both a blessing and a curse, since I usually ran traces under the ‘overpass’ of the legs, but the tighter packing would potentially allow FET packing in parallel for more current. A lot of new leadless packages for all sorts of devices really want you to use them with 4 layer boards, and I openly admit that moving to 4-layer would have made life a lot easier and added current capacity.

I also did some more look-ahead for the architecture of the controller. One of the things I wanted to do with RageBridge2 was finally move to a split signal board and power board architecture, which is fairly common the higher amperage R/C controller market. This would allow me to finally use 4+ ounce copper on the power board, which the fine pitch packages and traces of a signal board wouldn’t usually permit. The signal board could also be designed with tiers of components to drive differently sized power boards…. just look at my dreams of this from tinytroller (That’s a 600V, 200A, 3-phase IGBT module…)

So here we go. I decided to play with placements first, once again. I basically just imported a RageBridge outline to start with, to see if I could keep the controller in the same size class, rather than define a new physical form factor. The hidden agenda of this is that I have 1000 RageBridge 2 heat sinks and only 250 RageBridge 2s, so I’m gonna use those damn heat sinks!


One thing I was unclear on at the time was whether I wanted the gate drivers on the board or not. Having the drivers on the board would make the logic-power separation even more strict, as the only thing passing between the boards is command signals, not even the (relatively, compared to logic) high powered gate drive signals. This took up more space on the board, of course, so I had to get to a point first where I could judge the space requirements. You could really make an argument for both approaches, but the gate drive on logic board is more common in R/C-world.

I also made this crazier version which is basically just a block of MOSFETs. This was a complete “out there” concept, as there’s too much semiconductor to be useful – the rest of the board won’t really be able to support the current, and those two lone capacitors will become depressed quickly.

It also left zero space for things like current sensing resistors or really any gate drive parts. But it did show the potential of the HSOF package if I decided to make this board even slightly bigger to permit these components.

Another musing was if I could use the D2PAK-7s that I already have. The answer is “barely”. It also really needs a bigger board to work out. This specific layout, for instance, would make adding current sensing really difficult.

There was another version which I did not take a screenshot of where the FETs are spaced closer together after I played with gate drive routing, which left space for current sensing resistors on the left where they are picture now.  This version was actually a candidate worth pursuing if I did not end up using the HSOF packages.

Getting a little more serious now as I start actually listing the signals I need.  This is now back to the first configuration.

While I don’t intend to make current sensing a priority (as SimonK doesn’t support it), I made sure to add all the possible signals I WOULD need, which includes current sensor feedback pins and a thermistor, for instant.

(Kelvin refers to a Kelvin connection, by the way)

At this point, I also started thinking about what signal header to use. The 20-pin wide through hole header row was not the final selection. I looked around first in the libraries of parts I had to see if anything tickled my interest. While the common 0.1″ spacing single row headers would have worked, I wanted a more production-ready solution and also wanted to browse what the latest offerings on the market were.

Off to Digi-Key and Mouser for some window shopping. Connector manufacturers will often sample parts for free just to get you hooked on their product, so you keep coming back wanting more, and eventually you’re standing on a street corner with a baggie of mezzanine headers.

I found what I liked in a Samtec product, the HLE series. This is a “pass through board” header. My qualifications were basically…

  • 0.1″ pitch, so it is easy to use as an extensible standard – anyone with some perfboard could potentially work with this design in the future
  • Two row, since 1 row takes up too much boardwidth and three rows is more painful to route
  • Pass-through-board (connector on top side) because I did not want to pay extra for double-sided SMT assembly for ONE PART (the connector) which would be necessary for a non PTB design.

So I sampled a handful of HLE connectors and matching male-side dual row terminal pins, their TSM series. After getting these in hand, I decided to move on with them.

I generated the footprint for this part according to their datasheet, but the pads are a little shorter than specified to give me more space to work with. Check out the current working arrangement now. The decision to move the gate drive offboard was made, so this freed up space for more capacitors as well as current sensing. I realized that even two FETs in parallel was going to cause a massive capacitance shortage. Cue a day of shopping for the latest in capacitors…

In the end, I’m only able to get around 2,600uF of bus capacitance at 63V ratings – two 820uF large cans and three 330uF smaller ones. This ought to be sufficient, and is on par with RageBridge 2 which was easier to buy caps for due to its lower voltage operation.

This board is also about 0.25″ longer than RageBridge 2, accomplished by exploiting Eagle’s 100 x 80mm board limits by using the “Well, technically, it just limits where your COMPONENT CENTROIDS can be placed” method.

So I honestly tried for a while to put all the outputs on the right side for convenience. The narrowness of this board wasn’t very conducive (hehe) to it since it left very little space for power traces. This would limit the current capacity due to trace resistance, and ruin the point of two devices in parallel.

Again, a matter that a 4-later board can help fix, and so I might try a 4-layer version in the future.


In the mean time, to keep life simpler for initial testing, I moved the motor phase outputs to be next to the FETs. This also let me push everything to the right a little and give more space for routing.  Pictured above is the first shot at the power board, which was, uhh, rage-routed in my typical fashion.

This screenshot also shows the working project name for Brushless Rage, which is “ThreeBridges”. I honestly don’t know, because it sounded reasonable. Technically, you could argue it’s only three half-bridges. Go away.

Now that the power board is settled, time for the signal!

I set the signal board size constraint as being no wider than the two mounting screws on that end of the power board such that I could still unscrew them. The length was dictated by hitting the phase wires. This is after the “initial scattering of components”, where I was routing the logic power supply little by little at the top. For now, I put a row of right angle headers on the left side to make sure I leave space for routing signals, even though the SimonK board would only need one R/C servo input.

The gate drivers are all new – the FAN7390, which is like my old favorite the IRS218x4, but with a little more crank and with independent inputs. I went on the hunt for gate drivers that offered Vss-COM floating capability (kinda-sorta isolation) that were higher current than the IRS218x4, and found these quickly. Sure, why not!

The logic regulator is also a new addition to Charles_Favorite_Parts.lbr that I hope to learn to love. I decided to leave my good ol’ LM2594 behind and explore the higher voltage market a little. The LM2594HV is my go-to for all up-to-50v solutions, but I eventually wanted to go higher with this controller.

From looking at the DLUX 250, I know it used a LM5009 regulator, so I shopped in the same family of DC/DC regulators to start with, while also letting DigiKey show me what worked for my specifications. Ultimately, it seems like the easy one-chip converters stop around 100 volts. Makes sense – the higher you go in voltage, the less standard/well characterized the loads tend to be (e.g. every consumer electronics device hovers around 5-24 volts for power so there are many one-chip ready to go solutions).

I settled on the LM5017, which has roughly the same operating voltage range, can switch near 1Mhz (which I wanted to do in order to reduce passive size), and is higher current, for in the future if I want to drop this design on a more powerful gate drive.

This chip is a little………..special. I’ll get to that in a bit.


Moving more components in now – the microcontroller’s support passives have been added, the resistive sensing network for phase voltages has been added, and a new challenger appears at the bottom… what’s that? It’s a TLP2160 2-channel optocoupler in a SOIC-8 package.  I wanted to get into the habit of opto-isolating the logic signals, since it cuts another point which noise from coupled EMI or ground loops can be injected into the logic, so I explored the space of small optocouplers a little, most being the larger wide-DIP size. This part is another “Digi-Key, are there any in-stock parts that match these peculiar spoiled brat needs of mine?”


Version 1 of the signal board is complete after some more routing! This board was almost theraputically easy to route for some reason. The joys of having ONE INPUT and no giant MOSFETs next to you…

A quick synthetic image showing the stackup of boards.

These boards were sent out for fabrication through my current favorite shady Chinese PCB source, 3pcb (not to be confused with 4pcb, or really any of the [1:10] places). The signal board was to be fabricated in regular 1oz copper, and the power board in 2oz. I could have went for the full 4oz, but it was more than twice as expensive as the other options, so for a test board, it was not justifiable.

In the intervening week, I ordered a load of BOM parts from Digi-Key. First up is the HSOF package FETs!

Man, these things really are like a D2PAK-7 with the legs cut off. Pretty sure I can get the same effect doing it manually myself and save some money…

But less facetiously, they’re much thinner than the D2PAK and so have less thermal conductivity problems from the top side. They’re still designed to be heat sunk primarily from the bottom, though.

Everything else! There were so many new parts involved this time…

A day later, the PCBs show up. I’ve worked out that if I hit “go” on the DigiKey order as soon as I get a shipping notification from 3PCB, my orders will make it here in roughly the same timeframe (+/- 1 day).

The first thing I wanted to try out was the board stackup height. I was correct in choosing the male header pin height here, since the signal board sits just barely a millimeter higher than the tops of the FETs!

Next begins the job of populating the boards. I started with the signal board, so I can quickly test “FET integrity” by manually poking the drive pins with 10 volts to make sure nothing is dead.

The capacitor farm on the right was going to be impossible to assemble unless I tried some trickery. For the pins in the middle of the aisle between the small and large capacitors, I ran a bunch of vias to the bottom layer and added a small square of solder mask stop. That way, I can solder the capacitors in from the bottom by holding the iron to the bottom side and feeding solder from the top side.

Not a production tactic, but good enough for now.

I built this assembly in stages, testing each ‘new thing’. For instance, the next family of parts to assemble was the 15 volt gate drive power rail supplied by the LM5017.

This is where things got exciting, and where you have to know how technical datasheets for chips are produced.

First, a team of engineers working high up in a mountaintop monastery like this one writes the specifications for the chip – its operating voltage range, logic input thresholds, current draw, and so on. They summon the Gods of Silicon Fabrication through magic-smoke-heavy ceremonies shrouded in secrecy, tradition, and middle management. Next, to bring the chip into the world, the datasheet must be written by a group of immortal, trusted unpaid-intern scribes. Unfortunately, as this modern electronics research facility is a mountaintop monastery, it has no Internet connection.

So the chip specfication and application & design notes are communicated via one of several methods: via magic-smoke signals, or by dropping smooth pebbles from the mountain in such a way that they bounce a specific number of times before hitting the ground, with the number of times being interpreted as a character or a vector graphic drawing command. This is, needless to say, not a lossless method of communication, as winds and weather can hinder the processing of the smoke signals or inhibit them completely, and the backup provided by the dropping of the pebbles could be corrupted by the law of probability and how many mountain goats are grazing on the way down.

What I mean to say is, datasheets often suck and have inconsistent symbolic notations and naming schemes that make it difficult to understand precisely what is being asked of the designer. I messed up a few passive part value calculations (such as the feedback network filter among other things) which meant NOTHING WORKED. AT ALL. GOD DAMMIT. until I ran through the design equations basically 3 times before I finally got that ohhhh, you meant the on time AT MINIMUM DESIGN INPUT VOLTAGE, not maximum like the last page was talking about.

Then I got it to work.

This was the culprit. What is shown here is the waveform at the feedback network. Essentially what’s going on with this regulator is that it uses the voltage across the output inductor as a feedback element.

Capacitors, specially the output capacitor, take a little time to fill up (voltage to build up – current leads voltage) after you feed current into it, and by the time the final output voltage – taken directly from the capacitor in the usual case – rises above the feedback threshold, shutting off the current in the inductor then takes a little more time (voltage-leads-current), which fills up the capacitor past what is desired. You can often get an unstable feedback loop going this way with the regulator always hurrying to do exactly the wrong thing, and your output voltage becomes unregulated. The type of feedback network used by the LM5017 is more complex, but it eliminates the capacitor as a source of lag in the response.

What’s seen in the waveform is the scaled inductor current (represented as a voltage) increasing (ramp up) as the regulator pushes current from the input side (battery) into it, the peak tripping the feedback threshold, and then ramping down back down when the regulator shuts it off. The peak shifts left to right depending on the duty cycle – basically how much time the regulator keeps the current on vs. off.

This is a small waveform imposed upon a DC offset voltage which is provided by the usual two-resistor divider, which is for large-scale changes; for instance, a sudden load might drop the DC voltage significantly, which means the peak of the triangle won’t reach the regulator’s shut-off threshold, basically sending a “NO KEEP IT ON LONGER FOR REAL” signal.

The astute electronics engineer would note that I technically didn’t have to do any of this, just implement a normal feedback circuit, because the gate drive power can be “dirty” since the microcontroller’s power is derived from its own linear regulator from that, but I wanted to get used to these kinds of feedback circuits since they’re more common on high voltage regulator parts.

This is the output voltage at the ‘switching node’ – the output pin of the regulator, before the inductor, doing what it’s supposed to do finally . Again notice how it matches up with whether the slope of the feedback voltage goes up or down.

Mystery number 2 of this chip was that it clearly did NOT want to run at 1Mhz. It just sort of went crazy and the output waveform was extremely unsteady and not remotely square like this one.

I backed down the design frequency to about 600khz, and all was good.

By the way, thesea re in fact all screenshots from my beloved DSO Nano Quad.

Okay, with everything populated, it was time to take it for a literal spin. I designed the signal board to be a directly compatible port of the SimonK DLUX settings I made for Overhaul, so this part was super easy!

Aaaaand…. nothing happened. Hmm…. Well, at least it didn’t light on fire instantly! I have created something that is more than just an elaborate firework.

First little blue wire hack time!

So I read the TLP2160 is an inverting output. Sure, makes sense, most optos are set up that way. So  I just wire the output in an emitter-follower configuration and all is fine, right?

Nah, it’s a push-pull output that can both source AND sink current, overriding your clever inversion by doing whatever the fuck it wants. Whoops. So instead of reading  1.5 millisecond long pulse from the ratio, the ESC was receiving a 20ms – 1.5ms = 18.5ms pulse and becoming very confused. Time to bypass it for now… On version 2 of the board, I’ll add a tiny transistor inverter to make up for this.

Okay, it’ll definitely work now! Right!?

Well, I can hear it trying to do something, but it’s obviously not driving anything. Scoping all of the low-side MOSFET pins showed they were being switched on correctly, but none of the high-sides were driving at all.  Perhaps the bootstrap capacitor arrangement was too low-value to pump those big fine MOSFET gates. Nope, the voltage at the bootstrap capacitor read just fine. Might as well double check the pinout connection and…


Oh dear.

Again, another “Electronics engineers might get this” reference, but take a look at the FAN7390M1X datasheet and let me know what I did wrong.

Alright, more little blue wires time. I fixed this issue in the chip footprint and symbol right away, and it’s also now queued up for revision 2.  The other two drivers also needed this same hack.





Whoops. Another transcription error. Who’s the unpaid intern monk scribe communicating via smoke signals and goat droppings now?! Fortunately, this was quick fix. Ahhh, software…

Without further ado, I bring you….


literally because i didn’t write the software.

Not shown was the test after this where I almost beaned myself with a SK3 63/74 outrunner when running from Sadbot’s 10S battery. It tore itself out of the crude clamp and alligator clips I set up on the table and proceeded to attack me.

There was one additional small hack I had to make, and it was that the bootstrap capacitance was indeed a bit low for how fast I was switching and the gate charge of two MOSFETs, plus gate-to-source “insurance resistor” leakage. It ended up that I need something like a 4.7uF and I had a 1uf installed from stock since I already had it. The high-side drive voltage was sagging pretty far during long slow commutation cycles. I intend to resolve this by installing the correct capacitor next time and also backing down on the Rgs from 10k to perhaps 22 or 47k – something to keep them happy under undefined drive states, but it doesn’t need to be that low.

Well, to keep things going for now, I’ll just DROP ALL THE BASS on it. How’s 101uF of bootstrap capacitance sound to you? Good? ALRIGHT!

Future revisions of the signal board, or a different signal board altogether, may see a charge pump or other kind of high-side drive supply added. For now, it’s fine if the high-side gate drive voltage sags a bit on longer switching cycles, which would happen with slower motor rotation near full throttle, such as if I drive a bigass hub motor instead of a small fast R/C motor.

Shown here is my DSO Nano Quad and a bunch of little blue wire probes that I was moving around to check my work.


Here’s what a gate drive signal looks like! Nice and clean, just uner 1 microsecond switching time. The small twangs are the complementary (high-side) transistors turning on and off, which shows that my deadtime could afford to be a little less, but I will probably keep it here for insurance purposes – transistors start switching slower as they get hotter, for instance.

Again, this is on completely unchanged SimonK DLUX settings from Overhaul.

Out of curiosity, I took a snapshot of the phase voltage divider output (going to the microcontroller, blue), and the virtual neutral point (star network, yellow) which the controller bases its switching decisions from. For more technical and whimsical info on this process, see Xo’s post.  The controller bases its switching decision on the last drive state of the motor and the “zero crossing” – actually the phase voltage crossing the virtual neutral point.

The signal is clean enough and my switching is fast enough (sub 1 microsecond) that I may try increasing the switching frequency even further. Right now it’s around 20khz, and I’m thinking of trying 32khz. The higher the frequency, the less work the capacitors have to do, the more opportunities the controller has to sample the zero crossing, the lower the magnitude of current pulses which could induce noise, and the less I and my friend’s dog hear it. Downside is increased heating of the transistors in the form of switching loss, because how happy would you be if someone slapped you 50% more times a second?

All of this is speculative. My goal is to build three to four working units and beat them up using the SADBOT vs. OVERHAUL method, which I know everyone has been dying to see, including me! The revision 2 signal boards, incorporating most of these changes, arrive later this week, and my BOM for making a few more power boards should also get here in the same timeframe.

In the mean time, it’s time for OVERHAUL VS. BETA this coming week of BattleBots! I have a post-match being put together for that too.

A New Beginning, the Second Story; RageBridge 2 FINALLY Going to Manufacturing; Season 2 and #SADBOT2016

Dec 01, 2015 in Bots, MIT, Bostoncaster, Cambridgeshire, Motor Controllers, sadbot2016

It’s official – after December 31st of this year, my contract with MIT as the MIT-SUTD Collaboration‘s International Design Center shopmaster will end, and will not be renewed. As of then, I will no longer have official ties to MIT. Hard to believe, eh?!

There’s no better timing for this, too, as #season2 is on the horizon early next year. My goal is to use this same epochal shock to usher Equals Zero Designs into prime-time, with the release of RageBridge 2 and a host of other stuff I’ve been working on this fall semester – stay tuned for that.

Ultimately, it was a combination of the fear of complacency as well as organizational changes that is pushing me to move on. First, because I have commitment issues and can see myself being a shop instructor & design class instructor for the next q years, which frankly scares the shit out of me. Sorry, ladies. Second, the IDC has moved on from its more “Wild West” days of supporting any which project, towards a more professional research-centered model with strong ties to industry. This is without a doubt better for the Center and will make it sustainable past its years with the MIT-SUTD collaboration alone, but I just didn’t see myself contributing to it any longer. I’m one of the last of the “original generation” of IDC inhabitants, and that presence has made itself painfully obvious in the preceding few months.

The thing I’ll miss the most is not anything to do with the Center, or even “my own” shop, but my interactions with the student maker community and being the go-to guy for late-night uncommon parts and advice, because yeah, of course I have one and of course I’m upstairs right now. That, and not being able to continue the great experiment that is 2.00gokart, but perhaps this will be remedied in due time.

In the coming weeks, I’ll be winding down my operations at MIT and shifting most of it over…

…to my little corner at the Art is a NSA sylum. What I might lose in the coziness of “my shop” I gain in a real, dedicated space for shenanigans and a much wider array of on-site resources and a massive community of deranged makey-types. Thus begins the story of Big Chuck’s Robot Warehouse & Auto Body Center. What, you thought I was kidding?

The downside? I have so much shit to move.

So many more people making and building things at MIT is a mixed blessing: nowadays nobody can get their own little private corner for too long. I’m currently trying to knock down my stuff load, which dates back to mid-2007, across 3 or 4 different sorting systems (at least 1 of which is just “NONE”), and several midden-esque locations. So, perhaps watch out on the For Sale page soon


Oh dear, I’ve officially become one of those delayed crowdfunding product people in addition to being just a crowdfunding product person.

Ragebridge2 got basically pushed back a month to resolve one of the biggest issues plaguing it from the start: the one channel “giga-mode” where the two sides are tied together so Rage becomes a single channel twice-as-awesome controller. A lot of prospective users were asking for this so Rage could conceivably be used in a heavier robot design. For example, the two sides put together at 150 amps limited would be plenty of current for, say, an Ampflow A28-150 motor.

Now, how hard could this one-channel thing possibly be? Isn’t it just copying and pasting the output of one control loop cycle to the other?!

Well, basically. But first, there were secondary issues that had to be resolved.


One thing that eternally plagues power conversion and motor control designers is noise. Switching tens or hundreds of amps thousands of times a second is not easy on sensitive logic. The bigger the parts get and the higher the amps go, the more likely you’ll start seeing things like optical isolation and fully isolated independent gate drive supplies, and the like. I think Rage is on the big end of what is basically “non-isolated” designs, where power and logic ground eventually meet on the same board. When they do, layouts and trace routing become as critical (if not MORE critical) than exactly what FETs you use…. I could have the most hardcore power devices in the world, and my board would just reset over and over if the current draw went over 5 amps or something if I dropped a haphazard or autorouted (shudder) layout.

Now, fortunately, for Rage, the critical current wasn’t 5 amps, but more like about 130-150 amps. On very hard reversing with the current limits near the top, the board would still trip up. However, it was no longer the microcontroller resetting, but the Allegro A3941 chips themselves that were having issues.  In fact, one side (channel 1) would preferentially shut down.

In fact, here’s a scope trace between low-side return (LSS) of the gate drive chip and my logic supply ground measured at the logic bus capacitor, on a 100%-to-0% step where I just kind of let go of the transmitter stick, with the current limiter set to maximum (75A) per channel. That’s a nearly 6 volt peak to peak smash, especially with a strong negative component. And this was at PWM frequency – happening 15,000 times a second.

If Rage were in dual-channel mode, this resulted in that side simply no longer responding, needing a reset to clear. If it were in single-channel mode, well… stuff generally blew up.

There wasn’t much more trace and component placement optimization I could make, however. I repositioned several of the gate drive traces, and more importantly, moved where the gate drive chips got access to VDD (system voltage) and VSS (system ground), specifically moving them away from “right under the drain tab”. I’m not sure why I even did that, but…

One last thing I decided to finally do was to airgap the whole logic ground plane.

Before, the plane filled the whole area that is now black in the center. This placed it right next to the high-power planes and the switching output of the motor, not to mention the high dV/dt gate drive traces. This is no longer the case.

All of these changes called for a new board revision, number 6. I decided to try a new-to-me vendor that I’d been clued into,, not to be confused with I see what you did there.

They have the quickest turnaround of any place I’ve used so far that doesn’t cost four-figures. I’ve actually since used PCBWay for a few more sensor boards and consistently get orders in on Wednesday afternoon, and receive them the following Monday, including shipping time with an air express service and which doesn’t even cost that much. The “downside” is no “fancy stuff” like 4 layers, microvias, plated holes and edges, etc… on your boards or it takes as long as it normally does.


It, uhh… Oops.

I’m pretty sure I clicked on the wrong choices for LPI (solder mask) color and silkscreen (text) color. The buttons are actually next to each other, okay?

Just in time for the cold season, the wild RageBridge gains a brilliant white winter coat to better camouflage itself against low-inductance motors and people who don’t know how to solder.

To be fair, this doesn’t look bad. However, the white board is easily stained by flux, and after reflow-soldering the FETs and gate driver ICs, there’s obvious yellowing of the board to a more ‘off white’ or ‘soft white’ kind of color. I think this is partly the flux, and partly because I cooked it too long. My process is not nearly as controlled as a production reflow line, so it’s not an entirely correct criticism. For production, I’m going to stick with black.

But did this revision solve anything? Quantitatively, I haven’t recharacterized the noise, but qualitatively, I haven’t gotten the board to reset or shut down in any way once. It will now happily grenade the power traces on a cross-side short, and continue working once I bridge the gap. This is all while driving a motor like 10 times larger than what it should be driving.

Well, that means it’s still blowing up in single-channel mode. It turns out there were quite a few structural problems with the firmware that allowed the input-taking loop to ‘override’ the current control loop. As the fastest loop in the code, the CC loop is what should be controlling the outputs at all times. The issue centered around passing variable values back and forth between the two loops. This itself was not causing the board to explode, per se. It needed an accomplice on the hardware side.

The other issue was that my deadtime between high- and low-side FETs being turned on was too small for the switching time.

The red trace is the gate of the high side FET discharging, turning the FET off, and the yellow trace is the corresponding low-side turning on. There’s very little error room here. It seems like the high side barely makes it off before the low side turns on.

Again, not very bad if the two sides were separate, but if they were switch together, all of the components better match perfectly. A few extra dozen nanoseconds here and there in delay and switching time differences would cause one side to be momentarily on while the other is off, or vice versa.  When this happened, there was an audible click from the capacitors as the cross-conducting FETs swished what must be peaks of hundreds of amps out of them and in a loop around the board. That was my sign to, umm, power everything off right now.

Prior to this, the board only exploded made terrifying sounds at very high throttle percentages (e.g. above 95%). I found out that the “output overriding” issues in the firmware were permitting very high PWM duty cycles, since the input-taking loop does not constrain its outputs to include deadbands on the low end (0-5%) and high end (95-100%). When this happens, it means the low side FETs occasionally turn half-assedly on and off due to the rapid on-and-off cycle.

I increased the deadtime to a safer margin to test again. The combination of correcting my variable-passing and adding more deadtime made for perfection! I just had to make sure that the outputs never went above about 95% – from there, it jumps to 100% – to avoid the possibility of one-side off (no FETs on) and one-side on, which is a slightly less bad case of one-side-high, one-side-low.

This jump is handled by a conditional in the fast (current limiting) loop. In practical use, this is almost unnoticeable (and is also used in RageBridge 1 and basically all other motor controllers, to avoid the things I explained previously)

With these issues resolved, Rage is now incredibly close to production. I’ve put in for the assembly quote and have already amassed the Bill of Materials. Associated tasks include getting quotes for heat sink manufacturing, and of course, in due time, readying the website and producing documentation. I hope to have everything out the door by mid-week, so Indiegooglers stay tuned for a huge update!


Way back during the middle of #season1, when we thought building a 250lb robot in roughly 5-6 weeks was going to be a breeze, I came up with the idea of a “practice assbot” for the 4 newer team members to construct so we can practice driving Overhaul v1 against it. Because, y’know, we were totally going to finish a week ahead of time and have time for everyone to take a turn at it and decide the chief driver on who’s the most skilled and… okay, that kind of died a little bit as we were welding the last bits of the new lifter assembly together on Tuesday night of production week.

But we were left with this tool, which just had to be used on something. The original plan was to put some wheelchair motors and tires on a square tube frame (leftovers from constructiong the OH1 frame) and throw this on a third of said motor. It would just be an irritating practice opponent.

During the brief interlude before #season2 work took off in earnest, I decided to take this project to fruition and adopt it, much like I am adopting the name and concept of Overhaul itself – more on this in detail soon, is my hope. I wanted first and foremost to have a 250lb-class driving practice machine. The difference between driving a 30lber and Overhaul was much like a small sports coupe and an overladen Chinatown bus. The second goal would be to test stupid experiments for Overhaul V2 (….more details on this soon, again, as I hope!) and basically make a “prototype” to make sure that certain bad ideas work, or are ruled out, before the proper build.

So I extracted OH1′s wheelpods from the apartment  and proceeded to think of the simplest, most durable frame I could build around it. Each wheelpod had four mounting points which were rubber shock isolators, so I just needed something to bind it together. A simple tube frame would have sufficed, but it was actually not heavy enough. To really get in the weight range I needed, there had to be much more steel.

My salvation came in the form of giant C-channel, specifically the “6 inch x 10.5lb per foot” type. That’s how it’s sold, pounds of STEEL per foot. In all, the thing above contains about 140lb of steel alone. Add in two roughly 25lb wheelpods and  batteries and it should be right up against ~220lb, so I could run this in other 220lb Heavy events if I really felt like it. The wall thickness is around 1/2″. It’s just a blob of steel.

But what it really needed was the Stick of Poking. For that, I conjured up a quick structure to contain a modified, chopped-down version of it.

The gear ratio may or may not be similar to one I intend to use in OH2′s main lifter, with the tip possibly kinda-ish at around the same distance as the anticipated new lifter, and it also miiiiiiiight be expanding on using the BaneBots P80 in applications most people would make fun of me for. All maybes. Nothing is certain at this stage, after all, and we don’t want to get too far ahead of ourselves, right?

I elected to use chain to keep it simple, with stock keyed shafts and sprockets running on stock mounted bearings. No fanciness here, just something quick to put together. The structure is entirely 1/4″ steel weldments from waterjet-cut puzzle pieces. I’m pretty sure it’s too spindly to be battleworthy, but again, I just wanted to see the numbers at work.

Oh dear, this thing is now looking too legitimate. I added some big rubber bumpers (which I ordered months ago for OH1 but found them too hideous to use, as well as heavy and improperly sized). Even if the arm is never installed or functional, at least it will be (relatively) soft with the big bumpers. Maybe I can use it to tow vans.

One of the intentions of this build is, of course, after all the experiments and bad ideas are finished, to have a sparring opponent for not only the future Overhaul v2, but also the potential storm of new heavy-class bots emerging in this area.

So, because the only purpose of this bot is to get experimented on and thereafter, shat on and beat upon, I figured it must be really sad, and so began calling it sadbot. It’s only tangentially related to #sadboys, I promise.

I ordered an unnaturally large quantity of STEEL compared to my usual daily recommended intake from Turner Steel, a local distributor, who delivered for free. By which I mean, dropping off slabs of a future overpass/bridge on the loading dock, and leaving me to try and budge it while making adorable squeaking noises like a rubber squeeze toy. If there is anything that building one (and soon to be 2, later three?) heavyweight-class robots is doing for my benefit, is MAKING ME LIFT, BRO.

To make up for it, building the frame was actually the most straightforward thing ever. Ignore the painted weeaboo face – I was somewhat delirious at that point. The cuts were made on a horizontal bandsaw, chamfers were gouged in with an angle grinder, and future weldment regions cleaned up with one of those fluffy paint remover wheel things. Word of caution: they are not fluffy at all, in real life. In fact, they throw chunks of hard plastic coated with abrasives at you.

After the mounting holes were drilled, I bolted the wheelpods in and actually used this assembly as a welding fixture. Long bar clamps held the sides in place at the correct height, while the whole frame was on wheels so I was able to push it around. In this exact form, I poured a few more pound of MIG wire into the frame. All possible edges were welded, both inside and out.

Having to build a heavy-class bot across multiple shops and buildings sucks. I should have invested in an engine crane and swapped some pneumatic tires onto it to sling this around. Pretty soon, this became too heavy for me to lift by myself safely, so I had to grab whoever was nearby. Here, the baseplate’s been installed.

Check out the 2×2″ hole pattern that peppers the 1/4″ cold-roll baseplate. I lined up the edges of the plate on the waterjet to make the pattern in one go. It’s like an optical table, except dorkier. This ensures I can attach any stupid thing I want to this baseplate.

The battery brackets are two pieces of 1″ angle stock, with a channel milled through each. The battery will be retained by a giant ratchet strap threaded through those channels. Each Overhaul battery is 37v (10S lithium) and 16 amp-hours. That’s literally 2x the battery we needed per match as reported by the chargers, as it turned out.

Here’s the pokey-arm tower cut, cleaned, and assembled, but not yet welded. Like the frame, I’m cheating and using the mounted bearings and shafts as a fixture to give some kind of perpendicularity.

The next step was to prepare the poker itself, which entailed drilling a 1.25″ hole through the solid 2″ diameter steel handle. I purchased an annular cutter off eBay for cheap, which are basically hole saws but actually built for cutting steel instead of just being coerced into doing so. I’ve always wanted to use one, but they’ve either been far too expensive or I had not needed to ever go through this much steel at once.

After using my cold saw to sever the handle to the needed length, I set everything up on the Bridgeport mill and gently massaged the cutter through in low gear. The process was utterly painless and the resulting finish was spectacular.

It’s almost like paying for the right tool makes your life easier or something! Go figure.

To-dos on #sadbot2016 involve welding the poker-arm assembly together and making some permanent temporary wiring to get it up and running. I’ll have more updates on this thing as the science experiment results roll in.


RageBridge 2: The Indiegogo Campaign

Aug 27, 2015 in Motor Controllers

Back my kickstarter.

- Charles in every ironic statement ever

Today, that statement ceases to be ironic (or perhaps, is even MORE ironic). For I’m proud to announce the RAGEBRIDGE 2 INGIEGOGO CAMPAIGN!

You’ve been following the story of RageBridge 2 behind the scenes here, so now you can support its production and be first in line to get them! Or, perhaps, run far away because you know how derpy the development process is!

The link to the campaign is:


After the campaign has been fulfilled, RageBridge2 will be available on

RageBridge 2: The Rage Awakens

Aug 24, 2015 in Motor Controllers

At one point in time, I think I was working on some kind of motor controller. In fact, I might have sold a few here or there! And some of them might even still be working!

It’s been six months since I had an unexpected robot baby and had to drop RageBridge development efforts. But I’m glad to say that much progress has been made, and the first batch of beta testing units is almost ready for the SECOND Somewhat-annual RageBridge Breeding Program. We pick up the story again in June…

Here are some revision 3 boards under construction. Revision 2 was slated for immediately after Motorama 2015, but I discovered enough stupid board bugs on it to warrant skipping directly to revision 3. Namely, there were some incorrectly assigned pins to the ATMega chip and the current potentiometer was backwards. There were a few other trace optimizations made.

I use a small soldering tip – a Weller NT1 – to do everything but the “big power” components, then switch to a big chisel tip iron with a Weller LTD tip to restrain the FETs and other heat-grubbing parts, including the main capacitors. The gate drive chips, in ever-convenient TSSOP package, have their center thermal pads heat gun reflowed first, then the legs are soldered individually.

Two test units of Revision 3 built out and ready for abuse. At this point in development, the firmware was left in an R/C-only, hacked together mode. I began refactoring code I’d written “just to get by” for Motorama. At the same time, I started testing the boards using some standby motors:

Here’s Rage2 being tested on some motors it’s meant to drive – something roughly DeWalt sized, perhaps, and a scooter motor. I’m finding out some critical characteristics of the system, such as “Will my MOSFETS consume themselves?” (the answer is some times), and “Will it reset or stumble because of noise?”

Unfortunately, the answer to the last one is yes, and probably contributed to the Revision 1 unit that died at Motorama. With any hard reversing or command stepping – moments when the current draw increases sharply – the controller would reset, brown out, or exhibit other forms of bad behavior.

Uh oh. I’d been through this before, with RageBridge The Original, so I immediately checked the usual suspects. Poor ground routing. Placing capacitors in the wrong place such that they broke the grounding discipline. High power switching next to vulnerable signal traces, and so on. In the world of power electronics, where you put things is often more important than what you put there.

That’s my 5V logic power line, measured at the output of the power converter, being punched by nearly 1Vpp transients.

The brown wires are scoping points where I’d pay attention to the behavior of the system. The two blue wires were intended to jump the logic power input – which, up until this point, had been taken from the very end of the power plane feeding four gigantic MOSFETs – and gives it its own connection directly at the bus capacitors. It’s kind of like making a reverse Kelvin connection for the logic power.

As I suspected, I made a “cap derp”. The Allegro A3941 datasheet is not very clear (to me) about what it considered signal ground or power ground. In my view, it could stand to be a lot more descriptive about which pins need to be considered “dirty” – directly connected to switching power, so they should under no circumstances be routed to logic/analog ground. Instead, they choose to distinguish between “quiet ground” – what I’d call the logic ground – and “controller ground” vs. “power ground”.

I think I made a mistake here in routing the chip’s main bypass power – which is connected to VDD (battery positive) and “controller ground” – which I interpreted as logic ground for this board, but really should not be. I decided to try jumping this capacitor directly to the chip’s “ground” pin instead of taking it through the ground plane. I did the same for several other capacitors indicated on page 18 of the datasheet, forcing their “ground” sides to avoid the logic ground plane and basically making the only access point of the chip to the logic ground plane at its own ground pin (instead of in a few places).

These two hacks together basically resolved the resetting problem. I could no longer get the DeWalt – a very “dirty” motor, electrically speaking, to reset the board even with current limits off.

Once again – not what you put on the board, but where you put it.

With that cluster of issues resolved, I pushed a “revision 4″ with a few other changes like trace optimizations under the microcontroller, separating everything into a “tree” topology as much as I could – no longer was the 5V supply for the chip coming from 2 different places (!). All the microcontroller’s grounds were gathered and tethered to the plane at 1 location. I also separated the 5V line into a “clean” and “dirty” line – the dirty one is the one fed out to the headers, leaving the “clean” line, which is tapped after the final LC filter stage, to only the microcontroller and current sensors.

Some illustrations of trace optimization for the microcontroller region.

A week and some later, Revision 4 appears…

Okay, so I still had to put them together. This is what the board looks like.

Yes, on the last revision, I forgot to hit “Black LPI please!” and so it was green. I shall not make that mistake again.

This board refused to power on at all. No matter what, the 5V rail never came on, and instead hovered around a few tens of millivolts. What gives? How did I take that many steps back!?

I have a tendency to resort to “explosion debuggin” quickly. That means just running unlimited amps at a low voltage through what is shorted, and seeing what begins smoking first. Every motor controller I’ve made save for LOLrioKart’s controller has been “explosion debugged” at least once. And that’s only because I was running low on the large “brick” MOSFETs.

I took one of the spare boards and ran 10 amps through the 5V rail. Amazingly enough, nothing started smoking, indicating something very low impedance and near to the source. The board did get suspiciously warm in one corner, so it was under the microscope…

Oh my goodness.

It’s a left over stub of a trace that I thought I had erased, but in fact was still there, bridging my 5V straight to ground.

So you might be thinking… But Charles, wouldn’t DRC have caught this? Well yes, but my boards generate so many DRC errors (on the order of 1500+) I just ignore them all and use to check for the most obvious stupidity, but it doesn’t tell one net from another!

This is really just telling me I should set up design rules to actually conform to how I design boards ಠ________ಠ

Well, I suppose I’m glad I don’t have to do this for 250 boards.

A revision 4 board being absolutely hammered to death by the “end boss” of motors – the AM Equipment “D-pack” motor, a marine diesel engine starter motor that, many years ago, drove heavy- and superheavyweight Battlebots with contactor control because no ESCs existed which were hardcore enough to handle them. They can easily draw over 1,000 amps at 12 volts, and their no-load current alone is 30 to 40 amps.

And RageBridge passed the test spectacularly. Check out the “abuse video” here, featuring some other motors while I’m at it.

This is not to imply Rage can control 1,000 amp motors, but that the current limiting algorithm is robust. If I held onto the throttle for longer, the FETs would have unsoldered themselves and attempted to escape. It’s ultimately still thermally limited.

Some more brown fungus sprouts to double check that the noise demon has been exorcised enough within the performance envelope of the controller to not be a nuisance. Notice how I didn’t say eliminated. There’s no such thing in motor controller design.

The story, however, doesn’t end there. You know this to be true because if it did, I would be taking orders right now.

Ever since one of the late models of RageBridge 1 prototype, it has not wanted to operate above about 33 volts. The 5V converter would just shut off and enter what seemed to be a discontinuous mode, or some other mode where the frequency of switching was cut back drastically. Here’s an example, looking at the output pin of the converter BEFORE the inductor:

That’s normal – 24 volts in, 5 volts out. As soon as the voltage crests about 31-32 volts, this happens:

Less than 1 volt out! The ringing indicates that the buck converter is operating in discontinuous mode, but to enter it so quickly and suddenly? Something was going on. During this time, the LM2594 chip itself also got hot quickly, which is not advertised or documented behavior in discontinuous mode.

This fact has prevented RageBridge from operating above 30V reliably, forcing me to rescind the “up to 36V nominal” specification, which fortunately only affected a very small number of users.

So what gives? The LM2594HVM chip is supposed to run up to 60 volts. All my parts in that part of the circuit are 50V on the input, so it ought to at least be fine with that.

I ended up spending the night trying all sorts of stupid things, like making these inductor sculptures. Perhaps the inductance was still a little on the low side? After all, my HV requirements are still in the “coffin corner” of the LM2594 inductor selecton chart.

Nothing changed.

So what has been a constant factor in these boards? The LM2594 power converter design, which has been more or less copy and pasted from older schematics without change. However, everyone else seems to use them fine, including Shane. Since we talk about motor controllers like normal 20-something cosmopolitan guys talk about craft beers and beard maintenance (I have nothing in that department), I went to him for some more perspective.

Umm… let’s take a look at the schematic.

That part number – the MBR120VLSFT3G, is a 20V, 1A Schottky diode. In fact, I found the exact version of RageBridge 1 where I elected to put this diode in: it was when I switched back from the LT3433 buck-boost converter and remade the LM2594 circuit from scratch.

This sounds all too familiar.

Anyways, I likely picked that diode to minimize the losses associated with forward voltage, forgetting the fact that the Output pin of the LM2594 is connected to battery voltage periodically. The lesson here is therefore

don’t use 20v diode at 30v it doesn’t work

I shipped 94 of these.

Sounds good. I replaced both of the MBR120VLSFT3G parts with 50v parts – what I used in RageBridge versions long ago, the STP0560Z.


Three of the four Revision 4 boards in various stages of construction here.

Undergoing a little more stress testing here, now with the D-pack hooked up to a…. leftover propeller from the GLP electric boat class. I wanted a bit more viscous load such that it can draw more amps at higher duty cycles, as well as have a up to 950% greater chance of decapitation.

What else is new? After validating R/C mode, I used the same output driving kernel to make the “EV mode” a lot of you have been craving. I made the signal processing code as modular and functional block-like as possible, sacrificing some speed for the ability to pipe whatever garbage signal into it I please.

Analog mode has two submodes :

  • “unmixed”, using a sprung throttle. Single ended, expecting 1 – 4v active range to represent 0 – 100%, with a discrete reverse switch, or
  • “mixed” using 2 analog joystick axes centered at 2.5V, with a 0.1 to 4.9v active range, controlling forward and reverse and turning in one joystick. This was even easier to write, because that’s literally the same code as the R/C mixing mode.

Selecting the “Combine” jumper forces the outputs to act together, creating a single channel controller. Combine and Mix jumpers are mutually exclusive and logic-checked, since it can’t be single and 2 channel at the same time!

This single channel mode is still not entirely reliable. I’ve rebuilt one of the revision 4 boards twice, finally electing to scrap it.

Since it still is paralleling devices at the driver level, if one driver hiccups or lags, it’s easy to cause cross-conduction (a high side and low side FET of the same half-bridge turned on at once) and destroy everything instantly. To counteract this, I’ll likely increase the deadtime – which right now is just barely enough to not cause cross-conduction in one channel mode – to permit more timing slop.

Will from Hypershock paid a visit to help me test single-channel R/C mode on Hypershock itself. Unfortunately, the aforementioned unreliability made this test largely a flop. However, if I improve this reliability, Rage2 in single-channel mode is a great match to a single “short” Ampflow motor, which means it’s not out of the question for use in heavyweight / BattleBots classes.

The price of progress – the twice-rebuilt and scrapped board, along with some more destroyed parts. After a board blows up once, none of the semiconductors are really the same ever again, so I’m not sure why I even bothered with rebuilding.

When one Rage dies, 10 more take its place!

These are “revision 5″ boards – hopefully the last of the revisions, and once assembled, will go out for beta testing. A few are slated for appearance at Dragon Con in 2 weeks, another few are being sent to Power Racing Series competitors to see how it holds up under the rigor of racing. Two completely different loading regimes and set of input & output requirements!

It’s time to order more gate drivers.

Also, here is an interesting picture.

Motorama 2015, Part I: RageBridge v2 Drama

Mar 04, 2015 in Events, Motor Controllers, Überclocker ADVANCE

Let it be known! I shall not update my blog with the Motorama event report until all other MIT-based Motorama competitors update theirs. If you see the Part II, it means I’ve finally been satisfied… or got sick of waiting. I am a man of unyielding principle. For some background on this, through a spectrum of high-pressure sales tactics and peer pressure, an astounding number of new builders are attending; by my estimates, we had 6 totally new entries (and attendant totally new builders). One group elected to complete in the Antweight (1lb) tournament that runs on Friday, something that even I don’t normally do!

As I mentioned last time, none of the bots were in bad shape pre-Motorama, but I’ve been expending immense energy trying to get RageBridge v2 working in time. So why not start with it?

RageBridge v2

Previously in the adventures of RageBridge, I had gotten the bulk of the automatic input-reading organized through a depth of register-diddling greater than what I’ve ever dared do before. If you know me and how I program embedded systems, you know that registers are my most favorite things about the process, and there’s nothing I look forward to more when starting a new microcontroller project than hunting through the thousand-page programming manual and trying to write bit manipulation expressions.

Now, with the retching out of the way, time to try writing an input-taking routine.

One programming challenge for RageBridge v2 was the automatic input-mode detection. I don’t have a rail of jumpers to select the operating mode, and don’t intend on having one since the board is already SLAM-PACKED WITH RAGE!If I can get a reliable automatic input detection, then great! If not, then different firmwares will be made available.

The inputs to decide between are R/C, Serial packets, and analog. On power-up, Rage will take a second to let the inputs stabilize and any partner electronics like receivers and master microcontrollers boot up. Then it will, ever second, check for…

  • Serial buffer byte presence. It will read the first few bytes of the serial buffer and check for 64 or 192 (out of 255, an 8-bit value). These are “idle” commands for left and right motors. This convention is common to several robot controllers that have “simple serial” protocols, where 1 – 127 controls one motor and 128-255 controls the other. If these bytes are present, then assume Serial operation.
  • If there are no valid serial bytes, it will set up the channels 1 and 2 input pins for analog voltage reading. Additionally, it checks if the MIX jumper is set. MIX assumes “joystick mode” where the sticks are centered at 2.5v, so both inputs have to be at this level (within a small deadband) to select that mode. Else, if MIX is not in, it assumes 0-5v with 1-4v as the active range, meaning the signal must be approximately 1V (within a small deadband) to select.
  • If the analog voltages aren’t within the correct band (or it’s pegged to 5v due to the internal pullups) it will initialize the R/C inputs and wait to collect input pulses. Once valid input pulses for both Channels 1 and 2 are received – which must be 1500us +/- a deadband – then the mode is selected. The forced neutral-only mode selection acts as a zero-power-on-startup check too.

This pattern repeats once per second, and the motors will not drive until the appropriate signals are received. Overall, the code looks something like…

I had thought the Analog part would be the most difficult, with the deadband requirement and all. But in fact it was quite easy. With a few test potentiometers and scooter throttle handles, I could get it to reliably pop into Mix or non-mix mode every time. R/C mode proved to be the issue – no matter how much delaying or waiting I had it do, across different receivers even, I couldn’t get R/C mode to work!

As a bit of background, I use the PinchangeInt library to capture R/C pulsewidth signals without having to use the blocking (prevents rest of program from doing anything) pulseIn() function in Arduiono. After writing up a quick R/C only input-taking test program, I noticed something peculiar. All of the inputs read, no matter one channel or the other, simply looked like they were overflowing the variable over and over:

The PinChangeInt interrupt service function takes the difference between the micros() calls of two functions, a rising edge and a falling edge, to get the delta-time. micros() is an unsigned long (32 bit) type, and my R/C pulsewidth variables are signed integers (to be used later in mapping/scaling math). The pattern of values said to me that something was just counting further and further up – not taking the difference at all.

Checking with an oscilloscope confirmed that only one interrupt was being serviced:

I set and cleared a pin on the chip whenever the rising edge or the falling edge interrupt was being triggered. As expected, only one edge appeared. With this test, however, I couldn’t tell if it was the rising or falling edge…

…especially when it seemed that SOME TIMES, both interrupts were working! This shot clearly showed a 1000us pulse width, with two triggers. So what the hell was going on?

By the way, this is the first official usage of the DSO Nano 4 channel digital scope I picked up in Shenzhen! All of the initial debugging shenanigans happened at my desk as a result.

I reached out to the Arduino Forum, where the developer of PinChangeInt had a thread about the library, and learned some interesting facts… namely, that the code should never have worked the way I wrote it in RageBridge 1, and a couple of projects before that.

Well, hmmm.

To clarify without having to read the thread, here’s the difference. I’ve written all my R/C input code in the form of two separate interrupts, RISING and FALLING edge, since 2011 when I first started using the library. The form is similar to this, which was an excerpt from TinyCopter:

The takeaway is that there are two interrupts per pin. Allegedly, this should never have worked!

Yet, compiled in the latest version of Arduino, with the latest version of PinChangeInt, this is what happened. The same kind of nonsense I saw in my initial testing. It seemed to me that only the interrupt I defined last was executing, which contradicted what I saw on the oscilloscope – that some times both interrupt service routines did execute. But I freely admit that this could have been a oscilloscope artifact.

Pictured above is the structure that SHOULD HAVE been used this whole time – a single interrupt service routine, executed whenever the pin CHANGE’d states, and which subsequently read the state of the pin:

As the collected 1500us (approximate) pulsewidth shows, this works fine.

So what gives? Not even the developer knows, apparently! My “two interrupt” form was never supposed to work. I can only assume that between Arduino version 1.0.1 from 2013 andthe current 1.6, and from the first version of the PinChangeInt library I used to the current, that enough changed such that whatever loophole I used was no longer possible.

Either way, with the solution found, I backtracked a little and modified my “two interrupt” program to show which interrupt “won”, so to speak.

I changed the two-interrupt type to only increment or decrement a variable depending on which component was called. As I suspected, the last ISR to be declared always “won”. Here, vol_ch1_pw is being sampled by the main program loop, which shows it always decreasing. if I swapped the declaration order, it would keep increasing.

Whatever. Chalk it up to falling victim to the stochastic nature of Arduino developers, and y’all can lecture me about this is why you always use the programming manual yadda yadda I-don’t-care. It works now:

The PINC & [byte gibberish] portions of each ISR simply “select” the pin to read. Notice how it starts at 0b00000100 – this is because the first two bits represent the first two pins of port C, PC0 and PC1, which are reserved for the current sensors. PC2, PC3, and PC4 are the three channels of input.

With that mystery resolved, the entire automatic mode detection code worked instantly:

Shown above is Analog (unmixed, with a scooter throttle) and R/C mode inputs. Serial inputs are hard to capture on video since it’s one microcontroller talking to another. I assigned different blink patterns for the different modes to help during debugging, but they will be retained for actual operation.

The blink routine itself is interesting by itself. It’s the first time I’ve used an otherwise unused hardware timer (Timer 2 in this case) exclusively as a blinking machine. Here’s the code snippet that makes it work:

The software “prescaler” portion was carried over from my previous different motors controllers’ code, where it was part of the main loop. Either way, something executes that if() and builds up the prescaler variable. After enough times of this happening, it executes the blink part of the code.  Timer 2 was set up during the initialization as a simple counter with a hardware prescaler of 64 from the system clock of 16MHz. This resulted in a counting speed of 250KHz – every 4 microseconds, the count would increment. Left to its own devices, this count would overflow after 256 counts, or 1.024 microseconds. To obtain a clean (to us humans) number, we start the count at 6 (BLINK_INITIAL_VALUE) such that it only has to count 250 times per overflow, giving a clean 1 millisecond timer. With some frills, that’s basically the millis() function re-implemented. I could have included this in the main loop as a call to millis() and it probably would have worked just fine, but I wanted it on a separate interrupt to not hog main program loop time.

Next up is that horrific line of bit manipulation that somehow worked the first time. What this line does is turn PB5 – a.k.a Arduino pin 13, the LED, on and off according to the state of a byte that is being used purely as an 8-bit array, where a 1 means “LED on” and 0 means off. current_blink_pattern is this byte, and it’s assigned whenever the mode changes so the blinking pattern changes.

The line first takes PORTB (the output status of the pins) and masks off PB5. Next, it grabs a copy of current_blink_pattern and shifts it right by some number of bits – basically an array counter that is reset at the bottom every time it exceeds 7. It logical ANDs this with 0×01 to isolate the least sigificant bit (rightmost bit). Finally, it moves this bit leftwards 5 positions to line up with PB5, and jams the two together.

The result is that PB5 is always turned off every cycle but the result of (current_blink_pattern >> blink_index) & 0×01 turns it back on (or leaves it off for this cycle).

With BLINK_INTERVAL set to 100 and the interrupt happening every 1 ms, the result is a 0.1 second blink duration where the LED can on or off. Now, strictly speaking, with 8 bits I can only make 0.8 second-long blink patterns. That’s fine, I don’t care.

Yes, I get all the way to the end of this timing problem and don’t even care that I get clean 1-second long patterns.

One thing that all the scoping to get to the bottom of the interrupt issue was discovering that the input filter capacitance I put on the input pins, which are shared by both analog and digital signalling, was too great.

Ouch, that’s a 10us rise time there. The fall time is about twice as fast, but still bad. I put 4.7nf input caps on the pins, which I guess is too much for another little microcontroller’s pins to drive. I might have to compromise analog signal stability (or implement software filtering at some point) in favor of making the edges sharper.

Once the bizarre library behavior was accounted for, and the automagic mode selector finished, the rest of the code was actually quite easy. In concept, it was just like RageBridge 1, but better implemented.

First, the inputs are sampled and cleaned, with erroneous signals replaced with the “last known good” one and a signal-bad flag set. Next the signal is mapped to an output variable. The output variable is bounded by a maximum increment per loop (ramped), and the result deciphered into PWM + direction and output to the drivers.

Whereas in RageBridge 1 all of this took place messily within 1 loop, I organized it all into procedures so the different modes can be better isolated, even thought hey still acted on global variables:

Of course, right now, I only have the R/C code written.

I did away with the incredible machine that was the mapWithRampingAndDeadband() function of RB1. That was basically broken up to its constituents – the deadband was taken in the input processing stage, and the ramping output mapping just a compare and += or -=.

Soon, it was time to test. Without having made compatible heat sinks yet, I, uhh, created an innovative board clamping system to secure it to the old style Ragebridge 1 heat sinks.

Innovative. That’s the word.

It’s totally not “two binder clips and some electrical tape”.

The test subject was Clocker. By this point, it was Wednesday afternoon, so this was going to be a determinator as to whether or not I try running the new boards at Motorama or not.

During a few on-the-bench tests of pegging the throttle back and forth, I was able to get the board to reset several times. This is not a good sign, as it shows the design has noise coupling into it in some place that is making it all the way to the logic. I have a few suspects, namely the long analog power and ground traces feeding the current sensors and the less than optimal placement of the logic power supply taps from the main board power planes.

My first battle tactic is always to insert capacitance where it doesn’t belong to see where the noise was coming from. For starters, all the 0.1uF logic circuit buffering capacitors were changed to 1uf. Now, strictly speaking, I suppose it was capacitance that was there in RageBridge v1 but was removed, since all of those on version 1 were 1uf to begin with. I also changed the primary input bypass capacitor (on the Vcc pins of the micro) from 1uFto a 10uF.

For the most part, as far as I could tell, this resolved the issue. But capacitors are band-aids to the real problem, which is layout. I’m going to have to take a closer look at how the logic power is feeding in and out of the big patches of battery voltage and ground planes, all being switched hard tens of thousands of times a second.

There was also one particular pin connection on the A3941 gate drivers which I was unclear about, which may also contribute to noise coupling via ground fluctuation, but I will address that once I put together some more boards. In the mean time, I taped the board back into Clocker for some hard driving.

For the most part, the test went quite well…

This test revealed a very important hidden flaw in the drivetrain that I’m glad was caught. Namely, when I last took apart the DeWuts on Clocker to change the motors, I neglected to recheck the torque-limiting clutch screws. The clicking, clutch-slipping noise in the video is exactly that. A little bit of hex key wiggling – no sprocket removal even needed – and things were tightened up again.

During this and subsequent bench tests, I couldn’t get it to lock up or reset no matter how much I gunned the motors around. In fact, I did it so hard that…

What you see is a thin pall of DeWalt smoke from some rapid input reversal testing gone wrong. It seems that one of the motors had a borderline commutator short, which quickly became non borderline when rapidly smashed with +/- 26 volts.

The resulting quick short also took out one gate drive chip and two FETs on the half of the controller driving that motor. I replaced them both in 5 minutes, along with sending this motor to the pile of sad motors.

I ended up deciding not to run RageBridge v2 (board revision 1) in Clocker for this event, since I didn’t want to have to do ESC debugging in the field while my match is 2 minutes away. What I did do in the remaining day was add in the much-requested combine mode, which hard-parallels the two channels together at the hardware level. This enables Rage to function as a single large 1 channel ESC.

That part was easy. In combine mode, only channel #1′s current sensor is read and the assumed current is just twice that. The current control loop output calculated for channel 1 is applied directly to channel 2, making the assumption that the two halves, driven off the same PWM timer with the same gate driver, will switch on (within a small fraction of the total switching time) with eachother. This is not the most robust method, as it totally slaves channel 2 to channel 1′s mercy, and a failure on channel B will probably cause the whole thing to grenade. Maybe it’ll get revisited shortly.

Why did I put Combine mode together? Because another bot this time needed it…. and for that, we’ll need to wait for Part 2.