Show by Label

Friday, August 26, 2022

Dynamic AC/DC Load (CC, CV, CW, CR, Batt)

This will be a description of my process to build a new Dynamic Load.

I already have one, described here (, that served me well while testing Power Supplies. This is a simple Constant Current mode load, but with a pulsed output possibility.

For the new Load, I wanted to add more modes, apart from the Constant Current, I also want to add Constant Voltage, Constant Power (wattage), Constant Resistance and a Battery Discharge option. This will mean that it will have to be a digitally controlled instrument.

There are many designs that accomplish this already, but I could only find one that implemented an AC input, next to the usual DC input. The AC capability is useful for applying a load to non-DC inputs, like an AC sine-wave coming from transformers so you can profile them, and also other waveforms like triangle or pulsed like PWM signals.

Adding an AC input goes hand-in-hand with a True RMS measurement capability which is an additional challenge for me. To top this off, I also want to use the new Raspberry Pi Pico board. It has a lot of interesting features and also has a dual core. This may be required to calculate the True RMS voltages if I decide to do that in software. Dedicated chips that can do that are pretty expensive.

I have not decided on a set of specifications yet. My initial requirements for the design phase will be if I can get up to 400VAC at say 1A. A lower voltage could be 60-80V at 3A and 30V at 5A. I don't need a larger current sink, this should do for my own use.

The unit should have a "pulsed" mode to test transients, and as I mentioned above, a battery discharge feature. I'm not interested to build a PC controlled unit, that's beyond my capabilities, but I could possibly create an output that is compatible with existing PC-controlled software applications.

The user interface will be very simple. I envision a rotary encoder for the settings and menus, with maybe only one toggle switch or push-button to turn the load to the DUT on or off. I will try to use the rotary encoder push button to enter values and select menus. No key-pad! The display will most likely be a small 128x128 OLED display, most likely in color because the price difference between color and monochrome is very small thee days.

The enclosure should be a small as possible, because the available real-estate in my lab is very mimimal.

So there you have it.

Standing on the shoulders of others

I have been collecting various designs from others and looked at the way they did things. Several stand out, like the multi-part Youtube series from John Sculley:

Then the contributions from Jay_Diddy_B on the EEVBLOG.

I also studied the tear-down and schematics of the Array 37XX Dynamic loads done by another frequent user Kerry Wong, that can be found here:

Here is another one:

As I mentioned earlier, I could only find one DIY design that features a true AC/DC capability. That project from Rainer Schuster can be found here:

(there are two versions of diagrams available, you really have to search for the latest one)

Here is a Youtube video of the instrument with an elaborate explanation of the AC mode of operation and background theory.

My Humble Beginnings.

To start with the project, I build a mimimal load circuit, with just one Opamp and one MOSFET. This allows me to study the parameters, and add more functionality as I go.

Here is the schematic diagram I'm working from:

And here are pictures of the hardware contraption:

The power connections to the MOSFET need to be as short as possible, so I mounted the current shunt, the anti-oscillation capacitor and the rectifier bridge right on the MOSFET or close to it.

The rest of the parts are not that critical. 

I used my precision DC Lab supply (1mV/mA resolution) to act as a DUT, and I set channel 1 to supply 10V at 2A. Channel 2 was used to supply the reference voltage going to the positive input of the Opamp. I used a second supply  for the +/- 12V rails for the Opamp.

My DMM was used to measure the Gate voltage (VGS) while adjusting the CH2 reference voltage.

Because I use a 0.1 Ohm current shunt, the relationship between the reference voltage, supplied by the Lab supply was 10mV in to get a 100mA load current. I used my LAB supply display to verify the supplied current. Setting the reference voltage to 0V produced a current of 2mA. That tolerance value can be adjusted in the final circuit with the Opamp nulling. Increasing the reference voltage with 10mV increments showed the current to stay in-step all the way up to 2A, which I set as the maximum for this test setup.

I then used my Function Generator to supply a DC pulse instead of the reference voltage. I selected 100Hz as the frequency, a duty cycle of 30% on and set the pulse with an offset of 10mV and a maximum voltage of 40mV. This resulted in a current fluctuating between 100mA and 500mA. I used my DSO to look at the Gate of the MOSFET to see the effect, and also the Source. I then increased the frequency to 1 KHz and all was well. With this contraption, it makes no sense to go further to see the maximum. I also increased the maximum pulse voltage to get a current switching from 100mA to 1.5A without issues.

I also profiled the VGS to IDS relationship, to see how much of a rail I need for the Opamp. It turns out that the MOSFET is off at a VGS of 3.08V and needs 4V to let a current of 2A through. Some more measurements are in the schematic. This means that I probably only need about 8V for the Opamp, and I also only need -1 or -2V for the negative supply to really turn the MOSFET off under all conditions, mostly when I pulse it. 

What the effects of the minimum rail voltages will be with non-DC loads I don't know yet, that's something I will be able to test soon, becaus I need the analog multiplier (AD633) to do that. The multiplier is needed to "marry" the DUT waveform with the Gate voltage to make the current follow the voltage waveform in step.

Selecting the final rail values depends on the rest of the design.

Initially, I used the NPN/PNP Gate driver circuit that was in the original schematic, but decided to take it out for now. It's not needed at this moment. The MOSFET I use has a Ciss of 5690pF vs 4200pF for the SPW32N50C3 in the original design that can handle 560V at 32A. The one I use was tested in our Curve Tracer project. It is a 600V 52A device where the SOA diagram shows it can still handle 1A at 400V at a Tc of 25 and Tj of 150 degrees. If I use two in parallel, I should be able to get 400V at 1A. We'll see.

I also have two IXOS IXTH 80N075L2 lineair MOSFETS ordered, they only go to 75V and I should be able to get 4A at 50V out of one. I've never used a linair MOSFET so this is a learning experience.

The part's arrived, and I wanted to add the AD633 multiplier to my bread board. I ordered the SMD version so I soldered it on a carrier and used Rainer's original schematic to wire it up. Seemed simple enough, but when I tried it, it didn't work. There was a 25mA current flowing in the negative supply, oops! 

After trying a few things I took it out of circuit and built a little test circuit just to test the AD633. No dice, I was afraid that I could have blown the part by statics, something that's very rare for me. After a while tinkering some more I decided to study the specifications some more, and then it dawned on me. The pin-out for the PDIP-8 version, that Rainer used, is very different from the SOIC-8 that I have! I don't remember to have ever encountered such a difference in pin-out between packages. 

I probably blew the part by forcing -12V into the output amplifier (pin 5), which is a real bummer, because these things are not cheap. Analog Devices calls them "modestly priced packages", but with pricing close to $20, that's not modest enough for me. 

I studied discrete multipliers to see if I could use them as an alternative. Unfortunately, I couldn't get LTspice to get a decent and reliable output out of a few different circuits, so I gave up on that idea and ordered a new AD633. This time from a supplier that has the PDIP version, so I can more easily use it on my breadboard, and use a socket on the final PCB layout. It will take a few days to get here.

Unfortunately, the chip that arrived does not work either. The output does not follow the inputs and is always at a fix level of about 5V, even with grounded inputs. Building the Fig 13 circuit in the datasheet shows no frequency doubling and only distorted waveforms. This chip came from a reputable supplier and I reported the issue to them. I also ordered a third chip from a supplier in France that will get here in 1-2 weeks. 

Update: The supplier was so kind to send me a replacement chip, hopefully this time it's functional. The other one I ordered is in the mail. This is becoming an expensive chip for me...

I got the replacement AD633 and it seems to work in my test setup. Finally! More on this later.

I got the other chip from France, ordered from Ebay today and checked it out...not working at all! This was almost to be expected, I've reported it and asked for a refund and eventually I got my money back. 

Using the good AD633JN chip, I expanded the earlier test circuit to include it.

The analog multiplier is fed with the DUT voltage at the X1 input, and the Y1 input is connected to the V-ref supply. The DUT supply is reduced 10x by a resistor divider and the X1 input is also protected by a 10V Zener. In order to get a lineair relation between the V-ref and the DUT current, I found that I needed to use a trimmer to calibrate the 1:1 relationship. Note that because of the divide by 10 operation of the AD633 multiplier, the V-ref now needs to be 10x larger, so now 100mV results in a 100mA DUT current.

Another trimmer is used to calibrate the DUT current to zero with no V-ref input. This needs to be calibrated first, and then the DUT voltage trimmer.

At this moment, I'm still using a DC lab supply for the DUT. The DC supply voltage is adjusted such that I have 10.00V at the Source of the MOSFET, compensating for the voltage drop over the bridge. This allows me to calibrate the X1 input to 1.00V resulting in a lineair V-ref to DUT current at 10V.  By using the Lab supply, I can also monitor the DUT current. 

Because of the input multiplication of the AD633, raising the DUT voltage to 20V also doubles the DUT current because W=(X1*Y1)/10. The microcontroller therefore needs to monitor the DUT voltage, and adjust the V-ref level accordingly to keep the current constant (CC). This is a major departure from the normal DC load functionality for a CC mode, because the voltage should be independ of the set current. (hence CC).

Using a sinewave as the input

I used a center-tapped 12VAC transformer as a DUT supply. My mains has 50 Hz. Let me show you what I'm seeing.

Here is the AC signal from the transformer. Note that it's not a perfect sinewave, but for a transformer, this is quite normal. I'm also introducing the Vrms voltages on the DSO. The transformer delivers 13.37Vrms according to the DSO, but my DMM's measure 12VAC. I trust them more. The DSO has a much lower precision.

After quite some time experimenting, I found that there is quite a descrepancy between what the DSO reports, compared to my trusted but old Fluke 67 TRUE RMS DMM, and my 6 1/2 digit Siglent SDM3065X, which is still within calibration. So take the Vrms figures reported by the DSO with a grain of salt. Read on for a clarification and solution why this is so.

For the next screen shot, CH1 is measuring the voltage accross the current shunt of 0.1 Ohm with a Vref setting of 500mV. With a DC signal as the DUT voltage, this resulted in a current of 500mA. Here we show 57.6Vrms over a 0.1 Ohm resistor, so this should represent 576mA rms. Keep in mind though that there is also the Vrms input voltage multiplier in play here.

The bridge rectifies both halves of the sinewave, resulting in the "flipped" negative side into a positive voltage. That's perfectly normal, but I'm showing it here in detail so it is clear for everybody.

As we see, the current closely follows the voltage, which is what we want and it shows that the AD633 is doing it's job. 

Note that the CH2 calculated Vrms value is representing the voltage at the DC side of the bridge, minus the voltage drops over the bridge diodes. This will also be the voltage we will eventuelly measure and display.

Now back to the calculated Vrms value for the voltage accross the shunt. In the DC mode, we saw that with a Vref of 500mV, and a 10VDC input, we calibrated the system to deliver a 500mA DUT current. 

With a sinewave, the DSO calculates a Vrms of 56.7mV over the 0.1 Ohm shunt so that should represent an rms current (Arms) of 567mA. This is not with a 10VDC input voltage but with an AC of  12.26Vrms. 

However, keep in mind that the AD633 does not deal with rms values! One input of the chip gets a DC signal (Vref) and the other input is getting values that are represented by the CH1 yellow waveform we see on the DSO, so peak-to-peak values of a double rectified sinewave and they get multiplied together by the chip to drive the MOSFET. 

Like the AD633, we would need to make calculations all along the current waveform to see if they are indeed correct.

I tried a few methods to calibrate the Vref input levels 1:1 to the current outputs. I did not really succeeed because the linearity is not that precise. Here is what I mean:

The Vref is stepped by 100mV steps, and the resulting current is measured by the Fluke 76 (in current mode) in-line with the transformer to the bridge. The 500mV curve in orange is when I calibrate the matching at 500mA, and in grey is when I calibrate the matching at 1A. It does not seem dramatic in these graphs, but they are when you look at the percentages.

Unlike precise and stable DC signals, I'm afraid that with AC waveforms, the instrument will never be precise. This seems to be a function of the crest factor (how pure is the sinewave) and how much is the voltage deviating with higher currents, which will influence the multiplication. Also the multiplication itself is not perfect and not 100% lineair.

Using a triangle as the input

To test another kind of waveform, a triangle, I used the DUT supply from my Curve Tracer (described in another blog post). Applying 30Vp-p and using a Vref of 500mV produced the following display:

The current waveform is nicely following the voltage, with some abberations at the null transition.

A triangle with 30Vpp and a calculated Vrms of 16.22V results in a shunt voltage value of 80mVrms or 800mArms and 162mVp-p or 1,62Ap-p. The crest factor is 1.732, so if we divide 800mArms by the crest factor, we get 461.9mA. Reasonably close but again, this is not good enough for a precision instrument.

Profiling a transformer

One of the applications I had in mind of the AC/DC load, was to profile transformers. I once took a transformer out of a printer, but it had no markings. I ended-up using power resistors to figure out where the serious voltage droop level was and used those numbers.

The transformer I used for the first measurement is a center tapped 12-0-12VAC transformer, rated at 2A. To check that, I connected one of the 12VAC windings to the dynamic load and turned-up the current until the transformer could no longer output 12VAC, and the voltage dropped off rapidly. I used one DMM to measure the transformer AC output, and looked at the DSO for more clues. 

The DSO reported 14.29Vrms for the transformer output, while the Fluke 76 showed 14.68VAC. That's close enough for the DSO.

The good news was that I could turn up the Vref voltage to 2.2V = 2.2A before the AC voltage dropped below 12V. The Fluke reported that happening with a current of 1.98A. This seems to prove the value of this instrument.

This is what the DSO shows:. 

I guess this begs the question how good we can make this particular measurement without using the DMM's, and use the Arduino and ADC's to measure and report the RMS voltages and current.

That task will be addressed next...

Preliminary conclusion

My original plan was to build one instrument that could measure CC, CV, CW, CR and have a battery discharge option, both for AC and DC inputs.

After making the above measurements and analyzing them, I came to the conclusion that this is too much to ask for. The mere fact that we need a multiplier in the circuit for AC signals, defeats the "constant" elements of all the measurement. In my world, a Constand Current (CC) means that whatever the input voltage is, the current is kept constant, in real-time. That is not really possible with this circuit, because the microcontroller contineously needs to measure the input voltage and re-calculate the current setting to keep the set current value. This would require a tight PID loop which will really task the Nano with all the other tasks. In any case, I would call this a pseudo CC. The same is true for Constant Voltage, Constant Resistance and Constant Power.

This is a significant deviation from the "traditional" method that uses the microcontroller to setup the measurement and display the results, while the dynamic load circuit itself does it's job "unattended" and in real-time.

So my conclusion is that it will be really hard to marry AC and DC input values with the same hardware. Everything will have to be under tight real-time controll by the CPU. 

So what are the options?

1. Build a simple AC/DC load

You can build a simpel instrument for AC and DC signals only that is probably limited to a pseudo real-time CC mode with limited measurement precision. As we've seen already, it can be used to profile transformers and the likes. To keep it simpel, there will be no real CC load, just a load you set regardless of the voltage. This will have limited precision, but will function as a load.

2. Build a full fledged DC load with high precision

This is a dedicated DC only instrument that can be fitted with all the required modes and that can have a very high precision. This has been done many times already by others and is less of a challenge for me.

3. Build a combined AC/DC load with CC, CV, CR, CP

If you want to have real (true) CC, CV, CR and CP modes, this will be a compromise due to the loss of precision, unless this can be fixed somehow in software. It also needs a very fast and tight control of the current while taking the DUT voltage changes into account. I'm expecting that will be beyond the capabilities of an Arduino Nano. I have experimented with PID loops before and I'm not very good at the tuning part. Overall, I'm not sure if I can do all that and so I'm not too keen on taking on that development.

Having said all that, I need to rethink my goals and for now I will continue with the development of the combined AC/DC signal input, but first try the capabilities of software RMS measurements first and see how far I can get.

This is a good time to start with the voltage and current monitoring by the Nano.

I added the ADC components to the schematic.

The ADS1115 is on a breakout board and needs it's own 5V voltage rail so I used a simple 78L05. I did not add the components to the schematic that are on the breakout board for simplicity.

I'm wiring the ADC inputs such that I can measure the current shunt in a differential mode and the DUT voltage in a single-ended mode. 

I'm using the same Nano I was using to play with the OLED screen (see below), but I started a new sketch to read the ADC and to display the voltage and current on the display.

I got the DUT supply voltage measuring up and running quickly, by just using a 4V DC for the DUT because I did not yet add the input divider. 

Unfortunately, for some strange reason, I could not get the voltage measured accross the shunt.  However, my DMM on the same pins was reading OK, and when I moved the ADC input to the same connection for the DUT voltage, it worked fine.

While fooling around trying to get the differential mode working, I must have done something stupid, because the ADC1115 chip started to smoke and blew a little hole to let off steam. Bummer, I almost never ever destroy components, and this is already the second one on this project. Luckily these breakout boards are inexpensive, and available locally. 

I've now added serial resistors to protect the ADS inputs while I'm fiddling with it, and also added the divide by 10 voltage divider with the over-voltage protection Zener diode. Initially, in the testing phase, I want to get close to a decent factor of 10, so I used a 90K/10K setup with selected resistors. Later I can change that and calibrate the precision in software. 

I found two libraries for the ADC I tried, but settled on the Adafruit version. 

I also figured out why I blew the ADS1115 chip. The prototype that I put together had the -12V and the GND rails on the top side of the breadboard, and when I wanted to ground one of the ADC inputs, I must have touched the -12V rail, blowing the input protection diodes and then taking the rest of the chip with it.

Overall, the prototype was getting unwieldy by now and with so many connections I was having problems. Now that most of the circuits were sorted out, I soldered everything on a proto-board, using sockets for the chips.

I also put together a small and rough test sketch together for the Nano such that I can now display the DUT voltage and the DUT current on the OLED display. Right now I only display DC voltages and currents.

This is as far as I got today, I'm pretty happy with the results.

Now that I'm satisfied with this setup and sketch, I'll turn my attention to converting the measurements to RMS. I expect that will be a challenge (it was!). I've got a pretty good idea now how to convert a voltage to RMS (not!), but need to pick a method out of the several that I found, and then see if I can implement it on the Nano.

Unfortunately, I ran into an issue that stopped me from going forward. Have a look below at the topic called: "Calculating the RMS value of a waveform".

So with the RMS calculation topic more or less solved and underderstood, I can now start to use it with the prototype hardware. First of all, I needed to eliminate the AD1115 out of the circuit and preplace it with the on-board Nano ADC's.

After a lot of struggles, see the RMS and ADC topics below, the prototype hardware is now working with the on-board ADC's from the Nano, and are producing results for the DUT voltages and the voltage across the shunt. 

What I initially did not factor in yet, was the drop and change of the AC voltage before and after the bridge. This drop is not just caused by the bridge diode drops alone. As an example, using my 12VAC transformer, my DMM shows 14.48Vrms before the bridge, and 6.26Vrms after it. My DSO agrees with both values. BTW, in the DC mode, the DMM shows 11.70V after the bridge.

I need to measure the DUT voltage after the bridge, but show the value from before the bridge. Rainer used an Opamp to create this factor (using a 0.15 divider and then 3.26 gain) and software to further tweak it. Keep in mind that he also used a different RMS calculation without determining the "AC level". I used my DMM to calculate the conversion factor and added that to the script for now. It's OK but the compensation is not very lineair with higher input voltages.

What I did find however, is that the measurements fluctuate and are certainly not useful at all with 3 decimal digits. Two are more than enough and give me room to display the rms suffix. I first need to add Opamp buffers for the two ADC inputs to reduce the noise and take care of the Nano capacity switching at the front of the Mux.

Obviously, with the RMS setup I have now, I can't measure DC levels anymore. 

It's also becoming clear to me that I don't need a very precise DAC anymore. I think I can manage by using the Nano's PWM feature and create a poor-mans DAC. I'll try that soon.

I'm using a switch (a jumper for now) to change the mode in the script from measuring AC or DC and displaying the different results on the OLED display, and that works.

I also added buffers/amplifiers for the ADC inputs (they need to have a low impedance), and used a seperate 5V regulator to function as the 5V reference for the Arduino ADC. When I tried the internal band gap reference, it messed-up the RMS conversion. I've asked the author of the library what I'm doing wrong, or for a clarification if the library cannot handle it. I eventually got an answer, but is of no help for this application.

Here is the latest schematic of the prototype I now have in front of me:

I'm still not happy about the fluctuations in the RMS readings, but leave that for later. The AC signal comes from the transformer, which by definition is not that stable.

In contrast, here is the DC mode, but this time coming from a very good Lab supply:

I have added a digital low-pass filter, and made some improvements to the sketch related to the display of the values. I also added the code to make the AC/DC modes work better. Then I made a change to limit the measured values to only 2 decimal digits. More is useless due to the lack of precision of this setup. One of the other major changes is to limit the display update only when there is a new value. It reduces the flickering of the OLED display due to the updates.

I'm pretty happy with the results right now. Next I'm going to improve the current shunt Opamp hardware by making it more differential while still using the x10 gain so 1mV will be 1mA.

I have now also added the PWM code (see poor man's DAC below) and also the PWM filter hardware so I don't need my Lab supply anymore to supply the V-Ref voltages. It works really wel and is very precise, especially in the DC mode. 

I also want to add a dedicated voltage regulator for the Arduino so it is no more relying on the USB supply from my laptop. There is quite a large voltage drop by the time it gets to the Nano. It's in the schematic, but not yet realized.

After I added the rotary switch and the poor man's DAC to the hardware and software, I found that the digital filter slowed things too much, the response was too sluggish, so I took them out.

Latest schematics:

I spend the time today to eliminate the breadboard and moved everything to the protoboard. Looks a lot cleaner and will work a little bit more reliable and better.

The rotary encoder switch I use does not indicate the A and B pins, so of course I swapped them and  the rotation went the other way around. Easy to fix though. I first tried a 78L08 TO92 package voltage regulator, but it was getting too hot, so I replaced it with a TO220 version.

The sliding switch on the left edge is the AC/DC mode switch.

Now I don't need to connect the Nano to my PC to make it run.

A heads-up for a potential risk

Let me add a word of caution at this stage of the design. 

When you are going to connect the Dynamic Load circuitry to a real DUT, especially one with higher voltages, and also connect a USB cable between the Arduino Nano and your PC, you run a big risk! 

The GND of the Dynamic Load circuit will be connected to the DUT GND or one side of the AC connections, and through the USB cable, also to your PC. Depending on what your DUT is, and what the ground potential is, it is entirely possible to blow-up your PC or as a minimum the USB interface if it's earth ground connected.

I strongly recommend you to use an optically isolated USB connector interface in-between the Arduino Nano and your PC.

Don't risk it, use an optically isolated adapter, they are a lot les expensive than a new PC. Here is one from Adafruit, it sells for $35 but you can get less expensive ones as well. Amazon sells one for $15. I got myself an even cheaper one from Aliexpress because the USB transfer speed is less important for this application.

Understanding the reported values

I spend some time over the last couple of days to analyze the behavior of the instrument in the AC and DC modes, and tried to get reasonably close readings on the OLED display for both modes, compared to my other intruments.

It's not easy, and not very straightforward! Mostly because both modes have their own measurements, and calibrating the trimmers in one mode will upset the other. I have now added a number of calibration or fudge-factor values in the sketch to get as close as possible, and after all, I'm reasonably happy about it.

Let me try to explain just one of the challenges I'm having. I want to display the actual DUT voltage on the OLED display. This is the voltage before the bridge. Not only do I need to compensate for the diode junction voltage drop of the bridge, which by itself is not very lineair because it changes with the current. For AC voltages, there is also a difference in the RMS value that is calculated on the waveform after the bridge due to the fact that it's a full-wave rectified sinewave. For my transformer, the RMS value before the bridge is 14.5V and after the bridge it is 6.32V. I cannot explain the 2.3 factor, it is still a strange value to me. Unfortunately, this factor is also not very linerair. When I double the AC voltage, I measure a 29V input by the DMM and after the bridge 12.8V with the DMM. That's consistent. However, the resulting RMS calculation is only showing 25V. I needed a factor of 2.65 to get it right with that input value but applying half the voltage again, it now shows 17V instead of 14.6. Not good enough. After some playing around, I created a dynamic compensation factor that takes the DUT input voltage as part of the multiplier factor. I'm now getting pretty close with the two input values I'm testing with, but this is not good enough going forward when I will test with much higher voltages.

For DC voltages, the only compensation we need to factor in are the bridge diode junction losses. With no current, the dual junction voltage drop is 1.16V, however, with 500mA, the drop is already 1.48V. I'm settling for  a compensation of a middle-of-the road 1.3V for now and not worry about a dynamic compensation that takes the current into account. This instrument is not that precise to start with.
The consequence is that due to the AC633 multiplication, the changing voltage drop over the bridge is resulting in a different input voltage to the multiplier, and this in turn changes the actual amount of current to deviate from the current you are setting. It's acceptable for the "transformer profiling" application, but not what you would like to have or expect from an instrument.

With all these correction and fudge-factors in place, I'm getting reasonably good results for the DUT voltages in AC and DC, and also for the corresponding shunt voltages in AC and DC and hence the DUT load current. However, with all these magic fudge-factors I find this is now getting into a terribly weak solution.

There are three possible remedies for the AC voltage measurement.
One solution for the problem could be to move the measurement to before the bridge, not after, but that opens a can of worms with the circuit ground. I think that you would need to use an external ADC (here we go again) and an optical isolator somewhere in that circuit to feed the results to the Nano. That's a complicated remedy. 

The second is to convert the bridge rectified signal to a full DC level by adding a capacitor parallel to the D1 5.1V Zener diode and simply read the ADC signal without going through the RMS conversion. I tried that but found out that it also has a non-linearity as with the RMS measurement method. I'll keep the RMS method for now.

The third one is to drop the AC voltage measurement all together and only provide a current measurement. The AC voltage measurement in that case needs to be done by a separate DMM. That's a KISS solution and is accepting defeat. I'm not there yet.

I think it's time to start to play with the hardware True-RMS to DC convertors, like the AD736 and the delta Sigma LTC1966, and see how well they are doing. I'm getting a few of the LTC parts and I whipped-up a little PCB test board that's on order. That little project will have to wait until the end of October, because of my vacation trip. I've started a seperate topic below.

Stay tuned, I'll be back with more...


All code and other information about the project can be found here:

In the following sections, I will select certain sub-projects and describe them. Eventually they could or will hopefully transform and merge into the final project.

The Micro Controller

Rainer used an 8-bit MEGA32-P as the controller. It has a 10-bit ADC function that Rainer used to measure the DUT voltage, and he used a 12-bit MCP4921 DAC to generate the voltages to drive the MOSFET. 

The 16-bit dual core Pico I plan to use is the "H" model and has three 12-bit ADC's that can be used. It does not have a DAC function. You could use two PWM outputs combined to serve as a pretty good 16-bit DAC, (the GPSDO project uses that to drive the OCXO - described in a post) but I'm going to use the same SPI based MCP4921 DAC.

Rainer used seven 7-segment displays driven by a MAX7219 controller. The display I'm initially planning to use is an RGB 128x128 OLED display based on the SSD1351. It has an SPI interface.

Unfortunately for me, Rainer used Basic as the programming language for the MEGA. I am familiar with Basic as a language, but have never used it for embedded controllers other than for a few small PICAXE projects. I have more experience with Arduino "C++" and Python for the RPi. I will initially plan to use MicroPython for the Pico, which is also new for me, so this is going to be a bit of a challenge.

First of all, I will need to create my own "programming environment" for the Pico, and get familiar with that, so this will take some time.

Setting up the Arduino IDE for the Pico was fairly easy, and I got the Blinking LED running without too many issues. However, after trying for a few hours, I could not get the SSD1531 OLED display working without compiling errors. In any case, afyter a lot more searching, it seems that the SSD1531 library is not yet supported by the Pico environment using the Arduino IDE.

The next step was to install the Thonny IDE and start to use that environment. I saw that Adafruit is supposed to have the SSD1351 supported with MicroPython/CircuitPython. Installing Thonny was easy, and again I got the Blinking LED program running quickly. Unfortunately, I was having difficulties installing the libraries for the SSD1351. I used the Adafruit set of libraries, but in their attempt to be all for everybody, they make it way too complicated. I might be wrong, but I came to the conclusion that their SSD1351 support does not run on the Pico.

After many hours trying and searching the internet, I found very few displays supported by the Pico, and not the one I have or one I want to use. I also learned that the Pico ADC has some issues. For this project, I will no longer use the Pico and CircuitPython and will switch to an Arduino Nano and C++. If I find that I'm running out of room and need more power, I can use the same code on a faster 16-bit ESP32. The Nano only has a 10-bit ADC, which effectively is really an 8-bit ADC and also the 12-bit ADC on the ESP32 has some issues so I'm going to use the dual 12-bit ADS1115.

Decoding a Rotary Encoder

I'm using a rotary encoder for the settings and navigation through the menu's.
There are tons of possible solutions described on the internet, I spend some time figuring a couple of them out and tried to implement a few solutions while at the same time describing how they work in some detail.

Here is my post on the Blog with more information:

The OLED display

Several years ago, I already started on a sketch to use the OLED display to see how I could use it. I wanted to experiment with the code to select and change values, by stepping through the digits and changing them. I also wanted to get a rough idea on how to use the display and the encoder as the user interface.

A picture of the resulting code (an earlier version) on the display gives you an idea what of I have in mind for the user interface for this project:

Short clicking the rotary encoder switch button will cycle through the digits one by one left to right and then right to left on the Amp line. Rotating the encoder will cycle through the values of a digit. At this moment, only 0-9, it does not yet overflow to the next or previous digit. Stepping through the digits will change the color to red of the digit you can change. The sketch recognizes short, double, long and very long button presses, which is how I plan to switch to and through the menu system. 

At this moment, a double click will toggle between the input/edit mode and the display mode. In that case the selected values will be send to the DAC and the display will start to show the actually measured values. You can still cycle through the digits and adjust the values so you can change the settings on the fly, at least that is what I envision. How well this works will need to be tested with the real hardware supplying values.

I anticipate to always measure the DUT voltage, but the second line will show a measurement of whatever value the system is in like current in the CC and CV modes, Wattage in the CW mode, Ohms in the CR mode and the capacity/time in the Battery discharge mode.

Curently, the sketch uses a two interupt software method to decode the rotary switch that does not need any capacitors or resistors to debounce. For the moment that works really well, but I may need an interrupt for something else in which case I can no longer use this method. 

The four single pixel dots in the four corners of the OLED display are there to show me the boundaries of the active pixels during testing and positioning of the text. (it's hard to see where the active pixels are)

Calculating the RMS value of a waveform

I spent several days on and off writing a script to calculate the RMS equivalent voltage of a sinewave signal. The process is rather straightforward. You need to sample the waveform enough times to get a full cycle covered with enough samples, or better yet, get two cycles covered. To simplify the rather extensive theoretical formula, the sampling needs to happen at the same time interval. That's easy with a Nano, using one of the timers to create an interrupt during which you take an ADC measurment. When you have enough samples, you then apply the mathematical stuff, en presto, you have an RMS value of the waveform. Sounds simple...

It was very gratifying to see that the Vrms calculation of my DSO agreed with that of my sketch. Unfortunately, the two true RMS DMM's that I used to verify the result, did not agree at all. It took me several days and quite some time to study this issue and search for an explanation, to no avail. I could not figure it out. I was obviously missing something, but what?

I even used Excel to recreate the waveform from the ADC samples to see how well the script worked.

Everything seemed to be working as intended.

Frustrated, I posted a question on the Arduino forum, and asked for help. The answers put me on the right track to zoom into the root cause of the issue. And I found it. Have a look here:

A good theory can be found here:

So I now modified my sketch to take the offset issue (make the input signal AC coupled) into effect, by using a library that I found earlier but could not get to agree with my measurements. They were wrong, of course, so when I tried the library with my new found knowledge, it worked flawlessly. I then modified the example script to use interrupts. I put this script and the DSO screenshots for various inputs on the Github.

Here is an example of a double rectified sinewave, which will be the input from the bridge.

The screenshot shows the signal generated by my AWG. Its a 2Vpp signal of 50Hz, which is supposedly acting like the result of the bridge being fed with a 50Hz mains sinewave, becoming 100Hz. 

Note that I have to use AC coupling for this input channel, to make the DSO RMS calculations (shown here as Per.Vrms) the same way a DMM does, so they correspond. This allowed me to finally compare the results with the script.

The blue trace shows the sampling of the waveform, there are 40 of them, to really cover the waveform well, and eliminate drift of the calculations.

The Vrms output of the script is virtually the same as the Per.Vrms calculation of the DSO, and is also is very close to my 6.5 digit DMM. I verified the operation of the script with a sinewave, triangle, block (a simple and good test) and the above signal, and the results are very good and accurate.

One caveat of the obtaining the "AC" value by the offset calculation is that it takes about 6 cycles from the start to get a good RMS result.

Onother caveat is that the RMS calculation method for the AC waveform also renders the calculation of DC inputs useless, they will always be zero volt. I'll save that challenge for later.

Using the ADC1115 with the RMS conversion

Unfortunately, I found more limitations for my prototype setup.

After modifying the scipt I used above for the RMS conversions and use the ADC1115 instead of the on-board ADC, I found that I can't read the ADC1115 within an interupt service routine. This is because the I2C interface, that is using the Wire library, hangs the Nano in the ISR. The Wire interface itself uses interrupts. I found a different Wire library that does not use interrupts, so potentially I could use that, and also use direct register programming to communicate with the ADS1115, and not use a library, but either way, the serial interface will most likely slow it down too much.

The RMS conversion formula relies on the precise timing between the samples, so I want to continue to use the Timer. The only way use the timer interrupts is then to only set a flag in the ISR, and act upon that in the main loop, which is what I tried. Unfortunately, while modifying the RMS sketch to use the ADS1115 in that fashion, I found to my dismay that the fastest I can read and process the AD1115 sampling in the main loop is about 20ms.

That realization started a few hours of trying and investigating this issue. Here are two screenshots of my findings. The first one was made with a script that is only the toggling an output pin within a for-loop, nothing else. That needs about 7us and is normally the fastest the Nano can run. The next screenshot is with only the ADC read cycle added, and is shown in relation to a 50Hz signal. This time it needs about 20ms.

That's nowhere near fast enough to realiably sample a 50Hz input signal. As a minimum, I need 1ms samples. Bummer! I tried two other ADC1115 libraries, the fastest one I found uses the TinyWire library and that produced 8ms cycles. I did not know about that limitation, this is a rude awakening...

This seems to indicate that I can't use I2C-based chips, due to the slow serial interface, for the  sampling of analog signals with an Arduino Nano. I don't know if SPI is any better, I'm assuming it will be the same so I'm not even going to try. 

I could change the processor and see if I can get higher speeds, which must be possible, but for the sake of KISS I'm sticking with the Nano for now.

Using the Nano ADC with the RMS conversion

The only method I know of that can handle the ADC sampling fast enough is to use the on-board ADC from the Nano itself. That only has a 10-bit resolution, but from what I've seen so far with the RMS conversion and precision (or lack thereof), that's actually not a limitation at all. So, I can go back to the RMS test program and start use that with the prototype hardware.

I modified the script again and I'm back in business...

This is with 40 samples, as you can see, it covers two 50 Hz cycles and that also reduces the drift caused by the rms calculations. With drift I mean that the resulting RMS value slowly drifts up and down in a sine shape around the center value. 

I'm using a square wave here because the RMS calculation is simple to verify, it will be exactly 50% of the Vp of the input signal.

The next challenge is to process two ADC inputs and convert them both to RMS. The current library cannot handle that.

Designing a poor man's DAC

Because we really don't need the precision a real DAC can deliver, we can get by with a poor man's version, using a PWM signal and a digital filter.

To make the filter more effective, we need to increase the base frequency from the Nano that is normally 488Hz. When you program the registers, you can increase the frequency to 3.906Hz.

This makes the filter values smaller and the resulting DC voltage cleaner. The filter can be seen in the latest schematic diagram. Note that normally you would use a buffer to avoid loading the filter, but because the filter goes straight to the high impedance AD633 Y1-input, it is not needed.

I'm using the rotary switch to drive the PWM output, and limited that to 255 settings. With a 5V maximum of the PWM output, this translates to 20mA per step in the DC mode. In the AC mode, we need to adjust the value to RMS, and I did that by dividing the 20 mA steps by 1.4141 resulting in 17mA-rms per step.

I'm displaying this value on the OLED display to you can see what current level you are setting, and let the display also show the actual results.

Automatic AC/DC mode switch

During a search process for different RMS calculations, to see if there are better ones, I found a smart software solution to determine if the DUT voltage is AC or DC by using the analog comparitor (AIN0 and AIN1) available on D6 and D7.  I am already using these pins, but I might be able to relocate inputs and make them available again. I will look at that in more detail later. Saves a switch on the front panel.

Hardware True RMS to DC solution

There are two devices that are used a lot, the ADC736 and the LTC1966. The latter is more modern and less expensive. It uses the delta Sigma conversion method.

This is from Digikey: Explanation of True RMS to DC convertors

I want to try the LTC part and ordered three. I also created a little test board that will allow me to play around with it. Using a breadboard is a recipe for disaster because the inputs are low voltage and sensitive. I already lost too many chips for this project by mistakes using breadboards.

Here is the schematic that I put together. There are PCB boards available on the internet, but they are pricey and not as flexible.

It allows me to configure and try all modes.

More info will follow...


  1. Hi Paul. I am also investigating this topic and has found the following website. This guy also has an extensive video series about his project. I think he has got a very usable project. Wesite:

    1. Yes I know, this is the John Scully I referenced in my blog at the top. I'm a big fan, and actually build a few of his designs. Unfortunately, in my opinion and that of others, he kind of botched the design with the many kludges to get rid of offsets.

  2. Ok ... was not aware of it. Will appreciate if you will keep me in the loop with your efforts. I need a unit that can test the output off a Electric scooter's charger with the following specs: O/p = 67.2V and charging current is 2-3 Amps. Here is another one ...