Show by Label

Friday, April 5, 2024

Designing a DIY DC Dynamic Load Instrument

 





The Design Process of Building a DIY DC Dynamic Load

The conclusion of a very long time investigating the building of a combined AC-DC Dynamic Load (DL) led me to the realization that this is not really possible. At least not without making drastic compromises about accuracy and precision. The AC measurements do not need to be very precise and are, in my case, only occasionally needed, but DC measurements typically need to have the highest precision, stability and accuracy.

The attempts for this combined AC-DC DL are described in another Blog post. There is a lot of information there, so get some fresh Java and have a look. https://www.paulvdiyblogs.net/2022/08/dynamic-acdc-load-cc-cv-cw-batt.html

The above picture shows a stage in the development with the new DC DL prototype as the basis.

To help design this new version of the instrument, I asked for the help of my friend Bud. He is a real designer, and we've done a number of projects together, like the high current RPi UPS, the VBA Curve Tracer and the 100MHz Differential Probe all described on this Blog in different posts.

Bud started a Blog post on Hackaday mostly for the hardware design aspects that can be found here: Dynamic Electronic Load | Hackaday.io I have added that same information in a section below here, so it's all together in one place.

At this moment, we have finished the design of the new version and the final board V5.1 has been produced by my sponsor PCBWay.

Although we have a stable fully working system, I'm still tweaking the software side a bit, because this instrument will do some things a bit different, compared to many other DIY DL designs.

I'll explain that later in more details but here are some pictures to hopefully wet your appetite from the previous prototype V5: (this is almost the final version, read on...)



Specifications:

  • Input voltage: 1..100VDC.
  • Reverse polarity protection to -100V and a 10A fuse.
  • DUT is disconnected by a relays for invalid inputs like reverse polarity.
  • Maximum current of 10A @ 40V
  • Maximum power 180W @25 degrees ambient temperature (heatsink temp 85C)
  • Off state DUT current 1.9uA at 2V, 57.7uA at 60V.
  • Volt Accuracy: 0.4%
  • Current Accuracy: 0.4%
  • Power input: 12VDC Wall-wart 0.5A with reverse polarity protection to -24V and PTC fuse
  • CC, BT & CV modes with real-time operation in hardware.
  • CP and CR modes have active regulation supported in software (resolution +/-156uA).
  • Pulse/transient mode supported by an external Function Generator. 5V=10A
  • Current monitoring with a DSO. 1V=10A
  • GUI: 128x128 OLED 1.5' color display and a rotary encoder with dual button functions.
  • Two temperature controlled fans.
  • Protection for over voltage, over current, over power and over temperature limits
  • Overall dimensions: 21cm long, 18cm wide and a height of 118cm.
  • Weight: approx. 1110 grams


Testing the V4 prototype

This earlier version for the AC-DC attempt is still using the Arduino Nano as the processor. It also had provisions for an on-board transformer, but that got too hot so I took it off.


The Nano is not fast enough to process the CP and CR modes, which are regulated in software. At this time, I was planning on implementing the CV mode in software as well, but that did not work at all with this prototype. While looking for a faster processor, I eventually settled on the ESP32. It has all that we need, even though we won't be using the BLE and WIFI capabilities.

This was the first time I really started to work with the ESP32 so I started to experiment with it. This processor is not only much faster than the Arduino Nano, it has a dual core and it has a native RTOS. (real-time operating system) I was hoping that these major features would overcome the Nano limitations.

In the picture below you can see how I tested the ESP32 in-place of the Nano. I simply took the Nano out of it's socket, and used jumper leads to connect to the ESP32.


The next step was to test the ADC that we were planning to use, the 16-bit ADC1115 instead of the on-board 8-bit ADC from the Nano. The on-board ADC for the ESP32 has too many issues, so we can't use it with this application. The ADC1115 has double the resolution, the down side is that the communication with the chip through i2c is very slow.


In the above picture you can see that I wired-up the ADS1115 ADC on a break-out board. With this prototype, I still used the 16-bit PWM functionality, but we were already planning to use a hardware 16-bit DAC.

So after checking and verifying the changes, this resulted in a new prototype, that we called V5.


Testing the V5 prototype

Version 5 incorporated the ESP32, the 16-bit ADS1115 ADC, the REF5040 4.096 Voltage reference for the DAC, the 16-bit DAC8571, test hardware for the CV mode and Bud's vastly improved circuitry to drive the MOSFET's.

Unfortunately, we discovered a few layout issues that we needed to fix by jumper wires and Manhattan style additions. We also found that the ADS1115 was happy with 3V3 i2c voltage levels, but the DAC, that we could not test earlier because of its tiny package, did not. That called for two bi-directional 3V3 to 5V level convertors, and I used a 4-channel circuit board connecting it Manhattan style to test that. To be able to increase the i2c clock speed, I changed the 10K pull-ups to 2K2.

We then figured out a slightly different circuit for the CV mode, eliminating an extra DAC that we were planning to use. Using that earlier method would actually be cumbersome to drive with the planned user interface so the new method uses two CMOS switches to automatically change the configuration to use the DAC for the CC mode and also for the CV mode.



Unfortunately, we also found out that the heatsink I was planning to use, that would fit nicely in the enclosure I also wanted to use, could not handle the heat transfer. Not even close. Not only did things got really hot, we were far away from the specifications! I measured the NFET package temperature at well over 160 degrees C, and the heatsink temperature rose to almost 100 degrees, and that at a mere 90W for only a few minutes. Bummer!

The obvious solution is to use a different heatsink with a significantly larger surface. 

Unfortunately, larger heatsinks are very hard to find, unless you go for the typical PC CPU coolers. The ones that are available literally tower above the NFET, and it's not easy to use them for two NFET's or find an enclosure for this construction. 

We found two heatsinks that looked promising and I ordered both of them. Luckily, the most promising arrived early, so we could start to test with it. This is the one on the left. It has the largest amount of contact surface. 

The one on the right relies on a fan at the end (or even both ends) to blow the air through. Unfortunately, that calls for a small diameter fan and they have difficulty getting enough air displacement, unless they rotate faster, making a lot more of a whining noise. Which is another reason why it is not my favorite.


The one on the bottom is the one I had been using. I purchased a number of them for other projects many years ago. I did an extensive search, but I could not find anybody offering them anymore. 

The different heatsink called for drastically different construction because the length of the leads to the NFET's and the critical components on the PCB are very critical. We did not want to split the NFET's and give them each their own heatsink, or mount them on either side of the heatsink.

This is why we ended-up with the contraption below to just try it out. It did not need many PCB changes, so was relatively easy to setup and test. The original fan is now moved from the top to the bottom, getting its air from the bottom of the enclosure. The fan is blowing directly to the fins of the heatsink. We will need to use a second fan to suck the hot air out of the enclosure, which has some ventilation slots.

 

The first test already showed that we could now easily handle 90W for quite some time, which was not possible with the previous setup. The enclosure we selected later required us to rotate the heatsink 90 degrees horizontally, so a fan mounted on the back panel can suck the hot air out.



A longer-term test at 150W showed that we were on the right track. Everything stayed at manageable temperatures.


At this moment, let me explain what you see on the above OLED display.

On the top, you see the actual DUT (Device Under Test) voltage in blue and below it, the actual DUT current value in green.

Below that is a line that shows the mode (CC = Constant Current) the NFET's are driving the DUT (ON)  and the actually calculated DUT power in Watt. The display is in red because the power approaches the maximum value and is there to warn the user.

Underneath the horizontal line is the parameter you set with the rotary encoder. The mA suffix changes with every mode. The last line shows the actual 16-bit DAC value (while testing) and the heatsink temperature in degrees Celsius. The color is orange to warn the user that the temperature is above 60, it turns to red above 90 degrees.

The colors are used to warn the user for conditions like over temperature (90), over-power (150), low (<1V) or negative DUT (wrong polarity), Voltage too high (>100V), over current (>10A), etc.

The discrepancies in the display values for set/actual current are caused by the fact that I for this test I didn't use the sense inputs yet so the drop in resistance due to the high power and long leads is not accounted for. Yet.

The User Interface to drive the instrument is kept as simple as possible, and I let the software do most of the setup underneath the hood.

The rotary encoder that you see mounted on the PCB is there so I can more easily test the setup with this prototype. It will later be placed on the front panel. In the CC mode, as you see above, you set the current by turning the knob. The knob currently has two speeds. If you turn it fast, the resolution goes to 10x so you get to your destination rather quickly. Short pressing the rotary encode button switches the DUT output to on and off, by turning off the drive to the NFET's. A long press switches to the next mode. You simply cycle through the modes in a loop, so from CC to CV, to CP, to CR and from the BT mode back to CC. When you switch to another mode, the output is automatically disconnected, and the instrument is prepared for the next measurement. The mA suffix you see in the Set line, changes with the modes, so from mA, to V, to W, to R and in the BT mode back to mA. There is no separate transient or "pulse" mode, because this feature can be used in all modes. That may not be very practical in all modes but the pulse functionality is as versatile as your function generator supports. (amplitude, frequency, pulse form, pulse width, rise/fall times and offset)

On the front panel, in addition to the rotary encoder and the OLED display, there will be two toggle switches, one for selecting the sense input terminals, and one to select power. There are two BNC connectors, one for the transient/pulse input and one for the DUT current output to a DSO. There will be an USB-C connector to the ESP32 that is required in the Battery Mode and also allows for updating of the firmware. And finally, two 4mm Banana connectors for the power connections and two 4mm Banana connectors for the sense inputs. Simple and efficient. And no, there is no keypad. It is not needed. I dislike keypads so did my best to design around it.


A suitable enclosure

The heatsink has been tested and verified that we can now easily get to 150W, but that is still outside of the enclosure. Because of the height of the contraption, we also had to find another enclosure that would accommodate this construction. Unfortunately, there are not many compact enclosures that answered our requirements.

We prefer a plastic enclosure, because the heatsink is connected to the DUT through the non-isolated NFET's and that can get up to 100V DC.

We also need to modify the enclosure to get enough air in and out. That's a lot easier to do with a plastic enclosure. And we want to be able to make a PCB-based front and back panel.

The height of at least 9cm dictates that you will get (instrument) enclosures that are very wide, and not very deep. They are unsuitable for our requirements, but it's up to the other makers to select what they want.

The enclosure we selected is from the company TEKO. They have many enclosure types, but we selected the AUS series that is pictured below. The top one in the picture below is the one I already used for several of my designs, and was planning to use. With the new hardware construction, it is not deep and high enough. The middle one is wider, but has the same height. We settled on the bottom one, the  TEKO AUS33.5.  TEKO is a German manufacturer but with a little Google-action, you can find them all over the world, and there are suppliers that send them all over the place. I use www.tme.eu a lot for my purchases, and they carry these enclosures.

So with this version of the prototype, I have been very busy with the testing, implementing and again testing the changes we needed/wanted to make, and all the while further developing the software.


Final Version 5.1 PCB

Based on the now fully working V5 prototype, we have redesigned the board for the new heatsink configuration and made several other changes and corrections. The PCB has been produced again by my sponsor PCBWAY. They financially sponsor this project by producing the boards and sending them to me for free. The turn-around is mostly within a week, and the quality is excellent.



The small TO220 heatsinks you see on top of the NFET's help to disperse their heat better, because they are in the forced airflow. Instead of one 4-pin fan, we now have two connectors (the white ones top left) so the first fan sucks fresh air to the heatsink and the second fan that sucks the hot air out of the enclosure. Both fans are temperature PWM speed regulated by the sensor on the heatsink.

We also switched to another OLED display source, because the one I purchased many years ago was no longer available. We selected a good quality and commonly available version but that has a different pin-out so we fixed that on the PCB as well.

Here is a quick sneak preview of the completed instrument . Note that I switched to even larger TO220 heatsinks on top of the NFET's to get rid of even more heat now that these fins are in the airflow of the second fan.

Here is an overview of the construction.



The unit has been stress tested with a 180W 15 minute test while using an IR-camera to keep an eye on the temperatures. I believe we can support 200W, but I don't have a large enough current source to test it out. 


Above is a picture of the completed instrument. The sheet metal front panel that came with the enclosure was used to experiment and try out the connections. It will eventually be replaced with a PCB that will have the silkscreen indicating the functions and connections.

Top left is the 12V DC power switch. The larger empty hole to the lower right of the power switch was a mistake. The power switch was in that position earlier, but it was too close to the ESP32 board so I had to moved it away.

The black oval next to it is the USB-C to USB-micro adapter providing access to the ESP32. The USB connection to a PC is required in the Battery Mode, and can also be used to debug the firmware or upload newer versions.

The four empty holes around the OLED display stem from an earlier attempt to fasten it to the front panel. At this moment, I use sticky tape to mount it. I have an idea that I will try when I design a PCB as the front panel that will not show any holes or screws.

To the right with the large knob is the rotary encoder that controls the setup of the instrument and the measurements.

Lower left is the pulse/transient input BNC connector. It can connect to a Function Generator. The input voltage is 5V for a DUT current of 10A.

Below it are the two 4mm Banana jack sense input connectors.

To the right is the sense toggle switch, switching the voltage measurement to the sense inputs or to the main inputs. Using the sense inputs is really needed with high currents, due to the voltage drop over the main DUT leads.

To the right are the main 4mm Banana jack DUT power connections.

Slightly above that is the DUT current monitor BNC connector. The output is 1V for 10A of the DUT current.

The back panel has the second 90mm fan mounted and also the 12V DC input connector.


Battery Test Mode

The Battery Mode application that runs on a PC, communicates with the Dynamic Load, sets-up the instrument and does the graphing during the run is available on the GitHub site. It's a single executable that you can install on your PC wherever you like, and you can run it from there.

There is a separate Blog post that has more information about the project here: 
https://www.paulvdiyblogs.net/2019/03/a-pretty-universal-battery-cell-tester.html
My project was based on the work from John Lowen and his details can be found here:

I modified the original code that was running on the Arduino, made it work in the ESP32 environment of the DL and integrated it into the main menu structure.

Below is an example of the Battery Test mode. I'm using a Lithium 3.7V 14500 cell. The cell is several years old and had not been used. The specification is 650mAh and I tested it with a discharge current of 2500mA. The cut-off voltage was set to 3V.

These values are entered into the Battery Test PC program below on the bottom left hand side.
The test is started from this program, and it sends the parameters to the Dynamic Load and starts the measurement. 

During the measurement, the display is refreshed with the parameters coming from the Dynamic Load, such as the voltage, the current, the time and the calculated mAh value, shown on the bottom right. The graph is dynamically updated during the measurement.




As soon as the Dynamic Load measures that the cell voltage has dropped below the cutoff voltage of 3V, the measurement stops and removes the load. 

Just above the green Test Ended message, the Controller Message shows a Serial Time-out, instead of the Cutoff Voltage, because it was waiting for another measurement that took too long to send the data. The DL terminates the waiting loop and restarts the reception of the setup parameters or a mode change automatically.

This was a test of an EFEST 14500 IMR cell of 650mAh. These IMR cells can deliver up to 9.75A for short periods, or up to 6.5A continuous. Bud and I used these cells in the Raspberry Pi 3 UPS, to supply enough voltage to let the RPi ride out a power glitch or let it power down safely. I had not used these cells for many years and just charged them again for a few times to run this test. 

With just over 550mAh, the test shows that the cell is no longer meeting the specifications of 650mAh, but is still usable.  

In order to test at higher currents, you really need to use the sense inputs, which I did. I also used a metal battery holder, plastic ones would melt with these high currents.
 
Note that I faked the Rated Capacity of the cell in mAh from 650mAh to to 2000, to overcome the calculated  time limitation in the software (rated mAh/current), which would terminate the measurement prematurely. You can save the details including the graph, and when you do, you can enter more information about the cell and also add the weight of the cell, which is a good give-away indication for poorly "specified" or plane fake cells.

When the measurement is terminated or ended, you can restart the measurement in the PC software and test another cell. Long-pressing the rotary encoder switch on the DL brings you back to the CC mode. The original hardware that was intended for this PC program would also re-start the Arduino Nano controller. We don't need to do that, the DL software automatically takes care of all that.


Below are the details on the how and why, and finally a Theory of Operation, explaining the details of our design.

Designing the Dynamic Load

Here are the building blocks of how we got to the design of the Dynamic Load.
First of all, you need to start with a design that does not oscillate. Sounds simple, but we have found many designs that are barely stable, if at all.

Making a Current Source that does not Oscillate

We've seen some DIY articles that show the most basic topology for making a current source controlled by a voltage source. Here is a typical topology:


There is no compensation to prevent oscillation -- it assumes that the amplifier has infinite bandwidth and infinite gain. A more practical circuit might be this one:


R1 and C1 create a "pole" that overrides the Opamp's internal compensation to possibly prevent the circuit from oscillating. But this still neglects real world problems. Consider the circuit below:


R2 is added because the gate capacitance of M1 is large (maybe 10nF), which causes the amplifier to become unstable and oscillate. Adding R2 "isolates" the amplifier from the capacitance of M1. R2 is typically 50-300 Ohms. Now we're getting close to something useable.

The size or value of the current shunt R3 is also important to take into consideration. There are two important parameters that drive the value. One is the voltage drop over the resistor at maximum current, which drives the value to be as low as possible, to keep the power dissipation low. However, the value of the resistor also determines the value of Vcontrol, which will be a lower voltage with a lower Ohm shunt. With smaller control voltages you are quickly getting in the realm of component issues, tolerances, offset errors etc. But read on to find how we plan to get that under control.


Our Approach


Oooh...lots more components. 

True, but this schematic also accounts for the inductance of the leads connecting the source to our load (DUT). The inductance of the leads makes a big difference in compensating the circuit to prevent oscillation. The values of R_Lead and R_LEAD vary with the length of the wires used to connect V_SOURCE to our load. Typical numbers for L_Lead and R_LEAD are 3uH and 100mR, respectively.

The addition of Q1 and Q2 are not the traditional Totem Pole configuration to drive MOSFET's that you see a lot. In our design, the addition of Q1 tends to isolate U1 from the gate capacitance of M1 and still provide plenty of current to drive the gate. Q2 doesn't do anything...yet. R4 and C1 create a unity-gain crossover that is low enough that the phase shift through the circuit doesn't reach 180 degrees to cause it to oscillate.

With R4xC1 having a short time constant (high frequency) the open loop response of the circuit would look something like this:


Note that the phase margin is nearly 90 degrees and the gain margin is 25 dB, indicating that the circuit is very stable and unlikely to oscillate. But what happens when we include the DUT lead inductance?


Now the phase and gain indicate that the circuit will oscillate at about 283KHz. It's pretty ugly. But this has to be taken into account in the design. The most straightforward way to compensate for the lead inductance is to de-Q it so it doesn't create a large peak in voltage. That's where the snubber circuit comes in (R_SNUB and C_SNUB). If we add about 5 Ohms of resistance across the lead inductance it will reduce the Q of the resonant circuit and help prevent that oscillation. Here's what the open-loop response looks like with RSNUB=4.7 and CSNUB=1uF:


It's better, but the slope of the gain is too steep and the phase margin is only 23 degrees -- not good enough. Also notice that there is a peaking in the gain/phase response at 5MHz -- stay away from this. The easiest fix to increase the phase margin is to increase C1 until you get adequate phase margin. So increasing C1 from 300pF to 3.9nF gives us this:


This looks even more problematic, but it's not. Note that the gain slope as it crosses through zero dB is only 20dB (very desirable for a stable amplifier). Note also that the phase margin has increased to 86 degrees and the gain margin is around 35dB. What we have given up is bandwidth since this loop only has a gain-bandwidth of around 25kHz. But that should be good enough for our purposes. We still need the snubber because without it the phase margin would still be near 90 degrees, but the gain margin degrades drastically to less than 10dB, which is marginal to prevent oscillation.

But wait...there's more. If we decrease the set point current from a high current to a very low current, say less than 25mA, the gain-bandwidth of the loop decreases to around 130Hz. This is smaller than desired, but probably still usable.


So what are the other components for?

R1 provides current to decrease the emitter resistance of Q1 and also drive the gate toward GND. Q2  protects Q1 from a nasty transient that could damage it. And R2 limits the current into the base of Q2 if the Opamp output goes below GND. More on that in "Forcing Zero Current - Nicely"


NFET Selection

Bud had picked out quite a few NFETs that he thought would be good candidates for this project: IRFP150, IRFP250, IRFP350, IRFP460, etc. In my previous attempts, I used the FCH072N60 that we used in the Curve Tracer design and this worked well for me. I also tried it in the V5 with good results.

What's so critical about the NFET selection you ask?

Most MOSFET's are designed for switching applications. That's their target market. We use them differently, as a variable current source and that's not an ideal application. The most critical specification for our application is the Safe Operating Area (SOA for Current vs Voltage) under DC operating conditions. For some NFET's, this is not always specified, go figure!

Here is the SOA of the SUG80050E that is specified as a 150V and 100A device. The SOA diagram however, shows that we can only use it up to 10A at 40V and 4A at 100V - at 25C and at DC!

After reviewing Kerry Wong's video about linear FETs Bud went back through his list of candidate NFETs and culled out most of them. Nearly all of them did not specify a SOA under DC operating conditions...big red flag! Bud then went back to DigiKey and LCSC to see if there were any that would satisfy our SOA of 100V @2A. 

He found these: 

  • SUG80050E (Still the best one) 
  • FCH76N60NF (OK and we have a simulation model)
  • IPZA60R045P7 (can't get the sim to run with this spice model) 
  • IXTH60N20L2 (expensive and no model) 
  • IXFH56N30X3 (ditto) 
  • MS170N15IDC0 (Chinese, but specs look OK. Needs derating. No model.) 
  • NVHL055N60S5F (no model) 
  • RU1Z200Q (Chinese.)

Without a SPICE model it is difficult to tell if it will work in the circuit. Therefore all we can do is list them as potential substitutions for the one we eventually pick, which right now looks like the SUG80050E. Spoiler alert, we did.


Opamp Topology Analysis

The most critical element in a Dynamic DC Load is the current regulation. 

After we got the Constant Current (CC) loop stable it was time to account for the configuration of the rest of the circuit -- the topology. We stumbled upon a topology that appears to yield very good accuracy with the addition of just a few resistors. Below is the basic topology of a single NFET current loop:


What we need to know is how the output current depends upon the input voltage, VIN. The schematic above uses only 2 values R1 and R2 as a special case of this topology that we employ. V+ and V- are the voltages at the inputs of the ideal Opamp (infinite gain, no offset). 

The equations that govern this are:

V+ = (VIN - V2)(R2/(R1+R2)) + V2

V- = V1(R1/(R1+R2))

Since the Opamp forces V+ = V-, when you solve for V1 it yields:

V1 = VIN(R2/R1) + V2 , as you would expect.

And the output current, I_OUT is therefore:

I_OUT = (V1 - V2)/RS = VIN(R2/R1)/RS

Note that V1 and V2 drop out of the equation. Like an instrumentation Opamp. The only errors are the ratio of R1/R2 and the value of RS, the shunt.

When we expand the topology to two separate current loops we get this simplified schematic. Again, the resistors values are special cases to match the topology and make the math easier.


Now it gets a bit more complicated. We want the current, I_OUT, to be only a function of the input voltage, VIN. Here's the equation for V+, which is the same connection for both Opamps:

V+ = VIN R1/(R1+R2) + R1/(2(R1+R2)) (V2A+V2B)

and since V+ = V-,

V1A = VIN(R2/R1) + V2A/2 + V2B/2

But what we really need to know is what the output current is:

I_OUT = IA + IB = (V1A - V2A)/RS + (V1B - V2B)/RS

The Opamps are forcing V- to equal V+, and therefore V1A = V1B, so we can substitute :

I_OUT = IA + IB = (V1A - V2A)/RS + (V1A - V2B)/RS = 2(R2/R1)VIN/RS, 

which is only dependent upon VIN and the three fixed resistor values. Of course, this is a trick of a sort since I've forced the resistor values to be identical or a 2X multiple. But realize that the errors in the method are below the tolerance of the resistors (sub-1%).

By inspection, it is obvious that if the "B" side of the circuit has errors that increase the current through MB, then a corresponding decrease in current will occur through MA. In order to prevent this disparity from getting too large, a careful layout symmetry between the two sides must be preserved.

Accounting for the dual sense resistors

The next step in the process is to expand the sense resistors to two sets of two. This is to keep the power dissipation in the resistors to a reasonable limit. The math gets a bit unreasonable (for me) and so Bud resorted to LTSpice to corroborate the result -- it is the same.


This is the same circuit as before, but this time Bud inserted parasitic resistors, the ones labeled RP, to indicate where the various error voltages will come from. The values of RP depend upon the quality of the PCB layout -- they are not all the same. Note also that the ground return point of the current could be different than the ground reference of Vin. This is an important given for this topology that could mislead the unaware. 

The analysis shows that the errors will still be cancelled to a first order. Again, you get the same result, if you keep the resistor values in the same ratios, the output current is only dependent upon VIN, R2/R1 and RS.

One complexity is that the 2kR resistors must be Kelvin connected across the sense resistor, RS, in order to get the full benefit of this approach.


Simulation Results:

To prove the point, Bud simulated the circuit in LTSpice using Monte Carlo analysis. Here's the complete circuit:


The tolerance of the gain setting resistors is 1%, but I set them to near 0% in the first simulation while letting the parasitic metal trace resistors have a tolerance of 20% and a tempco=4300ppm/C. The simulation ran 50 times at 25C and 50 times at 100C. The results were uninteresting to say the least -- total variation in output current from the 10A set point was...13.6uA. That doesn't include any Opamp variation except temperature. That is a variation of only 0.000136%!

When Bud added a 1% tolerance to the other resistors the result was more interesting:


The bottom plot pane is the output current. It varies as expected, about +/- 1.3%. The top plot pane is the current through M2, which varies a lot more due to the 20% tolerance and higher TC that I set for the parasitic resistances. The results get even more interesting when the resistor tolerances are set to 0.1%.


The output current variation drops by a factor of 10, but the variation in the current through M2 doesn't decrease much since it has the added variation of the parasitic trace resistances.

So it would seem that using 0.1% resistors should negate the need for a trim...but not so fast. Try to find 80mR 0.1% sense resistors. 

If you re-run the simulations with 0.1% tolerances for the "regular" resistors and 1% tolerances for the sense resistors the simulations show that the output current variation is 0.62% (not 0.15%). It seems using 0.1% resistors will not yield much better results than 1% overall, unless you can get 0.1% sense resistors (good luck). We're keeping the trimmer.


Accounting for Errors in the CC Loop

We have selected a topology that minimizes gain errors to a first order -- primarily resistor tolerances. The next question is what Opamp will give us the best bang for the buck when it comes to all of the errors associated with the amplifiers? Bud put together a spreadsheet to add up the various errors caused by the Opamp.

For perspective, it is worthwhile to note that 1mA of current requires only 20uV of voltage across the 20mR sense resistor. With these small voltages you are quickly in the realm of component issues, offset errors etc.


I (Bud) have used a MCP6V51 Opamp on another project and was impressed. It is a chopper-stabilized (i.e. zero-drift) Opamp with incredible specifications. On the right side of the spreadsheet above is the TL071 -- a general purpose JFET-input Opamp. The first section lists each Opamps specs with regards to input offset voltage and input bias/offset current, as well as the open-loop gain (AOL) for both typical and worst-case values. Below that I calculated the effective resistances at the inputs to the Opamp and the expected maximum temperature range (25-100C).

AOL Error

In this application the amplifier has to drive the NFET gate to around 3-4V before any current flows in the NFET. If the open-loop gain is low then the amplifier will require more of a voltage difference between the + and - inputs, which incurs an error. The MCP6V51 has a typical open-loop gain of 150dB (32 million V/V) vs. the typical TL071 AOL of 125dB (which isn't shabby at 1.8 million V/V). To output 3V the MCP will need a voltage difference of 94nV vs. 1.7uV for the TL. Under worst-case conditions, the MCP needs a difference of 0.8uV vs. 7.1uV for the TL. So the the lower AOL causes about 0.3mA of error from the TL vs. only 0.04mA of error from the MCP.

Input Current Errors

Input bias current and input offset current errors are typically better for the TL but worse for the worst-case specifications.  They are small for both Opamps.

VOS Error

The input offset error is the biggie, and it's made worse with temperature drift. Worst-case VOS for the MCP is nearly 20uV, which is 1mA of error. Worst case VOS for the TL is more than 4mV -- an error of  more than 200mA. Even the typical TL VOS error is nearly 60mA, not good enough.

Temperature Drift

The initial offset of the system can be removed by measuring and storing the offset current. But as the box heats up from a high wattage load, the offset and gain terms will drift, causing errors. If you compare the VOS drift terms between the two Opamps there is a clear winner. The MCP has 50X lower drift over temperature.


Forcing Zero Current - nicely

When the system boots up the relay should be open and the CC DAC should be set to zero. But this doesn't necessarily set the output current to zero. If the Opamps controlling the current loops have a positive offset they will be unable to fix the current at zero. And if the offset is negative, the Opamp output will drift to its negative supply rail if not constrained. Therefore, the only way to get zero DUT current is to force it through some other means.

Dominik solved this problem by yanking the Opamp input to a high voltage, which drives the output to its negative supply rail. This does indeed enforce a zero current state at the output, but not without issues during normal operation. Here is some detail about his solution:


The leakage current from the collector of Q11 is not usually a term anybody cares about. In this case, the S9015 has ICBO=50nA, which is pretty low. However, this current generates an offset term across R18 equal to 0.5mV, or 5mA per Opamp (and there are 4 of these, but not all will generate a Worst Case (WC) leakage current. In our case, it would create an output current error equal to 12.5mA.

The Keysight design just yanks downward on the Opamp output, forcing the Opamp to output a short circuit current. This is bad because the Opamp generates a relatively large output current, but is good because any error current from the downward yanking device gets swallowed by the Opamp in normal operation and doesn't impact performance.

Both of the approaches above force the Opamp into a state of inequality. The output is driven to a rail and the inputs aren't equal, which is a bad thing. When the Opamp is released from this condition there is usually a transient spike of uncontrolled magnitude until the conditions of equilibrium are re-established. Generally not good.

We wanted to avoid the negatives so Bud decided to use a different path.


The BAV199 low leakage diodes are actually specified over temperature and voltage which is pretty unusual! They're spec'd at a max reverse leakage of 5nA at 25C, and 80nA at 150C. The datasheet even provides data for typical and max leakage current as a function of temperature: 3pA typical at 25C, 300pA typical at 100C, 5nA max at 25C and 30nA max at 100C. 

In normal operation D3 leaks current into the "+" input of the two Opamps controlling the current loops, getting absorbed by the 500R equivalent resistor at that input. But this is partially compensated by a reversed biased D2 leaking current into the "-" input of Opamp U1 (and D1 leaking into U2), getting absorbed by the 1k resistance at those inputs. The currents are not going to match, so we can use typical vs worst case to see what the range of error might be. But the difference between typical and WC is so large that the typical value can be set to zero. If D2 is leaking worst case then it will produce an output current error equal to -(30nA x 1k)/0.04R = -750uA. If D3 is the WC condition then it will produce an error current equal to +(30nA x 500)/.02R = +750uA. So it seems the error current will drift somewhere between +750uA and -750uA WC as the box heats from 25C to 100C. If we just use typical numbers then the offset error drift is only -7.5uA. That's manageable.

How it works

Normally, the DAC_OFF signal generated by the ESP32 is low (zero volts). Therefore Q6 and M3 are "off" and the BAV199 diode, D3, is reversed biased and not influencing the current loop significantly. If the DAC_OFF signal is asserted to 5V then Q6 drives the gate of M3 to a VGS ~ 4V and M3  switches "ON", which then pulls its drain to -5V. R29 then forward biases the upper diode of D3 and pulls the "+" input of U1 below ground. The amount of negative voltage at the "+" input of U1 depends upon what the DAC value is. If we assume the DAC is outputting 4.096V or less, then the Opamp "+" input is yanked below GND. Since the gate of M1 can't go below GND the Opamp output will drop, forward biasing D2 until the Opamp inputs equalize...somewhere around -1V. R3 is there to limit the current into the base of Q2. So now the gate of M1 is at GND and there is just some leakage current flowing through the NFET. 

Note that the ESP32 is a 3V3 device, so the DAC_OFF voltage is not asserted to 5V. This is accounted for in the final circuit values.

When DAC_OFF is de-asserted, D3 is reversed biased and the Opamp is freed to do what it wants. Since its output was held below GND while DAC_OFF was asserted, the output is now released and allowed to increase, at the rate determined by C1 and R8//R9 -- slowly if the CC DAC output is set slightly above zero. This could take tens of ms if the DAC value is low.

The final result of all this is that there is no big current spike at the output when DAC_OFF is de-asserted.


Yellow is DUT current, blue is DAC_OFF signal.



PCB Layout Challenges

With the design basically done, we can start to work on the layout, which, as you have seen above, is pretty critical in places.

There are a few tricky challenges when you deal with high currents. Here is a portion of the layout for the V5 PCB. The V5.1 is a bit different, but the principle is the same.



At first, we were going to use a higher amount of copper for the PCB, but that would increase the price and the delivery time. It's also easy to forget to order this thickness, and that could cause serious issues for other Makers. So instead, we are specifying the default 1oz copper for this PCB. That change increased the traces carrying 10A to blow up to 6mm width and the traces carrying 5A are now 2.5mm wide.

The GND reference

The first thing to notice is pin 2 of J1 (find it just below and to the right of U7) -- that is ground zero for the entire PCB. It is the absolute GND reference potential for the system. This is where the negative input lead of the load connects to the PCB. All of the various power inputs and outputs connect to this point. 

The 12VDC power adapter negative lead (in Blue) snakes around to the right and comes directly to that lead (a Kelvin connection). The top-side metal traces (in Red) that bring currents from the sense resistors, R4-R5 and R8-R16, are split equally/identically in terms of resistance, from those resistor's pads to J1 pin2. Those traces carry a maximum of 5A/each and are properly sized, by width (2.5mm), to carry that current without over heating.

The snubber capacitor, C11, also connects directly to the J1 pin2, but with a much smaller trace width since the currents should be smaller.

Lastly, the ground plane is almost a Kelvin connection but must share a small section of bottom-side metal trace. Hopefully, it will not matter much.

High Current Paths

The high current traces carry 10A max and require a trace width of 6mm. The input connector, J1, has a 6mm wide trace (in back-side metal, Blue) from it's positive terminal to the fuse, and also from the fuse to the relay (back-side metal, Blue), where the trace eventually splits and reduces to 2.5mm to handle the 5A currents to the drains of M1 and M2. 

High Voltage and Creepage

The pads of the high voltage devices/connectors must have sufficient distance from other pads to prevent creepage. High potential between pads located close together can develop conductive "growths" that cause parasitic currents to flow and can eventually cause failure. This is not only a problem for exposed pads or traces that are not covered by the solder mask. The recommended pad separation distance to prevent creepage for a 100V potential is about 1.5mm. Traces located under a solder mask only need to be separated by 0.4mm to withstand 100VDC. The layout conforms to these restrictions.

Kelvin Connections

This connection technique is named after Lord Kelvin. Here is the layout detail on the left side:


The current tends to spread in 45 degree funnels from a single point to a connection point, such as a pad on a component. In order to make the Kelvin connection, the current should be zero at the point of the Kelvin connection. I made triangular copper pours to distribute the current to the two sense resistors. The back-side of the pads should have zero current flowing to it and therefore a good place for a Kelvin pickup. The pickup points are on the middle-inside of the pads on the sense resistors. Those traces connect the feed resistors for sensing the voltage across the sense resistors.

There is another method of picking off Kelvin connections from SMD devices, but this method was recommended by the manufacturer of the sense resistor...who am I to argue. We'll see how well this performs when we get the PCBs to evaluate.



Theory of Operation

In this section I will explain the hopefully final circuitry in more detail.

Here is the latest schematic of V5.1a:



( I have made a few refinements for the off-board parts, so PCBWay can produce and populate the board for their clients)

The rotary encoder can be placed on the PCB if you want to use it without the front panel. It's easier to rotate and press that way. The sense switch is shown for clarity, but it is also positioned on the front panel.

When you use 0.1% resistors for R40, 38, 43 and 41, you can omit the RV1 voltage trimmer and replace that with a 0Ohm resistor for R39.


It looks pretty busy but most of the circuitry is rather simple and straightforward. I'll explain some of the various blocks that may not be that transparent in more detail in the sections below.

Dual fan

We use two fans to cool the heatsink and get the hot air outside of the enclosure. The mechanical details will show that. What is not so clear is that we selected 4-pin fans so we can drive them with a PWM signal directly driven by an I/O port of the ESP32. These 4-pin fans also have the capability to sample a Tacho pulse that will allow you to calculate the RPM. Because the fans are in parallel, you only need to monitor one. The Tacho signal needs to be pulled high so you can drive an I/O pin with an interrupt. I used the Tacho signal during the development, but do not use it al the moment. When we added the second fan, I found to my surprise that the second fan did not work without the pull-up. This resulted in a small revision from V5.1 that we have, and the V5.
1a to give both fans their own pull-up so we could, potentially, still monitor one of them. At this moment, we only have V5.1 produced and that is what Bud and I are using. Eventually, we will publish the Gerbers for V5.1a, but will do that when we have completed all the tests.

Power Supply

This is a straightforward supply that uses an external 12V DC Wallwart. To protect for mistakes, we added a PTC fuse. There are two footprints, one of which is a THT, so you can use what you have or like. The PFET provides polarity protection. The resulting almost +12V input is used for the two fans. With the available headroom, we decided to use an LM7809 to provides  the +9V rail. The +9V rail also feeds an LM7805, which provides the +5V rail, and a CMOS voltage converter that provides the -5V rail. We use the -5V rail to ensure that the Opamps can regulate all the way to GND. The ESP32 Devkit provides its own +3V3 and that is the output level for the I/O ports. It is also used as a source for the bi-directional logic level pullups used with the i2c level shifters.

Because the ADC and DAC require TTL level i2c bus levels, we use bi-directional level shifters implemented by M7 and M8. We use pull-up values of 2K to allow for the highest i2c bus speeds.


DAC Circuit

Instead of using a PWM based voltage regulation, we decided to go for a more precise 16-bit DAC solution. We selected an i2c version DAC that needs an external 4.096V reference to give us precise voltage (CV mode) or current steps. A CMOS switch is used to either supply the current in all operating modes, and a fixed current (set by R42 and R46) in the CV mode.

The current resolution has a range of 0-4.096V.  The DAC output is divided down to a full scale of 0-0.2048V to the two current loops controlling the current through two 40mR resistances, so the full scale current is 0.2048/0.02 = 10.24A, with a resolution of 0.15625mA/bit. It will take 64 DAC steps to make a 10mA output current step. The software deals with all that and presents usable numbers.

The ADC Circuit

We selected a 16-bit ADC that is also i2c controlled, to measure the DUT voltage, the DUT current and the heatsink temperature. The ADS1115 has two differential inputs, or 4 single-ended inputs, of which we use 3. The DUT input voltage is supplied by the circuitry in the Remote/Local Voltage Sense section. We use a DPDT switch on the front-panel to input either the voltage from the main DUT input connectors, or through the remote sense input connectors. With higher currents, you can avoid the cable or lead voltage drops by using the sense inputs. They carry no current so will provide a more accurate voltage reading of the DUT. The DUT input voltage is attenuated by R45 and the combination of R43 and R41 to get a 24.15 voltage divider. U4 provides a differential input to the DUT voltages and with the use of trimmer RV1, you can calibrate the final input to the ADC to represent 100V with 4V to the ADC. Software will do the rest.

The DUT current is measured by a seemingly complex circuit around U3. In principle, this is a real differential measurement setup that takes PCB trace losses into account (see the description above). The DUT current measurement is taken directly across the dual sense resistors R16+R18 and R5+R4 with Kelvin connections. These inputs are fed through 20K resistors to the inputs of U3 and then fed into the ADC. 

The heatsink temperature is measured by U7, an LM35DT in a TO220 package which is easily mounted with an isolation pad(!) on the heatsink in between the two main NFET's.

The DUT input protection

After several discussions, we decided to protect the instrument for polarity changes by using a relays, K1 or alternative K2. Applying a negative voltage will most likely fry the NFET's. We provide two foot-prints for different versions. 

The nice things about relays are that they don't leak current when they're open and have decent contact resistance when closed so measurement errors caused by the contacts are minimal. 

At boot-up, the relays is off, but note that we can still measure the DUT voltage directly on the input connectors. If the instrument detects a too low or negative voltage at any time, the relays stays off or is switched off and the user is warned by a message on the OLED display. Only when a valid voltage is detected, the relays is turned on such that a load can be applied. 

We also use a 12A fuse to protect the instrument and the DUT from excessive currents if a mistake is made. Especially when you are using high capacity battery cells, this could happen.

Under software control, we can also remove and apply the load by turning the NFET's on or off through the circuit around Q6, M3 and D3. 

The CC mode operation

Actually, also the CR, CW and BT modes have basically the same operation mode, because the amount of current is regulated to provide a constant current in hardware, resistance or power controlled by the software. The Battery Test mode (BT) actually works in the CC mode so also controlled in hardware.

Software controlled means that the DUT voltage is measured, and divided by the requested resistance to drive the current to keep the resistance constant. In the CP mode, the DUT current is multiplied by the DUT voltage and the software controls the current to stick to the requested power setting. The speed of regulation in these loops is highly depending on the processor speed but even more so on the serial interface (i2c) speed to read the results from the ADC. 

This is the main reason why I selected the ESP32, not only for the higher clock speed, but also for the dual core. In our design, one core deals with the control loop that needs to run as fast as possible, and the other core with the measurement setting and display of values on the OLED, and also controls the fans with a lot less urgency.

The voltage and current feedback are constructed with instrumentation amplifiers that are calibrated with a trim for accuracy. The current feedback amplifier's offset errors can be removed by measuring the zero current feedback voltage and subtracting it in software. The voltage feedback amplifier is a zero-drift chopper-stabilized Opamp that should have very low offsets. This will give us very stable and accurate DUT voltage and current measurements that are optimized for PCB trace losses but still leaves temperature drift as an error however.

The CV Mode Challenge

Originally, I was planning to implement the Constant Voltage (CV) mode in software, like the Constant Resistance (CR) and Constant Power (CP) modes. The CR and CP modes work really well while controlled in software, but the CV mode loop is too slow and creates problems, even with the ESP32 using the RTOS in the dual core mode.

Apparently, as we found out, a CV mode is difficult to accomplish in software. After doing some more research, we've found that even some commercial units don't supply this mode because they may have found also that it's not so easy to provide that under software control. Some commercial units like the Keysight 6060B and 6063 do provide a CV mode, but by using a hardware loop, and we wanted to try to do that as well, so Bud started to study their design. 

If you want a head-splitting headache, take a look at the schematic in the Keysight Service Manual for these instruments. Some cheaper bareboard electronic loads implement it poorly. And as mentioned, some commercial electronic loads, such as the Array 371, don't implement it at all.

Our CV mode is a bit simplistic compared the the Keysight as shown by the circuit below. (don't get too hung up on the used component values below):


In normal CC operation, VSET=0V and the VCV node is clamped at least a diode drop above GND. This effectively removes the CV loop from interfering with the CC loop since the highest voltage the divided ISET voltage can provide to the input of U3 is 200mV.

The baby is ugly, but can it perform the function?

It appears so, but when Bud designed it we only had simulation to rely upon (and simulation is not reality). Here's a simulation result showing the system at startup. The parameters were VLOAD=20V, RLOAD=1k, ISET = 0.05 (125mA max) and VSET=0.2V (5V). The green line is the load voltage. The red line is VCV and the blue line is the load current.

In CV operation VSET is a voltage between zero and 4V, which equates to a load voltage of 0-100V. ISET sets a maximum output current for the current loop and the CV loop decreases that current, by forward biasing D2, until the current at the load balances. This will happen when V_DUT equals VSET. There must be a current limited voltage source or a series resistor, RLOAD, in place for this to work. The astute observer will note that the voltage feedback is via the "+" input of U2 and therefore there is nothing controlling the CV loop dynamics except what is available in the CC loop. The easy way to see this is realize that at high frequencies U2 is essentially a voltage follower to its + input. This may prove to be a big mistake. (spoiler alert, it is not) It would have been preferable to use two inverting opamps in the CV loop so that the V_DUT signal would be attached to the "-" opamp input and separate loop dynamics could be implemented. (Like what Keysight did.)

The system is held at zero output current for 5ms and then released. The CV opamp is out of control until VSET changes from zero to 0.2V, but it has to slew to 1.2V below GND before it takes control from the CC loop. Since the CC loop can output 125mA it drives the output voltage to zero (125mA x 1k = 125V, but only 20V is applied). Once the CV loop overcomes the CC loop the current decreases in the CC loop and the load voltage rises to the set point (5V). A 1V-peak sinusoid on top of VLOAD is applied at 560ms to show that the CV loop can keep the output voltage stable when disturbed. I think it performs pretty well, if slowly.

But slowly might be OK. The way that Paul is approaching the user input is to start at low values and have the user scroll the setpoints to whatever he/she desires. A user is a pretty slow animal too.

To demonstrate the other end of the spectrum, here is a different set of conditions/parameters: 


The input voltage is only 5V and the max CC current is set to 10A. RLOAD = 10R and VSET = 0.1V (2.5V). Note that the CV Opamp takes longer to slew to start controlling the CC loop, but the result is pretty much the same. There is a lot more disturbance caused by the 2Vp-p wiggle on the load voltage, which begins at 900ms. Still, the reduction in load voltage wiggle is substantial.

At this point in the design process Bud was hoping that the CV mode is "good enough".

When we actually tested this with the real hardware, I found that it works really well! Unfortunately, it will take a few more weeks before Bud can build his instrument and compare notes.

The acid test is of course to lower the DUT voltage by applying more and more current. They way I implemented this in software, is to first measure the DUT voltage, and then set the CV mode voltage at 110% of that value. This will not cause any current to flow when you turn-on the Dynamic Load, but you are now already close to the tipping point. If you now lower the set voltage by the rotary encoder you will see that the current will start to increase, eventually forcing so much current that the DUT voltage starts to cave in. It's the tripping point that is so difficult to implement in software due to the relatively slow loop response, typically resulting in a sudden over current that can cause issues, especially with power supplies that have a CC/CV mode itself. It's easy to mess-up the regulation, making the CV mode pretty useless. 

Our version works really well, kudo's to Bud!

The V5.1a schematic shows the real implementation of the CV mode. When the CV mode is selected, the DAC output is switched through a CMOS switch (U15) to an Opamp (U10) that controls the output circuitry through R567 and D3. This is the same circuitry that turns the output section on or off. (signal DAC_OFF)  The CMOS switch U14 supplies a maximum current of about 4A for the CV mode set by R42 and R46.  You can change that if you're brave.

The resolution of the voltage control in CV mode is 16-bits -- 1.5mV/bit. The software creates a manageable resolution set by the rotary encoder.

Using the CV mode

From a user perspective, most DL modes start with an initial zero value for the encoder setting, but that would create a problem in the CV mode because it means maximum current. To avoid that situation, the system measures the DUT voltage and sets the initial tripping point to 105% of the DUT voltage. This means that there will be no current flowing when the DL is turned on, but the decoder setting is pretty close to the tripping point already. This initial setting is only activated when you select the CV mode.

CV mode with a regulated (CV/CC) power supply

Note that with a Lab Power Supply as a DUT, the CV mode is a bit more difficult to use due to the rapid switch of the power supply from CV to CC at the DL tripping point. You need to carefully adjust the encoder to get to an actively controlled load.


CV mode with an unregulated supply

To better test the CV mode and get more familiar with it, you can use an (unregulated) power supply that does not have current fold-back or current limiting/regulation. A transformer with a (bridge) rectifier and an electrolyte filter capacitor will much better show the CV mode regulation in operation. This kind of DUT will clearly show the sagging DUT voltage as a result of the load.


CV mode with a battery

Basically any battery or cell will provide another DUT to get familiar with the CV operation. Be aware that some of these cell can deliver a lot of current. This is one of the reasons that in the firmware, the current limit in this mode is set to 4A, hopefully preventing injuries or fire-works. Because the battery or cell will to its utmost to keep the voltage stable, you can clearly see the effect of the current changes.



Transient/Pulse Mode

Instead of adding a special external digital transient mode, we decided to add an input for a Function Generator (FG) to produce arbitrary waveforms. The resolution is 5V = 10A. The Function Generator allows you to set an offset, to allow switching between a lower and a higher current, use different frequencies, different waveforms, and even set the leading and/or trailing edges of the waveforms. Whatever your FG can do. Of course, you can still feed a TTL level signal created by anything you concoct (555 timer?) or desire to use. You can even use the calibrator output from your scope.

To protect for ground shorts between the Function Generator and the instrument GND, which is connected to the DUT, we use a PTC.

There is no special transient mode, this functionality works in principle in all modes, although in reality, that may not be very practical.

Nota that the transitions or edges that are turning the load on and off are not very fast, so of limited use to really test power supply transient responses, but it is sufficient in most cases.


DUT Current monitor

We also added a Current Monitoring capability -- a voltage output scaled to 1V = 10A, to see the real-time current transient output on a DSO. This allows us to see the DUT responses when power is applied or removed to test the regulation of the DUT. This works together with the Transient/Pulse Mode.

To protect for ground shorts between the DSO earth ground and the instrument GND, which is connected to the DUT, we use a PTC.


When using the Current Monitor, you will see some "hash" on the trace. 


Here we see the monitoring of a 1Amp current, but on top of the trace we also see the SPI related hash. The OLED display is updated at regular intervals with some critical information, and every second with the rest, as indicated by the hash with a longer duration.

Unfortunately, these high-speed SPI signal transitions find their way into the rest of the circuit. 


Above you see the SPI CLK signal in relation to the hash on the Current Monitor.



Here is the CLK signal in more detail. The SPI CLK signal generated by the ESP32 has a period of about 120ns at a 3V3 level. This is powerful enough to make it's way into the rest of the DL circuits.

I tried to reduce this effect by designing an SPI-isolator circuit that galvanically separates the OLED display circuit from the rest of the circuits. The OLED display board has it own Buck regulator to create a 3V3 voltage and also has a higher voltage Boost regulator to supply approx. 12V. At first I tried to give the OLED board it's own power supply, but that didn't make a difference. Of course that still used the same common ground. Interestingly, when I pull the OLED plug from the main board, the hash is gone. This lead me to design a circuit that galvanically separates the OLED board from the rest of the DL circuits, with the (unfounded) hope that the hash originates from the OLED board, making it's way back to the main board.

I designed the circuit such that it can be inserted in-between the connector on the main board, and the OLED display cable going to the other end.



The ADUM5000 provides a galvanically separated power supply where the output can be selected between 3V3 and 5V with a jumper. The ADUM7440 is a 4-channel isolator circuit. The 5th connection, the RST line, is not passed through, but re-created by an R/C combination to provide a power-on reset. 


PCBWay produced the board and shipped it to me free of charge as part of their sponsoring agreement with me.

The circuit works flawlessly, unfortunately, it does not improve on the hash situation at all so it must be the ESP32 that needs to be fully isolated from the critical circuits. That's a bridge too far.

So this circuit will not be used for this project. However, I designed it such that it can be used on other projects that need this level of separation.

Dynamically increasing the ADC resolution

While working with the DL in real applications, and also during the development of the calibration and verification instructions, I became aware of a "design" constraint that I initially built in. While developing and testing the instrument, I was forced to set the internal gain of the ADS1115 ADC to the minimum (gain=0) because the maximum voltage that we apply to the ADC input required that. 

As you can see in the DL schematic, the DUT input voltage going to the ADC is divided by 24.15 through the input attenuator, With 105V as the maximum before the software cuts the load,  the attenuation drops this to a value of 4.37V. Below is the table in the ADC1115 data sheet:


A Programmable Gain Amplifier (PGA) inside the ADS1115 can be programmed with different gains to create the maximum LSB size for the input. As you can see, I could not program a gain higher than 0, so we were "blessed" with a high enough input range (6.144V), but "stuck" with a resolution of 187.5 uV. And that for the whole range from 1..105V. While investigating the data sheet again, I got an idea and searched around for confirmation. The information is scarce but it seemed possible to change the gain dynamically and when I tried that, it worked. 

In the firmware, I now read the ADC first to see what the DUT voltage is, set the appropriate gain if not already correct, and if needed, do a second ADC read with the new gain. This works great so we now have a much better resolution for lower voltages. That's the good news. Unfortunately, this does not work well with reading the current. I do however use the optimum gain setting for the temperature input.

The resolution for the DUT voltage is now:

  • Gain 0 for 99-105V  4.54mV/bit
  • Gain 1 for 49-99V    3.02mV/bit
  • Gain 2 for 24-49V    1.51mV/bit
  • Gain 4 for <24V       0.75mV/bit

The downside is that we now have to send more sets of instructions over the SPI bus to the ADS1115, instead of one, and that increases the loop-time of the firmware to about 35mS. This influences the dynamic behavior for the CP and CR modes a little because they are regulated in software, based on a calculation that involves the DUT voltage and the DUT current. A small price to pay.

Because the OLED display will flip about 3mV in the 49-99V range for every bit change of the ADC, I'm using a moving average filter with a ring buffer size of 16 to reduce the annoying flipping of the OLED display. This filter is only used for the OLED display values, and is not used for the values that are used in the main loop so that we keep the system as responsive as possible.


The CP and CR modes

As we have seen earlier, the CC and CV modes, and the derivative BT mode of the CC mode are all regulated in hardware. The system sets the parameters by the rotary encoder and furthermore just collects the voltage and current values to display them.

The CP and CR modes are different. In both modes, we use the desired setting (in Watts or Ohms) and translate that into a DUT current, because that is what we can control. This means that in the CP and CR modes, we need to use the encoder setting in either Watts or Ohms and calculate on the fly what the current needs to be, to create the right amount of load for the DUT. 

Several DIY designs I found allow you to setup the measurement, but they don't take changing DUT voltages into account. That's not good enough for me, so I do the calculations and regulation on the fly. This is the main reason why we need a very fast processor, and also a very tight controlling loop so the response to changes is as fast as possible. That's also the reason I selected the ESP32 with the RTOS system, so I could create different tasks that run on different cores, and keep the main loop as fast as possible (currently about 18ms).

In essence, the controlling loops for the CP and CR modes measure the difference (the delta) between the desired setting and the measured and calculated DUT result, and adjust the DAC on the fly to create the desired result. The DAC is incremented and decremented in steps based on the delta between the desired and real results until the delta is zero. Initially, when you turn on the load, the delta will be reduced progressively in several steps getting to a zero difference. This happens with the loop-time of about 35ms and that determines the step granularity over time. The positive side effect of this active regulation is that it compensates for temperature related changes. The resolution of the regulation is +/- 1 bit of the DAC setting or about 156uA.

From a user standpoint, the CR mode works a little different from the other modes (albeit more like the CV mode) because you would expect the decoder to start with an initial low value. A low (resistance) value will result in the maximum current and this is undesired and not very user friendly. So the solution to this is that the system measures the DUT voltage, and creates an initial resistance value that will result in a safe current of only 100mA, when this mode is selected. The user can then change the resistance from this setting onwards.


One Caveat to watch out for in the CR mode

When the regulation loop is trying to get the delta to zero, there could be some overshoot in the current when the DL is turned on with low resistor values (high currents). If you use a lab power supply at the maximum, it could trip the CV/CC regulation of the supply.


In the above screen shot, the DUT voltage was 30V, the DL was set to a resistor value of 10 Ohm, which would result in a 3A load when the DL is turned on. The overshoot in this case is approx. 400mA for a short period. There is no problem when switching the DL load off.


Temperature drift

Here are some measured temp drift numbers that Bud made:

60V -- 1.000722A @ 30C, 1.001466 @46C (0.074%, 46ppm/C)

60V -- 3.000393A @ 30C, 3.0103 @80C (0.33%, 66ppm/C)

30V -- 6.0014A @ 30C, 6.020A @ 79C (0.31%, 63ppm/C)

The above numbers are consistent with the 50ppm/C sense resistors we used. That's what we bought from LCSC. You can get 25ppm/C 2512 resistors for about $1/each from Digikey ( TLRP3A30CR080FTE) or LCSC. LCSC even has 15ppm resistors for about $12/each Y14870R08000D0R. A 15ppm/C resistor would be a big improvement -- maybe only 25ppm/C drift, which would be 0.125% across 50C. If you used the 25ppm/C resistors figure around 0.175% f, which might be worth spending the $4 on (or only $0.8 at LCSC).




Construction

Details of the construction will be described in a dedicated Blog post here: 

https://www.paulvdiyblogs.net/2024/09/building-diy-dynamic-dc-load.html




Note that I'm still tweaking the Blogs for this instrument.


Gerber Files, Firmware & BOM's

Located on my GitHub here: https://github.com/paulvee/Dynamic-DC-Load



More later...


If you like what you see, please support me by buying me some Java: https://www.buymeacoffee.com/M9ouLVXBdw

For those that did, thank you!


No comments: