Consuming Power - DC Load Part 3

A DC Electronic Load

Peter Stewart

Issue 74, September 2023

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

Log in

Faster data entry and higher power with a rotary encoder and an upgraded MOSFET module.

In Part 1 of the DC Electronic Load (see Issue 70), I indicated it was based on a design by Louis Scully, “Electronic DC Load” in 2016. Initially, in his design, he used a Rotary Encoder and four push buttons for his data entry and mode selection. Later on, he updated his design as he developed more functions where he replaced the four push buttons with a Keypad. He still retained the Rotary Encoder.

Louis also upgraded his MOSFET design to allow it to absorb power more efficiently and also incorporate current limiting to protect the MOSFETs. I have done something similar, by updating my MOSFET Module. Now, if you are happy with the current 20 Watt power absorption of the DC Electronic Load, you can leave the MOSFET Module alone.

In this article, I first look at just adding the Rotary Encoder. Then, if you want more power absorption, the article then shows how I increased the power absorption up to 60 Watts.


With my original design, I decided to go straight for the keypad and remove the Rotary Encoder that Louis Scully had in his design, as it required three Input/Output (I/O) pins on the processor.

As the processor I used was the ESP8266 based WeMOS (Lolin) D1 Mini, which does not have a lot of I/O pins, this at the time seemed a sensible way to go. However, when writing my article “DC Electronic Load” and taking photos, which required me to do some set-up changes, so as not to give away my WiFi SSID and password, I realised this was tedious. A Rotary Encoder would be much more efficient for inputting data, specifically WiFi SSID, MQTT names and passwords. It would also speed up changes to current, power and resistance settings.

The problem is, as already mentioned, I would need three I/O pins to interface a Rotary Encoder and its push button. While, if you look at Schematic Diagram of the “DC Electronic load” in Part 2, you will notice I have not used D0 (16), D3 (0), D4(2), D5 (14), and D8(15) (GPIO numbers in brackets). So you would think there is no issue connecting a Rotary Encoder. That is until you realise that GPIOs 0, 2 and 15 are set up as part of the ESP8266 program load process.

In theory, they can be used, but depending on what is connected, you could upset the program load process. I tend not to use them for this reason. That just leaves two GPIOs, 14 and 16. Only GPIO 14 could be used. GPIO 16 is normally used as an output when “Deep Sleep” is used to reset the ESP8266. But the main problem with GPIO16 is that it does not support interrupts, which are required for processing signals from the Rotary Encoder. The other issue was the wiring required from the main board to the front panel of the DC Electronic Load.

Now, all the modules, with the exception of the DHT11 Temperature Sensor, interface to the ESP8266 processor via the I2C bus. If only you could get an I2C Rotary Encoder! Well, you can! Adafruit has produced the reasonably priced “Adafruit I2C QT Rotary Encoder” complete with a library to interface it with Arduino processors. But you do have to provide your own Rotary Encoder (EC11 type). There are one or two more on the market, but they are more expensive. Then I thought, I already have a couple of EC11 Rotary Encoders and lots of ATtiny85 processors. How hard could it be to make my own I2C Rotary Encoder? As it turns out, not very hard at all.

Rotary Encoder

To make the design as easy as possible to integrate into the DC Electronic Load, I wanted the I2C Rotary Encoder to output the same codes as some of the keys on the Keypad. For example, when you rotate the Rotary Encoder shaft clockwise, I wanted it to provide the code the same as pressing the “↑” key on the Keypad (the increment button). When rotating the Rotary Encoder shaft counter-clockwise, I wanted the “↓” key code provided (the decrement button). Finally, when pressing the shaft in, I wanted the same code provided as the “E” key on the keypad (the Enter button). This would greatly reduce the amount of code to be changed in the DC Electronic Load program. As you will see later, only a few extra lines of code was needed.

I chose the ATtiny85 to interface to the EC11 Rotary Encoder and provide the I2C interface for a few reasons. Firstly, I had several in my parts box. It is still a popular processor used by many makers/hobbyists. It has in-built hardware to support I2C natively. It is a small 8-pin DIP and, therefore, can be installed in an 8-Pin DIL socket. It is also still relatively cheap to purchase. It is supported by the Arduino IDE and easy to program. You can use the programmer I presented in my very first DIYODE article “Keeping Time”, published in December 2021 (Issue 53).

The Build: The Rotary Encoder

Parts Required:JaycarAltronics
1 x ATtiny85 MicrocontrollerZZ8721Z5105
1 x EC11 Rotary EncoderSR1230-
2 x 10k Ohm 0.25 Watt Resistor*RR0596R7582
1 x 100nF Ceramic Capacitor*RC5490R2930A
1 x 10uF Tantalum Capacitor*RZ6648R2638A
1 x Knob (For EC11 Rotary Encoder)#HK7734H6109
1 x VeroboardHP9542H0712
1 x 8-Pin DIL Socket (for ATtiny85)PI6500P0550
1 x 2-Pin Male Header+HM3422P5512
1 x 4-Pin Male Header+HM3424P5514
1 x STEMMA QT/Qwiic JST SH 4-Pin Cable with Female SocketsAdafruit: ADA4397-
26 AWG Stranded White Hook Up Wire^WH3007W2257

Parts Required:

The complete Schematic for the I2C Rotary Encoder is shown in Figure 1 and the Veroboard layout in Figure 2.

The Parts List is found at Table 1 shown below.

Figure 1 - I2C Rotary Encoder Schematic
Figure 2 - I2C Rotary Encoder Veroboard Layout

Cut the Veroboard to size 25.4 mm (10 holes) x 30.5 mm (12 holes). Cut the tracks indicated by the “X” using a “spot face cutter” or 3/8” drill bit. Solder the hook-up wires as shown. Solder the resistors, capacitors and 8-Pin DIL socket in place. The two 10kΩ Resistors (R1 and R2) are not really required as there are already pull-up resistors on the I2C bus within the DC Electronic Load. But I wanted this I2C Rotary Encoder to be a general device, as I have used it elsewhere.

You will also notice I have two right angle headers, 4-Pin for I2C interface and a 2-Pin for debugging. You do not have to install the 2-Pin header. I used this for debugging my program. To use this, I could not use the push button of the Rotary Encoder as the debugging output used the same pin on the ATtiny85 as connected to the Rotary Encoder Push Button. Look at the code as discussed further within.

Case installation

To install the I2C Rotary Encoder into the DC Electronic Load, I first carefully drilled a hole between the Keypad and Test Terminals to fit the EC11 Rotary Encoder. Then using the supplied Nut and washer, I secured the I2C Rotary Encoder in place. You will also need a spacer (another nut or some washers) on the inside between the front panel and the EC11 Rotary Encoder to just provide a little bit of space between the front panel and the ATtiny85. Of course, if you feel brave, you could solder the ATtiny85 directly to the Veroboard and leave out the 8-Pin DIL Socket, then you will not need the spacer. The I2C Rotary Encoder is then connected to the BH1750 Light Sensor using the QT cable with Female Sockets (Pakronics ADA4397). This is an extension of the I2C Bus from the Main Board via the BH1750 Module. The following photograph shows the internal view with the I2C Rotary Encoder installed.

The software

The software will be described in two parts. Firstly the I2C Rotary Encoder Software and then the changes for the DC Electronic Load software.

I2C Rotary Encoder Program

The program for the I2C Rotary Encoder starts with the DEBUG define being commented out. If you want to run the program with debug statements active, uncomment this line. If you do uncomment the DEBUG define, you will not be able to use the push button on

the Rotary Encoder. To see the Debug output, just connect a FTDI module with GND to GND and the FTDI Rx connected to the I2C Rotary Encoder Tx.

As usual for Arduino programs, the Libraries used are declared at the beginning of the program.

The and libraries are built into the Arduino IDE and do not have to be installed. The “TinyWireS.h” Library does have to be downloaded and installed. This can be done in the usual way by using the Arduino IDE Library Manager. The “TinyWireS.h” Library is a very efficient library using as little program space as possible. I then define all pin allocations for the I2C and Rotary Encoder connections plus variables for timers and state tracking. If debugging is enabled, as described earlier, I use the Library. This is a very cut down “Serial.Print” Library and again is efficient with the use of program memory, which of course is limited to 8 kBytes in the ATtiny85.

The I2C Address of the I2C Rotary Encoder is declared as 0x36. This is an arbitrary address and I have chosen this number so that it is not the same as any other I2C address in the DC Electronic Load. You can pick any number up to 0x7F.

//#define DEBUG 1 
// Libraries 
#include <avr/io.h>          // for GPIO 
#include <avr/interrupt.h> // for interrupts 
#include "TinyWireS.h"     // I2C library for ATtiny84A (and other older ATtinys) 
// Pin assignments 
#define PIN_SDA   0 // I2C Serial Data (PB0) 
#define PIN_SCL   2 // I2C Serial Clock (PB2) 
#define PIN_ENC_A   3 // rotary encoder A (PB3) 
#define PIN_ENC_B   4 // rotary encoder B (PB4) 
#define PIN_ENC_SW   1 // rotary encoder switch (PB1) 
#define ROT_CW   '1' // equivalent to UP on Electronic Load 
#define ROT_CCW   '2' // equivalent to DOWN on Electronic Load 
#define BUT_PRESS   '7' // equivalent to ENTER on Electronic Load 
unsigned long But_Timer =0; // Time used for debouncing Encoder Push
#define BUT_TO 50 // Encoder Push Button Debounce Timeout 
byte lastButState = HIGH; 
byte ButState; 
#if DEBUG 
// For debugging only 
#include <SendOnlySoftwareSerial.h> 
SendOnlySoftwareSerial mySerial(PIN_ENC_SW); // Tx pin 
// I2C parameters 
#define I2C_ADDR    0x36 // I2C address of the device 
volatile int8_t I2C_Data; 
// Flag from interrupt routine (moved=true) 
volatile bool rotaryEncoder = false;

Next is the Interrupt Service Routine (ISR) which processes Pin Change Interrupts for the Rotary Encoder, when it is rotated. All this ISR does is set a flag to indicate a new rotation has occurred.

// Interrupt routine just sets a flag when 
// rotation is detected 
ISR (PCINT0_vect) 

  // interrupt caused by Rotary Encoder 
  rotaryEncoder = true; 

The next function is a callback function for whenever the DC Electronic Load polls the I2C Rotary Encoder and requests the latest movement from the I2C Rotary Encoder (I2C_Data). This function will send a ‘1’ for a Clockwise rotation, a ‘2’ for a Counter-Clockwise rotation or a ‘7’ for a press of the Rotary Encoder button. This function then sets the “I2C_Data” to zero indicating no movement. If the DC Electronic Load receives a zero response, it knows no action has occurred with the I2C Rotary Encoder and takes no action.

// Function to process I2C requests 
void requestI2C() 

  I2C_Data = 0; // Set to null data 

The next function, “checkRotaryEncoder()”, is the clever part of the I2C Rotary Encoder program. It determines whether the Rotary Encoder has been turned Clockwise or Counter-Clockwise. It uses an algorithm described at the web address shown in the following section. The algorithm is very clever and works very well.

We now move to the “Setup()” function. This is always executed on power-up. First, the pins connected to the Rotary Encoder in the ATtiny85 are set as inputs with internal pullup resistors. This reduces the number of components required in this design. If DEBUG is enabled, however, the pin connected to the Rotary Encoder Push Button is not set up, but the serial debug output is enabled.

The ATtiny85 I2C function is initialised with the callback setup to handle incoming I2C requests from the DC Electronic Load. This is followed by setting up the Pin Change Interrupts. Pin Change Interrupts occur whenever a signal on the set pin has a rising or falling signal level on it.

// Rotary encoder has moved (interrupt tells us) but what happened? 
// See 
int8_t checkRotaryEncoder() 

  // Reset the flag that brought us here (from ISR) 
  rotaryEncoder = false; 
  static uint8_t lrmem = 3; 
  static int lrsum = 0; 
  static int8_t TRANS[] = {0, -1, 1, 14, 1, 0, 14, -1, -1, 14, 0, 1, 14, 1, -1, 0}; 
  // Read BOTH pin states to deterimine validity of rotation (ie not just switch bounce) 
  int8_t l = digitalRead(PIN_ENC_A); 
  int8_t r = digitalRead(PIN_ENC_B); 
  // Move previous value 2 bits to the left and add in our new values 
  lrmem = ((lrmem & 0x03) << 2) + 2 * l + r; 
  // Convert the bit pattern to a movement indicator (14 = impossible, ie switch bounce) 
  lrsum += TRANS[lrmem]; 
  /* encoder not in the neutral (detent) state */ 
  if (lrsum % 4 != 0) 
    return 0; 
  /* encoder in the neutral state - clockwise rotation*/ 
  if (lrsum == 4) 
    lrsum = 0; 
    return ROT_CW; 
  /* encoder in the neutral state - anti-clockwise rotation*/ 
  if (lrsum == -4) 
    lrsum = 0; 
    return ROT_CCW; 
  // An impossible rotation has been detected - ignore the movement 
  lrsum = 0; 
  return 0; 

Note: I have used direct ATtiny85 register addressing. I found this easier and much more efficient. The Arduino “attachinterrupt()” function did not seem to work as well.

void setup() 

  // No pullup resistors connected to encoder 
#if DEBUG 
  // Start I2C function 
  I2C_Data = 0; // Initialise to null data 
  // We need to monitor both A (PCINT3) and B
 (PCINT4) pins of Rotary Encoder, 
  // rising and falling for all states 
  PCMSK |= (1<<PCINT4) | (1<<PCINT3); 
  // Enable Pin Change Interrupts 
  GIMSK |= (1<<PCIE); // PCIE enabled 
#if DEBUG 
  mySerial.println("Setup completed"); 

Lastly is the “Loop()” function. This is executed continuously while the I2C Rotary Encoder is powered. If in DEBUG mode and an interrupt has occurred, this loop just checks for what rotation has occurred and stores it in the “I2C_Data” variable and then prints it to the serial debug port.

If DEBUG is disabled, the Rotary Encoder Push Button is checked to determine if it has been pressed. The code I have used here is the standard Arduino button debounce code. Once a button press has been determined, the “I2C_Data” variable is set to “BUT_PRESS” which for the DC Electronic Load indicates the same as the ‘E’ Key on the Keypad being pressed.

void loop() 

  // Has rotary encoder moved? 
  if (rotaryEncoder) 
    // Get the movement - ROT_CW, ROT_CCW or invalid 
    I2C_Data = checkRotaryEncoder(); 
  #if DEBUG 
    // If valid movement, print it 
    if (I2C_Data != 0) 
      mySerial.print("The direction is ");  
#ifndef DEBUG 
  // If the debounce timeout has expired and the 
  // Push Button State 
  // has changed back to a HIGH, we have a valid 
  // Button press 
  if(millis() - But_Timer > BUT_TO) 
    ButState = digitalRead(PIN_ENC_SW); 
    if(ButState != lastButState) 
      But_Timer = millis(); 
      lastButState = ButState; 
      if(ButState == HIGH) 
      I2C_Data = BUT_PRESS; // I2C Data to indicate Push Button Pressed 

Changes to the code

To accommodate the I2C Rotary Encoder, some minor changes to the DC Electronic Load program is required. The first is to define the I2C Address (0x36) of the I2C Rotary Encoder and a data variable to hold the data received (EncData) from the I2C Rotary Encoder.

// Rotary Encoder parameters 
#define ENC_ADDR 0x36 
char EncData;

Next, a function, “Get_Encoder_Data()”, is added to fetch data from the I2C Rotary Encoder. Here, the DC Electronic Load sends a request for one byte of data from the I2C Rotary Encoder. It keeps reading data while it is still available. This “while” loop would normally only be executed once as the execution speed of the ESP8266 is very high compared to the ATtiny85.

char Get_Encoder_Data( void) 

  char E_D; 
  // Initiate a data request from the Rotary 
  // Encoder 
  Wire.requestFrom(ENC_ADDR, 1); 
  while (Wire.available()) 
    E_D =; 
  return E_D; 

Lastly, a couple of lines of code are changed at the beginning of the “Loop()” function of the DC Electronic Load. It is changed from:

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


void loop() { 
  // Check if Keypad or Rotary Encoder touched 
  KeyData = EL_Keypad.getKey(); 
  EncData = Get_Encoder_Data(); 
  if(KeyData == NO_KEY) KeyData = EncData; 
  if(KeyData != NO_KEY) 

Here, added is a read request to the I2C Rotary Encoder. Then, if there was no key pressed from the Keypad (NO_KEY received), then the data received from the I2C Rotary Encoder (EncData), is substituted to be processed. If the data from the I2C Rotary Encoder indicates no rotation or keypress, ie. a zero or “NO_KEY” is returned. Then no Keypad processing occurs. Otherwise, the returned I2C Rotary Encoder data is processed as though it was a keypress on the Keypad.

The MOSFET module

In Part 1 of the “DC Electronic Load” (DIYODE magazine Issue 70), I indicated that the DC Electronic Load could handle voltages up to 25 Volts and currents up to 3 Amps. However, it could only handle power absorption of up to 20 Watts. While, for myself, that was adequate, I still thought I could do better. I again looked at Louis Scully’s design and decided I could incorporate some of his improvements.

It’s simple to handle more power. You just add more Power MOSFET’s or a bigger heatsink, or a bigger fan, or all of the aforementioned. I sort of decided to upgrade the lot but with restraint. Louis Scully increased his Power MOSFET count to four. I thought that was a little ambitious for me. Also, I did not want to increase the size of my new MOSFET Module too greatly. I also did not want to change my design much, but just have minor and simple modifications. So, I decided two MOSFET’s, a bigger heatsink and a more powerful fan was all that was required. If I could increase the power absorption to double, I would be happy.

MOSFET Changes?

Nothing is simple, of course. I first looked at the MOSFET I originally used, the IRF540N. At first view, it looked like it should be adequate. I then did a bit more research on other Electronic Loads. I came across a MOSFET type called a Linear MOSFET. Apparently, these are better at absorbing power, but they also cost a fortune. I decided to compare specifications and did not see a lot of differences.

The main thing I noticed was a lower RDS(on) (IRF540N is 44mΩ) the on resistance of the MOSFET between the Drain and Source. The other parameter which I could see was different was a lower VGS(th) (IRF540N is 2.0 to 4.0 Volts), the threshold voltage applied between the Gate and Source which turns the MOSFET fully on. The MOSFETs used by Louis Scully seemed to have a lower VGS(th).

I decided a better MOSFET might be needed and found the Toshiba TK3R2E06PL (RDS(on) 2.4mΩ and VGS(th) 1.5 to 2.5 Volts).

It is listed by Element14 at twice the price of the IRF540N, but was not in stock. I managed to get some from Mouser Electronics. I wasn’t convinced that the TK3R2E06PL would be much better than the IRF540N even with the lower RDS(on) which by rights should allow it to take ten times the current while dissipating the same amount of power.

I decided to build two new MOSFET Modules. One with two IRF540N MOSFETs and the other with the Toshiba TK3R2E06PL MOSFETs.

Heatsink change

The Heatsink I used on my DC Electronic Load was small, especially considering it helped the IRF540N absorb 20 Watts. The new heatsink should help absorb twice that power. The Heatsink I used originally was the Jaycar HH8522, which had a Thermal Resistance of 11 °C/W. The addition of the fan most probably reduced the Thermal Resistance to around 5.5 °C/W.

One of the limitations of the heatsink size was the size of the case in which I installed the electronic components. I decided I did not want to make too many changes to the physical components and layout, so I chose a heatsink, the Jaycar HH8570, which was only 55mm high (it could still fit inside the DC Electronic Load case). It also had a thermal resistance of 2.5°C/W. This heatsink was also big enough to accommodate two MOSFETs. So with a better fan, I could most probably reduce the thermal resistance much further.

The Build: Fan Change

Figure 3 - DC Load Schematic Diagram

In my original design, I used the Altronics F1110 40mm
5 Volt Fan, which had a flow rate of 5 CFM. I could not find a much higher flowrate fan that operated off 5 Volts and still had a 40mm diameter. I would have to go for a 12 Volt fan. How do I power this? The battery voltage was a maximum of 8.4 Volts. If you powered the DC Electronic Load from the Plug Pack, that only gives 9 Volts. I did not want to get another Plug Pack, so the Fan would have to operate from the 8.4 or 9 Volts somehow. Then I remembered, I have some small Boost Converters in my Parts Box. These would boost any input Voltage from 2 to 24 Volts to 2 to 28 Volts (as long as the output voltage was greater than the input voltage).

I had two types of modules, a HW668 and a MT3608. I chose the HW668 as it had a smaller footprint and I could install it on the Main Board in a spare space.

Note: many of you may find the MT3608 is more readily available. Just use hookup wire to connect it to the Main Board.

The Fan I then chose was the Jaycar YX2504 50mm 12 Volt Fan which had a flow rate of 16.6 CFM. The 50mm diameter fits the original case also.

Build Modifications

Firstly, the Modified Schematic Diagram is shown in Figure 3. You will notice several changes to that of my original schematic, namely the addition of the HW668 Boost Converter, the extra MOSFET with transistors attached and also, the Temperature Sensor changed from a DHT11 to a DS18B20. The Temperature Sensor change was necessary for a couple of reasons. The DS18B20 has a temperature measurement range of -55 °C to +125 °C. The DHT11 was limited to 50 or 60 °C maximum, depending on what version you have (See discussion in original article). To support the DS18B20, you have to add R14 pullup resistor. The other reason for using the DS18B20 was that I was thinking of adding a further new MOSFET Module which would have another DS18B20 attached. DS18B20s can be bussed. That means multiple DS18B20s can be connected in parallel.

The Build: New MOSFET Module

Now let’s have a closer look at the new MOSFET module. Looking at the schematic (Figure 4), you can see I have added a second IRF540N (Q3). It is basically in parallel with the original Q1 MOSFET. Now the problem with MOSFETs and any other semiconductor, for that matter, is that they are not identical. All you have to do is look at a datasheet and you will see for nearly every characteristic, there is a range of values. So firstly, to try and balance the current going through each MOSFET, R11 and R12 (0.1Ω each) have been added. These resistors do have a small effect on trying to keep the current through each MOSFET balanced. However, this is not their major function. Their major function is to generate a voltage in combination with R8 across the base/emitter junctions of the 2N4401s of Q4 and Q5. As the voltage approaches the VBE(sat) turn on voltage (somewhere between 0.75 and 0.95 Volts – see datasheet), the 2N4401 starts to conduct. (Note any similar NPN transistor can be used rather than the 2N4401, I just have lots in my Parts Box, eg 2N2222A). This causes a reduction in the voltage applied to the gate of the IRF540N, which causes the MOSFET to start turning off, i.e. reduces the current flowing through it.

Figure 4 - MOSFET module schematic

This helps with the potential current imbalance between the IRF540Ns (Q1 and Q3). So for Q1, the combination of R11, R8 and Q4 are a current limiting circuit. Note R9 and R10 have been added so that the current limiting on Q1 does not impact Q3.

I did some testing on two MOSFET Modules. One fitted with IRF540N MOSFETs and the other with the TK3R2E06PL MOSFETs fitted. I built a special test circuit that would allow me to try and drive up to 4.0 Amps in total through the MOSFETs. I connected one channel of my Oscilloscope to the base of Q4 and the other channel to the base of Q5. I also recorded the output of the DAC which drives, via Operational Amplifiers, the gates of the MOSFETs. The results were interesting. The above photographs are from my Oscilloscope. The first is for the IRF540N Module. The current limit for this module appeared to be 3.3 Amps. You will also notice from the first photograph, that the maximum voltage at Q4 and Q5 bases were 560 mV and 552 mV respectively. This indicates to me that the current through each MOSFET is very close to being the same.

The second photograph is for the TK3R2E06PL MOSFET Module. Here the current limit appeared to be 3.7 Amps with the voltages at Q4 and Q5 bases being 676 mV and 668 mV respectively. Now, I did measure the VBE(sat) of Q4 and Q5 on both MOSFET Modules, using my cheap component tester and they ranged from 676 mV to 678 mV – pretty close to being identical. So I would have thought I would have seen similar base voltages on both Oscilloscope photographs. I also noticed that consistently, a higher voltage from the DAC (up to 250 mV), was required to drive the TK3R2E06PL MOSFET Module for the same current.

Another surprise was the temperature I measured on the back of the heatsink was within one degree for both MOSFET Modules for the same current. I would have thought the TK3R2E06PL MOSFET with an RDS(on) of less than one-tenth of the IRF540N MOSFET, would run several degrees cooler.

Overall my calculations for R11 and R12 were not too far off. A higher value for R11 and R12 could be used to ensure the maximum current capability of 3.2 Amps for the INA219 Current Sensor is not exceeded. However, the DC Electronic Load software will only allow a maximum of 3.0 Amps to flow through Q1 and Q3 combined. But as you have most probably realised, if Q1 is very different to Q3 and takes a lot more current, the combination of Q4, R11 and R8 will most probably limit the current to around 1.65 Amps maximum for IRF540Ns and 1.85 Amps for TK3R2E06PLs.

While the circuit in Figure 4 does not provide perfect current balancing, it does offer a good degree of protection against over current for each individual MOSFET. However, surprisingly, the expected performance improvement of the TK3R2E06PL was not that great and I cannot see any reason for not using the cheaper IRF540N.

Figure 5 shows the Veroboard layout of the new MOSFET Module. You will notice I have doubled up on all the connectors. This allows for paralleling another MOSFET Module to further reduce the current and thus heat for each MOSFET.

Figure 5 - MOSFET board

The Build: Main Board Mods

Parts Required:JaycarAltronics
2 x IRF540N N-Channel MOSFETZT2466Z1537
2 x TK3R2E06PL N-Channel MOSFET (Alternative to IRF540N)Element14 4173100-
1 x DS18B20 Temperature SensorElement14 251555301-
2 x 2N4401 NPN TransistorElement14 1574373-
2 x 2N2222A NPN Transistor (2N4401 alternative)ZT2298-
1 x UF5408Element14 9551735-
3 x 0.1Ω 1 Watt 1% Resistor*Element14 2448927-
2 x 2.2kΩ 0.25 Watt 1% Resistor*RR0580R7566
1 x 4.7kΩ 0.25 Watt 1% Resistor*RR0588R0574
1 x HW668 or MT3608 Boost converterAliexpress or ebay-
1 x VeroboardHP9542H0712
1 x HeatinkHH8570H0520
1 x 50mm 12 Volt FanYX2504-
1 x Black Acrylic Sheetebay-
26 AWG Stranded White Hook Up Wire^WH3007W2257

Parts Required:

The modifications to the Main Board are fairly minor. These are shown in Figure 6. There are four wires that are required to be removed (the ones highlighted in blue). Five further track cuts are required (shown by the red ‘X’s). Don’t miss the one under the Blue and Red wires on the left ground connection of the HW668. There are eight new wire connections required (the ones highlighted in red). The R14 and the HW668 Boost converter is added. The Fan #2 connector is optional and only required if a second MOSFET Module is to be added. The following photograph shows the modified Main Board. Table 2 shows the extra parts required to modify the DC Electronic Load. I am assuming you will not be reusing the parts from your original MOSFET Module, otherwise, subtract as required.

Figure 6 - DC Load main board

Also, if you have no intentions of adding a second MOSFET Module and your DHT11 is currently working okay, you could reuse it rather than changing to the DS18B20 and by the way, you do not need to add R14.

The Build: Case Modifications

Figure 7 - Back Panel

With the New MOSFET Module, unfortunately, it does not fit where the old MOSFET Module was located, being of a larger size. You will need to rearrange some of the internal components. You will also need a new back panel.

For the back panel, you will need a black acrylic sheet, which you can get from Ebay or Craft Shops. You will have to cut it to size. Use the pattern in Figure 7. It will also be included as an uploadable resource from DIYODE, which you should be able to print and use as a template.

The above photograph shows how I changed my internal layout to accommodate the MOSFET Module, the Main Board and the Battery. The INA219 Current Sensor was not moved. There is also space for a second MOSFET Module. I also found I did not have to modify any of the cables. The Fan cable is, of course, a new cable and has to be terminated.

Software modifications

The software modifications are fairly minor. The new program is included in the associated project resources from DIYODE. The first change is associated with the new libraries associated with using the DS18B20 Temperature Sensor. I have commented out the DHT11 Library. If you are not changing the DHT11, none of the following changes are required.

//#include "DHT.h" 
// For Temperature Sensor on  Heatsink 
#include <OneWire.h> // For DS18B20 Temp Sensor 
#include <DallasTemperature.h> 
// For DS18B20  Temp Sensor

Next are the declarations for the DS18B20 Temperature Sensor. Note the timeout “Temp_TO” has been reduced from 1000 milliseconds to 100 milliseconds. This is because the DS18B20 is a much faster sensor that the DHT11 and can be read more often.

//// Define DHT11 (Temperature Sensor) parameters 
//#define DHTPIN 12 // connected to GPIO12 
//#define DHTTYPE DHT11 // DHT 11 
//DHT dht(DHTPIN, DHTTYPE); // Initialize DHT 
// Define DS18B20 (Temperature Sensor) parameters 
#define DSPIN 12 // connected to GPIO12 
OneWire oneWire(DSPIN); 
DallasTemperature DS18B20(&oneWire); 

//#define Temp_TO 1000UL 
// Time between readings for DHT11 
#define Temp_TO 100UL 
// Time between readings for DS18B20

Next are the changes in the “Setup()” function.

// Set up DHT11 Temperature Sensor 
// dht.begin(); 
// Set up DS18B20 Temperature Sensor 
  DS18B20.setResolution( 9); 
// Set Resolution to +/- 0.5C

Finally are the changes to the “Loop()” function. The DS18B20 works slightly differently to the DHT11. To get a temperature from a DS18B20, you first have to make a “request”. Then you have to wait for the DS18B20 to sense the temperature and convert it ready for reading. Note if you have multiple DS18B20s on the same bus, they all get this request and make ready their individual readings. To read the temperature from each DSB18B20, use the “getTempCByIndex” function. So for example, if you had two MOSFET Modules, you would have two DS18B20s. The first would be read using “DS18B20.getTempCByIndex(0)” and the second would be read using “DS18B20 getTempCByIndex(1)”

  // Note can only read temperature every 1 
  // second on a DHT11 
  // Note can only read temperature every 100
  // millisecond on a DS18B20
     if(millis() > (Temp_Timer + Temp_TO)) 
    DS18B20.requestTemperatures(); // Request
    // DS18B20 to take a temperature measurement 
    delay(Temp_TO); // Have to wait between
   // Request and being able to read temperature 
   // ELH_T = dht.readTemperature(); 
    ELH_T = DS18B20.getTempCByIndex( 0); 
    Temp_Timer = millis(); 


The inclusion of the I2C Rotary Encoder to the DC Electronic Load makes data entry and operation more efficient and easier to use. I believe this is a worthy addition to the DC Electronic Load.

The I2C Rotary Encoder can be used in other applications also. It is not restricted to just the DC Electronic Load. I have already used this in an upgrade project of my Power Bank Spoofer, which I may be presenting in a future article.

The New MOSFET Module allows you to increase the load power capability by more than double. With this new Module, I was able to continuously load a 20 Volt power supply to 40 Watts. I also had no trouble loading up to 60 Watts. However, at 60 Watts, the heatsink temperature eventually rose above the 55°C maximum allowable temperature and the DC Electronic Load immediately switched to the Load Off mode, which most probably saves the MOSFETs from damage due to thermal runaway.

Because of the way I have designed the new MOSFET Module, a second module can be added to increase the load capability beyond my original desired goal of 75 Watts. You will need four cables, one for the second temperature sensor, one to drive the MOSFETs, one for connection adjacent to the negative load terminal and one for connection to the “-RS” of the INA219. I have yet to test this, but “in theory” it should work!! (Famous last words!) Also, no software modifications will be required.


Peter Stewart is a retired engineer and regular contributor to DIYODE magazine.

Other projects include an ATtiny85-based general purpose timer with buzzer in Issue 53, WiFi Temperature Sensor with Scrolling Display in Issue 60, an ATtiny84-based Auto-Ranging USB Current Meter in Issue 64, and Arduino-based Car Presence Sensor & Parking Assistant.

Peter Stewart

Retired Engineer and Regular Contributor