I thought I would provide an update on this project. I've had to travel a bunch for work in the last few weeks, but I'm finally back home for a few days and have had a chance to make some progress. Apologies in advance for the long post… lots of things have changed
First, I ended up switching to a common collector topology using an NPN pass transistor. In the end, I've found it much easier to stabilize this type of circuit, and the additional Vbe drop cost is not a limiting factor for my needs. The circuit can now be powered with a much higher voltage (though at the cost of control precision), so no problems there.
Second, I tried to make all the feedback loops ratiometrically controlled (I think that's the correct terminology). At the cost of a few trimmer pots, it's relatively easy to account for the inevitable variances in component specs, and use less expensive components like, for example, a cheap 0.1Ω 5% ceramic resistor.
Finally, I added a switching preregulator to remove the total amount of power dissipated by the system. Especially low power/high voltage combinations, the pass transistor was getting unacceptably hot, to the point that I was unsure that
any amount of heat sinking would have been enough to prevent it from burning out.
Rather than rolling my own buck converter, I ended up buying a cheap LM2596-based module from Amazon (~$1 CAD each in a set of 10) and making a small mod to allow its output to be controlled by injecting an external voltage through a resistor into the existing feedback divider.
Finally, I decided to use an MCU to control the circuit. I added in an inexpensive Arduino Mini Pro clone and added a few 12-bit AD/DA converters to give me reasonably accurate control over voltage and current limits (I didn't bother with the preregulator, choosing instead to use the ATMega328's internal ADC and a simple PWM control as a DAC, because I only need relatively rough control over its voltage). There is no UI yet—the plan is to eventually build a separate, galvanically isolated circuit, that can control multiple floating copies of the PSU and allow things like voltage and current tracking.
With an MCU in the picture, I became worried about weird failure modes; for example, if the MCU crashes and the preregulator voltage control pin goes to 0V, the prereg will dump its maximum voltage and current into the pass transistor, regardless of what the output voltage is set to—something that doesn't sound very healthy. So, I added a line from the Arduino to LM2596's enable pin that is normally pulled high, which means that the preregulator is off unless positively turned on by the MCU. In case of failure, there is still current leaking from the base to the emitter, but this is limited by R202, which I think should be okay.
I also added a Schottky diode between the preregulator's output and the pass transistor's collector to account for the possibility that the software will crash and somehow leave the preregulator at a lower voltage than the desired output voltage. This would lead to current leaking from the transistor into the output of the LM2596, which again doesn't sound like the best thing in the world.
I breadboarded the circuit and it seems to work pretty well. Thanks to the preregulator, the pass transistor doesn't get hot at all—so much so that I think it might not even need a heatsink. The prereg gets warm, but even at 2A a small heatsink gets it below 50ºC. This is confirmed by the fact that, at 10V / 1A output (a convenient 10W), the input power draw is 11W, which implies around 90% efficiency. Line regulation is at around 0.1% and the ripple is below a level detectable with my (admittedly primitive and limited) setup and skills, though I guess we'll have to see what happens when I spin an actual PCB.
New schematics attached below, alongside a picture of the circuit in all its breadboardy glory. Apologies that the schematic is on multiple sheets—this setup just helps me think better about things.
This is easily the most complex circuit I've ever come up with, so thanks again for all your help getting me here. I'm sure there's still plenty suboptimal and/or wrong, so I welcome all suggestions as always!
—CC