Projects

Portable Arduino Power Logger

Part 1

Liam Davies

Issue 46, May 2021

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

Log in

Monitor and log the behaviour of lab gadgets with this Arduino power logger! It can log voltage, current, power, energy and even disable or enable your connected circuits if something is not quite working as it should. It also has a 9V battery and a LCD display to make it fully portable!

BUILD TIME: 4 HOURS
DIFFICULTY RATING: Intermediate

Often when making and testing circuits, it’s vital to know how much power they’re using, potentially for a number of reasons. Testing a circuit’s efficiency, charging, or use time in the case of battery-operated devices, or simply just testing the operation of a power supply to ensure it is working properly are just some of the many applications for these devices.

For those getting started in electronics, the total energy per second a device uses is known as power, expressed in Watts and is the equivalent of Joules Per Second. A microwave oven, for example, might use 1000W, which equals 1000 Joules of energy per second. Conveniently, in DC circuits it is also equal to Voltage multiplied by Current.

While we can’t measure power directly, we can measure both voltage and current and then multiply them to get a resulting power figure. By then integrating (effectively adding up the power readings over time) the power, we can get the total work done by the device in Joules. This can directly be converted to other units such as Wh, kWh, (e.g. 1Wh = 3600J) or even dollar figures when factoring in the average cost of electricity, $0.24 per kWh here in NSW, Australia for instance. Because we have the power of Arduino at our disposal, we have the opportunity to add these features by just popping some more code into the program.

How It Works

Since our device includes both an ammeter for measuring current, and a voltmeter for measuring voltage, our device needs to be connected in between the power source and the load on both terminals.

The voltmeter setup is quite simple. Since the Arduino chip we’re using – the common Atmega328 – includes 6 ADC (Analog to Digital Converter) pins, it’s really just a matter of reading the measured voltage at the positive input terminal and saving it for later when we calculate our power. However, the Arduino can’t measure anything above 5V without risking damage to the input pins. Since many circuits run on higher voltages such as 12V or 20V, we can use a voltage divider to scale a large input voltage to a range suitable for the Arduino to read. With an additional 5.1V Zener diode that will protect against voltages above 5V, this is a great way of measuring higher voltages than the Arduino is rated to read.

The current measuring circuit is a bit more tricky. Since the Arduino can’t measure current, we need to create a variable voltage that represents a proportional change in current.

To do this, we’re going to use a shunt resistor. A shunt resistor is really just a piece of wire with a known very low resistance. You can make one yourself with a piece of wire and measuring its resistance, or you can use a low-value resistor that can withstand the required power. There are also shunt resistors purpose-built to produce very accurate readings. By connecting the shunt in series with the load we want to measure, the shunt generates a voltage drop across it, proportional to the current drawn by the load.

As shown in the diagram, there are two configurations to connect a shunt resistor – low side and high side sensing, each with its own advantages and issues. The first method is low side sensing, where the shunt resistor is placed between the load and ground.

This is the simplest method since any voltage across the shunt can be amplified with reference to ground, and is directly proportional to the current flowing through it. This occurs when the device under test has the same ground as the power source. For example, powering an Arduino off of a USB from a PC coming through the Power Measurer, and having a USB-UART cable, used for getting data off the Arduino, also plugged into the PC. Approximately half the power return current will actually go through the UART cable (even if you didn't intend it to), and therefore, bypass the low-side measurement.

In critical applications where current sensing could make the difference between safe operation and overloading electronics, this is a serious problem. High side sensing fixes this problem by placing the shunt resistor in between the positive voltage and the load. This means that the load now is directly referenced to ground and the current measured is always correct. High side sensing is difficult to accomplish with cheap setups since any amplification required needs to have a high Common Mode Rejection Ratio (CMRR) to remove the high voltage on both sides of the shunt and only give us the voltage across it. Cheap amplifier setups typically aren’t great at doing this.

Choosing the resistance of this shunt is a double-edged sword, which needs to be chosen depending on the application of the power logger. A large valued shunt - 1Ω for example – is good because it generates a 1V drop across it for every amp flowing through it, however, this drops the output voltage. This becomes an issue since our power logger is intended to impact minimally on the output characteristics of the circuit. A smaller value shunt, such as 0.1Ω or even 0.01Ω, for example, interferes less with the output circuit, however, its smaller voltage drop means its harder to measure and requires more amplification to be useable with our Arduino. A 0.1Ω shunt would generate just 100mV with 1A flowing through it, using only 2% of the available measuring range of the Arduino.

The INA260 module from Adafruit. Very precise current, voltage, and power measurement.

There are a number of ways to accomplish this, ranging from fully integrated IC chips that are specifically designed to measure current with their own inbuilt shunts and digital conversion circuitry, to a cheap and simple Op-Amp amplifier circuit as we’re going to use.

When we were initially designing this project, we were planning to use the INA260 chip, which offers I2C communication of current and voltage measurement with a much more capable and accurate range. However, we want to demonstrate a ‘barebones’ analog solution that could be used for various low-level signals. It’s also customisable so it can be used to measure many different ranges of currents and voltages. For this, we’re using the very common LM358 op-amp. This chip isn’t expensive but is suitable for a simple amplifier circuit. By choosing appropriately sized feedback resistors, we can create a desired gain to amplify the drop across the shunt to a usable voltage for the Arduino.

Relay

We’re also including a high-side relay for enabling or disabling the load through software. This turns our power logger into an automatic switch that can be actuated when certain conditions are met! For example, we could specify that we want the load to be disconnected when it reaches 10Wh of energy used, or the load draws under 5A current at any point. You’ll notice in our schematic the relay is connected after the voltage measuring circuit, so even if the relay has opened the circuit, we can still measure the voltage of the source. To drive the relay, we’re using a MOSFET connected to a digital pin of the Arduino, with a flyback diode to protect against inductive spikes of the solenoid inside the relay.

Limitations

It shouldn’t come as a surprise that a device running on a standard Arduino chip isn’t capable of making super precise measurements. The Arduino chip we’re using only has access to a 10-bit Analog-to-digital converter, which means we can only sample 1024 different voltages between 0 and 5V – a precision of about 5mV. Of course, we could go one step further and use a dedicated ADC chip, with potentially 16, 24, or 32 bits of precision to really dial this power logger in. But, as a general design philosophy, choosing what not to do is just as important as choosing what to do. We want to keep this project simple as possible both for the sake of understanding the concepts of measuring power, and to reduce any problems associated with adding extra components.

It’s worth acknowledging that while this project may not be necessarily super precise, it certainly can be accurate! What we mean by this is while our measured values may be in comparatively large steps and will not represent the real world precisely, we will be able to calibrate our power logger so we can remove any offsets and unwanted trends in the values we are reading.

Fundamental Build:

Breadboard Prototype

Parts Required:JaycarAltronicsCore Electronics
1 x Dot Matrix White on Blue LCD 20x4 CharacterQP5522-ADA198
1 x 40 Pins Male Header StripsHM3212P5430FIT0084
1 x LM358 Op-ampZL3358Z2540CE05262
1 x RGB Illuminated Rotary Encoder--COM-15141
1 x 15Ω 10W Ceramic Resistor or similar values* %RR3354R0425KIT-13053
1 x Relay SPDT Sealed - 10A (G5LE)SY4066S4160CCOM-15207
1 x 1N4001 Diodes or EquivalentZR1004Z0109COM-14884
1 x 5.1V Zener DiodeZR1403Z0614COM-10301
1 x Arduino Uno or compatibleXC4410Z6280A000066
1 x N-channel MOSFET (30N06 or similar)ZT2466Z1537COM-10213
1 x 0.1Ω 50W Power Resistor ^RR3206R0401002-284-HS10-0-1
2 x 220k Resistors*RR0628R7614FIT0119
6 x 10k Resistors*RR0596R7582COM-10969
1 x 680k Resistor*RR0640R7626FIT0119
2 x 10k Horizontal TrimpotsRT4360R2480BCOM-09806
4 x 0.1µF Ceramic Capacitor or EquivalentRC5496R2930AFIT0119
1 x 10µF Electrolytic CapacitorRE6066R4767CE05274

Parts Required:

* Quantity required, may only be sold in packs. A breadboard and prototyping hardware are also required.

% A variety of 10W ceramic resistors for testing. In our test, we used a 15Ω 10W.

^ We couldn't find the exact shunt resistor we used in our build from our suppliers, so we've provided some similiar ones with lower power ratings. Be sure to check the power rating of the unit you use.

Let’s get to building. There are two main parts to our fundamental build, the analog measurement and amplification, and the digital logic and display circuitry.

The first step of the fundamental build is building the current measurement. Since we’re building the circuitry on a breadboard, we can connect our Arduino Uno later to the points we need to measure.

Setting up the LM358 Op-Amp is pretty simple, we just need to hook up the two power rails to 5V and ground – that’s pin 8 and 4 respectively. Since the LM358 is a dual package, it includes two op-amps for both our voltage offset and our current amplification circuitry. It’s also a good idea to add a 1µF capacitor between pin 8 and ground to decouple the LM358’s power rails and provide more stable operation.

Next up, we can start to add the four resistors that set the gain to amplify our current signal. We are using 220kΩ and 10kΩ resistors to set our gain, which should be around 22 depending on the tolerance of your resistors. That is, the voltage drop across the current shunt will be amplified 22 times (Gain = R2/R1) larger, giving us a measurement range of about 2A at 5V. Depending on the current range desired, feel free to swap out the resistors for smaller or larger gains. It’s important that the two pairs of resistors for both the non-inverting and inverting sides are identical in value, otherwise, one side will be amplified more than the other. You’ll notice we’re using 10kΩ carbon-film resistors, which isn’t optimal as they have a 5% tolerance and thus are likely to have a disparity in resistance. In your own build, we recommend using 1% (or less) tolerance metal-film resistors which should be very close in their values. The yellow wire connected to the output of the other op-amp will be configured in the next step to produce an offset voltage.

The purpose of this circuit is to compensate for the offset voltage of the op-amp, a characteristic that requires a small voltage to be applied across the terminals to correctly produce zero volts at the output. This is because an op amp cannot measure all the way to its supply rails, and considering that we are amplifying the difference across the op-amp’s terminals, any voltage offset we have will be amplified too! The LM358’s datasheet reports a typical 2mV offset across the terminals, which will be amplified to 44mV at the output.

This circuit simply uses a potentiometer in a voltage divider configuration to produce a small voltage (Around 70mV) to compensate for this, which can be adjusted down until the output reads 0 volts. We used a 680k resistor and a 10k horizontal potentiometer, which should do the trick. We also need to hook up the output of the op-amp back to its inverting input to produce a voltage follower. Note that the 680k resistor won’t be connected to 5V, and is instead connected to the 5V analog reference pin (AREF) on the Arduino to directly reference values read from the op-amp’s output to the Arduino’s ADC.

The voltage measurement circuit operates on the high-side of the load, and involves a voltage divider and a relay to monitor and control whether the load is enabled or not. Like the current measurement circuit, setting different resistors will change the range of the maximum voltage that can be read.

We used a 300k and a 100k resistor to produce a maximum range of 0-20V. We suggest choosing values that are the most useful for your desired applications, considering that the larger the range, the lower the accuracy due to the Arduino’s 10-bit ADC. For example, if you plan to use the power logger with microcontroller projects only, a 60k and a 10k resistor would produce a 0-6V measurement range. The range can be determined with the voltage divider equation with 5V as the maximum value read by the Arduino: 5V x R1 / (R1 + R2).

To protect against voltages above the maximum range, it’s recommended to add a 5.1V Zener diode to short any high voltages to ground. We also added a 100nF capacitor between the voltage divider and ground to provide more stable readings of the voltage.

As mentioned in the How It Works section, we need to connect the relay circuit after the voltage measurement circuit so we can still measure the power supply’s voltage. The relay we used is 12V, and unfortunately, the 5V rail does not produce enough current when connected to the relay to close the contacts. To solve this problem, we used an external 9V battery to provide enough current to close the relay when required. In our final circuit, the battery will be used to power the entire power logger anyway, so this is not an unnecessary addition. To sink the current, a low-side N-channel MOSFET can be used in series with the relay’s coil. We can simply drive the MOSFET by applying a voltage to its gate via the Arduino. A 10kΩ pulldown resistor is also needed to keep the MOSFET in a known state when being controlled by the Arduino.

The relay itself is not breadboard compatible in terms of spacing, which led to a bit of jamming and bending pins. When making this circuit at home, it might be a better idea to use a premade breakout board or solder on jumper wires to the relay.

It’s super important to add a ‘flyback’ diode to the relay, otherwise, the reverse voltage created when the coil is de-energized could cause damage to components. It’s super simple to do, just add a general-purpose diode such as a 1N4007 in the reverse direction to the relay.

We can then connect our load and shunt resistors. These will be in series, connected to a lab bench power supply so we can monitor current and voltage and compare it roughly to any values we read. As a temporary setup for the fundamental build, we used alligator clips to connect everything up outside of the breadboard. Since our shunt is low-side, the positive end of the power supply needs to be connected to the load resistor. Depending on the size of your load resistor, you may find that it gets very hot! When testing the circuit, use low input voltages at first to ensure you don’t exceed the power rating of the resistor.

And that’s the heavy lifting of the circuit done, now we just need a way to control the power logger! There are a number of options to accomplish this, ranging from buttons, to a digital only interface such as a website over WiFi. We’re opting to use a simple rotary encoder set up with an LCD display. This is a fairly common route with bench equipment as it’s effectively possible to navigate menus and select options only by rotating the knob and pushing in the button. The rotary encoder we’re using from Core-Electronics includes inbuilt RGB LEDs, which can be used to display the status of the device its used with or perhaps providing feedback by lighting up when a press is acknowledged.

For those unfamiliar, rotary encoders may just look like a fancy potentiometer, but their operation is very different. Potentiometers have ‘absolute’ position, so their limits of movement are usually less than a full rotation. Rotary encoders have distinctive ‘steps’ when turning, and can be turned indefinitely in any direction – they have two switches, outputting signals corresponding to the direction of the rotary encoder. Many also have pushbuttons built in, which can be used to select options on menus. Since many rotary encoders are not breadboard compatible, we suggest to either use one with a breakout board included or solder on header cables as we did. If you go this route, be sure to add heatshrink to prevent shorts on the pins.

The LCD display we’re using is the 20x4 dot matrix display from Jaycar, which is an incredibly cost-effective unit for displaying varying sets of information. It only needs six digital pins to run, and super easy to use with Arduino code. A small breadboard was used for the ‘interface’ side of the power logger, mounting the LCD and rotary encoder separately from the current and voltage measuring circuitry.

There are a couple of connections to get the LCD display running, including its three ground connections to the following pins: VSS (Ground), RW (Read/Write), and K (Backlight Cathode). The display also needs 5V power to the VDD pin and the A pin, which is the anode of the backlight LED. This LCD module’s backlight is safe to connect directly to 5V since it internally includes a 51Ω resistor. The VO pin controls the display contrast, which we suggest using a 10kΩ potentiometer to make it adjustable. The pins on the potentiometer need to be connected to 5V and Ground, and the middle goes to VO. Regarding the data wires of the LCD display, we’ll come back to them when we wire both the interface circuit and the measurement circuit to the Arduino Uno.

There are two banks of pins on the encoder, one for the stepping outputs that pulse depending on which direction the encoder moves, and one for providing power to the RGB LED and inbuilt pushbutton. The RGB LED circuit is common anode, so it needs to be connected to 5V. Each individual colour can be pulled to ground to enable it, with appropriate resistors. Since the red LED has a lower forward voltage than the other colours, we are using a 150Ω resistor to appropriately limit current and 100Ω for the others. The 10kΩ pulldown resistor can be added to the pushbutton.

The stepping outputs have a common connection between them, which we suggest debouncing with two 100nF capacitors. The ‘chattering’ of the outputs can be difficult to deal with software-side, so this approach should provide cleaner reading for the Arduino.

Now all that’s left is to connect the interface and measurement boards to the Arduino Uno itself. It is not necessary to use an Arduino Uno specifically, any board based on the ATmega328P (the Nano, for example) should be compatible.

Note that we aren’t showing detailed photos for the wiring here, because the jumper wires are pretty hard to navigate – the Fritzing or schematic will be much more helpful!

The Code

void setup() {
  // put your setup code here, to run once:
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(RELAY_PIN, OUTPUT);
  pinMode(lightR, OUTPUT);
  pinMode(lightG, OUTPUT);
  pinMode(lightB, OUTPUT);
  digitalWrite(lightR, HIGH);
  digitalWrite(lightG, HIGH);
  digitalWrite(lightB, HIGH);
  pinMode(encoderA, INPUT_PULLUP);
  pinMode(encoderB, INPUT_PULLUP);
  pinMode(encoderButton, INPUT);
  attachInterrupt(digitalPinToInterrupt(encoderA), encoderCheck, FALLING);
  attachInterrupt(digitalPinToInterrupt(encoderB), encoderCheck, FALLING);
  Serial.begin(115200);
  lcd.begin(20, 4);
  lcd.setCursor(0, 0);
  lcd.print("DIYODE Power Logger");
  lcd.setCursor(0, 1);
  lcd.print("--------------------");
}

The code for this project can, ultimately, can be made as simple or as complex as desired. Since we have direct access to our voltage and current measurement, we could do anything from self-calibration to calculating battery capacities. Those functions are secondary to getting working measurements of our load, so let’s get that going first!

We haven’t included all of the code here, however, you can see how we’re initialising the pin inputs above. We’re using the Arduino Uno’s two pin interrupts on Pin 2 and Pin 3 so we will never miss inputs from the rotary encoder. This is super important because missing encoder pulses when the Arduino is writing text to the LCD display or stuck in a delay() function will result in a frustrating and inconsistent interface.

When the Arduino is triggered by an interrupt, the code is paused at the current stage of execution to go to the requested function, in this case the “encoderCheck” function. When it’s complete, it continues doing what it was doing before. We’re not actually using the encoderCheck function in the fundamental build, but it’s good to check the rotary encoder’s movements are detected. Instead, we’ll be using the inbuilt pushbutton on pin 12 to enable or disable the relay, and change the RGB LED to red or green accordingly. This is included in our looping code, which you can see above.

Also included here is our LCD display code. After converting the voltage and current measurements to readable figures - explained in the next section – we then write them to the display. Note we also need to set the cursor position to change where text appears before writing the data. The ‘energy’ variable is the integral of power, so we need to multiply it by however long was between this and the last power reading to get a value in Joules.

Conversion Function

Converting the raw voltage and current measurements – between 0 and 1023 from the Arduino’s ADC – to readable values is more tricky than one might expect. One approach would be to, based on the theoretical behaviour of the op-amps and voltage divider, create a simple function that changes the input voltage to an output value. For example, since we know our current sensing gain to be 22, theoretically a 1A current through the 0.1Ω shunt should produce 2.2V at the Arduino’s analog pin. Unfortunately, due to our offset voltage, the imperfect behaviour of the op-amp, and even the actual resistance of the shunt resistor, this approach tends to fall short of being considered accurate.

void loop() {
  if(millis() - lastRecord >= LCD_REFRESH_DELAY) {
    updateLCD();
  }
  if(digitalRead(encoderButton) == HIGH) {
    lastRelayState = !lastRelayState;
    setRelay(lastRelayState);
    delay(450);  
  }
}
void setRelay(bool state) {
  digitalWrite(RELAY_PIN, state);
  digitalWrite(lightR, !state);
  digitalWrite(lightG, state);
}
void updateLCD() {
    // put your main code here, to run repeatedly:
  double current = 
currentConversion((double)analogRead(A0));
  double voltage = 
voltageConversion((double)analogRead(A1));
  double power = current * voltage;
  energy += 
power * (millis() - lastRecord) / (double)1000;
  lastRecord = millis();
  lcd.setCursor(0, 2);
  lcd.print(voltage);
  lcd.print("V");
  lcd.setCursor(7, 2);
  lcd.print(current);
  lcd.print("A");
  lcd.setCursor(14, 2);
  lcd.print(power);
  lcd.print("W");
  lcd.setCursor(0, 3);
  lcd.print(energy);
  lcd.print("J");
  lcd.setCursor(9, 3);
  String loadText = (!lastRelayState ? 
"ON " : "OFF");
  lcd.print("[Load " + loadText +"]");
}

The method we used was to output averaged, raw readings of the ADC voltage to the Serial monitor for a given current. By putting this figure and the reported current of the lab bench power supply into columns of a spreadsheet, we can use linear regression to calculate the correlation and offset between the reported and actual values. This essentially means we get an equation in the form:

i (actual current) = gradient x reading from ADC + offset

We know our op-amp is working correctly because of the gradient figure, ≈0.0022 representing a gain of 22 when scaled in the ADC. All we have to do now is to plug the gradient and offset into the code to convert between the voltage reading and the real value! The same process can be accomplished for the voltage.

const double gradient = 0.00223464283;
const double offset = -0.008949904924;
double currentConversion(double input) {
  return input * gradient + offset;
}

This process isn’t perfect, though. It should work well for the time it was recorded at, however, as the supply voltage or ambient temperature changes, characteristics such as thermal drift come into play. Op-Amps change offset voltages based on temperature, typically expressed in datasheets as μV/°C. When our main build is completed, we hope to add a ‘self-calibration’ process that allows the power logger to measure and calibrate itself based on a set of known resistors.

As you can see in our photos, the Fundamental Build works well, especially with some calibration. However, if there is poor grounding around the circuit, as can be common in breadboard circuits, we found the Arduino’s ADC has a hard time reading the right values of current and voltage. In our main build, we’ll be transitioning to a prototyping board for more reliable operation.

Main Build:

Perfboard Circuit

Parts Required:JaycarAltronicsCore Electronics
1 x Universal Perfboard Plate (2.54mm pitch)HP9550-ADA2670
1 x 9V Battery HolderPH9235S5048-
1 × 9V BatterySB2423S4970BCE05337
4 x M3 x 10mm Tapped Metal Spacers*HP0900H1216003-STOFFHEX_10MM
1 x 40 Pins Female Header StripHM3230P5390POLOLU-1014
1 x 40 Pins Male Header StripHM3212P5430PRT-12693
2 x Binding Post - BlackPT0454P9254PRT-09740
2 x Binding Post - RedPT0453P9252PRT-09739
1 x ATmega328P ProcessorZZ8727Z5216ADA805
1 x LM7805 Voltage RegulatorZV1505Z0505CE05291
1 x Breadboard mount SPDT Switch--ADA805
1 x 16MHz Quartz Oscillator CrystalSupplied with ZZ8727V1289ACOM-00536
2 x 22pF Ceramic CapacitorsSupplied with ZZ8727R2814CE05206
1 x FTDI Programmer BoardXC4464Z6225DFR0065
2 x 2-pin 2.54mm Terminal BlocksHM3130P2040AADA2138
1 × 8-Pin IC SocketPI6452P0530PRT-07937
1 x 28-Pin IC Socket (or 2 x 14)PI6510P0571PRT-07942
1 x DPDT Panel Mount SwitchSS0852S2010-

Parts Required:

* Quantity required, may only be sold in packs. Hook-up wire is also required.

Due to time constraints, we weren’t able to get a PCB delivered and assembled for this month’s issue. Next month, we’re aiming to compact this main build process into a single PCB and significantly reduce the complexity of the project. For the time being though, we’ll show you how to assemble the Power Logger with DIY materials.

The first thing worth noting is that the main build perfboard will have a fair number of components in a small area, so it’s important to be clean and compact with soldering and wiring. We wanted to keep the build as small as possible so its enclosure fits on small 3D printers and takes up little room on a workbench. Since there’s just one mainboard, we can attach all external parts of the project onto it via headers. We recommend following the Fritzing layout and schematic when building the project as there are connections on both sides of the board and small ones are easy to miss!

We won’t be going into every step in detail since we’ve already discussed how most parts of the circuit work in the Fundamental Build. There are a couple differences, including the barebones Arduino chip, the 5V regulator and the programmer board.

First up, we need to solder in the headers for connecting the interface parts and banana plugs. This must be done first so we know where to place key components accordingly, without worrying about overlapping on mounting locations.

The 16-long header bank at the bottom of the board connects to the 20x4 LCD display, which is soldered into the bottom-left corner. Solder one end at a time onto the perfboard before ensuring it’s seated correctly, then solder in the remaining pins. The screw terminals can be seated opposite each other on the board, which will be connected to the input and output terminals. We recommend using high-quality screw terminals here, as the ones we used had a nasty habit of poorly gripping the terminal wires. Good ones include metal clamps that grip the entire width of the wire thread. The sockets for the ICs need to be added, which we recommend to avoid the arduous task of completely removing and resoldering a replacement IC if one is broken. We suggest placing these in a location and orientation that will be most convenient to connect nearby components to.

The first part of the circuit that should be finished is the Arduino power and ground wiring. Since, unlike the fundamental build, we’re building this as a barebones Arduino chip without the Arduino Uno’s supporting circuitry, we need to add our own. There are two ground and VCC connections on the ATmega328, sitting opposite each other and one pin diagonally across on the pinout. Below the ground connections are two XTAL pins for a 16MHz quartz crystal for setting the clock frequency. The crystal should bridge these connections and, on both sides, two 22pF capacitors should be used for decoupling to ground. Since the circuitry here is so close to the LCD pins, we suggest running the ground traces of the Arduino along with the same pins of the LCD to save space.

The ATmega328 also includes a Reset pin on pin 1, which needs to pulled high to 5V unless a reset is desired, in which case it can be connected to ground. Since we wish to save space on the board, we’re omitting a reset pushbutton here and will simply use a 10kΩ resistor as a pullup. The FTDI programmer, which we’ll discuss later, can also reset the Arduino via a 0.1µF capacitor to this pin.

Image shown upside down to show connections better

The LCD header pins need six connections to work properly with the Arduino. The four data pins connect directly to the corresponding data pins on the Arduino, e.g. 4-D4, 5-D5, etc. These are on the underside of the board as this area is occupied on the top side by the oscillator crystal. The R/S and Enable pins connect to the A4 and A5 pins, which are on the opposite side of the ATmega chip. At this point, we also added a 10kΩ potentiometer on the VO pin to adjust contrast.

The Op-amp circuit must be connected carefully to avoid connecting the resistors in the wrong way. As mentioned in the fundamental build process, it’s highly recommended to use metal-film resistors here with low tolerances to correctly amplify the signal. We had to connect a 220kΩ resistor vertically to save space in this area.

Once the current sense amplifier is complete, it’s then just a matter of connecting the offset circuit with a 680kΩ resistor and a 10kΩ potentiometer. Don’t forget to connect the LM358 chip to 5V and ground.

The high-side circuit will handle the measurement of the power supply voltage, and the relay wires. Since the relays we’re using do not have 0.1” pin spacing and also have quite wide pins, we need to mount the relay somewhere else in the chassis and connect external wires to it. This relay is controlled by the N-channel MOSFET mounted on the board, and of course, don’t forget the flyback diode.

The voltage measurement circuitry is simply a voltage divider, with a 5.1V Zener diode and 100nF capacitor for smoothing out the readings. As we’ve mentioned, if you prefer a different voltage range, swap out the voltage divider for values you find most useful. This only needs to have a connection to pin A4.

Since we’re operating our power logger from a 9V battery, we need to add a regulator that will supply 5V to the Arduino, Op-amp and LCD display. Efficiency isn’t our priority in this project, however, if more efficiency is desired a DC-DC buck converter could be used, which would remove losses from heat dissipation of the 7805. Current isn’t super demanding for this project, most of which will come from the LCD display, Arduino and RGB encoder lights.

Note: Not shown in this image is the power switch we later added, which acts as a simple power switch for the project (when the one on the enclosure is not used) and prevents the 7805 from operating when the FTDI programmer is connected and supplying 5V.

3D Printed Enclosure

3D Printing for this project is completely optional, however, if you choose to do so, you’ll be able to package the power logger up into a neat and completely portable package that can be taken anywhere. The 3D prints required are fairly simple and can be accomplished on a small printer such as the Flashforge Finder as we used, with a print area of only 140mm in every dimension. When printing, attempt to print everything flat so minimal support is needed. Since there are a lot of flat surfaces in the models, you may find that the prints are very prone to warping away from the bed. To avoid this problem, be sure to level your print bed or add some form of adhesive to it.

The faceplate is used to mount the LCD display, encoder and input/output banana plugs. It also includes some labels so it’s easy to tell how to connect the circuit. The main enclosure houses all the remaining electronics and holds everything together. We had some trouble getting the LCD mounting holes to fit, so you may have to file out existing or drill new holes depending on your printer’s tolerance.

The main enclosure includes mounting holes for the shunt resistor, 9V battery and relay. Use appropriately fitting screws for each, which will either be M2 or M3 screws. We also added a couple of washers between the shunt resistor and the plastic to prevent direct contact. While it shouldn’t get very hot due to its very low resistance (According to P = I^2 x R) and heatsinking, this is just a precaution.

The only thing left to do is plug everything in! For the banana terminals, you can either wrap wire around them and tighten down with the nuts, add spade connectors, or solder them directly to the connector depending on what type you have. Finally, push in the header pins for the encoder and connect the battery holder.

Testing

The handy thing about building a circuit with the same pin assignments is that it’s just a simple matter of uploading the same code as the Fundamental Build. With any luck, the power logger should start right up, exactly the same way as the previous build. Uploading the code needs to be done through an FTDI programmer with a USB port, but most settings in the Arduino IDE can be left as-is.

NEXT MONTH: PCB Build

While the main build of the Power Logger is a success, we weren’t totally happy with the overall package of the project. There are many wires running through the chassis and soldering all of the different components onto a small perfboard isn’t as neat as desired.

Next month, we’re planning to design and order a PCB that will compact all of the parts of this project onto a PCB. It’ll still operate the same way, however it’ll hopefully be much easier to solder together and use. This is especially true if you aren’t confident in soldering your own wires between components and fixing any issues that arise as a result of errors when doing so. We had a number of issues after completing the board, all of which were a result of simple mistakes when soldering.

This means that the project will be kit-ready, and can virtually be used with only the parts soldered onto the board. 3D printing isn’t totally necessary as the terminals and interface hardware is mounted onto the board directly. However, we’re still planning to build an enclosure similar to this month’s project to add an aesthetic finish and to protect against short-circuits. We're also going to polish the menu system and add the capability to automatically perform analysis on the power data it collects!

If you built this first part of the project, or came up some clever modifications or improvements, let us know at @diyodemag. We’d love to see what is possible.

Liam Davies

Liam Davies

DIYODE Staff Writer