Archive for the 'Motor Controllers' Category

 

The Semi-Official Launch of RageBridge

Feb 05, 2013 in dewut?, Motor Controllers

After months of design, iteration, and testing (most of which has ended up on this very website), I’m proud to introduce RageBridge for general sale to the robot-inclined public.

Get yours today!

Now, this isn’t a launch announcement per se – I’m waiting for the DeWut CNC mounts to arrive, then a more official announcement will be done once those are ready. But, given that some events like Motorama are coming up, I figured this pre-grand-opening-grand-opening will be helpful.

Here’s roughly what the DeWuts will look like in component form; this preview was sent to me by the CNC ship a few weeks ago when the order was not yet complete.

And thusly, Big Chuck’s Robot Warehouse begins humbly. 2013 is shaping up to be a great year so far…

The Forthcoming RageBridge: Stick Calibration

Feb 02, 2013 in Bots, Motor Controllers, Project Build Reports, Reference Posts

They’re here!

All of the RageBridges! All of them ever!

Or rather, 100 of them, in neatly packaged panels of two. Here’s what one of the manufactured panels looks like.

Pretty cool.

Okay, so these actually got in last week, but I’ve been doing some background and infrastructural work since then. I’m planning on gathering a few friends and flashing, populating headers, and testing all of these this coming weekend. I decided to leave the chips unflashed because I was not yet satisfied with the firmware (and the flashing was a few hundred extra dollars), and the headers are purposefully left unpopulated because many people prefer soldered-on pigtails or their own wiring configuration. It’s definitely a little more legwork on our end, but for such a small run (100, maybe with a few duds) I think it’s still manageable, and will allow the fine settling into best practices that inevitably accompany any parts business. Time to be a little adventurous.

From a firmware perspective, the only thing RageBridge has been missing since the last board revision is a way to calibrate the servo PWM range. This is generally preferred because not all radios are created equally, and some may have more stick travel & adjustable PWM endpoints than others. For instance, my (nice for 2006) Spektrum radio can hit the full 1000-2000uS servo range if I navigate through the menus and tell it to stretch its range a bit. But my cheesy Hobbyking 6 channel radios can’t do the same unless connected to a computer to program them – the stock range is more like 1200 to 1800us. So, any fixed input range will inevitably be a compromise – for some people, the stock settings will be too twitchy (i.e. stick travel range is greater than the board’s accepted input range), or you might not ever hit full throttle (because the radio stick travel doesn’t go far enough to match the controller input range).

Calibration has always been one of those things that I accepted as working, but never thought about implementing. Depending on how it’s done, it can be relatively simple, or a mess of state machine code.

One of the most common modern calibration paradigms is the “stick-high” method, used by most R/C model controllers, whether air, sea, or ground. This involves powering on the controller with a receiver attached (and generally, already powered and outputting valid pulsewidths) and you commanding full positive travel. If the first thing that the ESC sees, or sees within 1-2 seconds, is a full positive signal, then it waits for a few seconds and checks again. If you are still holding full positive, then it beeps or blinks (accepting the full positive position), and then you back off to full negative and hold for a few seconds, then back to neutral. For single channel ESCs without many other features, it’s pretty much the way to go.

I decided to implement stick-high calibration for RB, except modifying it for both channels at once. This entailed adding a timed loop in the middle where normally you would just check for full positive and full negative signals. The idea is that during the timed loop, the user just swirls the sticks around all at once and the controller will capture both ranges simultaneously. At any point, if the signal returns to neutral for more than 2 seconds, the calibration routine exits and writes the results to EEPROM so it is persistent.

Of course, there’s other little touches to make the system more robust like checking for pulse validity (rejecting malformed or misread pulses) and fail-safe performance if the user bails out in the middle. In all, it took me a few hours of planning and a few hours of beasting Arduino code, and I’m quite pleased with the final result.

So, in a completely out of context brain bump, here’s RageBridge’s stick calibration code. When I ship it through e0designs.com, the full source code will be released along with board files, but I’m putting this early because I’m particularly proud of it.

I subscribe to the Expository Essay school of code commenting – I literally write what every line and every procedure does, in detail, and in natural english. To hardcore and experienced coders this might seem like a waste of characters, but I find it particularly easy to read my way back through old code and decipher what the hell I thought I was doing when I wrote it. So there’s actually plenty of paragraphs in the comments.

As a bit of backstory since I didn’t post all the variable definitions, anything with a _1 or _2 is referring to the channel of RB it is relevant to. The code is written with Arduino 1.0.1 using the PinChangeInt and EEPROM libraries (PCI is not used in this section as the interrupt procedures that capture servo pulsewidths are not shown).

  • RCMAX, et. al. are all declared as signed integers at the beginning of the code (not shown).
  • CALIBRATION_CONSTANT is a fraction of the total stick travel, right now 0.66. In other words, anything ABOVE 66% of the current maximum travel is grounds for entering calibration mode. This is one of the tricks I added to prevent calibrating yourself out of your own radio travel bounds. So, basically what it entails is each time you calibrate you could reduce the range by 1/3rd if you had to.
  • neutral_counter and NEUTRAL_CYCLES_MAX refer to how many iterations of the neutral signal checking routine can run before the calibration procedure is declared to be done.
  • NEUTRAL_DELTA is the pulse width deviation around the current neutral point that can be recognized as a new valid neutral point. For instance, the default neutral pulsewidth for servo PWM is 1500us. If NEUTRAL_DELTA is defined as 100, which it is, then anything from 1400 to 1600 may be set as a new neutral point. This is to make sure you cannot drift the center stick zero throttle point too far, even on purpose. You can, of course, do so by running multiple calibration cycles. But why!?
  //Collect the user calibration endpoints from EEPROM. If the EEPROM values return 255
  //then calibration has never occurred, so use defaults.
  RCMAX_1 = (signed int)EEPROM.read(100);
  RCMAX_1 += (signed int)(EEPROM.read(101) << 8);
  RCMIN_1 = (signed int)EEPROM.read(102);
  RCMIN_1 += (signed int)(EEPROM.read(103) << 8);
  RCCENTER_1 = (signed int)EEPROM.read(104);
  RCCENTER_1 += (signed int)(EEPROM.read(105) << 8);
  RCMAX_2 = (signed int)EEPROM.read(106);
  RCMAX_2 += (signed int)(EEPROM.read(107) << 8);
  RCMIN_2 = (signed int)EEPROM.read(108);
  RCMIN_2 += (signed int)(EEPROM.read(109) << 8);
  RCCENTER_2 = (signed int)EEPROM.read(110);
  RCCENTER_2 += (signed int)(EEPROM.read(111) << 8);

  //Bytes will return 255 if they were never read; full 16 bit result is 65535
  if(RCMAX_1 == 0xffff ) {
    RCMAX_1 = RCMAX_DEFAULT;
  }
  if(RCMIN_1 == 0xffff) {
    RCMIN_1 = RCMIN_DEFAULT;
  } 
  if(RCCENTER_1 == 0xffff) {
    RCCENTER_1 = RCCENTER_DEFAULT;
  }
  if(RCMAX_2 == 0xffff) {
    RCMAX_2 = RCMAX_DEFAULT;
  }
  if(RCMIN_2 == 0xffff ) {
    RCMIN_2 = RCMIN_DEFAULT;
  } 
  if(RCCENTER_2 == 0xffff) {
    RCCENTER_2 = RCCENTER_DEFAULT;
  }  

  delay(1000); //Just chill for a bit to make sure radios have bound and begun sending out good signal.

  //Calibration mode procedure.
  //After initialization, check for good signal on channels 1 and 2
  //If the signal is above the calibration threshold on both channels, keep waiting. If not, enter main program loop.
  //If at the end of 5 seconds the stick has been held, enter calibration mode. If it has not, enter main program loop.
  //Even if there is no good signal, proceed to main loop anyway - the main loop begins in failsafe mode. 
  if(is_pulse_good(vol_ch1_pw,RC_ABS_MAX,RC_ABS_MIN) && is_pulse_good(vol_ch2_pw,RC_ABS_MAX,RC_ABS_MIN)) {
    signed int init_calib_threshold_1 = (signed int)(CALIBRATION_CONSTANT*(RCMAX_1-RCCENTER_1))+RCCENTER_1;
    signed int init_calib_threshold_2 = (signed int)(CALIBRATION_CONSTANT*(RCMAX_2-RCCENTER_2))+RCCENTER_2;

    if(vol_ch1_pw > init_calib_threshold_1 && vol_ch2_pw > init_calib_threshold_2) {

      //To check for stick hold, begin the timer and set a flag that will be cleared if the stick is released
      unsigned long calibration_timer = millis();
      boolean entered_calibration = true;

      //Enter 5 second wait loop, constantly checking for stick release. Invalid signal also constitutes "stick release".
      while(millis() - calibration_timer < 5000) {
        if(is_pulse_good(vol_ch1_pw,RC_ABS_MAX,RC_ABS_MIN) && is_pulse_good(vol_ch2_pw,RC_ABS_MAX,RC_ABS_MIN)) {
          if(vol_ch1_pw < init_calib_threshold_1 || vol_ch2_pw < init_calib_threshold_2) {
            entered_calibration = false;
            break;
          } //End stick release check
        } else {
          entered_calibration = false;
        } //End pulse good check

      } //End wait for 5 seconds to check for stick hold

      //If the flag is still true, then the user has held the stick for > 5 seconds above the threshold
      //Calibration mode description:
      //Resetting the old max and min bounds to a lower threshold (CALIBRATION_CONSTANT * RCMAX_n)
      //If a newly captured value exceeds the thresholds, save it. 
      //If a newly captured value is within a certain % of neutral (NEUTRAL_CONSTANT * RCCENTER_n above or below RCCENTER), start a timer
      //After 3 seconds of this, assume the user has returned stick to desired neutral and take several samples for neutral position
      //If any pulse is invalid, bail out of calibration and retain old values.
      if(entered_calibration) { 

        digitalWrite(BLINK_FURIOUSLY,HIGH); //Set the LED on solid to let the user know that calibration has begun

        //Set initial thresholds to exceed. The thresholds are a certain % of the current set of maxes and mins
        //such that the controller can never be "calibrated out". By only exceeding the threshold very slightly
        //subsequent iterations of calibration can narrow the range of signals too, if it is necessary.
        signed int rcmax_1_temp = (signed int)(CALIBRATION_CONSTANT*(RCMAX_1-RCCENTER_1)) + RCCENTER_1;
        signed int rcmin_1_temp = RCCENTER_1 - (signed int)(CALIBRATION_CONSTANT*(RCCENTER_1-RCMIN_1));
        signed int rcmax_2_temp = (signed int)(CALIBRATION_CONSTANT*(RCMAX_2-RCCENTER_2)) + RCCENTER_2;
        signed int rcmin_2_temp = RCCENTER_2 - (signed int)(CALIBRATION_CONSTANT*(RCCENTER_2-RCMIN_2));
        signed int rccenter_1_temp = RCCENTER_1;
        signed int rccenter_2_temp = RCCENTER_2;

        boolean am_calibrating = true;
        boolean commit_calibration = false;

        byte neutral_counter = 0;

        //Set the main calibration loop going. 
        //First, check for good pulses. If any are bad, the routine is immediately ended and changes are NOT saved.
        //Next, check for pulses near neutral. If any are, increment a counter. If the counter is over a threshold,
        //then the user has returned the stick to netural and calibratoin can exit/changes be saved.
        //If any subsequent pulses are outside of the neutral bound, zero the counter. 
        //Next, expand the pulse range if the new set of pulsewidths are greater in magnitude deviation
        while(am_calibrating) {

          //Sanity check - if any pulses are out of range or invalid, exit.
          if(is_pulse_good(vol_ch1_pw,RC_ABS_MAX,RC_ABS_MIN) && is_pulse_good(vol_ch2_pw,RC_ABS_MAX,RC_ABS_MIN)) {

            //Save a copy of the current "volatile" pulsewidths (which can change randomly due to the interrupt)
            ch1_pw = vol_ch1_pw;
            ch2_pw = vol_ch2_pw;

            //Neutral check. If the signal is within the box of valid neutrals for enough cycles, exit and save changes.
            if(ch1_pw < (RCCENTER_1 + NEUTRAL_DELTA) && ch2_pw < (RCCENTER_2 + NEUTRAL_DELTA)) {
              if(ch1_pw > (RCCENTER_1 - NEUTRAL_DELTA) && ch2_pw > (RCCENTER_2 - NEUTRAL_DELTA)) {
                if(neutral_counter > NEUTRAL_CYCLES_MAX) {
                  am_calibrating = false;
                  commit_calibration = true;

                } else {
                  neutral_counter++; //Within bounds, but not exceeding number of allowed cycles, so increment and move on.
                  rccenter_1_temp = ch1_pw;
                  rccenter_2_temp = ch2_pw;
                }
              } else {
                neutral_counter = 0; //If any of the within-bounds checks fails, reset the counter since the stick has moved.
              }
            } //End neutral check

            //Bounds check; If the new pulses exceeds the current set of temporary calibration bounds in either direction
            //set them as the new bounds.
            if(ch1_pw > rcmax_1_temp) rcmax_1_temp = ch1_pw; else if(ch1_pw < rcmin_1_temp) rcmin_1_temp = ch1_pw;
            if(ch2_pw > rcmax_2_temp) rcmax_2_temp = ch2_pw; else if(ch2_pw < rcmin_2_temp) rcmin_2_temp = ch2_pw;
          } else {
            am_calibrating = false;
            commit_calibration = false; //Something has gone wrong and caused the calibration loop to terminate early...
          } //End sanity check
          delay(20);
        } //End main calibration loop

        //Save changes?
        if(commit_calibration) {

          //First, reassign the constants for this power cycle...
          RCMAX_1 = rcmax_1_temp;
          RCMIN_1 = rcmin_1_temp;
          RCCENTER_1 = rccenter_1_temp;
          RCMAX_2 = rcmax_2_temp;
          RCMIN_2 = rcmin_2_temp;
          RCCENTER_2 = rccenter_2_temp;

          //Next, write these new values to EEPROM!
          byte rcmax_1_lowbyte = (RCMAX_1 & 0x00ff);
          byte rcmax_1_highbyte = ((RCMAX_1 >> 8) & 0x00ff);
          EEPROM.write(100,rcmax_1_lowbyte);
          EEPROM.write(101,rcmax_1_highbyte);

          byte rcmin_1_lowbyte = (RCMIN_1 & 0x00ff);
          byte rcmin_1_highbyte = ((RCMIN_1 >> 8) & 0x00ff);
          EEPROM.write(102,rcmin_1_lowbyte);
          EEPROM.write(103,rcmin_1_highbyte);

          byte rccenter_1_lowbyte = (RCCENTER_1 & 0x00ff);
          byte rccenter_1_highbyte = ((RCCENTER_1 >> 8) & 0x00ff);
          EEPROM.write(104,rccenter_1_lowbyte);
          EEPROM.write(105,rccenter_1_highbyte);

          byte rcmax_2_lowbyte = (RCMAX_2 & 0x00ff);
          byte rcmax_2_highbyte = ((RCMAX_2 >> 8) & 0x00ff);
          EEPROM.write(106,rcmax_2_lowbyte);
          EEPROM.write(107,rcmax_2_highbyte);

          byte rcmin_2_lowbyte = (RCMIN_2 & 0x00ff);
          byte rcmin_2_highbyte = ((RCMIN_2 >> 8) & 0x00ff);
          EEPROM.write(108,rcmin_2_lowbyte);
          EEPROM.write(109,rcmin_2_highbyte);

          byte rccenter_2_lowbyte = (RCCENTER_2 & 0x00ff);
          byte rccenter_2_highbyte = ((RCCENTER_2 >> 8) & 0x00ff);
          EEPROM.write(110,rccenter_2_lowbyte);
          EEPROM.write(111,rccenter_2_highbyte);
        }

        //We're done with calibration! Flash the LED a few times to indicate success.
        for(byte caliblink = 0; caliblink < 10; caliblink++) {
          PORTB |= (1 << 5);
          delay(BLINK_DURATION);
          PORTB &= ~(1 << 5);
          delay(BLINK_DURATION);
        } 
      } //End of master calibration routine

    } //End of check signal over calibration threshold

  } //End of check signal good

RageBridge Revision 3: Boost Converters and the Market Survey

Dec 11, 2012 in Motor Controllers

Continuing the story of Ragebridge’s quest to find a stable power converter design, I received the updated version 3 boards earlier last week, and got around to assembling and testing them over the weekend. I think RB is ready, at this point, to enter the release candidate & fine tuning stage of the development process. But first, I had an adventurous time remembering what boost converters did.

First, if you want to skip straight to the RageBridge potential customer & user survey, feel free to just click through.

To summarize, the RB project has seen me move away from a known stable (but not that vintage) power supply design to exploring other ways of generating logic voltage and gate drive voltage in order to push the lowest operating voltage down below about 18 volts. My general setup has been dropping a switching regulator on the battery input and buck converting to 15 volts (gate drive voltage) and then a linear regulator to 5v (logic voltage).

This arrangement has been reliable, but it pretty much limits the working voltage of the controller to greater than 13 volts or so. The switching regulator, a LM2594, can turn entirely on and pass the input voltage, but it has a 1.3 volt saturation voltage penalty. Add to that the other 1 volt or so of diodes (one before and one after), and the gate drive ICs turning off at 10 volts, means that operation down to that level or below is undefined.

My intention is to make this board also useful for 12v lead-acid and 3S lithium systems, of which there are still plenty, and hence I needed a way to make sure the board is logically determinate down to maybe 8 volts. The previous board version, as detailed in its post, explored an integrated buck-boost converter, the LT3433.

Unfortunately, while it could have worked in principle, it turned out the chip couldn’t supply enough current to run everything on the board. At around 20 volts, the output began sagging out of spec.

Turning my attention to a more serial arrangement of components, I decided to take the slightly less efficient (in principle) method of chaining a boost converter after a buck converter. In this case, I was going to convert battery voltage directly to 5v logic, and then from there, boost to 15v gate drive. This keeps the regulators (nominally) separate and out of eachothers’ affairs. The chip used was the LT3460, a small dedicated boost converter controller. There would be no more linear regulator, so I had to pile on the capacitors to keep ripple voltage lower and also added a transient voltage suppressor diode to the 5v bus.

That’s where the design stood as of 3 weeks ago, and the corresponding board layout is:

I pretty much followed the recommended layout of the 3460 exactly. This had better work. I sent out this design to MyroPCB, once again, but in 1oz only (since I was just out to test this converter, more or less) and…

in black. I’ve always wanted black boards – they just look so much more badass. As usual, I placed my Digikey order when Myro notified me of the boards shipping, but that seems to have gotten delayed, so my Digikey order appeared a few days before the boards.

The first thing I wanted to test was the power converter, so it was assembled first thing. It’s important to note here that I also bought a same-footprint-and-pinout equivalent of the LT3460, the MIC2288. The alternate chip has a much higher (1.3A) switch current limit than the 3791 at 300mA. This will become important later.

With the power converter testing out good, I finished one board fully and did a load test with a small 5v fan (0.15A) and a spektrum receiver (0.09 to 0.12A, because what?). This was just to make sure the thing could hold up under load. The gate drive, at this point, was not yet enabled (the receiver was in failsafe mode).

After that was done, it was time to drive motors. I remembered that I had Segfault’s old drive motors, which are CIM motors stirring a hydraulic brake a 27:1 Banebots P80 gearbox filled to the brim with thick grease. This thing draw like 15 amps just running freely, and an overvolted CIM can certainly push enough current  to scare most controllers. One of Überclocker’s batteries provided the bus voltage. Even though testing unknown controllers on a battery (a source of potentially infinite amps) is a bad idea, I did it because..

ouch. The sketchy switching lab supply has that as its output voltage waveform. I thought I was chasing down a noise issue on the board when I realized anything the scope probe touched was displaying this waveform or some linearly transformed version of it! Oops. I had forgotten that switching power supplies are usually pretty bad in terms of voltage ripple and noise, cheap ones especially.

It might be worth iterating to other aspiring secret board ninjas that you DON’T EVER USE A SWITCHING POWER SUPPLY TO TEST SENSITIVE LOGIC CIRCUITS. Linear power supplies, though lower in amperage, supply a much cleaner power rail that can be essential for correct operation of circuits, especially analog ones.

Anyways, after switching to the battery, I realized the noise issue was probably something else. The symptom was, like just about every disease that afflicts motor controllers, frequent and unexplained resetting. Maybe it was some weird positive feedback effect between 2 switching regulators? I tried scoping the 5v and 15v supplies to check for their stability, and it seemed okay. What was weirder was that the behavior was only present if the radio was on and the signal was valid. The board wouldn’t exit failsafe mode.

Leading me closer to the culprit was the fact that the behavior was basically the same as hitting the reset button. It took a little while of sitting and watching the 5V rail, but finally I saw a strange transient:

Wow. That’s my 5 volt bus dipping to about 2.8 volts, then flying back up to 6.5 volts. Something weird was happening.

The critical clue was seeing this transient occur whenever the board entered running mode (i.e. left failsafe mode). It also happened immediately after reset, before the program has a chance to load. The transition from running to failsafe mode was smooth, and by pure accident, I left the USB cable plugged in (while trying to mess with the code to see if I could get the reset to occur elsewhere) and noticed this transient did not occur. I could, in fact, “bootstrap” the board with USB power, then after it enters running mode, unplug the USB. And it will be fine.

It was clear to me now that it was caused by something suddenly wanting a ton of power from 5 volts. But what? The microcontroller doesn’t need that much of a load at the start.

The only thing that happens when the board leaves failsafe mode is that the gate drivers are enabled. Could that be the problem? I began to suspect that the sudden current demand of all the gate drivers enabling at once caused the boost converter chip to go crazy. To test this hypothesis, I ‘staggered’ the re-enabling of the gate drivers into 2 groups, separated by 5 milliseconds.

It was definitely the boost converter beating my 5V buck converter into submission now. The fact that there is a transient whenever the gate drivers turned on was the decisive piece of evidence here. What’s funny is, the board worked fine in this state. It seems the sudden pull from the 5V rail is no longer enough (since only half the gate drivers are demanding current) to reset the chip.

The explanation as to why the gate drives suddenly want a burst of current is that the first thing they do when enabled is turn on the low side FETs on all the H-bridges (i.e. feeding a pretty big capacitor in the form of the gates). The bootstrap capacitor for the high side also charges at the same time. A small dip in voltage occurs on the 15 volt bus as a result.

Because the boost converter is much faster than the buck – 1mHz vs. 150kHz, it responds by pushing more current through the inductor (briefly 1.3 amps worth at least, according to the MIC2288′s rating) and it does so quicker than the buck converter can respond. As a result, by the time the buck converter duty cycle catches up, the transient power demand on the 15v bus has already been fulfilled, so the boost converter backs down output current. Again, because the buck converter is slower to respond, it overshoots and then slowly adjusts itself again. That’s how I think it goes anyway.

So basically, I need a precharge circuit or something for my 15v bus. Well, one way to combat capacitor dumping is with more capacitors:

First, I replaced the small 10uF 16v ceramic output capacitor of the boost with a giant 47uF one. On this board, its brethren are buffering the 5V line.

This had very little effect. It seems that the problem is still the boost slurping from the 5V line when it has a sudden demand on the output (necessitating charging up the inductor with a burst of input current). So I moved it to the other side.

This made the transient less in magnitude, but unfortunately it was still causing the ATMega to brown out.

Facing another potential redesign of the board to add even more capacitors or something, I thought about other bad hacks like isolating the 5V power converter from the rest of the logic with a low-ohm resistor, such that even if the converter itself goes under a little, the local capacitors at the ATMega and current sensors, etc. will keep them afloat briefly.

Then I remembered the LT3460 has a 300mA internal switch current limit. The MIC2288 has a 1.3A limit. I began thinking that maybe putting a converter that can briefly eat 1.3A after one which can only source 0.5A (the LM2594) was a bad idea.

The LT3460 has the exact same footprint, exact same feedback resistor and compensator capacitor needs, and exact same output cap and inductor specs. Alright, why not… I’ll swap it in.

That fixed the problem completely. Even with the “staggered start” removed and the extra 47uF of capacitor gone, there were no startup issues. The transient on the 5v rail had declined to the point where trying to detect it was difficult with the scope’s noise floor.

Above is a picture of the 15v rail under switching conditions, when the gate drive is running. As can be seen, all of the FETs being switched on at once causes a brief dip in the power supply (on the order of 0.2 to 0.3 volts). Meh.

I zoomed way in on the 5V supply and AC-coupled the scope to catch the power converter’s actual output waveform. The 1mhz switching freq. of the LT3460 can be seen over the 150khz switching frequency of the LM2594. The 5V ringing is a bit concerning, but it doesn’t seem to be affecting the controller function.

In the interest of reducing this ripple, I’ve spec’d out a 100uF 6.3v ceramic cap  just for the 5V rail. It has the same package as the 47uF on there now, so it will simply drop into place. I’m also going to add more bypass capacitance at the ATMega and current sensors, upping it from 0.1uF to 1uF.

I waterjet-cut the updated heat sink plate design for RB and laser cut my remaining silpad sheet to make the insulator. This is basically what a stock RB will look like, without an additional fan mount or something. I’ve accepted a quote for punching out the heat sink design from 1/8″ 3003 aluminum, with a silpad die-cut piece bonded to it. The future is exciting.

Here’s a picture of all generations of RB so far!

I’m now going to throw this board into something like Null Hypothesis and ride it around drive it to obtain a reasonable robot drivetrain test for temperature and current draw.

In the mean time, I’d like to rally some help from everyone.

(more…)

A Little Update on RageBridge v2

Nov 17, 2012 in Motor Controllers, Stuff

In the last episode of RageBridge, I redesigned the logic regulator section of the board in order to make it compatible with a wider range of low input voltages. The current logic power architecture is a single LM2594 buck circuit that supplies the gate drive circuitry with 15 volts, and then a linear regulator to the 5v microcontroller & peripheral logic and receiver power. The issue was that this setup limited the minimum voltage of the input to be around 13 volts – too high for 3S lithium/12 volt systems which are still very common – because the gate drivers shut down at 10 volts. I determined that a better architecture would be to convert down to 5 volts first, then boost from that up to 12 volts. 5-to-12 converters are very common, as are switching buck regulators for 5 volt systems – hell, even the LM2594 is $2 cheaper in small quantity if I only want the fixed 5v form.

Another approach which I settled on after deciding it was at least worth trying is using an integrated buck-boost chip that could handle a very wide input voltage and still give me 15 volts out. This would have necessitated changing the power regulator chain the least, so it was the solution I favored first. After a long period of staring at manufacturer datasheets for relatively simple self-contained buck-boost regulators, I picked the LT3433 to experiment with. It was supposed to be this super magic one-chip solution to the issue, and would allow me to keep the 5v linear regulator (since it could, in principle, generate me 15v from anything between approximately 8 volts to 57).

That’s the board design I sent off to MyroPCB to fabricate. Only 4 this time, though even that was kind of overboard… I figured if it did work out, I could assemble more of them as needed.

2 weeks or so passed, and I received the boards:

Between the last board revision and now, I discovered how to make Eagle ‘pave over’ vias with solder mask. The technique is generally known as ‘tenting’ the via, and its main goal is to prevent exposed vias from wicking solder away from nearby pads (in a via-in-pad situation or via-kinda-awkwardly-hanging-out-near-pad situation if you’re me) or being another source of potential shorts. Turns out there’s a DRC setting for that. Hence, I basically set the Limit under the Masks setting to juuuust bigger than my standard signal via (16 mils). All of the little layer change signal vias were therefore tented, and the whole board just kinda looks better as a result.

I assembled two of the boards for starters. 3 is probably better to reduce the chances of assembly errors and flukes making it through, but I again ran into the trouble of running out of critical components. In this case, it was the 16mhz ceramic resonator and 30A current sensors.

Sadface.

The LT3433 was supposed to make this easy. And as far as I can tell through much testing and component replacing, the chip is working just fine. However, it is not as magic as I had hoped.

The symptom was that while the board by itself worked fine between voltage of about 7 to 55 volts, once I connected a receiver or fan to the thing, I could only get down to about 16 or 15 volts before the gate drives dropped out completely, and the 15v rail began dropping in voltage even up to 22 volts. This was worse than the previous configuration!

I used a Spektrum BR6000 receiver known for being very power-hungry for most of the testing. Maybe it’s not realistic of a receiver these days load-wise (this thing drew, by itself, upwards of 100+mA), but Spektrum receivers are still very common and I’m not sure if they’ve gotten any more efficient. Regardless, if the power supply is unstable supplying just a receiver or fan, it’s definitely not going to work for both at the same time. A Hobbyking receiver, which draws less current (50 or 60mA), fared better.

The picture shows a series resistor I added to the inductor in order to try and measure its current. The 3433′s datasheet is somewhat confusingly written, and I’m thinking I interpreted the load line graphs as a “minimum” load (i.e. load must be this amount or more to retain output stability, because boost converters need that kind of thing). The page of design math also pulled variables out of nowhere (or had other bad notation issues), and I actually skipped over it the first time figuring that the reference circuit would work just fine.

It turns out the current was indeed a maximum limit, meaning with my component choices I could only realistically get 160mA in “bridge mode”. Additionally, the reference design (8-60v to 12v converter) enters bridge mode at 18 volts – with my output voltage requirement being 3 volts higher, I indeed saw the transition happening at around 21 to 22 volts.

I tried other dumb inductor hacks like adding 2 of my 330uH discrete inductors in series (for more inductance), hoping to store a little more energy in that “bridge mode” . Unfortunately the results were not much better, and the reason is because small power inductors of such high inductance values also have very high DC resistance. Hence, the majority of what I gained was lost to I*R drop in the inductor itself. They also heated up quickly, indicating the same.

I ended up playing with the maximum output current design rules and found that yes, more inductance would help, but only if I could keep the DCR very low. In the size of inductor I use, the amount of space available for wire is very limited, and so all of the ones on DigiKey higher than 330uH were also much greater than 1 ohm – a few up to 5 or 6 ohms!

For instance, I can get output currents of 400mA if I had a 1mH (1000uH) inductor, but only if the DC resistance was still under 1 ohm. If I used a known part specification (6 ohms) in the design equations, then the result is actually not much better. I would be burning more watts in that inductor than what would be passed to the board.

“Bridge mode” on this converter is kind of strange. Basically it not only pushes current into one side of the inductor (standard buck converter behavior), but at some point it also starts pulling the other side to 0 volts (boost converter behavior). The input side voltage is the yellow trace and output-side voltage the blue trace – right now, the input is lower than the output, so it is operating solidly in bridge mode.

This is too weird for me, man. I’m not into discontinuous converters like that.

In conclusion: This version of the board is kind of fail. Let me be very clear that the LT3433 is not necessarily a bad thing – I just seem to need more current out of it than what my space-constrained layout, voltage demands, and component choices can sustain. It seems that I definitely need a solid 3 or 400mA+ converter serving the board for worst-case loads of a power-hungry receiver and a fan, and maybe some blinkenlichten.

It’s also not like the board doesn’t work – it functions just fine at voltages above 22 volts (topping out at 50+v with current part selection), or even down to 15-16 volts with suboptimal gate drive performance. But as a result it’s not really an improvement over the original LM2594 input-to-15v conversion. So I’m going to keep these two around anyway in case one of the higher-voltage devices needs one. For instance, Null Hypothesis can run this at the moment because it has a 25.6v nominal systemm.

Therefore, I’m going to quickly whip together a third board revision that retains the minor power and signal layout changes of this revision, but uses the LM2594 again, a circuit that I know and understand well.

But instead of converting to gate drive voltage (15v) first, I’m going to convert to logic level (5 volts) directly, then use a tinyboost like the LT3460, which seems nice and simple, to generate the 15 volt gate drive rail. The 15v will then be only for gate drive – no external tap will be available.

Bucking directly to 5 volts is a little riskier because switching converters will inevitably have more noise than an equivalent linear regulator, and if I am to spec 5v fans to be powered from that , it introduces yet another potential source of noise. I think massive bypass & bus capacitance spamming and 5v TVS diodes will make this a non-issue. I do trust the 2594 to be a stiff 5 volt rail, however. Using the fixed output version instead of the adjustable 2594 will also save on the space taken up by passives.

I don’t have this board designed yet, but hopefully will by the end of the weekend such that I can fire it off ASAP.

The First Testing Results of RageBridge(Two!)

Oct 25, 2012 in Motor Controllers, Project Build Reports

Barely a week after I first put out the call for RageBridge testers, I’m stoked to say that I’ve gotten the first usage reports back! Two of my boards were in use at the Combots Cup this past weekend, one in a 60lb bot and one in a 120lb class bot. Here’s what went down:

AWESOME! The board worked flawlessly until it caught on fire.

That’s actually what I want to see, because this establishes a good upper bound on what the board should be used for, as well as how it should be mounted.

The two robots used similarly powered motors in their drivetrains, but one was very weapon-centric and the other (which suffered the explosion) very pushing and drivetrain-centric. I’m told by attendees that after 2 minutes of a hard pushing match, the RageBridge board gave out. The other board seemed to have survived fine, given that in its application it was most likely not hitting the current limit as often due to the robot’s primary goal of chasing after an opponent with its whacky bar thing.

The thermal situation in the pushybot was also a little suboptimal:

Above is the robot, Ziege, a 120lb middleweight powered by 4 EV Warrior motors (admittedly a little power-starved on 60A). The black blob of tape between the two rear motors? Ragebridge. Talk about good ventilation! Basically what I’ve concluded right now, after only 1 data point, is that perhaps without additional cooling/heat sinking, it’s not a good idea to use RB in a 120lb battlebot. This is more informative than the statement’s facetiousness may indicate.

First, all ESC ratings lie to you.

Second, it’s been known to me that RB’s “40A” rating was a little optimistic. It was calculated assuming a constant current causing a certain amount of Joule loss (I²R) in the FET, and using the datasheet’s quoted temperature rise per watt of dissipation (Kelvins/Watt) to estimate a temperature rise from 25C ambient. Basically, for the FETS I used (the IRFS3004), this worked out to be around 76C for a final temperature of 100C. I picked that as the target temperature because most big electrolytic capacitors are rated to 105C. However, that does not include any additional sources of heat. In fact, the capacitor itself is a nice source of watts that is located very close to the FETs, hence contributing to their heating. The board traces, being relatively thin copper, will also contribute some resistive heating.

Interested in just how many “true continuous” amps Ragebridge could push with no help (e.g. fans, heat sinks), I set up a test rig over the weekend which was basically the board puking into a huge RL load while suspended in midair:

The “Big RL Load” in question is Cap Kart’s motor, a separately excited giant-ass DC motor. To get the duty cycle of the controller’s outputs to a reasonable range, a very small amount of field current was injected such that the rotor could barely overcome friction and spin up to a tame speed,  hence generating enough back-EMF to force the controller to work at around 50% duty cycle for the current I wanted to test. To maintain that current, I just set the Semi-Intelligent Current Limiter to the value desired.

The reason this was done was because different duty cycles load different controller parts preferentially. If I had just dumped into the big rotor windings at stall (which I tried), the controller would be running at like 5% duty cycle the whole time. That would have been all the voltage needed to hold 30 amps into the ~30 milliohm rotor winding (at the 20 volt test voltage). Very high and very low duty cycles preferentially stress one FET because it is either supplying all the current or having to freewheel all the current and is kind of unrealistic unless you know for a fact that people are gonna be running such low or high duty cycles all the time.

50% duty cycle is a nice worst-case scenario. While heating would be distributed evenly across both FETs of the conducting H-bridge half, 50% duty cycle really kills the capacitor (Here’s a good application note kind of thing with good buck converter design equations).

Every once in a while, temperature readings were taken of the region between the high-side FETs and the capacitor. This would be the single hottest part of the board, and hot it did get.

I became concerned about how fast the cap was approaching 100+ celsius after the first test. To mitigate this, I temporarily doubled the capacitance. Kind of cheating, I know, but I was also interested in seeing what the FETs were capable of. The first test was on just 20 amps, and the FETs had barely crested 50 Celsius when I called it off. They have quite a long way to go, but the capacitor was probably about to detonate.

Finally, after the extra 680uF of capacitor was added, the test was repeated at 30 amps:

SCIENCE. SO MUCH SCIENCE.

The “data” was recorded with a video camera and the data points gathered by watching the video and picking the temperatures that looked like of good. So, not exactly rigorous science, but it gets the point across. With no additional heat sinking, fans, airflow, or other cooling assist, the RB board sort of levels off at around 100-105 celsius after about 5 minutes.

Thermal equilibrium is really what determines what a controller’s “continuous” rating is. RageBridge is a “30 amp” controller at heart.

The only way to raise this current ceiling is by active cooling of the board. There is very little amount of practical heatsinking that can be done to raise the steady-state current. A well-designed and many-finned heat sink is more effective on its own because the increased surface area encourages more natural convection anyway, but a plain heat plate wouldn’t increase the surface area much. Hence, it would only prolong the time until the temperature limit is reached.

The world of ESC ratings is a perilous one. If I really sold Ragebridge right now as a “30 amp” controller, nobody would buy it. The reason is that the majority of robotics and traction duties aren’t truly continuous. A typical robot will accelerate in under a second, drawing full current, then cruise at a much lower current. Vehicles may hold that acceleration current for longer periods of time by virtue of being heavier and not being geared to safely spin the whels at a  low motor current. Unless you’re trying to drive motors that are way larger and more power-hungry  than needed for the application, the average current will be far lower than the peaks.

This is why “one number” ratings, like “40A continuous”, are useless without considering the circumstances of the test. Some ways to get around this rating are citing a number as “continuous” for some number of minutes. A typical “robot duty” might be 3 or 5 minutes. In this case, I think RB2 is a good 40A “3 minute” controller.  A truly 40A continuous ESC needs to have enough thermal dissipation ability to safely dump several watts of heat in the best case. It’s probably going to have a rather large heat sink or at least a fan, or be very ridiculously low resistance , which some R/C type ESCs acheieve by being very low voltage and using many small FETs in parallel to reduce resistance even further. For R/C controllers in particular, some amount of airflow is implied, usually prop wash from a plane.

Peak ratings can be even more bogus. It’s generally not disclosed how the test was performed – for the typical R/C ESC, it’s usually “Rated battery voltage” / “Rds-on of the FETs divided by number of FETs”, resulting in hilarious ratings of 1000+ amps from a ESC with 14 gauge wires. Without a method of test – like “100 amps for 10 seconds before reaching 150 degrees Celsius” it’s impossible to really tell what the “peak rating” is. However, for RB2, it’s dead simple – it’s whatever I set the hysteresis limit to!

With this test rig pretty well practiced and easy to set up, I might go ahead and try some other well-known robot ESCs to determine what their real ratings are.

For RB, though, I intend to generate several of these graphs and make them public & part of the eventual user manual. Maybe 2 different currents under 4 different cooling conditions (no cooling, with a heat sink plate, with a fan but no heat sink, with both). It would look much like the average IC or semiconductor datasheet, and it would be kind of easy to extrapolate what a safe amperage is for the custom application based on those graphs. I’d still have to cite a “one number” specification for the eventual brochure or specs box, though, but at least with Real Dataz behind it, I don’t feel as bad fibbing a little.

With 30 amps under the belt, I decided to try adding a little bit of forced convection. Here’ a quick fan mount I whipped up for the board that uses the existing standoff/mounting holes and a very small 12v, 0.12A 40mm fan.

The CFMs from this thing are rather low – about 10CFM rated, but it’s split fairly evenly in 3 directions (the 4th is blocked by a flap of the mount I made), so each side really gets about 3CFM.

This was also a chance to test out my new load. This is a 0.6 ohm, 550 watt power resistor. Conveniently, it’s not wound to cancel its own inductance, so it’s a nice…..little?…. RL load.

With the resistance being fractional ohms, it’s easy to push tons of current through this thing. I also have a known fixed relationship between current and voltage, so if I wanted to achieve the ideal 50% duty cycle for stress-testing the board, then I can set the power supply accordingly. For instance, if I wanted 50% duty cycle at 30 amps, I would have set the power supply to 36 volts (30 amps * 0.6 ohms = 18v output at the controller, and 50% duty cycle represeting 18 volts average means 36v input).

Unfortunately, the board has seemingly started exhibiting regulator resetting issues again. It usually occurs a few minutes into testing the current limit, and the failure is “soft” i.e. the gate drives just shut off due to low voltage. The regulator once again enters a weird latched up state that I supposedly solved on RageBridge1 a few months ago. This time, I’ll need to hunt down the error a little more carefully. It could have been that, for example, a solder joint was stressed during the last test’s heating and cooling cycles, or some other equally hard-to-find bug.

Before the board reset, though, I was able to get the temperature to hold approximately steady at 58 to 60 celsius after about 4 minutes. This is a good sign that I can (after I figure out that damned regulator issue) start upping the amps to find the limit of what airflow can do!

In the time I’ve been waiting to hear back from users, I’ve made a few changes to the board to resolve some of my (and others’) complaints and some of the issues exposed in this thermal testing:

ragebridgetwo v2

RB2′s first version had a few issues which were typical of me rushing a board out the door.

  • There was a single digital pin input to enable the Mix mode, but it had no corresponding ground or 5v jumper to attach to! Not sure what I was thinking there – to active mixing I had to solder a jumper wire (and tell other people to do so).
  • The one capacitor is clearly not enough, and some rearranging of things is needed in order to fit one more per side.
  • The gate drive regulator only takes approximately 15 volts input. I think it should have the ability to run off a 12 volt battery, because 12v systems are still extremely common in small robots as well as in FIRST Robotics. I’m not discounting the possibility of eventually going after FIRST with this thing, but having a controller which has a very wide voltage input is just nice.

The latter problem took a while to think about and fix. There are very few commercial regulators which can stand the whole range of voltages I wanted – down to 7 or 8 volts (for the really, really flat 12v battery) and up to 55-60v for a 36v nominal system which can see some spikes and surges. The standard solution for me is to buck-regulate (down-convert) to the gate drive voltage (12-15v) and then linear regulate to logic levels (5V). However, this means pretty much the lowest voltage that RB can operate at – period – is about 12-13 volts. The buck regulator, a LM2594, just switches full-on during this condition, but it has a 1.1v drop from input to output. Add in another drop of the output diode of approximately 0.75v and I am wandering dangerously close to the 10v shutdown point of the IR21844 gate drivers. That means RB technically can’t run off anything lower than 4S lithium polymers (14.8v) safely, hence cutting off the “12v lead acid” market.

A more robust method is to buck down to 5 volts first, and then boost from 5v to the gate drive voltage. Many super LV-input controllers either do this or the janky thing of just running the gate drive on 5-7 volts. The downside is that it requires 2 converter chips – a high voltage input buck regulator and then a little boost. Neither are that cheap, especially HV input regulators. But, this method allows operation almost right down to 5 or 6 volts!

Wouldn’t it be nice if they made something which could either buck or boost and take the entire target voltage input range? It turns out (after hours of rummaging on Digi-key) that such devices do exist.

One example is the LT3971, a buck-or-boost converter designed for LED power supplies. It takes 4 to 60v input and gives you whatever voltage out that you select. I was really favoring this until I realized it doesn’t have internal switches – i.e. integrated FETs. I was going to have to build a motor controller on top of my motor controller (sup dawg) with tiny FETs in order to use it! This is basically a project entirely on its own.

Then I found the LT3433, which is a much simpler device with internal switches and needing just an inductor and a handful of passives. It could theoretically accommodate 4-60v also, but presumably due to the compromises of its design compared to the more freelance 3971, it really can only work down to about 8 volts in my application. Whatever, close enough. It was also kinda okay priced in large quantity – only $3.40 in 100 or more on Digikey. I’m certainly getting gouged for buying one or two for testing (what do you mean it costs 6 dollars)…

Doing the layout for this thing was an adventure. First, it needs so many passives. It has all kinds of fancy compensators and buttons and switches. Second, I use 1206 parts.

Stop laughing. I know it isn’t 1982.

I’m invested pretty heavily in 1206 parts, though, and find them convenient to work with because they are still quite large. Really I should be working in 0603s – about the biggest thing you find in modern electronics.

Here’s the first picture of RB2V2:

Doubled caps, check. Actually useful MIX enable header, check. The main power inputs had to move, so I’ll have to rebuild my test jig, but that’s a small potato.

I also added an external LED header. One of the ways people apparently mount these things is heat-shrinking the entire thing and gluing it to the robot. I’m mildly peeved, but even they deserve blinking lights, okay? The header is pretty much a tap from the LED circuit, so there’s no resistor required.

The LT3433 and its passives have not been routed yet. It took a few rounds of arranging before I settled on something which wasn’t utterly terrible.

Here’s the final routed layout of the new power regulator. I’m sure I could have placed some things more scrupulously. What I learned here is that I hate TSSOP packages. You can’t even thread a trace through their pins because they’re so damn close together. This also isn’t a 4 layer board, so it’s not like I can just escape onto another layer. That thermal pad in the middle is really, really in the way of everything.

There’s some parts of this board which I have doubts can actually handle the output of this chip (400mA-ish maximum), but I’m hopefully never going to run that level of current on the gate drive rail unless someone’s powering lights off the fan header or something.

I’ll let this design “bake” for a while, stare at it again, and send it off for fabrication. There will not be another alpha testing round, however. I’m going to get maybe 4 of these maximum and beat them up in various ways. The power lay out and most components are totally unchanged from the current testing round. If these boards prove to be legit, then I plan on launching a production run ASAP.