DIY wattmeter with an Arduino
Measures 21 parameters related to voltage, current and power. Suitable for AC and DC.
Fig. 1: Prototype of the Arduino wattmeter.
It is difficult or sometimes even impossible to measure power and energy with ordinary multimeters. To carry out such a measurement reliable and accurate, a special wattmeter is required. Because these meters are very expensive, a cheaper solution is presented here as a DIY wattmeter based on a Arduino Nano board.
This wattmeter measures the real power, apparent power, reactive power, phase and energy. Beside that, the wattmeter measures also the mean, RMS, standard deviation, maximum, minimum and frequency of both the voltage and current. And it can measure the area of the voltage (flux) and current (charge) and keeps track of the measure time. Depending on the used display two or four parameter can be read simultaneous.
As an ideally instrument should do; it makes no distinction between AC or DC. It all boils down by choosing the right parameter which all are mathematically justified calculated. The bandwidth is approximately 1.8 kHz for the voltage, current, real and apparent power. The bandwidth for reactive power and phase is limited to 50~60 Hz mains frequencies.
Considering that an Arduino isn't the most accurate board, still a reasonable measurement instrument can be made with it. When the prescribed components are used and after calibration an accuracy of 0.2 % over a temperature range of 10 °C can be achieved.
The Arduino code for this wattmeter is available as a text file: arduino-wattmeter-code-v1.0.
Read the safety instructions below.
To keep the circuit and construction as simple as possible, one sacrifice had to be made: The meter has fixed ranges for the voltage and current inputs. On the other hand, only a single amplifier is used, this to keep the burden voltage of the current measurement as low as possible.
Fig. 2: Circuit diagram of the Arduino wattmeter. The voltage and current range can be customized by changing R1 and R3. In this example the range is ±50 V, ±5 A.
The voltage is measured between the "COM" and "V" terminal. A voltage divider R1 and R2 reduces this voltage so it can be measured with the analog input A4 of the Arduino. The diodes D1, D2 protect the Arduino against overvoltages. The current to be measured flows from the "A" terminal through the fuse F1 and the shunt resistor R3 to the "COM" terminal. The current through R3 causes a voltage drop across it that is proportional to the current. Because this voltage is very small (±50 mV full range) it is amplified by IC1 with R4,5 before providing it to a analog input A5. The diodes D3,4 protect the electronics against voltage spikes.
In order to make it possible to measure positive as well as negative voltages, the "COM" voltage must lie at half the reference voltage. The used internal Arduino reference voltage is 1.1 V, so the "COM" voltage must be approximately 0.55 V. The impedance of this voltage must be reasonably low compared to R2. Because the Arduino reference voltage can handle only small loads, the half reference voltage is derived from the 5 V power supply with the voltage divider R6 & R7. This voltage may vary over time but will not influence the accuracy because it is also measured (input A6) and used in the calculations.
The measured parameters can be read from the 16*2 (or 16*4) character LCD-module that is connected by a 4 bit databus and 3 control signals to the Arduino. These parameters are selected by the four switches S1...4. The LED D7 is a overflow indicator and will light up if the voltage or current input is overloaded and the measurement isn't accurate anymore. The wattmeter is powered by a 9 VDC adapter connected to the Arduino VIN and GND. The current draw is approximately 75 mA.
Voltage & current range
Fig. 3: The analog input section of the wattmeter. Partial build underneath the Arduino board.
The voltage and current ranges are fixed and therefore the input circuitries must be adapted to the application wherein the wattmeter is used. When choosing a range, anticipate to higher peak values rather than the nominal value. For instance: when the wattmeter is used for a 12 V PV-system, the battery voltage can reach over 14 V and the open terminal voltage of a PV-panel could be high as 18 V. For the current values this could become much worse due to inrush currents. Keep in mind that the selected range concerns peak values. The peak value of a 100 Veff sinusoidal alternating voltage will be √2 higher: 141 V.
Voltage input attenuator
The voltage input attenuator is determined by the resistors R1 and R2. This resistor network will divide the input voltage so that the Arduino measures half reference voltage, 0.55 V, at maximum range. The resistor R2 has a fixed value of 10 kΩ, and the range is set by R1 and is calculated as:
If for instance a 50 V range is required, R1 must be 899 kΩ. Because this value isn't a standard value, the closest higher E12 value is 1 MΩ. The value for R1 is may never be chosen lower than 10 kΩ to retain the overvoltage protection. Therefore the lowest possible range is ±1.1 V.
The current range is determined by the resistive value of the shunt R3, the amplification and the analog input sensitivity. Because the Arduino input sensitivity is fixed at ±0.55 V and the amplification is also fixed at 10 times, the voltage drop across R3 at full range is ±55 mV. So the range is set by the value of R3 and can be calculated as:
If a 5 A range is required, R3 must be 0.011 Ω, and is rounded to 0.01 Ω.
Shunt resistor properties
Fig. 4: The advised Vishay-Dale shunt resistor.
The shunt resistor is a critical component and needs some special attention. The resistive value of resistors are subject to temperature changes. Not only by the ambient temperature, but also by self heating. To reduce the self heating of the shunt resistor, the allowable power dissipation must be quite overdimensioned. The specified power dissipation must be approximately 10 times higher than the real maximum dissipation. In the given circuit the shunt resistor dissipates 5 A · 50 mV = 0.25 W, so a 3 W type is suitable. If the shunt resistor has a temperature coefficient of 50 ppm/°C than a tolerance of 0.1% is feasible within a 20 °C temperature range. This is including the self heating of the shunt resistor and the temperature rise within the instrument casing. If a shunt resistor is used with a higher temperature coefficient it will become dominant. The initial tolerance is of less importance: this is compensated by the calibration.
The burden voltage across the shunt is chosen very small (50 mV max.), therefore the resolution is 50 μV at a four digit display. The consequence of this is that thermoelectric voltages at junctions with different metals become noticeable if there are temperature differences between both terminals. These temperature differences can easily occur due to different power dissipations of components surrounding the shunt. Even small differences in the solder joints on the shunt resistor can cause temperature differences. Most resistors generate significant thermoelectric voltages and are useless in this application. The advised resistor for the shunt is the VISHAY-DALE - WSL3637R0100FEA who has excellent properties.
The LTC1050 is a special rail-to-rail opamp with a low input offset voltage (5 μV) and a low input bias current (10 pA). Don't replace the opamp with any other type with unknown or worse specification.
Components analog section
All the resistors used in the analog section, R1, 2 and 4...7, are 0.25 W metal film types with a tolerance of 1 % and a temperature coefficient of 100 ppm/°C or better. The protection diodes D1...6 must have a very low reverse leakage current. However the specified 1N4184 isn't the most suitable type, it normally performs well. There is a fairly large spread in the reverse leakage current, therefore it is advisable to measure this leakage current. To do so, connect the diode in reverse direction in a series circuit with a voltmeter (Ri=10MΩ) and a 9 V battery. The voltage measured may not exceed 100 mV, what corresponds to 10 nA leakage current.
The wattmeter prototype shown in this article is build as a single PCB-unit to avoid external wirering to connectors. Only the fixed mounted riser board for the four push button switches is a kind of exception. It can be build on a Perfboard 80*100 mm large and is straight forward. Only the following needs special attention:
Fig. 5: Connections to the shunt.
The current is measured by a four point measurement to the shunt resistor R3. The resistor has four terminals for that reason: I+ & I- wherethrough the current flows, and S+ & S- whereof the burden voltage is sensed. this is shown in the photo beside. Observe the star point connection in the circuit diagram at the sense terminal S- on the "COM" side. All the connections to this artificial "null" may only be made at this point to avoid measurement errors. The last thing is the distinction between the digital ground used for the switches and display, and the analog ground used for the analog input circuit. Don't connect these two grounds together, the Arduino has an internal connection between these two grounds.
After soldering clean the circuit board and also the Arduino Nano board thoroughly with Isopropyl alcohol. This to eliminate leak currents due to the flux residue.
Table 1 shows the part list for the wattmeter. Note that the values for R1 and R3 depends on the desired voltage and current range. The carbon film resistors may be replaced by metal film resistors, but don't replace the metal film resistors by carbon film types.
Fig. 6: Layout and connection. Bigger version.
To let the software know for what voltage and current range the hardware is build, a conversion factor for both inputs ranges must be specified. The conversion factor for the voltage range is calculated by:
and the conversion factor for the current range is:
With the component values in the given circuit shown in figure 2, the conversion factor for the voltage range will be 1 MΩ + 10 kΩ / 10 kΩ = 101, and for the current range it is 1 kΩ / (10 mΩ · 10 kΩ) = 10. Both number must be filled in the code under "Calibration & Hardware Data" as shown in the code section below. Also the used display type is specified here.
/*********** Calibration & Hardware Data ***********/
float Vdiv = 101.0; // Voltage conversion factor
float Cdiv = 10.0; // Current conversion factor
const byte LCDlines = 2; // LCD: Number of lines
const byte LCDwidth = 16; // LCD: Number of character per line
The meter will now measure with a basic tolerance of ±10 %. This poor accuracy is mainly due to the tolerance of the internal reference voltage of the Arduino. But this can be improved to ±0.2 % by calibrating and adjusting the wattmeter.
To calibrate the wattmeter, a reliable multimeter and a stable adjustable power supply is needed. Be sure that the code with the raw conversion factors as calculated above is uploaded to the Arduino. Power up the wattmeter, power supply and multimeter and let them warm up for 30 minutes. Connect the power supply to the wattmeters voltage input and connect the multimeter in parallel at the wattmeter terminals. Set the voltage of the power supply at a value near the higher end of the voltage range and read the value on the multimeter Vref and wattmeter Vread. The new voltage conversion factor is calculated as:
Replace the Vdiv value in the code with this number.
Next the current range is calibrated and adjusted. Set the power supply in current limiting mode, first at 0 A. Connect the power supply, multimeter (current range) and wattmeter in series. Use the wattmeters current input. Set the power supply current at a value near the end of the wattmeters current range and read the multimeter Iref and wattmeter Iread. The new current conversion factor is calculated as:
Replace the Cdiv value in the code with this number.
Disconnect the wattmeter and upload the modified code. After this adjustment, calibrate the voltage and current range again to confirm the accuracy. Now the wattmeter will read voltage and current values with a much greater accuracy. Because the internal voltage reference and other components still changes with temperature, the accuracy will be 0.2 % within a 10 °C temperature range.
Fig. 7: Calibrating the voltage range.Fig. 8: Calibrating the current range.
Never use this wattmeter to measure on the mains grid or high voltage sources!
Fig. 9: Input terminals with safety banana sockets.
However it is strongly discouraged to use this wattmeter directly on mains voltages, it is unavoidable that people will still do so, I want to give some instructions to limit the risks:
- First of all: don't use an external adapter. The low-voltage power cord isn't suitable insulated to handle mains voltages. Also the bare metal connector can easily be touched and is therefore a serious safety risk. Build the power supply with the wattmeter inside a plastic enclosure, or use batteries.
- Use push-buttons with a long plastic shaft, so the touchable parts are at least at 6 mm distance from the conductive parts.
- Place the display behind an acrylic plate glued to the inside of the plastic enclosure.
- The resistor R1 can't withstand mains voltages. Replace R1 by two resistors in series with a equal resistive value who have the same total resistance as calculated.
- And finally use safety banana sockets for all three inputs terminals.
Fig. 10: Circuit diagram of the wattmeter connected to a power source and load.
The circuit diagram in figure 10 shows how the wattmeter is connected to a voltage source and the load. Figure 11 shows the same connection in a real life situation. Connect the voltage terminal to the point whereof the power must me measured, eg. voltage source or load, to eliminate measurement errors due to voltage drops across wires.
The polarity of the connections has a influence on the measurement results. If the voltage and current have the same polarity, the measured power is positive. If the polarities are opposite, the measured power is negative.
Fig. 11: Connecting the wattmeter to a power source and load.
Each display line holds one parameter. The parameters are freely selectable with the use of the control buttons. With the left button the line is selected, the display shows "....." at the parameter name placeholder. Now the parameter can be selected with the second button (parameter down) and third button (parameter up). Some parameters are resettable, see table 2. This reset function has a little protection to avoid accidentally resetting the values. To reset the parameters: hold down the fourth button (reset) and press the first button (line select).
The wattmeter is suitable for measurements on DC as well as AC systems. The real power and energy are always correctly measured without setting the instrument for a specific source. The same goes for measuring voltage and current and the selected parameter determines which property of the voltage or current is measured.
- The mean values measures the average value and is mainly used for DC-applications
- The sdev values measures the RMS value over the AC only portion. It is used for measuring on AC voltage sources and can also be used for measuring noise and ripple levels on DC systems.
- The RMS values measures the RMS-value over the total signal (AC+DC). It is used for impulse shaped AC & DC applications.
Fig. 12: Overloading the voltage input with the corresponding indicators.
kWh & Ah
The wattmeter measures the energy in the SI-unit: Joules (J), or Watt*seconds (Ws). To get the energy in kWh, the read energy in joules must be divided by 3600000 (3.6*10^6). Something similar is happening with the charge measurement. It is measured in the SI-unit Coulomb (C), or Ampere*seconds (As). To convert this in the common used Ampere*hour (Ah), divide the reading by 3600.
Voltage and current input overload
If a voltage or current is out of range the overload indication D7 will light up. At the same time an indicator "^" at the affected parameter is shown between the value and unit. The measured values are unreliable if there is an overload indication.
The wattmeter samples each input, the voltage on A4 (Vadc), current on A5 (Iadc) and null on A6 (Nadc), with 4808 samples per second. The null-value is subtracted from the measured voltage and current so the ADC-values can become positive as well as negative. The averaging of the input signals is done over Ns = 3200 samples and the time constant is 0.67 seconds. The conversion from the raw ADC-values to the real voltage and current values is done with a scale factor: For voltages this is Vscale = ADCsense * Vdiv, and for current Cscale = ADCsense * Cdiv. ADCsense is the ADC sensitivity: 1.1 V / 1024.
|Standard deviation voltage||Vsdev||V|
|Maximum voltage||Vmax||V||The highest instantaneous voltage sampled||Resettable|
|Minimum voltage||Vmin||V||The lowest instantaneous voltage sampled||Resettable|
|Voltage frequency||f (V)||Hz|
|Standard deviation current||Isdev||A|
|Maximum current||Imax||A||The highest instantaneous current sampled||Resettable|
|Minimum current||Imin||A||The lowest instantaneous current sampled||Resettable|
|Current frequency||f (I)||Hz|
|Apparent power||S||VA||Only valid for sinusoidal waveforms|
|Reactive power||Q||var||Only valid for sinusoidal waveforms|
|Maximum power||Pmax||W||The highest instantaneous power sampled||Resettable|
|Minimum power||Pmin||W||The lowest instantaneous power sampled||Resettable|
|Phase||φ||°||Only valid for sinusoidal waveforms|
|Time||t||s||Counter with pre-scaler running with the ADC-interrupt routine.||Resettable|
Download the Arduino wattmeter code here: arduino-wattmeter-code-v1.0.
ADC & multiplexer
The driving part of the program is the ADC-interrupt routine. The ADC-interrupt routine is called by the Analog to Digital Converter each time a conversion is finished and the results are available. To get a high bandwidth, the sample frequency is chosen as high as possible. Considering the amount of calculations that is performed by the interrupt routine, the sample frequency is set at 19231 Hz. This is not feasible with the standard Arduino analogRead function. Therefore the ADC is configured in free running mode. This ensures also that there is enough processing time left for the main program.
The ADC measures three inputs: the input voltage, the current and the null-reference. Because the Arduino processor has only one ADC and can only perform one conversion at a time, the inputs must be sampled in sequence. The selection of the inputs is done by the multiplexer set in the ADMUX register. Every time the ADC is ready and the interrupt routine is called, the next channel is selected. Note that when the ADC-interrupt routine is called the next conversion already is started. So, the new selected channel will only be handled at the next following conversion. The result of that conversion stands ready the interrupt after that. This implies that the ADC-result is that of two interrupt later than the MUX is set.
Fig. 13: ADC interrupt timing diagram. It shows the delay between writing the multiplexer and the conversion ready for that channel. Eg.: the interrupt routine that select analog input A7, processes the current (A5).
Program and data flow
The ADC interrupt routine does the first processing of the measured voltage and current. It calculates the square values for the RMS calculation and the product of the voltage and current for the power calculation. All these results and the voltage and current values are added a fixed number of times to obtain a first averaging. Beside this, the waveform period is detected and the number of periods and period time is counted for the frequency measurement. Also the button debouncing controlled by this interrupt routine. Altogether a quite large task considering the routine is called 19 thousand times per second. Therefore the tasks are divided over four interrupt calls.
All these results are transferred to the main program. Here a secondary averaging takes place. This secondary averaging is done with an array to get a more flowing presentation of the measured parameters. Four times per second all the parameters are calculated as floating point numbers from the averaged and directly from the ADC obtained values and put in the result array. Simultaneously the values are corrected for the sensitivity and calibration data. From these final results the presented values are picked to be displayed.