A low-cost current measuring technique for IoT devices – DIY

Everything in engineering is about utilizing your resources. In our case, we care about CPU or memory usage of our algorithms (at least in software engineering we do.) Yet, power consumption plays a vital role in the battery life of our IoT devices.

You will want to examine and identify what part of your code, algorithm is draining your power source. Nothing provides better results than an experimental observation that is verifiable and repeatable. I will present you with an inexpensive technique to measure power consumption.

We will begin with a theoretical introduction. Second, we will make an analysis. Third, we will compare our results with the uCurrent Gold. The uCurrent Gold can be considered as the de-facto standard in the IoT community.

My intention is not to persuade anyone of not using the uCurrent Gold. It has a wider frequency bandwidth and current amplification range. The uCurrent Gold is used as the source of truth. This is somewhat a viable and low-cost solution that you can build in an hour or less and will cost you a little-bit less than 10 US$ for the amplifier.

Theoretical introduction and definition of terms

In this article, I will use relative terms like fast and slow, for the sake of clarity. I will explain how to determine the resistance and how to pick an amplifier. This work is a design for the milliamp range. Its intention is not to observe the sleep currents of your IoT device. All these devices are wireless, so radio communication consumes some “visible energy.”

You can use a multi-meter to measure constant current usage. But, when the current changes at a higher frequency rate, matters become a little trickier. A simple diagram is shown in figure 1.

Measuring current with ammeter.
Figure 1, Ammeter in serial connection with the power source and load

First, the sampling speed becomes a crucial factor. If the current consumption changes fast, which of course, it does on an RF stacked up MCU, e.q. the ESP32, which I will refer to on this site and in this piece. For example, our multi-meter can only sample 6 points in a second. We can not see the changes that may happen between two sampled points. Everything quicker than 3 Hz is “invisible” to our eyes), according to the sampling theorem.

Thus, we would like a plot to see the current change. We need an oscilloscope (or some data logging device.) We need to convert the continuous signal into a discrete form, such we can work with it.

Measuring current is not as straightforward as measuring a voltage. We need to find a convenient way to convert current into voltage. In other words, we need to have a current probe since the oscilloscope plots voltage in the time domain.

Shunt resistor and current measurement

The uCurrent Gold is a current to voltage converter circuit. If you are in need and cannot wait for it to arrive, I propose to use a simple instrumentation amplifier to save time and money. The basic idea behind the “current-to-voltage” transformation is in the shunt resistor. A shunt resistor is a resistor between the power source (battery) and your IoT device. By applying Ohm law, as shown in equation 1, the current that passes through the resistor will produce a voltage (as shown in equation 2.) Since we know the shunt resistance, calculating the current consumption is easy, shown in equation 3.

(1)   \begin{equation*}     I=\frac{U}{R} \end{equation*}

(2)   \begin{equation*}     V_{SHUNT}=I*R \end{equation*}

(3)   \begin{equation*}     I=\frac{V_{SHUNT}}{R} \end{equation*}

Shunt resistor, voltage difference.
Figure 2. Simple schematic of our shunt resistor between power source and the load.

Kirchhoff’s voltage law states: the directed sum of the potential differences (voltages) around any closed loop is zero. [Wiki]. This statement (Figure 2) can be transformed into equation 4.

(4)   \begin{equation*}  VDC=V_{SHUNT}+V_{LOAD}=IR_{SHUNT} + IR_{LOAD} \end{equation*}

By looking at equation 4, we can transform it into equation 5.

(5)   \begin{equation*}  V_{LOAD}=VDC-V_{SHUNT}  \end{equation*}

By looking at equations 4 and 5, we can immediately see the restricting factors of our method. The shunt resistance is the bottleneck. Firstly, because of its voltage drop. Secondly, limiting the current flow.

If the resistance is too large and the load significant, our device under test may not even start. That is due to the voltage drop, as well as limiting the passing current. The voltage at the load is not its operational voltage, nor the current is available required by the IoT device. Probably, the IoT device would not even start.

Another drawback of our method is the temperature coefficient of the resistor. The resistance starts to vary with temperature fluctuation. That may influence our voltage drop. We will ignore it for now.

To avoid the voltage drop and current supply issues, we must use small resistance values. The lower the resistance is, the lower the voltage drop will be. The same holds for the current decrease, mathematically expressed as in equation 6.

(6)   \begin{equation*}  I=\frac{U}{R} =>  \lim_{R\to0} \frac{U}{R} =\infty \end{equation*}

We should be aware of the operational voltage of our device under test (DUT.) The supplied voltage (VDC), subtracted by the maximal voltage drop, should not be below the lowest operating voltage of the DUT. Such information is in the datasheet for the DUT (e.q. ESP32 datasheet.)

Well, we did not completely solve the problem, yet. Choosing the resistance value can be vague. If the resistance is too low, we will have a hard time picking an amplifier. The amplifier must meet all the constraints when used with a high amplification gain.

The intended voltage drop at the shunt resistor will be in the range between 0.1mV and 100mV at most. If you are looking for the answer, how I obtained these values, do not worry, it will become immediately evident. I decided to use a resistor of 0.1 Ohm, and the currents I want to observe are between 1mA and 1A (0.10.001=0.0001V and 0.11=0.1V.)

Amplifying the voltage drop on the shunt resistor

My goal is to amplify the voltage drop on the shunt resistor. Besides, we do not want to add and multiply other adversary sources of errors. These constraints can be met by understanding different interdependent properties of the amplifier.

Some well-known “sources of errors” in amplifiers are: offset voltage, temperature voltage drift, non-linearities in amplification, slew rate, common-mode rejection ratio (CMRR), and gain bandwidth. Let us ignore the not mentioned “sources” of errors, for now. If we select the amplifier without consideration, these parameters will affect the result. The amplified voltage drop may be affected by orders of magnitude. If the amplifier properties do not meet our application, they will boost the error proportion. In that case, the sampled result values would be of no use. They would not portray the actual current consumption of the DUT.

Input offset voltage

I will not go into the details, but these parameters can be our archenemies if they are poorly selected. For instance, the input offset voltage error would be the added voltage to the sensed voltage on the shunt resistor. Let us assume the amplifier has an offset voltage of 7mV, and the sensed voltage is 100mV. The amplified result could be off by 7%, as explained by Paul Pickering. If the sensed voltage is 100 mV and the input offset voltage is 0.25 mV, the resulting error is only 0.25% now. The output voltage, from the amplifier, is given in equation 7.

(7)   \begin{equation*}  V_{OUT} = (V_{SENSE}+V_{OFFSET})*GAIN \end{equation*}


    \[    V_{SENSE}=V_{SHUNT} \]

These 7mV are dynamically changing according to the normal distribution, otherwise, we could eliminate the error from the result. Of course, the error “grows” the smaller the input signal gets.

At this point, we know that the offset voltage plays an important role. But, the ratio between sensed voltage and the offset voltage is far-reaching. The ideal amplifier does not exist. An example, assume the input signal is between 1V and 5V, and we need to amplify it ten times. If the offset is ~0.250mV the result will lie between 10.0025V and 50.0025V. If our ADC resolution is 50 mV, then the offset will not affect our outcomes, and we can live with it.

Gain-Bandwidth product and Bode plot

Another phenomenon that comes into play is the gain-bandwidth product. We want our amplifier to linearly amplify our input signal. That is our goal, most of the time, to achieve the linearity in anything we design (the math becomes then easy.) Although the bandwidth of the amplifier is a function of the signal frequency. In other words, the output is linear for input signal under a particular signal frequency. Once we go past this frequency, we can not guarantee the amplification linearity. That implies the shape of the output signal is not proportional to the input signal shape. One way to check the bandwidth of our amplifier is to look into the datasheet or generate a Bode plot.

“Among his several important contributions to circuit theory and control theory, engineer Hendrik Wade Bode, while working at Bell Labs in the 1930s, devised a simple but accurate method for graphing gain and phase-shift plots. These bear his name, Bode gain plot and Bode phase plot” [Wiki].

You will need a frequency generator and an oscilloscope to generate a Bode plot. I will use the Analog Discovery by Digilent since it includes both. In the following video, the Bode plot of my amplifier circuit can be seen. The amplification linearity, as well as the phase shift, can be seen. It matches pretty much the one in the datasheet. These plots are in the frequency domain (the x-axis.)

The amplification drop, as well as a phase shift of 180 degrees, becomes visible at the end of the clip. That is the nonproportional shape change. That is where the amplification process becomes unstable. In plain English, the output signal is not a good representation of the input signal. It becomes visible in the time domain as well. The yellow sine wave is the input/source signal we want to amplify. The blue sine wave is the amplified output signal and it is scaled to match the yellow sine wave since otherwise it would not fit on screen. The blue output signal is 11 times amplified the yellow source signal.

As the signal frequency increases, the plot goes further right. Thus, with higher frequency, comes the instability. The second vertical red line in the chart is at -3 dB compared to the first vertical red line, which is the gain I have configured the amplifier (20.72 dB which is a factor of ~11.) At the -3 dB point, the output is basically worthless.

(8)   \begin{equation*}  GAIN(dB) = 20\log _{10} (\frac{V_{OUTPUT}}{V_{INPUT}})=20\log_{10} A \end{equation*}

where A is the amplification factor

    \[    A=\frac{V_{OUTPUT}}{V_{INPUT}} \]

Slew rate

We will define the slew rate. The slew rate is the change of voltage per unit of time. Slew rate unit is V/μs. “When given for the output of a circuit, such as an amplifier, the slew rate specification guarantees that the speed of the output signal transition will be at least the given minimum, or at most the given maximum” [Wiki]. This property defines how fast the voltage can rise, input vs. output. A good depiction of the effect is in figure 3.

Slew rate image
Figure 3. Slew rate depicted as how fast the output signal can rise compared to the input signal. Image courtesy of electronics notes

It is calculated using equation 9. Let us introduce an example of how the formula may be applied. We want to use the input frequency of 635 kHz. After the amplification, the output voltage peak is at 1V. Then we can calculate it by inserting the terms into the equation. The required slew rate of the amplifier would be ~3.99 V/µs.

(9)   \begin{equation*}  \text{Slew rate}[\frac{V}{\mu s}] = \frac{2*\pi*f*V_{PEAK}[V}{1000000[\mu s]} \end{equation*}


    \[    f=\text{frequency \quad } V_{PEAK}=\text{Maximum output peak} \]

    \[    \text{Slew rate} = \frac{2*\pi*635000Hz*1V}{1000000\mu s} \approx 3.99 \frac{V}{\mu s} \]

This value impacts, the earlier mentioned, gain-bandwidth product. It will contribute to the inconsistencies in the output wave shape. Higher voltage output requires a higher slew rate. Thus, in my experiment, I used the gain of ~11. If I would have had used the gain of 100. The output would be ~10V, thus the required slew rate of ~39.9V/µs.

Common-mode rejection ratio (CMRR)

The common-mode rejection ratio (CMRR) is the last term we will introduce. “The common-mode rejection ratio (CMRR) of a differential amplifier (or other device) is a metric used to quantify the ability of the device to reject common-mode signals, i.e. those that appear simultaneously and in-phase on both inputs” [Wiki].

Having a high CMRR is usually a sign of an instrumentation amplifier that is resistant to noise. Since I described only the basics, there is a great introductory video on the Texas Instruments training site.


I had a couple of different instrumentation amplifiers lying around. The Texas Instruments INA128P had the most suitable characteristics I described earlier. If you cannot find the TI INA128P, you may look for another instrumentation amplifier. The properties are essential and should be similar or better. The thought process, how to derive the values, should be the same. It may have only a different wiring configuration, check that in the datasheet.

The INA128P had the most suitable characteristics when it comes to the input offset voltage, gain bandwidth and high CMRR. So it was an obvious choice to go with it. The offset voltage was typically 25uV. It had a linear gain-bandwidth frequency of 700 kHz at a gain of 20dB (gain factor of 10). It was easy to set the amplification with only one resistor (I used two 10K in parallel to get the 5K.)

According to the datasheet, the gain is given in the equation 10.

(10)   \begin{equation*}  G=1+\frac{50k}{R_{AMP}} \end{equation*}

where in my case

    \[    R_{AMP}=5k \]

The schematic is given in figure 4.

INA128 Current measurement schematic
Figure 4. Schematic of the amplifier with the load connected to it.

Keep in mind, this is an instrumentation amplifier, and the input common-mode voltage should not exceed 2 V less than the maximal power supply voltage. Put differently, VDC on the schematic should not exceed 18V-2V=16V. Since we will use this on our IoT devices that work on 3V, 3.3V, 5V, or less, we are good to go! If you do not have a negative power supply, you can use two 9V batteries connected in a serial connection.

The amplifier is not isolated!!! So if you are using it with a power supply connected to AC current, and an oscilloscope, avoid ground-loops.

The shunt resistor is a 0.1 Ohm, 1% 3W resistor, thus the size is so big. The rule of thumb is more precise components will lead to fewer deviations from the actual values. Avoid making such a large loop as I did with the gain resistor as it acts as a noise antenna. Well, do not expect a piece by Leonardo da Vinci, figure 5, and figure 6.

INA128 and PCB board, side view.
Figure 5. Shunt amplifier marked with red arrow. Gain amplifiers marked with blue arrow.
INA128 and PCB board, top view.
Figure 6. The gain amplifier loop is visible. AVOID LOOPS!

Results and comparison

In this section I will describe the test bed and compare the results.

Test setup

My test-bed diagram can be seen in figure 7. I used the ESP32 as the test load. The positive terminal of my power supply is connected to the positive input terminal of the uCurrent gold. The negative input terminal of the uCurrent gold is connected to the positive shunt terminal of the INA128 circuit. The negative terminal of the shunt resistor is connected to the positive VCC pin of the ESP32 board. GND pin of the ESP32 board is connected to the negative terminal of my power supply. The INA128 is supplied with +-9V, which is not shown in the diagram.

Output terminals from the uCurrent Gold are connected to the oscilloscope channel 1 of the Analog Discovery. Output terminals from the INA128 circuit are connected to the oscilloscope channel 2 of the Analog discovery. The Analog Discovery is attached to the notebook via a USB cable. The notebook runs Linux Ubuntu and Digilent’s software WaveForms.

Figure 7. Diagram of the test setup and how the measurements were compared.

You can see a video of the test setup, as well as a couple of photos.

Comparison of results

The yellow curve (channel 1) is the amplified output from the INA128P circuit. The blue curve (channel 2) is the output from uCurrent Gold. The red curve is equivalent to the yellow curve (channel 1) but divided with 1.1 to get the actual current consumption. The signal was sampled with a sampling rate of 1 MHz.

To compensate for the amplification of 11, we need to divide by 1.1. In other words, to get an amplification of 10. Amplification with 10 can be seen as if the Shunt resistor was 1 Ohm.

Figure 8. A few seconds of current analysis sampled with the Analog Discovery. uCurrent Gold (blue) and INA128P (yellow).

We can immediately see there is less noise in the yellow signal compared with the blue signal. This can be seen even better in figure 9.

Figure 9. Zoomed in current consumption of ESP32 with overlay of INA12P signal (red) over uCurrent Gold (blue)
Figure 10. Zoomed in current consumption. Red curve is less noisy and follows the blue curve precisely.
Figure 11. Zoomed in peak.

I did not expect the results to be so good since it is on an empty through hole prototype PCB. I will conclude my thoughts here.

If you have any questions, remarks regarding my test setup, or if you spot a mistake, please let me know and drop a comment.

Refik Hadzialic Written by:


  1. Sean Straw
    July 27, 2020

    I think your claim of building this for US$2 is a bit off – the InAmp you’re using has a current Q1 pricing of about US$11. Your readers might be interested where they might find it in the $2 budget.

    My go-to InAmp is the AD620BRZ, which has just slightly higher CMRR than your TI part. However, they’re a couple dollars more apiece.

    While current _draw_ of a circuit is straightforward, if someone goes to construct a metering circuit that can handle bidirectional current flow (discharge AND charge), they’ll need to bias the reading or use an amp with a negative rail.

    • Refik Hadzialic
      July 28, 2020

      You are right Sean, I just checked the price on the TI store, one-piece costs 8.82$. Thank you. I will correct it. If you need bi-directional current sensing, you could bias the REF pin with the bias voltage, if your range is 1A, then 1V (or a little bit above would be the way to go). Thank you for your comment.

  2. Brian
    July 29, 2020

    I’m not sure why you chose a gain of 11 rather than 10. To set the gain to 10 replace the 5 kOhm resister with a (50/9) kOhm value. Which is roughly 5.6 kOhm in parallel with a 680 kOhm and two 10 kOhms in series. The precision of the 5.6 kOhm resistor dominates, so 5% tolerance is probably good enough for the other three. The alternative is 18 100 kOhm resistors in parallel. This spreads the power disipation and maybe even averages out the tolerances.
    Cheers, Brian.

    • Refik Hadzialic
      July 30, 2020

      Hey Brian,

      to set the gain of 10, the required resistance would be 5.556k, according to the datasheet. I had two 10K resistors and it was easier. Since inside the WaveForms software, I could easily divide by 1.1. So the only reason why I set the gain of 11 was of practical nature. No other reason behind it. By setting the value to 11, I didn’t lose that much bandwidth. I will keep this in mind, your approach. I think I wouldn’t gain that much with the power dissipation since the current is small, however, averaging out the tolerance is something worth doing. Thanks for your question.

Leave a Reply

Your email address will not be published. Required fields are marked *