-
Proof of Function
10/10/2023 at 06:40 • 0 commentsThis is just going to be a few videos showing the fully assembled system in action. They are all going to be unedited clips, so I apologize if they are a bit slow. Consider these more as "proof of function" than education or entertainment. I'd recommend checking out the overview video in the main project details section, or the other project logs for more informative content.
-
Turning it up to 11...or actually 64
10/10/2023 at 02:59 • 0 commentsPicking up where I left off, the previous prototype with 8 stages was a success. It successfully demonstrated the principal of operation, and it also revealed areas needing attention. Building the full-size version of this project in a little over a month was really tight, but through luck, determination, and brute force, it has come through just in the nick of time (as I write this less than 8 hours from the deadline)
A ton has happened since the last update with the prototype, so this is going to be a long post. Let's go!
Bigger and Better Control PCB
The new control PCB is kind of a monster. Here are some highlights:
- Supports 64 load stages (up from 8)
- Upgraded microcontroller from STM32F103 to STM32F429, in one of their biggest packages (LQFP-208)
- 6-layer PCB (three ground planes)
- Same analog circuitry for each load stage as the prototype, just compacted and replicated.
- Current signal analog summing now done in multiple stages for routing sanity and bandwidth improvements
- Changed buffer ICs for straight through routing
- Lower cost / more common TVS diodes
This was a tight layout but I'm really pleased with how well it came out. Still, I had to take some shortcuts. There was no room for the isolated DC-DC converter on the back side, there was barely any room for test points on the PSU section, and some of the analog trace spacing is tighter than I'd like. I'd initially wanted to support 65 stages (13 per level x 5 levels in the chassis) but it quickly became clear that wasn't going to happen.
The primary reason for switching the microcontrollers was simply the need for more pins than were available in the STM32F1 family. I really wanted the enable signal for each load stage to have a dedicated GPIO pin, and for those to reside on mostly dedicated ports of the microcontroller. This is purely for speed, since switching the load stages in 100us pulses doesn't leave a lot of time to run shift registers. This way, I can directly write to the five GPIO ports where the enable signals reside and control all of the load stages in something like 10 clock cycles.
I was also hoping to upgrade to a larger screen with touch input driven by a parallel bus but I had to cut that upgrade due to time constraints. I'm still holding out hope I might be able to bodge in a 3.5" SPI touch screen though.
Why 64 stages?
One thing I found working with the prototype was that the load stages all had a higher effective resistance than their nominal rating would suggest. (I may also throw around the term "conductance" in mA / V since that is how I wrote the firmware. See the firmware post for more details.) This resistance change only worsened as they heated up.
Referring to the table below, you can see the cold (room temp.) and hot (200C) conductance values I measured in the load stages of the prototype. The 8R, 4R, and 2R stages were relatively accurate regardless of temperature. However, the 0.5R stages, and especially the 0.1R stages, were quite poor. A stage that would, in theory, be 0.1R, actually measured at 0.117R at room temp., and 0.130R when hot. I think the cold variation is from the cables and the connector contact resistance. While the hot variation is probably mostly the temperature coefficient of resistance for the load resistor.
Either way. the conductance of the 0.1R stages could be reduced by over 23% from ideal, and the 0.5R stages reduced by over 10%. This was all made worse by the realization that the input voltage at the connector from the DUT was not going be 12.6V under heavy load. Between the droop designed into the power supplies (partially for load sharing), and the voltage drop over the PSU cables, the input voltage could easily drop to 11.4V.
All in all, a 0.1R stage that I expected to consume 126A at 12.6V is only going to consume 87A at 11.4V after all the aforementioned losses. This all meant that if I wanted to hit my headline figures of 10kW (I kind of boxed myself by putting that in the name, didn't I?), I now needed more load stages, quite a few more.
Thus, 33x 0.5R stages are now 42x, and 16x 0.1R stages are now 18x.
Connector PCB
The connector PCB is as boring as ever, just bigger now. It is now a 6-layer PCB with the inner layers at 2oz copper and the outer layers as 1oz. (JLCPCB couldn't do their economical assembly service the outer layers were 2oz. I don't know why, and they didn't either.). I'm also now mounting it to an aluminum plate for better rigidity, the ability to use more of the PCB due to THT pin clearance, and because getting the screws lined up with nuts in the aluminum extrusion last time was a real pain and risked damaging the board.
Also, the footprint for the binding posts is now oval shaped to perfect fit the threaded shaft with flats, without allowing rotation. Finally, there is a slight issue where the connectors are too close to each other back-to-back. Depending on the exact connector housings on the cables, the housings might interfere with each other, even if the connectors themselves are fine. You can still make it fit though but putting sideways pressure on one housing while inserting the other one.
Load Stages
These are completely unchanged from the previously documented rev 2!
Cable Management
In working with the prototype, one of the biggest issues needing attention was cable management. Specifically, preventing the cables from being damaged by the sheet metal the load stages slot into.
I also wasn't thrilled with the design slotting the load stages directly into the sheet metal but it technically worked, and since time was of the essence, I chose to stick with it. That's not to say it's without improvements though.
After several iterations, I came up with a 3D-printed retention clip design that works quite well.
The clips serve two purposes:
- They center the load stage PCB within the sheet metal slots and prevent the load stages from coming out. Once clipped in, they retain the load stages quite well. The system could almost be shipped like this...almost.
- They cover the interior sheet metal edges of the cable guides, preventing any metal-on-cable contact.
They are easy clip-in or remove, but while clipped in they are quite secure. They almost make the PCB in sheet metal slot design feel like a good idea.
Separately, in the previous version there were notches cut in the sheet metal between the load stage slots, where I imagined the CAT6 signal cables would lay. That didn't work at all in the prototype, so I replaced them with holes that can be used for custom plastic clip-in zip tie mounts (3D printed of course). My design eventually converged on to the same design that push-in zip ties uses. As usual, I decided to learn it the hard way by coming up with my own designs, but it turns out the commercial offerings are designed that way for a reason!
Chassis Maintainability
As you might have seen in some of the previous photos, the chassis has a new feature: each level can now hinge upwards to provide access to the load stages. While this doesn't make it easy, it is at least possible. Without these, I think replacing a stage on a lower level might have required disassembling most of the system. The best part about the hinge design is that due to their placement, the entire system can be hinged open without having to disconnect any cables (except for the main power cable for the control PCB).
The hinges are from Miusmi and are designed for aluminum extrusion, but they weren't designed to be used like this. In the spirit of the project, I am using them in a way they weren't intended. They have no official rated load when used in this orientation. Given how heavy the entire system is now, I'd recommend caution when using these, and at the very least using three or four hinges on the lower levels that have to bear the most weight.
When opening the system like this, I have a piece of aluminum extrusion that I put in as a kind of kick-stand (or whatever the name is of the piece that holds up the hood of your car), but I bolt it into place, because if it were to fall down on you it could do some serious damage.
On the rear there are flat brackets used to secure the levels when not being hinged open.
To wrap this up, I was going to show the system in action but I'm going to put all of those photos in a separate post since this was has gotten so long, However, suffice to say, it works, and it hits 10kW.
-
Software eats the world
10/10/2023 at 00:28 • 0 commentsWhile not nearly as easy to photograph as other parts of the project, the firmware has been a big undertaking in the project, and it was my primary focus through August.
The firmware has to manage a number of different things, many of which are somewhat interdependent:
- Provide a GUI for the screen
- Handle the buttons, and rotary encoder for the user input
- Measure the voltage at the input and the current through the entire system (analog current sum)
- Measure the current through each of the load stages
- Sample the thermistor and thermocouple signals from each load stage and implement software cold junction compensation
- Control the fan speed based on those calculated temperatures
- Calibrate the load stage conductances
- Solve for the optimal load stage selection for a given requested current
- Rapidly switch the selected stages on and off during pulsed mode with precise timing
(Regarding the software, you'll notice I use conductance instead of resistance. This is because the microcontroller can more quickly do a multiplication operation like "current = input voltage * selected conductance", instead of a division operation like "current = input voltage / selected resistance". Also, since there are multiple load stages being enabled in parallel, the conductances of each can just be summed together. Compared with the "inverse of the sum of inversed resistances" calculation you'd do to calculate the equivalent value of multiple resistors in parallel, which is actually just converting them to conductances and back anyways.)
Control Algorithm Overview
(More details for each point below)
- On startup, the conductance of each load stage is measured and stored
- When the user requests a specific current value, the input voltage is measured and used to convert that to a target conductance
- An approximate solution to the subset sum problem is used to determine which load stages should be enabled to get as close as possible to the target conductance, and thus target current.
- This solver is run every 50ms, so any change in input voltage results in a new target conductance to maintain the same current target.
- While a stage is enabled, it's conductance is regularly measured on-the-fly to take into account temperature variations. This live measured conductance is used for the next subset sum calculation.
Subset Sum Problem
One interesting thing I found early on, is that I've apparently have run head first into the Subset Sum Problem. Essentially, there are many different load stages each with a different conductance (mA / A in my firmware). The current value requested by the user is converted to a target conductance using the input voltage, and then the software needs to determine which subset of all possible load stages should be enabled to get as close as possible to that target conductance without going over. Going over would mean drawing more current than the user requested, which might be considered a bad thing in some scenarios.
It turns out that this is a fairly fundamental problem in computer science, and there is no perfect and fast solution. If I had only 8 load stages, I could easily pre-compute the sum for all possible 256 combinations. However, if I have 64 load stages, that's over 18 x 10^18 combinations, so there is no chance our little microcontroller could even store all of those, let alone compute them in under three years.
Fortunately, in this case there is a simple approximate solution, the "Simple 1/2-approximation". Essentially, the firmware just has to take a list of all of the load stages sorted by conductance, select the largest one that fits within the target conductance, then subtract the selected stage conductance, and finally repeat the process with the remaining amount. If the load stages were perfect binary values of each other, this actually would be an optimal solution. However, this leads to another issue: the load resistors have a tolerance of 10% and they also vary substantially as they heat up.
for (int i = 0; i < NUM_STAGES; i++) { uint32_t stage_num = load_stages_sorting[i][kStageNum]; uint32_t stage_conductance = load_stages_sorting[i][kStageConductance]; bool stage_overpower_OK = StageOverpowerOK(stage_num, vsense_mV) || (GetMode() == kPulsedMode); if ((stage_conductance > 0) //Make sure stage isn't empty && ((int32_t)(remaining_conductance - stage_conductance) >= 0) //and load stage conductance doesn't exceed remaining needed && (stage_overpower_OK) ) { output_config |= ((uint64_t)1 << stage_num); //Set the stage num bit to mark as enabled remaining_conductance -= stage_conductance; } }
A snippet of the subset sum solver. (Note that I'm actually storing the on or off state of the stages as single bit in a 64-bit number. 64 bits for 64 stages.)
Calibration
Presently at startup, the system calibrates each load stage. It does this by briefly enabling each load stage individually for a short pulse, and then simultaneously sampling the input voltage and the current going through the load stage being calibrated. With these measurements, it can calculate the conductance of each stage and store that for future use. This takes care of the manufacturing variance of the load resistors, and the added resistance of the connectors and cables, but still doesn't account for the temperature variation. (It also relies on there being a PSU connected that can handle the 100A+ pulses from enabling a 0.1R load stage. In the future I'll store the calibration data using EEPROM emulation on the STM32 to avoid this. I'm also not even starting to go into the issue with non-linearities as the input voltage approaches the 3V minimum, where the FETs aren't fully turned on.)
To compensate for the temperature variation, the system will periodically do what I call a "live calibration", where it measures the input voltage and the current going through a stage while it is turned on. It then uses the live calibration conductance value instead of the value measured at startup. In effect, as a load stage gets hot its conductance drops and so it goes further down the sorted list for the subset sum solver, and eventually if another stage is a better fit, it is selected instead.
This works, but it isn't ideal because you can't live calibrate a stage that isn't enabled. It would be possible for a stage to be enabled, heat up significantly so its conductance decreases, then be turned off. In this case, the software currently would use that last live calibration value for future calculations. However, now the load stage could cool down and so the previous hot live calibration value would no longer be accurate. I'm not sure quite how to solve this one. It might be possible to actually generate and store a conductance vs temperature curve for each load stage and use that to predict what the conductance would be for a given temperature. Or just let the load enable the stage when it thinks it's the right solution, do a live calibration, and then disable it again because the conductance value is updated and it's no longer the best fit.
Other musings and issues
Another issue (or maybe feature?) with this subset sum solver approach is that it will never produce a solution that results in a higher conductance that requested. If the user requests 12A of current, the software measures the input voltage, lets say 12V, and determines there should be a target conductance of 1000 mA per V. If one of the 1R load stages is slightly lower resistance, it could have a conductance of 1001 mA/V, and thus it would never be selected. This is the case even if the next closest solution was 500 + 250 + 125 = 875 mA/V (for 2R, 4R, and 8R load stages respectively). Effectively, priority goes to never exceeding the target, at the expensive to possibly higher overall error.
All in all, I'm not sure if this would be considered a closed loop or open loop system. The system never measures the total current and uses that to determine whether to enable or disable load stages, like you'd think a typical closed loop system would.
I suppose the output is controlled based on a prediction of how the load stages will respond. Then the factors used to create that prediction, the conductance values, are actively measured. However, if the actively measured conductance values are then used to calculate the output, is that feedback?
I've admittedly never worked with real control loops like PID before, but I'm not even entirely sure how you'd apply something like that to this system. Would you have the control algorithm adjust the target conductance fed into the subset sum solver, so it isn't directly correlated to the input voltage and requested current? Perhaps you could use that "target conductance = target current / input voltage" as a starting point? (feed-forward?)
Either way the fact that the system is just a bunch of huge resistors means it is all at relatively predictable, at least within 10%. And that means even running in pure open loop where you'd just enable specific stages based purely on their nominal rating with no calibration, you can get fairly close.
This idea of running in open loop control is somewhat how the system operates when in pulsed mode. It uses the startup calibration data but doesn't do any live calibration. It would be possible to do live calibration during the pulses as long as they are long enough, though.
To wrap up, I'll say that the most difficult piece of all of all of this for me was...the GUI. As usual, I can make something that works, but making something is functional and maintainable without descending into chaos continues to elude me. Maybe next time. (Or actually I might try out implementing LVGL instead of making my own from scratch.)
-
Can't stop the work
08/06/2023 at 03:45 • 0 commentsThis is just going to be a quick update post showing off everything that's happened since the last post. Cue the pictures!
The new load stages PCBs arrived. These feature:
- Updated optocoupler circuitry to greatly reduce turn-off delay.
- Switched to using MINI blade fuses, sometimes in parallel, to reduce cost dramatically. Those previous MAXI fuses could be nearly $3 each, and the MINI fuses are around 0.08$ each!
- Relocated the capacitor Cgd on the FET to be as close possible. Also, added series resistor with it to dampen the oscillation it caused. (Kind of feels like a dirty hack but it works...or at least now I can't see it)
- Added thermal reliefs to all the through-hole parts. Last time I discovered they are definitely not optional. I might need to make them even thinner next time since those PCIe connectors are still hard to solder and need a pass from each side of the pin. They are going directly in to solid planes though.
- Moved the gate driver transistors much closer to the FETs.
- Switched to a different TVS diode type to align with the PCB assemblers preferred parts (and they are just cheaper and just as good otherwise)
- Added a series resistor to the NPN push transistor in the gate drive. This allows input voltages to go higher than 14V without quickly being at risk of burning up the FET gate protection TVS.
- More optimized gate driver pull-up transistors to reduce quiescent current consumption
Thermocouples have been DIY spot welded, crimped, and epoxied to the load resistors. The thermocouples will someday get their own post but I'm using a cheap Li-Ion battery based spot welder intended for welding nickel strips when making battery packs. It works pretty well for this. The epoxy has to be a special high-temp cement (CC HIGH TEMP from Omega) to survive the 250C+ of the load resistors. I tried JB-Weld first a while ago but that just becomes soft and falls apart at those temperatures.
Main Control PCB Assembly
The control PCB has over 570 components on it, which was rather painful to pick and place by hand. I timed myself and it took me almost exactly 5.1 hours to place the 511 SMD parts on the back. So I can do about 100 parts per hour. Not great, but there is a high component mix with 65 unique parts on the back. This whole system I'm working on right now is the prototype so the control PCB only supports 8 load stages. If all goes well, a future version will support the 50+ needed.
Connector PCB Assembly
This board has the job of taking in power from the DUT and distributing it to all of the load stages which operate in parallel. It also provides a remote voltage sense signal for the control PCB. It's only partially loaded here to support the max current levels I'm expect to hit on this prototype. The binding post solution on this is pretty weak since it's clear to me these were designed for panel mounting and not an electrical connection to a PCB.
Putting together the mechanical chassis
Here is the first level of the chassis. Like everything else in the project, it's designed to scale to multiple levels. Each level can hold 13 load stages and three 120mm fans. I'm not sure what possessed me to use PCB hooks as a mounting mechanism for the load stages. It'll work because the whole thing is stationary but otherwise not a great solution. I suppose it is cheap though!
Putting it all together
This has the second load-stage chassis level installed which also provides the mount for the control PCB. There is an extension of the chassis the sticks out the front for the connector PCB to mount to. The connector PCB has to overhang that a bit to support the right angle connectors on the front edge as well as the binding posts. I suppose since I used standoffs anyways, if I moved the binding posts around that could probably be eliminated. It's now sitting on an unrelated aluminum frame cart so I can still use my workbench, and also so I can back it up to a window to exhaust the heat directly outside.
Adding in some preliminary wiring
You can see here how each load stage connects to the connector PCB. Cable management is going to be a big challenge. This small version only has 7 cables now but the full-size version with all load stages populated will have over 70 power cables I believe. I think it will work but maintenance is going to be a nightmare. I'll probably need to redo the load stage mounting pieces / cable guides. I'm going to try to 3D print plastic inserts to go in the cable guide sections to protect the cables from the sheet metal edges and to act as retaining clips for the load stage PCBs. I'll probably build in zip tie points as well. If I also shorten the front load stage power cables to reduce the excess, I might stand a fighting chance. However, if I have five levels of these with 13 load stages per level, I'm going to need some way to de-stack the various levels for maintenance access. I've learned before that planning on not needed much maintenance is a bad idea.
Software
With the electrical and mechanical hardware done, the only thing left is the software. I use the term "only" very loosely here because the software is going to be a major undertaking.
Software goals/wishes:
- Input voltage and total system current measurement and display
- Individual load stage current draw measurement
- Precise load stage sequencing and correct combination enablement
- Constant and pulsed current mode, with configurated high/low levels and timing
- Closed loop load stage sequencing to handle any input voltage and minimize error as load stages vary under temperature
- Thermistor and thermocouple monitoring for each load stage
- PWM fan control based on load stage temperature
- Reverse input voltage alert
- Slew rate control (both increasing and decreasing) by either turning on faster load stages briefly at startup to allow a faster slew rate, or sequencing through the load stages slower for a lower slew rate.
- Voltage sense disconnect protection, load stage over temperature protection, current cutoff failure detection
- Individual load stage calibration?
I'm currently starting to work on the software but progress is slow. (It turns out learning as you go is very hard and time consuming.) The MCU bring up was smooth and below you can see me testing the differential remote voltage sense reading. This is literally all it does right now. So I've got my work cut out for me to get some basic functionality implemented by the deadline Tuesday.
I want to get this thing consuming current in some sort of pattern and vaguely resembling the correct value by Tuesday. I'd better get back to work! (And I realize now this post was very much not short.)
-
Why design a discrete gate driver circuit?
07/25/2023 at 00:13 • 0 commentsWhile waiting for the load stage rev 2 PCBs to arrive, I'll share some of my thought process in deciding not to use an off-the-shelf isolated gate driver IC on the load stages. Switching the power to the load resistors is arguably the most important part of the entire design, and so a lot of work went in to designing, simulating, and testing it. (The second most important part is probably everything that keeps the inductive spikes from blowing up the MOSFETs.)
Tl;dr: I like making life harder for myself, I'm a terrible cheapskate, and my questionable goal to work down to 3.3V on the DUT's power supply eliminates essentially all off-the-shelf solutions.
Here is the deep rabbit hole I went down again in recently reevaluating the design and deciding not to use an off the shelf isolated gate driver IC with some real reasons, and some retroactive rationalizations:
- It should be cheaper to do a discrete solution (as long as I don’t value my time...), and if I need 50 load stages, costs start to add up. A $1 part adds $50 to the system BOM.
- I thought it would be more challenging, and I seem to like making life harder for myself.
- Most isolated gate driver ICs have an output power supply requirement of 10V+. Since I’m powering the gate drivers from the DUT’s power supply, this would mean the load stages might not work at lower input voltages.
- There are some with a lower output VCC minimum like 4.5V like the IS480P or FOD8480 that look like they might work but now we’re at $0.93 or $1.67 each respectively in 100 qty.
- Also, 4.5V is still higher than I’d like if I want the system to work down to 3.3V DUT input voltages.
- If I want to turn off the MOSFETs quickly to minimize power dissipation during switching (only for the 0.1R 122A load stage does this matter), I need the driver to be able to sink a decent amount of current.
- IS480P looks like it can sink 160mA+ so that would probably be fine. FOD8480 could sink 80mA which may or may not be enough.
- If that isn’t enough current, then I need to follow the isolated gate driver with a BJT push-pull buffer. However, that then means that my max gate drive voltage is limited by the logic output high level of the gate driver IC. The parts I just mentioned can both swing somewhat close to VCC so that wouldn’t be an issue I think.
- Isolated gate driver ICs seem to have fairly high quiescent current draw.
- IS480P has a supply current of 1.9mA typ. to 3mA max. FOD8480 is similar at 1.6-2.5mA.
- Since the gate drivers are powered by the DUT, and there will be 53 load stages, 3mA each means 159mA drawn from the DUT whether the load is enabled or not.
- If operating with an input voltage of 3.3V is a hard requirement, I don’t see a single isolated gate driver part that can operate that low on the first page of a Digikey search, with Voltage - Output Supply filtered to have a minimum at or below 3.3V.
- This is probably for a sane reason: the threshold voltages of many MOSFETs might be around 2.5V, so there would not be much margin to work with. I never claimed my requirements were completely sane though...
- You'd think an IC would be able to have lower quiescent current draw but since I don't care about the turn-on time at all in my application, I can use high value pull-ups to minimize the quiescent current and come in little lower than an IC.
- The best, more integrated solution would probably be a logic output optocoupler like a TLP2361, followed by a BJT push-pull driver stage. It can operate down to 2.7V VCC, with a supply current max of 1mA. However, its max VCC voltage is 5.5V, which is a problem. Interestingly, the inverting version, TLP2358 can operate 3-20V. So now we need to use the TLP2358 and follow it with an inverter, and then the BJT push-pull stage. This inverter output has to swing to at least 11V if we want to be sure we can drive the MOSFETs gate above 10V to minimize Rds losses, that’s going to be hard to find, and then we’ll also have to add additional regulation to make sure the inductive voltage spikes don’t blow up our inverter. Or we could use a discrete BJT common-emitter inverter but now if we’re using a BJT push-pull driver stage, and a BJT inverter, and an optocoupler...isn’t that exactly where we started?
The result of all of this is that there are no good solutions that meet my questionable requirements. I could add on more and more complexity, or stick with the discrete design that works even if it has a higher quiescent current draw and perhaps isn’t as fast as it could be.
-
New Optocoupler for Gate Driver
07/14/2023 at 18:23 • 0 commentsTwo posts ago I discussed the need for a faster optocoupler than the LTV-816S I was using before, and I mentioned the 6N136. Here’s why I selected that part:
- It was the first and most common result when searching for optocouplers on Digikey with transistor output, turn-on time less than 1us, and sorting by price.
- It’s a common component available from multiple manufacturers
- It was mentioned online as a faster alternative to slow phototransistor-based optocouplers.
- I probably have a tendency to see a part / get an idea and run with it, rather than evaluating all the options first. Which is kind of how I got sucked into this project in the first place...
Here’s the design I’ve settled on:
This has a few changes from the last design to accommodate the 6N136:
- It requires a higher drive current, so the input resistor is now 49.9R, combined with 49.9R series termination resistor on the control PCB, that should make the drive current 14-19.7mA depending on the Vf of each optocoupler.
- It has a max VCC voltage (pin 8) of 15V. Inductive spikes can cause the load stage input voltage to go up to 25V on a 12.2V input, only limited by the existing slew rate control circuitry and TVS diodes. I added a 12V TVS to VCC on the optocoupler with a 1k current limiting resistor to address this. This should clamp VCC to below 15V, and the supply current is minimal so the 1k is no problem otherwise.
- It needs a decoupling capacitor across its VCC and GND pins. I initially thought I might be able to get away without this, but testing showed it really is needed. I was getting an unusual oscillation of the gate drive on turn-on that went away when I touched the VCC pin, so the capacitance of my finger is all it needed in that case. The oscillation was most prevalent when switching higher currents, or when the cable inductance was increased.
- The output pullup resistor was changed from 3.3k to 10k. Performance was satisfactory with the 10k, and it reduces the load stage quiescent current from the DUT to 1.3mA. This matters when there are 53 load stages.
- The pullup for the BJT inverter after the optocoupler was changed to 100k from 1k. This dramatically reduces the quiescent current. The resistor determines how much current the BJT push-pull driver stage can source during turn-on. However, for the turn-on transitions the gate driver speed doesn’t actually matter at all. The inductance of the load resistors is always the limiting factor, not the MOSFET turn-on speed. The turn-off transitions matter much more (and even then, only on the highest current 0.1R 122A load stages).
- I’ve added an optional diode in the VCC supply for the 6N136. I’ll probably just short this out but it leaves me the option to place it later. Any capacitance across the load stage supply is a large problem, because when the load stage turns off, the inductance of the load resistor and cables causes a voltage spike. This voltage spike causes any capacitor to get charged above the voltage of the DUT, so once the spike is clamped and the voltage comes back down, the capacitor is discharged back in to the DUT, forcing it to sink current. How much current can a power supply sink safely? I have no idea. I even wanted to eliminate the RC snubber across the MOSFET for this reason, but I don’t know of any other way to get rid of the ringing of the cable inductance and FET//TVS capacitance. The diode will prevent this added capacitor on the 6N136 from discharging this way, although the 1k resistor reduces the magnitude of the current going in reverse, even if the actual charge amount is the same.
I’m relying heavily on simulation for the load stage design, so that was the next step after part selection. I know the simulation models won’t be perfect, but they are a whole lot better than my mental models!
In the simulation I confirmed the VCC pin on the 6N136 stays under 15V. This isn’t a given when the load stage is switching a lot of current, bouncing around on the inductance of the cables.
Once the new parts arrived, I mocked up a breadboard test before bodging it in to the load stage PCB I’ve been testing on.
A bit of creative 3D soldering later and the operation was a success!
The results speak for themselves.
Breadboard Testing
Old optocoupler - LTV-816S with 2N3904 output inverter, 3.3k opto pullup, 1k inverter pullup
Turn-on delay: 1.40us
Turn-off delay: 30.36us
New optocoupler - 6N136 with 2N3904 output inverter, 10k opto pullup, 1k inverter pullup
Turn-on delay: 332ns
Turn-off delay: 572ns
New optocoupler - 6N136 with 2N3904 output inverter, 10k opto pullup, 100k inverter pullup
Turn-on delay: 2.73us
Turn-off delay: 560ns
(turn-on limited by 100k inverter pullup but this is fine)
Load Stage Testing
Turn-off delay with new optocoupler:
Turn-on delay with new optocoupler:
I consider going from 30us to 500ns a big success. On the upcoming new PCB revision, I might try reducing the 100k to something a little smaller like 47k to maybe reduce the turn-on delay a bit, because that won't increase the quiescent current that much. Other than that, I'm calling it good!
-
Already finding weird behavior in other things...
07/14/2023 at 03:18 • 0 commentsI was testing the load stage at higher currents today after installing a second MOSFET on the PCB to support a 0.5R load resistor, when I ran in to some bizarre turn-on behavior.
At first I feared this might some complex interaction between the two MOSFETs. Could they somehow be turning on at different times and causing some weird feedback? But why would the current track the change in voltage if it isn't going below the FET threshold voltage? Is the 100k pullup driving the BJT push-pull gate driver stage not enough? I've really gone too far this time.
I started probing around as well as varying the frequency and pulse width from the signal generator:
What madness is this? I'd expect the voltage across the load stage to drop a little as the current increases due to the resistance of the cables, fuse, current shunt, etc. You can even see this happening at the very start, but then they start to become correlated. The input voltage drops and the current drops simultaneous...what?
The only thing that would make sense would be the... power supply.
Yup. The bench PSU is messing with me. Both of them, in fact. I have a Korad KA3005P and KD3005D that both show the same behavior. I'm not sure if it's the rapid change in current, or the somewhat inductive load, or something else. I'm just glad this isn't my problem this time!
I switched to the server PSU I'm using for a lot of this testing since it can supply 100A at 12V and the issue went away.
Looks at those beautiful 22A 100us current pulses! You can clearly see how the inductance of the 0.5R load resistor is limiting us here. Pay no attention to the ugliness of the FET_EN signal. I think that's caused by current actually flowing back through the scope's earth connection to the PSU, since ground isn't ground when you're swinging this much current around over cables. That'll have to be its own blog post.
In case anyone is keeping tracking, this means the 8R, 4R, 2R, 1R, and 0.5R load stage configurations are working successfully, which covers a current range of 1.5A to 25A respectively. Tomorrow I'm going to assemble a 0.1R load stage that has to work at 122A, that's where things get serious.
-
Turn-off delay investigation
07/13/2023 at 18:41 • 0 commentsLet’s take a look at that turn-off delay issue.
Yellow is FET_EN, Blue is gate drive output. Turn-off delay is 28-32us depending on test conditions. If my goal is to be able to do 100us pulses, having a 30us turn-off delay is a problem. The timing is fairly critical because I need all of the load stages to switch at the same time, more or less. I’d also like the option to precisely sequence the load stages to either control the DUT current slew rate, or to compensate for the higher inductance load resistors which have a slower current slew rate by turning on some of the “faster” low inductance stages briefly. I think I’d like the load stages to respond within 5us, and ideally faster.
After more learning and research, I think I’ve determined the root cause. In short, I picked a cheap and slow optocoupler with phototransistor output, the slow kind. (PN: LTV-816S)
I didn’t read the datasheet closely enough and was relying on the listed 3-4us response time, but I didn’t pay attention to the test conditions. They actually specify that response time with a V_ce of 2V, an R_load of 100R, and I_c of 2mA, which actually means they are measuring a voltage swing of 200mV around a 2V signal. Definitely not the 0-600mV swing needed in my design to switch the following BJT inverter. Also, I was using an output pull-up of 3.3k which made things much worse.
I think the fact that I'm pulling up to a higher voltage (12.2V assumed from DUT) and then clamping the output with the following BJT inverter is actually helping me do better than these numbers. I recreated the optocoupler and inverter section of the gate drive circuitry on a breadboard and used that to confirm the issue. Although, I could pretty clearly see how long it was taking the optocoupler output to rise measuring in-circuit on the load stage.
Schematic of breadboard demo setup Well there’s your problem... Yellow is FET_EN, Blue is collector of optocoupler on breadboard setup. I also tried to reproduce the datasheet specs under their test conditions, with 2.2V Vcc on the optocoupler output, a 100R pullup resistor, and then reducing the input drive current until the voltage when low was 2V, thus a 200mV swing or 2mA I_c. I was able to get 8.3us response time on input going low (Tr), and 14.5us response time on input going high (Tf). Technically within the max specifications I suppose but not good enough for me.
I found reducing the input drive current would reduce the turn-off delay, but it would also increase the turn-on delay so it’s not much of an improvement. Also, reducing the designed input drive current to keep the phototransistor from saturating would mean we are depending on the optocoupler CTR to stay the same, and that spec can vary wildly between parts and over temperature, I believe.
Yellow is FET_EN, Blue is gate driver output. Now driving the optocoupler with a 1.45V signal through the same 180R resistor, meaning lower input drive current. Turn-off delay is better (8us vs 30us before) but now turn-on delay is worse (11us vs 1.3us before). I also didn’t want to reduce the value of the optocoupler output pullup resistor, because that resistor is always drawing current from the DUT, and so it directly affects the quiescent current of the load stage. This means even at 3.3k, assuming a DUT voltage of 12V, the load stage has a quiescent current of 3.6mA. With 53 load stages, that becomes 191mA drawn from the DUT even when all the load stages are off. That’s a lot more than I’d like on principle alone, even if it wouldn’t matter much in my application. This ties in with the question of “Why power the gate drivers from the DUT anyways?” which I need to address in the main project details section at some point.
Knowing that my optocoupler circuit is fundamentally flawed, that left a few solutions:
- Do nothing in hardware and compensate for the turn-off delay in software
- In theory this could work, however the delay also varies with the DUT supply voltage. It also varies non-linearly, where it might be 30.7us at 3.3V, 28.8us at 6V, and then 30.4us at 12.2V. It might be possible to model the change in delay vs input voltage to adjust the compensation dynamically. Or I could even implement a calibration routine to measure the delay time of each stage from the FET_EN signal to a rise measured on the current sense signal. The current sense amplifier signal bandwidth is low but we’d only care about delay time, not necessarily rise time, so I think it might be possible to use that to measure delay. This is a lot of complexity, all to work around a fundamental hardware issue though.
- Use the same optocoupler with a more complex circuit that lets the optocoupler stay out of saturation and keeps the voltage swing on the optocoupler collector minimal to reduce the effect of the B-C miller capacitance, and thus reduce rise and fall times.
- This adds more transistors, takes more time, and adds more complexity. All just to try to avoid paying a little more for the next solution.
- Performance still might not be great.
- Use a better photodiode-based optocoupler like a 6N136, with a similar circuit to what we already have
- This adds some cost for the better part. $0.348 for a 6N136S vs $0.145 for the currently used LTV-816S (Digikey pricing at 100 qty)
- The 6N136 has more strict absolute max ratings, particularly a 15V max VCC voltage on the output side which will be a problem. It also requires more input drive current and possibly a capacitor decoupling capacitor. Any capacitance on the load stage concerns me because with the cable inductance it directly causes current to be injected into the DUT when the load stage is turned off.
- The datasheet promises much faster response times of 1.5us maximum even at higher output pullup resistor values.
I settled on the last option: redesign the gate drive circuitry to use a better optocoupler, the 6N136.
In the next post I’ll go over the new design with the 6N136, the extra protection circuitry it requires, and its performance.
-
Fun with inductors in disguise
06/29/2023 at 23:48 • 0 commentsIn the last post, I mentioned how the MOSFET in the load stage, which is supposed to turn on and off the load resistor, was oscillating. I've been looking in to this more and I think I understand what I did to create the issue, even if I don't fully understand exactly how the oscillator I managed to create works.
I present to you, our culprit:
Do you see it? While it might look like an innocent trace, it is really an inductor in disguise.
I believe the capacitor I added, Cgd (C25), the gate-drain capacitance inside the MOSFET, the parasitic inductance of the traces, and the amplification of the MOSFET, have formed an oscillator.
If you run the numbers, 1nF cap + 12nH inductance (ballpark guess) resonates at 46MHz, which is at least in the same order of magnitude as the 72MHz I'm measuring.
The gate-drain cap was added in the first place to slow down the MOSFETs turn-off transition. This lowers the slew rate of the drain-source voltage, which slows down how quickly current must stop flowing through the inductance of the cables and load resistor (dI/dt), which thus reduces the inductive voltage spike across the MOSFET. However, in exchange more power is dissipated in the MOSFETs when switching. This cap, combined with the other mitigation strategies I'll describe in the future (RC snubber, TVS diodes, flyback diodes), should be enough to manage the inductive spikes for the 8R to 0.5R load stages (Currents 1.5-24A). The 0.1R load stage that will operate at 120A needs something a bit more special.
To test this and remove nearly all of the trace parasitic inductance, I managed to cram the gate-drain capacitor right next to the MOSFET and solder it in. One end of the capacitor is actually soldered to the small bit of exposed drain terminal that sticks out the side of the MOSFET package.
I don't think it's possible to get any lower inductance than this. The reason I didn't do this during the PCB layout is that I prioritized the trace inductance from the MOSFET to its TVS, and to the large capacitors used in the inductive energy capture circuit for the 0.1R load stage variant.
The result is very good:
For comparison, here is the turn-off waveform with no gate-drain capacitor:
Just for fun, here is the waveform with no RC snubber. I believe the ringing is the inductance of the cables (700nH-ish?), the C_oss capacitance of the MOSFET (264pF), and the capacitance of the TVS (900pF). It rings at 6 MHz which is quite close to the 5.6 MHz I calculate for those values. :
Although it feels less elegant, I'm probably going to leave the gate-drain capacitor off of the next load stages I assemble, and I'll try increasing the gate resistor to 3.3k to slow down the transition speed instead. Simulation shows that should work about the same. On a future revision of the load stage PCB, I'll add a footprint to put a gate-drain cap right next to the FET.
Next up: why is there such a long 30us delay between the FET_EN logic signal going low, and the gate drive circuit output going low? I'm kind of regretting doing the gate driver in discrete components at this point.