Consuming Power - DC Load Part 2

A DC Electronic Load

Peter Stewart

Issue 71, June 2023

This article includes additional downloadable resources.
Please log in to access.

Log in

Provides Constant Current Load, Constant Voltage Load, Constant Power Load, can determine Battery Capacity and also determine the MPPT Voltage of Solar panels. It also has WiFi capability which enables Battery capacity and Solar Panel data to be sent via MQTT to a Home Automation System for plotting and analysis.

Last month in Issue 70, I introduced you to the design, and the main components needed for the DC Load's operation.

This month, I describe how to assemble, code and operate the comleted project.

The Build:

Figure 3
Figure 4A
Figure 4B
Figure 5
Parts Required:Jaycar
1 x WeMos/Lolin D1 MiniXC3802
1 x LCD2004 LCD Dot Matrix Display ModuleQP5522
1 x I2C Port Expander Module for LCDXC3706
1 x 4x4 Matrix KeypadPhipps Electronics PHI1001230
1 x PCF8574 I2C GPIO Expander Breakout-
1 x 2-Channel Voltage Level Shifter-
1 x MCP4725 DAC Module-
1 x BH1750 Light Sensor Module-
1 x INA219 Current Sensor Module-
1 x IRF540N N-MOSFETZT2466
1 x 2N7000 N-MOSFETZT2400
1 x MCP6002 Operational Amplifier-
1 x AMS1117 5 Volt Regulator-
1 x SOT223 Adapter (For AMS1117)-
1 x LM340-5 Voltage Regulator (Alternative to AMS1117)-
1 x LM7805 Voltage Regulator (Alternative to AMS1117)ZV1505
1 x 1N4004 Diode*ZR1004
1 x UF5408 Diode*-
1 x 5Volt Relay-
1 x DHT11 (DHT22)XC4520
1 x 0.1Ω 1 Watt 1% Resistor*-
1 x 100Ω 0.25 Watt Resistor*RR0548
1 x 1kΩ 0.25 Watt Resistor*RR0572
1 x 2kΩ 0.25 Watt 1% Resistor*RR0579
1 x 10kΩ 0.25 Watt Resistor*RR0596
1 x 18kΩ0.25 Watt 1% Resistor*RR0602
1 x 560kΩ 0.25 Watt 1% Resistor*RR0638
1 x 1nF Ceramic Capacitor*RC5336
2 x 100nF Ceramic Capacitor*RC5490
2 x 10µF Tantalum Capacitor*RZ6648
1 x 9Volt Plug PackMP3484
1 x 5V Fan 40mm-
1 x HeatsinkHH8522
2 x DC Chassis Connector 2.1 x 5.5 mmPS0522
1 x Push Button SwitchSP0718
1 x VeroboardHP9542
1 x 3A Thermal Circuit BreakerSF2293
2 x 18650 BatteriesVarious
1 x 18650 Battery HolderPH9207
1 x Instrument CaseHB5910
1 x Red Binding PostPT0453
1 x Black Binding PostPT0454
1 x 8-Pin DIL Socket (for MCP6002)PI6500
4 x 2-Pin Male Header*HM3412
2 x 3-Pin Male Header*HM3413
1 x 4-Pin Male Header*HM3414
2/3/4/8-Pin Male Headers (Alternative)*HM3212
3 x 2-Pin Female Headers*HM3402
3 x 3-Pin Female Headers*HM3403
2 x 4-pin Female Headers*HM3404
1 x 6-Pin Female Header*-

The complete Schematic for the DC Electronic Load is shown in Figure 3. You will see all the components I discussed in the previous section, plus a few others. You will notice that I use a relay to power the fan, with the relay interfaced to the WeMos D1 Mini via a N-MOSFET (2N7000). The reason for using the Relay was that I had lots of them. Also as the fan operates from 5V, I wanted next to no voltage drop to the fan. If you don’t have a relay, you could replace it with a P-MOSFET as I have used in a couple of my projects published in DIYODE Magazine (for example see Issue 53 or Issue 64).

I also use a 5V regulator (AMS1117-5.0) to provide power to all modules including the D1 Mini. I have connected the output of the AMS1117 to the 5V pin on the D1 Mini. The D1 Mini has an on board 3.3V regulator to power the ESP8266 processor on the D1 Mini. Now, when programming the D1 Mini via the USB port, the D1 Mini can use the power provided via the USB connection or the 5V provided at the 5V pin. On the D1 Mini, there is a diode connected to the USB power input, which means you can have both the USB and the 5V from the AMS1117 connected at the same time without any issues. Note, for those who don’t have an AMS1117, a LM340-5 or LM7805 could be used. The Veroboard layout (Figure 4A) would have to be changed.

Note, I mentioned that there is a 3.3V regulator on board the D1 Mini for the ESP8266 processor. This means all the I/O operates at 3.3V. This could be an issue for all the I2C modules connected, which operate at 5V. Therefore, as can be seen in Figure 3, I have added a Level Converter. I have used the “Adafruit QT 3V to 5V Level Booster Breakout” as supplied by Pakronics. The advantage of the “Adafruit QT 3V to 5V Level Booster Breakout” is that not only can you solder it to a board (Veroboard in my case), but it also comes with two connectors allowing you to daisy chain connect via cables to other I2C modules operating on one side at 5V and on the other side I2C modules operating at 3.3V.

The last thing you may have noticed from Figure 3, is how the DC Electronic Load receives its power. Initially, I wanted to use Battery power as I wanted the DC Electronic Load to be portable, especially when testing Solar Panels. As I expected the DC Electronic Load to be fairly power hungry, especially when operating the fan, I decided on two Li-Ion Batteries. If you use decent Li-Ion Batteries, you may get a couple of hours of operation. However, then you have to either replace the Batteries or recharge them. I chose to add a DC connector socket to allow connection of a Battery Charger. You can still use the DC Electronic Load with the Battery Charger connected, but the whole system is not really portable. As a side project, I have designed a Power Bank Spoofer that allows a QC3.0 compatible Power Bank to become a Battery Charger at any voltage from 5V to 12V. I use a 20000mAh Power Bank with my DC Electronic Load. This provides several hours of operation for the DC Electronic Load.

If there is any interest in my Power Bank Spoofer, contact DIYODE Magazine and I will provide details in a future article. Most of the time, though, you will use the DC Electronic Load in your Lab (for me my Study), where 240VAC is available. So I have included another DC Socket for a 9 Volt Plug Pack. Note, I am using the common 3-pin DC Sockets. These sockets have three pins, one being for the positive connection and the other two connected together while no DC plug is connected. Once a DC Plug is inserted into the socket, the connection between these pins is broken and only one pin is connected to the negative of the DC Plug. I use this switching to isolate the Battery when using the Plugpack. You can still use the Charger Socket to charge the Battery though.

The Parts List for the DC Electronic Load can be found opposite. I have used Veroboard to mount many of the components. There is the Main Board containing the D1 Mini, the DAC, the Operational Amplifiers, the 5V Regulator and interfaces to other I2C modules and then there is also the separate MOSFET Board. The Veroboard Layouts for the Main Board and MOSFET Board are shown in Figures 4A and 5 respectively.

Note: If not using the AMS1117 Voltage Regulator and using either an LM340-5 or an LM7805, see Figure 4B.

As usual when using Veroboard, you cut the Veroboard to size. In this case the Main Board is 108mm x 64mm (or 42 holes x 24 holes). The MOSFET Board is 40mm x 34mm (or 15 holes by 13 holes). Make sure you get the orientation correct so that the tracks are running in the direction shown in Figures 4A/B and 5. Cut the tracks where indicated by the ‘X’ or where there are gaps in the tracks (for example, where the mounting holes are drilled).

Main Board

Then, for the Main Veroboard, solder all the wires on. I have used white hook up wire, but you can use whatever colour you desire. (Note, I use PTFE hook up wire as the insulation does not melt easily when soldering). Where the wires are short, ie they connect adjacent tracks, I use bare solid wire as it is easier. Then solder the resistors, capacitors, diode and 2N7000 N-MOSFET. Solder in the 8-Pin DIL socket for the MCP6002 IC. Use the type specified in the parts list. You can use the sockets with the round pins, but they are a lot more difficult to remove components from. Or if you feel really brave, do not use a socket at all and just solder the IC in directly. Then solder in all the header pins, Voltage Regulator and Relay. Note with the 3-Pin Header for the DHT11, I used a 3-Pin header broken from the 40-Pin Breakable Male Header (Jaycar HM3212 or Altronics P5430).

This is because it is close to a mounting hole and the other header type (Jaycar HM3413 or Altronics P5493) would interfere with the mounting screw. Note you could use the breakable headers everywhere as they are cheaper. However, the other headers give a tighter fit when the connector is inserted. (see top and back photos)


For the MOSFET Board, again solder the wires, then components and then the Headers. Note here, I have used only the breakable type headers. This is due to the tight spacing. You may even have to lightly file the 3-Pin header between the two 4-Pin headers. The 4-Pin headers are made up of two 2-Pin headers. On the bottom of the Veroboard, the pins on each 4-Pin header are all connected. This is because I will use four wires to connect to the INA219 RS- connection and the negative front panel Terminal. This is to reduce resistance as much as possible, and thus reduce

any voltage drops. I do perform a calibration on this and incorporate this into the program to reduce errors on voltage measurements. I also solder on the short cable for the DHT11 Temperature Sensor, which is glued to the heatsink. Note the Sensor is glued in such a way to allow enough clearance to put a socket spanner on to the nut securing the MOSFET to the heatsink. (See the above series of photos and the photos in the “DESIGN” section).

Before soldering the MOSFET/Heatsink/Temperature Sensor to the veroboard, you will have to slightly enlarge holes in the veroboard for the Heatsink mounting pins. Once you mount the heatsink with the N-MOSFET and DHT11 Temperature Sensor onto the veroboard, only solder the N-MOSFET. This makes it easier to remove if you have to replace the N-MOSFET, which I had to. It turned out that the N-MOSFET I bought on ebay, was not a full specification device. Best to buy from reliable suppliers like Jaycar and Altronics.


Next, I prepared the Keypad. The one I have used is a 4x4 Matrix Membrane keypad.

As seen in the “DESIGN” section, the keypad is labelled with numbers, letters, a ‘#’ and a ‘*’. This is not very helpful when trying to remember which button to push for which function. I did try sticking Dymo labels on each key, however, this was not great as over time the Dymo labels started to peel off. So, I decided I should paint the keys and use letter transfers. The paint I used was a white acrylic craft paint which came in a pen. You can buy them from craft shops and suppliers like Amazon. It did take about three coats of paint to stop the original colours bleeding through.

I then bought some 5mm adhesive letters, which come on a sheet, also from craft shops, and applied them to the keypad. I’m afraid when it comes to arts and crafts, I am a novice. You need a bit of patience and steady hands, both of which I lack.

Next, to make sure the letters do not eventually rub off, I applied a bit of craft varnish, available from craft shops and also Bunnings. The keypad had to be trimmed a little as it is a bit tall for the case I chose.

I cut off the top and bottom close to the white lines. This does not damage the keypad and it will continue to work fine.

Case Installation

The case I have used can easily fit all the components. You could use a smaller case, if you used a smaller keypad. As previously mentioned, even with this large case, I had to trim the keypad a little. The case also comes with some ventilation slots which helps with cooling and fan operation. The internal layout is not too critical. I did play around with the internal layout and also the front and rear panels. Once I settled on a layout for the front and rear panels, I made templates, which I printed and taped to the plastic front and rear panels.

This helped with cutting the holes in both panels. (The template is included in the Project Resources).

Above are the front and rear panels.

The cabling from the Main Board to the MOSFET Board is not critical as it is all low current and low frequency. Consideration has to be given to the connection of the MOSFET Board to the negative connection (RS-) on the INA219 Current Sensor Module and from the MOSFET Board to the negative terminal (Black) on the front panel to which your test devices are connected. These connections can carry several Amps, so ideally, heavy gauge wire should be used. However, I found the heavier gauge wire to have poor flexibility and would not fit into the current sensing screw terminals on the INA219 Module.

I used four hook-up wires in parallel. This worked quite well and resulted in fairly low resistance cables. (This is why there are four pin connectors on the MOSFET Board). I used the same technique for the cables between the positive terminal (Red) on the front panel to the thermal circuit breaker and also, from the thermal circuit breaker to the positive input of the INA219 (RS+). The below photograph demonstrates this cabling (before I tidied it up with cable ties!). This is the first time I have mentioned the Thermal Circuit Breaker. It is shown in Figure 3 and located electrically between the Front Panel Positive Terminal and the RS+ input to the INA219. Physically, it is located on the Front Panel above the positive terminal. It gives extra protection against over current loads.

Also from the below photograph, you can see the locations of the Main Board, the MOSFET Board, the INA219 Current Module and the PCF8574 Keypad Adapter Module.

The Main Module and the MOSFET Module are mounted on 6mm M3 nylon spacers. With the Main Board, you will have to file down or remove a case mounting pillar, as it is too high and will not let the Main Board mount properly. With the INA219 Current Module, I used a single screw (M2.5) to secure it to a case mounting pillar.

Take note on how I mounted the PCF8574 Keypad Adapter Module.

I first soldered an 8-Pin male header to the PCF8574 Module. The cable from the Keypad then connected to the underside of the PCF8574 Module. I then used double sided Outdoor Mounting tape (which is fairly thick) between the Keypad connector and PCF8574 to secure the Keypad connector and PCF8574 to the inside of the Front Panel.

I then used a STEMMA Cable (see photo) to connect the PCF8574 Module to the Main Board. I used the same cable to connect the INA219 Current Module to the Main Board. With respect to the BH1750 Light Sensor Module, I connected it also with a STEMMA Cable, but with JST SH Connectors on both ends. This allowed me to use the daisy chain connection on the PCF8574 Module to enable the BH1750 to be accessed via the I2C Bus. With respect to the connection of the LCD2004 Display Module, I made this cable using 4-Pin Female headers on each end soldering wires in between. (See the Cables Diagram in the Project Resources). The LCD2004 Display Module is mounted to the front panel using M3 screws with 6mm M3 nylon spacers.

You may notice the two 18650 Batteries in a Battery Holder. The Battery Holder is secured to the Case using countersunk M3 screws. There are two holes in the bottom of the Battery Holder to facilitate this. The Battery Holder flying leads have a 2-Pin Female header soldered to allow termination on the Main Board. The same applies to the Fan cable.

Lastly, the cables from the Back Panel are made (as per the Cables Diagram) and connected to the Main Board. As previously mentioned, the internal cabling looked a bit messy. So, with a few cable ties, I made the internal wiring look a bit neater.

I have also labelled the connectors and switch on the Back Panel. I resorted to using Dymo Labels. I don’t think I will be putting my fingers too often in this area, so the Dymo Labels should be safe.


As already mentioned, there are several modes of operation for the DC Electronic Load. I will now go through each mode and hopefully you will see how to use it. After powering up the DC Electronic Load, you will see the “Welcome” screen and then the display shows the last mode used. If this is the first time using the DC Electronic Load, it defaults to the Constant Current Mode.

Constant Current Mode

The Constant Current Mode screen is as shown in the above photo and is selected by pressing the “CC” key on the Keypad. Here the display shows the Voltage (VL) from the device being tested. Also the Current (IL) from the device being tested when the load is “ON”. The Power (PWR) is also calculated. If using the internal Battery, the Battery Voltage (BAT) is shown. Note, when the external 9V Input is used, the voltage shown will be the output voltage of the plug pack connected. On the bottom line you will see, if WiFi has been configured and connected “↑” or if not connected “↓”. The Heatsink Temperature (HT) is also displayed.

If the Electronic Load has been enabled “ON” is displayed, otherwise “OFF” is shown. Lastly, the current mode of operation is shown. The first, second and fourth lines are common to most modes. For Constant Current Mode, you set the desired load current. The cursor will be located under the digit you can modify. You can modify each digit using the “↑” or “↓” keys on the Keypad. To move the cursor left or right use the “←” or “→” keys on the Keypad. Once you have set the desired current, press the “LD” key on the Keypad to turn the DC Electronic Load “ON” and again for “OFF”. Note, in any mode, if the “HT” rises above 45°C, the Fan will turn on and if the “HT” exceeds 55°C, the DC Electronic Load will disable the load and display “OFF” on the fourth line of the LCD Display. Note the maximum current setting should not be more than 3 Amps. The maximum the INA219 Current Sensor can reliably handle is 3.2 Amps.

Constant Resistance Mode

The display for the Constant Resistance Mode is shown in the abobe photo and is selected by pressing the “CR” key on the Keypad. All that was described in the Constant Current Mode applies. The only difference is that you are setting up a Resistance value to be connected to the device under test. Note, the maximum resistance value is 1000Ω and the minimum is 1Ω.

The reason the maximum resistance is 1000Ω is because the current that will flow is getting down to 1 mAmp, which is the minimum current than can be set. Warning, when setting a resistance of 1 Ω, this most probably will result in a current of greater than 3 Amps. This will cause the Thermal Circuit Breaker to trip, protecting the DC Electronic Load from damage.

Constant Power Mode

The display for the Constant Power Mode is shown in the above photo and is selected by pressing the “CP” key on the Keypad. All that was described in the Constant Current Mode applies. The only difference is that you are setting up a Power value to be drawn from the device under test. Here the DC Electronic Load will try to draw a Constant Power from the device under test by adjusting the current up and down even if the voltage from the device under test is varying. As discussed earlier, do not exceed a Power setting of 20 Watts, unless the Heatsink/Fan is upgraded.

Battery Capacity Mode

The display for the Battery Capacity Mode is shown in the above photo and is selected by pressing the “BC” key on the Keypad. All that was described in the Constant Current Mode applies. Here the only thing that can be adjusted is the Battery Type. I have programmed into the DC Electronic Load four Battery Types, Lithium Ion (Li-

Ion), 9 Volt USB Re-chargeable (9 UR), Nickel Cadmium (Ni-Cd) and Nickel Metal Hydride (Ni-MH). It is really only the names I have programmed, the discharge currents and voltages can be set to anything (See Settings section later on). Once the “LD” key on the Keypad is pressed, the battery is discharged at the starting current and terminates when the minimum discharge voltage or minimum discharge current is reached (All set up in the Settings Menu). At this point, the DC Electronic Load is disabled and “OFF” displayed on line four of the LCD Display. If WiFi and MQTT has been setup (See Settings below), the following is sent to the MQTT Broker (which, in my case, is read by my Home Automation System for analysis):

  1. DC Electronic Load internal Battery Voltage;
  2. The Battery under test Voltage;
  3. The current being drawn from the Battery under test; and
  4. The accumulated Battery Capacity.

Solar Panel Mode

The display for the Solar Panel Mode is shown in the above photo and is selected by pressing the “SP” key on the Keypad. In the SP Mode, there are no settings. You just connect the Solar Panel to the positive and negative

terminals of the DC Electronic Load. Make sure the polarity is correct as I have not incorporated reverse polarity protection into the DC Electronic Load. The other difference is seen in line three of the LCD Display. Here the Light Level is displayed in Lux. The DC Electronic Load will keep adjusting the current load on the solar panel to try and achieve the maximum power output. The DC Electronic Load will keep a record of the Voltage at the Maximum Power, this is the Maximum Power Point Tracking (MPPT) Voltage. The MPPT Voltage is very useful to know when designing Solar Battery Chargers. If WiFi and MQTT is setup (See Settings below), the following is sent to the MQTT Broker (which, in my case, is read by my Home Automation System for analysis):

  1. DC Electronic Load internal Battery Voltage;
  2. The latest measured MPTT Voltage; and
  3. The latest measured maximum power output.


The initial display for the Settings Mode is shown here and is selected by pressing the “ST” key on the Keypad.

By pressing the “↑” or “↓” keys on the Keypad, you can select the Settings Menu you want to initiate. The cursor will be under the number of the menu selected. Then pressing the Enter “E” key on the Keypad initiates that setting menu.

Setup WiFi. The following display is shown for setting up WiFi data, ie SSID and password.

First the WiFi SSID is setup. Initially, it is shown as a line of ducks. The ducks represent “null” characters. For those familiar with using strings in programming, strings always terminate with the “null” character. The cursor is initially under the first character (duck). Using the “↑” or “↓” keys on the Keypad, you can select the character for the first letter of your SSID. Then by using the “←” or “→” keys on the Keypad, you can move the cursor to the desired position to setup each character in your SSID. Once you have setup the SSID, press the Enter “E” key on the Keypad. This will bring up the Setup WiFi Password Display.

Again using the “↑” or “↓” and “←” or “→” keys on the Keypad, you can setup your WiFi password. Again once finished press the Enter “E” key on the Keypad. This will take you back to the Settings Mode Display.

Setup MQTT. You can now setup your MQTT settings.

The same key presses on the Keypad are used again. First the MQTT Server Name. After you have finished and pressed the Enter “E” key on the Keypad, you setup the MQTT Server password.

Again, once finished you press the Enter “E” key on the Keypad. Now you setup the IP Address of the MQTT Server.

You need to setup the four digit IP address not forgetting to put the “.” between each number.

Again, once this is complete and you have pressed the Enter “E” key on the Keypad, you can setup the MQTT Port number.

The Port number displayed is the standard MQTT Port Number and is usually not changed. So all you need to press is the Enter “E” key on the Keypad. This again will take you back to the Settings Mode Display.

Set Battery Data. You now have the option of setting up your Battery Capacity Test Parameters.

If you have finished, you can always press the Clear “C” key on the Keypad and this will take you back to the last operational Mode Display. As indicated earlier, I have programmed in four Battery types. For each Battery Type, you can set the Minimum Voltage (Min Volt) – this is the voltage of the battery, for which the battery capacity is being determined, is allowed to discharge to. You can then set the Starting Current (Start Amps) – this is the current the DC Electronic Load initially places on the battery.

Then finally, the Minimum Current (Min Amps) is set – this is the minimum current load the DC Electronic Load will place on the Battery before the DC Load automatically disables the loading on the Battery. The “Min Volt” and “Min Amps” are used together to determine when the DC Electronic Load is disabled. Examples for each configuration is shown in the following photos.

Test WiFi and MQTT

Once you have setup the WiFi and MQTT parameters, you will want to know if everything is correct and working. Pressing the Test WiFi (TW) key on the Keypad will initiate a WiFi connection test. Sometimes this may fail but the DC Electronic Load continues to try and establish the connection. When the display on the LCD Display returns to the last operation mode display, you may see on the fourth line of the Display, the WiFi symbol is showing an “↑”. This means a connection has been established. If you still see the “↓”, this may mean you have input the WiFi credentials incorrectly. So you should check them in the Settings Menu and change if necessary. Once the Wifi connection has been established, you can then check if your MQTT is setup correctly. This time you press the “TM” key on the Keypad. If you do not get a success message, either you have not setup the MQTT credentials correctly or there is no WiFi connection.

Software Update

For advanced users, there is a capability for updating the software loaded onto the WeMos D1 Mini using an Over The Air (OTA) capability. This can be performed in conjunction with the Arduino IDE, which was used to develop the software for the DC Electronic Load. To use this capability, a WiFi connection has to be already established and the computer running the Arduino IDE must be connected to the same WiFi Router as the DC Electronic Load. Otherwise nothing will happen. To initiate the Software Update, press the “SU” key on the Keypad. On the Arduino IDE under “Tools/Port” a new port will appear with the IP address of the DC Electronic Load and “EL8266” as part of the Port Name. Once you select this port and start the download, you will be asked for the download password. It is “1234567890”. This will then download your new build of software and once complete cause the WeMos D1 Mini to be reset. If all has gone well, you will have your new software executing. The OTA software updating capability has the great advantage that you do not have to open the DC Electronic Load case or make any physical connections to update the software.


I mentioned in the MOSFET Board section of the Build, that some calibration was performed. The reason for this is that the INA219 is used to measure the input voltage, which is displayed on the LCD Display as “VL”. Referring to Figure 3, the INA219 measures this voltage between the “RS-“ pin and its Ground connection. This is called the “Bus Voltage”. The voltage drop between the INA219 “RS+” and “RS-“ pins is also measured by the INA219. This is known as the “Shunt Voltage” and is used by the INA219 to calculate the current flowing through the Shunt Resistor. So the voltage between “RS+” and ground can be calculated by adding the “Shunt Voltage” to the “Bus Voltage. However, there is also a voltage drop from the Positive terminal on the Front Panel to the “RS+” input of the INA219. There is also a voltage drop from the Negative terminal to the MOSFET Board. While I have used four wires in parallel on both of these connections to keep the resistance low and thus the voltage drop low, there is still a measurable voltage drop, especially as the current increases.

So to determine what the resistance of these two connections are, I used the Calibration Setup in Figure 6. Here I setup the DC Electronic Load in Constant Current Mode. I adjusted the current in steps of 0.1 Amps from 0.1 to 2.0 Amps. I set the Power Supply to three voltage levels, 5V, 10V and 15V. Using a Digital Multimeter, I measured the actual voltage between the Positive and Negative terminals of the DC Electronic Load. I compared this with the “Bus” and “Shunt” voltages reported by the INA219 in the DC Electronic Load. I recorded all this data in a spreadsheet. From this data, I determined the average resistance of the two cables of concern. The value I derived was 0.07Ω. This was incorporated into the DC Electronic Load program as “Cal_Int_R” (Calibrated Internal Resistance), and used when determining the actual voltage at the DC Electronic Load terminals, displayed on the LCD Display as “VL”.

The software

The software for the DC
Electronic Load, as previously mentioned, was developed using the Arduino IDE. First, let’s look at the settings I have used on the Arduino IDE. Notice under “Flash Size” I have selected “4MB (FS:2MB OTA:-1019KB)”. This will ensure enough memory is allocated if you use the OTA capability.

The software program is “Electronic_Load_PS_V2_1”. (A copy is included in the Project Resources). So you will notice I am onto Version 2.1.

The first DC Electronic Load, I built used some different components and did not have the “Constant Resistance” Mode. So some changes were required. Also, the original Version was written a couple of years ago and my coding expertise was not great – not that it has improved greatly even now! However, as the original code worked well, I decided not to change the structure at all. It may appear to be a bit inefficient, but when you are onto a good thing, stick with it I say!

As usual with an Arduino program you declare all the Libraries used. The libraries are fairly well identified by the comments against each “#include” statement and all the hardware for which these libraries are required have been described earlier.

// libraries 
#include <Wire.h> // For I2C 
#include <LiquidCrystal_I2C.h> 
// For LCD2004 Display 
#include <Adafruit_MCP4725.h> // For DAC 
#include "DHT.h" 
// For Temperature Sensor on Heatsink 
#include <BH1750FVI.h> 
// For Light Sensor on top of case 
#include <EEPROM.h> // For saving NV variables 
#include <ESP8266WiFi.h> // For WiFi connections 
#include <PubSubClient.h> // For MQTT data 
#include <Adafruit_INA219.h> 
// For INA219 Current and voltage Sensor 
#include <Keypad_I2C.h> // For Keypad 
#include <Keypad.h> // For Keypad 
#include <ArduinoOTA.h> // For OTA Software Updates

The only library which needs a mention is the library. There are a lot of settings I wanted to save after a power down. All these settings are saved in a “structure”. A “structure” is a simple way of saving a lot of data in EEPROM. The structure I have used is shown here.

// Data Structure to be saved in EEPROM 
struct { 
int WiFi_Init; // Set to 12345 when WiFi setup 
char SSID [20]; // SSID of WiFi Router 
char pass [20]; // WiFi Password 
int MQTT_Init; // set to 12345 when MQTT setup 
char M_Name [20];// MQTT Server Name 
char M_Pass [20]; // MQTT Server password 
char M_IP [20]; // MQTT Server IP Address 
int M_Port; // MQTT Server Port number 
int L_Mode; // Last mode used for Electronic Load 
float Bat_Min_V[BT_Max]; 
// Minimum Discharge Voltage for Battery Types 
float Bat_Strt_I[BT_Max]; 
// Starting discharge current 
float Bat_Min_I[BT_Max]; 
// Minimun discharge before turning EL off 
} EL_Data;

Below the Library “#includes”, there are all the declarations for the variables and constants. It is best to look at the “Electronic_Load_PS_V2_1” program as there are many variables and constants. I also declare the functions called from within the “Setup()” and “Loop()” functions. While the Arduino IDE does not require forward declarations of functions, some other development environments, eg. PlatformIO, do. It is also good practice to do this. Most of these functions are to do with updating the individual lines of the LCD Display. Line 1 of the LCD Display is the same, independent of the mode configured.

// Function declarations 
void LCD_Display_Update(int OP_Mode); 
void LCD_Display_Update_1(void); 
void LCD_Display_Update_2(int O_M); 
void LCD_Display_Update_3(int O_M); 
void LCD_Display_Update_4(int O_M); 
void LCD_Display_Set(int OP_Mode); 
void LCD_Display_Options( void ); 
void Disp_Bat_Data(unsigned int T); 
float Get_Adj_Voltage( float Current);

Lines 2, 3 and 4 of the LCD Display are dependent on the Mode of operation. The function “float Get_Adj_Voltage( float Current)” uses the Calibration Internal Resistance (Cal_Int_R) and the measured current to accurately provide the voltage at the terminals on the front panel as previously discussed.

This now just leaves the two main functions “Setup()” and “Loop()”. In the “Setup()” function all the hardware is initialised, i.e. Fan GPIO, EEPROM, DHT11 Temperature Sensor, BH1750 Light Sensor, MCP4725 DAC, the LCD Display, INA219 Current Sensor, and Keypad.

// Enable Serial for debugging purposes 
// Setup GPIOs 
pinMode(ELF_Pin, OUTPUT); // EL Fan Pin 
// Enable EEPROM to be read from/written to 
// Set up DHT11 Temperature Sensor 
// Set up BH1750 Light Sensor 
EL_BH1750.begin(BH1750SDA, BH1750SCL); 
// Start Light sensor 
EL_BH1750.powerOn(); // Needed only really after a 
//    read, as sensor turns off 
// Set up MCP4725 DAC 
dac_value = 0;
dac.setVoltage(dac_value, false); 
// Initialse dac output to zero 
// Could use true to save in dac EEPROM at pwer up 
EL_Load_F = false; 
// Load flag indicating load is not enabled 
// Set up LCD2004 
lcd.init(); // initialize the lcd 
lcd.backlight(); // Enable Backlight 
lcd.createChar(0, duck); 
// A duck will be printed for null chars 
lcd.createChar(1, wifi_u); 
lcd.createChar(2, wifi_d); 
lcd.createChar(3, ohm); 
// Clear display and set cursor to top LHS 
lcd.print(Welcome1); // Print startup on LCD 
// Second line of startup message 
lcd.print(Welcome2); // Print startup on LCD 
// Third line of startup message 
lcd.print(Welcome3); // Print startup on LCD 
delay(2000); // wait 2 seconds before continuing 
// Setup INA219 Current Sensor 
//Setup keypad 
// Read EEPROM to determine last 
// Operation Mode used, 
// set to Constant Current (CC) 
// if EEPROM is rubbish 
EEPROM.get(0, EL_Data); 
if((EL_Data.L_Mode < Mode_Min) || (EL_Data.L_Mode > Mode_Max)) 

// EEPROM Not set up yet 
EL_Mode = CC; 


EL_Mode = EL_Data.L_Mode; 

LCD_Display_Set(EL_Mode); // Display Mode screen 
lcd.cursor(); // enable cursor 

After this all the variables are initialised.

Set_I = 0.0; // Init Set Current to zero (CC Mode) 
Set_R = 1.0; // Init Set Resistance to one (zero 
//               not allowed) (CR Mode) 
Set_P = 0.0; // Init Set Power to zero (CP Mode) 
Calc_I = 0.0; 
// Init Calculated current from INA219 to zero 
Calc_V = 0.0; 
// Init Calculated voltage from INA219 to zero 
Calc_P = 0.0; // Init Calculated power from 
// calculated voltage and current to zero 
BAT_Cap = 0.0; 
// Init Calculated Battery capacity to zero 
BT = 0; // Init Battery Type to Li-Ion 
BC_Flag = false; // Battery discharge flag init to 
//  above minimum discharge voltage 
Cur_P = 0; // Init Cursor Position to 0, first digit 
N_MPPT = 0.0; 
// Init new MPPT Power calculation to zero 
P_MPPT = 0.0; 
// Init previous MPPT Power calculation to zero 
EL_Load_F = false; // Init load off 
Disp_Timer = millis(); 
// Int Display Timer for updating 
dac_Timer = millis();
// Set timer for updating the dac output 
Temp_Timer = millis(); 
// Set timer for reading Temp Sensor 
Menu_Level = 0; 
op_set = 0; 
SU_Flag = false; // Software Update is off

Now the fun starts. The “Loop()” function is where all the work happens. This function can be split into four sections.

  1. Process Keypad input;
  2. If the DAC Timeout has occurred perform processing related to Heatsink Temperature, Load enabled/disabled. The DAC can only be set so many times a second, so a timer is used. The timeout “dac_TO” is currently set to 100 ms;
  3. If the LCD Display Timeout has occurred then the data on the LCD Display is updated. The timeout “Disp_TO” is currently set to 1000 ms. The reason for this timeout, is to have most of the processing given to the DAC functions and not cause too much flickering on the LCD Display;
  4. Finally, if the Software Update “SU” key on the Keypad is pressed, everything is halted and OTA updating is initiated.

Process Keypad input is a very considerable amount of coding (see the “Electronic_Load_PS_V2_1” program. It consists of one outer “” control structure for each of the possible keys on the Keypad being pressed. Then within each “case” statement, there may be further “” control structures which will process the key pressed dependent on the current set Mode of operation. A small code snippet is shown below.

// Check if Keypad touched 
KeyData = EL_Keypad.getKey(); 
if(KeyData != NO_KEY) 

// process Key touched 
// Serial.print(" Key pressed "); 
// Serial.println(KeyData); 1
switch (KeyData) 

case '1': 
// Up key pressed 

case CC: 
if( Cur_P == 0) Set_I = Set_I + 1.0; 
if( Cur_P == 2) Set_I = Set_I + 0.1; 
if( Cur_P == 3) Set_I = Set_I + 0.01; 
if( Cur_P == 4) Set_I = Set_I + 0.001; 
if( Set_I > 3.0) Set_I = 3.0; 
// 3.0 Amps is max allowed current 

LCD_Display_Update_3( EL_Mode); 

Here, the “↑” key, originally labelled “1”, has been pressed. Now if the current operational mode is Constant Current “CC”, then dependent on where the cursor is, the set current (Set_I) is incremented. The maximum current of 3.0 Amps is not allowed to be exceeded. Then function “LCD_Display_Update_3” is called to update line 3 on the LCD Display as this is where “SET I” is shown. Because I have used the “” control structures, processing is very fast even though there is a lot of code, very little is executed at any one time.

Next is the process DAC Timeout. The Timeout (dac_TO) is currently set to 100 ms. You could set the timeout lower, but I believe it is not necessary. This timeout means that the DAC output is only updated 10 times a second. This means the program is reasonably responsive in getting Keypad input and updating the LCD Display.

Normally, when the DAC is initially set with a value, it is very close to the current required to be drawn from the device under test. It usually only has to vary by 1 or 2 bits, so higher update rates are not necessary. The following code snippet shows what happens when the DAC Timeout occurs, the DC Electronic Load is enabled (EL_Load_F = true) and the operational mode is Constant Current (CC).

if(millis() > (dac_Timer+dac_TO)) 

// Process whichever operation is in progress 
// First Read Temperature to see if the 
// Fan needs turning on 
// Note can only read temperature every 
// 1 second on a DHT11 
if(millis() > (Temp_Timer + Temp_TO)) 

ELH_T = dht.readTemperature(); 
Temp_Timer = millis(); 

if(ELH_T > ELF_TonT) 

digitalWrite(ELF_Pin, HIGH); // Turn on Fan 
ELF_F = true; // Set flag to indicate fan on 


digitalWrite(ELF_Pin, LOW); // Turn off Fan 
ELF_F = false; // Set flag to indicate fan off 

// It temperature exceeds the maximum operating 
// temperature (ELL_Off), switch off Load 
if(ELH_T > ELL_Off) 

EL_Load_F = false; // turn off load 
dac_value = 0; 
dac.setVoltage(dac_value, false); 
// Initialse dac output to zero 


// Process data to update display when load 
// is on 
switch (EL_Mode) 

case CC: 
// In Constant Current mode 
// First Read current from INA219 sensor and convert to Amps 
Calc_I = ina219.getCurrent_mA()/1000.0; 
// When EL is unloaded negative values can result, 
// this is removed by using fabs() 
Calc_I = fabs(Calc_I); 
// Compare with Set Value 
if(Set_I > Calc_I) dac_value+=int(819.0 * (Set_I-Calc_I)); // 819 = 1 Amp
if(Set_I < Calc_I) dac_value-=int(819.0 *(Calc_I-Set_I)); 
if(dac_value > 4095) dac_value = 4095; 
if((Set_I == 0.000)||(dac_value < 0)) dac_value = 0; 
dac.setVoltage(dac_value, false); // set dac output 
// Read voltage from INA219 sensor 
Calc_V = Get_Adj_Voltage( Calc_I); 
// When EL is unloaded negative values can result, this is removed by using fabs() 
Calc_V = fabs(Calc_V); 
// Calculate Power 
Calc_P = Calc_I * Calc_V; 


// First Read current from INA219 sensor and convert to Amps 
Calc_I = ina219.getCurrent_mA()/1000.0; 
Calc_I = fabs(Calc_I); 
// Read voltage from INA219 sensor 
Calc_V = Get_Adj_Voltage( Calc_I); 
// When EL is unloaded negative values can result, this is removed by using abs() 
Calc_V = fabs(Calc_V); 
// Calculate Power 
Calc_P = Calc_V * Calc_I; 

dac_Timer = millis(); // reset dac timeout 


First, the Heatsink Temperature (ELH_T) is read from the DHT11 Temperature Sensor. Note another timeout is incorporated here as the DHT11 can only be reliably read once a second. This temperature is reflected on line four of the LCD Display, when the LCD Display is updated. The temperature is then compared to the Fan turn on temperature (ELF_TonT). If the turn on temperature is exceeded, the Fan is turned on. Otherwise the Fan is turned off. If the maximum operating temperature (ELL_Off) is exceeded, the DC Electronic Load is disabled. This hopefully will stop the MOSFET from being destroyed by thermal runaway.

If all is still good and the DC Electronic Load is enabled (EL_Load_F = true) and the operational mode (EL_Mode) is Constant Current (CC). The current flowing is read from the INA219 Current Sensor (the result will be in mAmps). It is converted to Amps. I found that when the DC Electronic Load was unloaded, negative current could be measured. So the result is always converted to a positive number, otherwise crazy things happen. The DC Electronic Load then determines what value is required to load into the DAC (dac_value) to get to the Set Current (Set_I). It does this by looking at the difference between the measured current (Calc_I) and the Set Current (Set_I). The difference is in Amps. This difference is multiplied by the magic number 819. Not really a magic number. When 5 Amps is flowing through the feedback resistor (R8 – see Figure 3), this gives 0.5V across it. This means the output from the MCP4725 DAC was 5V. As the MCP4725 is a 12-bit DAC, the 5V equates to a count of 4095. Therefore, for 1 Amp, the count would be 819. There are also some checks to make sure the calculation of the new “dac_value” does not exceed 4095 nor is lower than zero. Otherwise crazy (or unexpected) things can happen also. Once the DAC has been set with the new value, the input Voltage (at the front panel terminals) is determined and power calculated. These values will be updated on the LCD Display when the LCD Display update cycle occurs.

If the DC Electronic Load is not enabled (EL_Load_F = false), the current (Calc_I) flowing is still determined (it is usually zero, although on occasion I have found a residual current flowing from a Test Device?). The voltage (Calc_V) from the Test Device is also measured and power (Calc_P) calculated. These values are updated on the LCD Display during an LCD Display update cycle.

if (millis() > (Disp_Timer + Disp_TO)) 

  if((EL_Mode != ST) && (!SU_Flag)) LCD_Display_Update(EL_Mode); 
    Disp_Timer = millis(); 

When a Display Update Timeout (Disp_TO) has occurred, and the Operational Mode is not the “Settings” (ST) mode nor the “Software Update” (SU_Flag) been initiated, the LCD Display is updated relevant to the current operational mode (EL_Mode).

Finally, if the “Software Update” has been initiated (the “SU” key on the Keypad has been pressed and there is a WiFi connection, otherwise pressing the “SU” key is ignored) then the OTA process begins as described earlier in the “OPERATING THE DC ELECTRONIC LOAD” section.

// If Software Updating is enabled, 
// look for OTA requests 
if(SU_Flag) ArduinoOTA.handle();

Now the Software Updating process is completely blocking. No other DC Electronic Load function can be initiated unless you power down the DC Electronic Load and power it up again.


I think the DC Electronic Load project has been one of the most interesting projects I have undertaken. It uses many sensors and an LCD Display, all operating on the I2C bus, the exception being the DHT11 temperature sensor. Data is saved between power downs in EEPROM. WiFi and MQTT is in use. OTA Software Updating is also incorporated. A MOSFET is used in its linear operating zone instead of just being a switch (we are in the analog world here!)

Of course, the DC Electronic Load also allows you to test Power Supplies, Chargers, Solar Panels and determine the capacity of rechargeable batteries. You can also determine the capacities of non-rechargeable batteries, but doing so just flattens them, so you cannot use them again!

Consuming Power - DC Load - Part 1
Consuming Power - DC Load - Part 2

Peter Stewart

Retired Engineer