# Measuring bidirectional voltage drop across current shunt on positive rail

I want to measure a voltage drop across a current sensing resistor (in both polarities) on rails up to 30V using an Arduino / AVR ADC with 1V1 reference.

For background, this is a part of a battery monitoring system that needs to measure the current going in or out of the batteries / PSU / load. In this application, it is to support up to 10A measurement on voltages up to 30V.

I have a superficial knowledge of opamps, and I have come up with the following configuration:

The opamp is (hopefully) configured as a differential amplifier with 10x gain. The left side connects across a shunt on the positive connection (all grounds are bridged). I have tried adding some resistors to bias the output at 500mV, however, I don't know if it's right or how to systematically come up with the solution. Is this a correct solution? Does this bias method have a name?

I am planning to use LM358 as the opamp, would it work?

• There's dedicated chips that do all this for you, like the INA226. What's wrong with using one of those instead of reinventing the wheel? Commented Feb 20, 2022 at 19:50
• You can do it with 4 resistors (plus shunt) and two ADC inputs. No need for op amps or other chips. For reduced current consumption add a pair of MOSFETs to switch the connections on and off. Commented Feb 20, 2022 at 20:01
• You will have difficulty meeting any reasonable accuracy requirement using that approach and with the LM358 the common mode voltage will be out of bounds of the opamp. Commented Feb 20, 2022 at 20:01
• If you decide to do this, you should use the 3 op-amp version of the differential amplifier. The one op-amp version is very sensitive to slight deviations in resistances. Also, at this moment in time, parts are very difficult to procure, so I do understand why you would want to do this. The INA240 or INA226 (or whatever) would be much easier, but if those parts are on allocation then not so easy. Commented Feb 20, 2022 at 20:09
• Yes instrumentation amplifier configuration. I was not suggesting you buy the gold-plated LTC part. But the application section of LTC datasheets is like a free master class in analog design. The example on page 17 is exactly what you are trying to do, more or less. You still have to work through lots of details but it is a solid start. Commented Feb 20, 2022 at 20:30

Linear Tech (now part of Analog Devices) have a line of current sensing amplifiers that are perfect for this job (high-side sensing). Example: LTC6102 which can handle up to 60V. For bidirectional sensing you would use two of these to monitor charge vs. discharge current. See the datasheet.

More ideas here: https://www.analog.com/en/app-notes/an-105fa.html

• Nice. Know any that work between 250 V and 650 V? I could set aside my discrete mess, then. :)
– jonk
Commented Feb 20, 2022 at 21:34
• I added an appnote link. They show a solution for 500V. Commented Feb 20, 2022 at 23:05
• Thanks! I need to think more about the design. It's kind of ugly to me, right now. But I need to give it time to sink in. The design I have is "nice" to my eye. But perhaps that is because I've put time into it. So I need to give this a chance. Thanks for finding that! +1 just because I'm happy to find another topology and IC combination to consider...
– jonk
Commented Feb 21, 2022 at 5:13
• They show a couple of interesting ones using optocouplers, but I think the long-tail FET approach is a winner. Commented Feb 21, 2022 at 5:31
• @Antonio51 Floating the supply is an idea I've applied for regulating a high voltage rail, before. I've also used pairs of current mirrors that "float" apart from each other using resistors between them. And Analog Devices I use when I can afford them. ;) Nice, though. Thanks!!
– jonk
Commented Feb 21, 2022 at 21:47

Since you chose LM358, let’s see if we could make it work. If that’s the part you got to work with, you’ll get results now rather than whenever you get an inevitably more expensive and/or hard to get part that’d be more suited. LM358 should be available anywhere electronic components are sold, it’s one of the most basic active parts to have in one’s assortment.

LM358 is a tricky part to get going in this application. At low voltages, it doesn’t have much headroom. It has common mode across full temperature range of 0V to VCC-1.5V. It also cannot sink much current when the output is close to ground - just a couple uA across temperature range. As soon as you’re sinking 0.1mA or more, the output voltage is 1V at the minimum, although this can be overcome by adding a pull-down resistor to ground.

So, the differential amplifier is not the best solution with such an op-amp. Its common mode voltage is too high for LM358 at low voltages. But even at higher voltages, we could use a difference amplifier with gain 1 - with a twist :)

Instead of a diff-amp, let’s use an Improved Howland Current Pump, and use a load resistor to convert the current into voltage. This has benefits:

1. Common mode voltage can be set independently of the output current.

2. The output voltage range can be adjusted by scaling the current produced by the pump.

The circuit below demonstrates how it could be done.

## An Example Circuit

This one is tested and it works reasonably well between 5-30V across the op-amp’s temperature range. At room temperature, it works down to 4V supply voltage. Given more time, I probably could make it work across the op-amp’s full operating voltage range of 3V-30V, but you didn’t specify the lower battery voltage limit, so I didn’t bother :)

Resistors are 1% metal film.

There’s 0.1uF || 10uF decoupling across the op-amp’s power supply pins.

The current consumption is <2mA.

The full scale output voltage range on R2 is about 0.15V to 1.0V. Properly shielded and laid out, the resolution is ~30mA with a 10 bit ADC.

CircuitLab simulator can't handle this one and is downright misleading vs. real parts, so I didn't bother with that.

The PCB or breadboard layout must keep parasitic impedances in mind. Due to high node impedances, the circuit will need to be shielded to get rid of line frequency common mode interference.

I presume that you’re also measuring the battery voltage with the Arduino. Thus, you have the information necessary to detect when the battery voltage is below 8V. When that happens, the LVMODE output should be set to a logic high value. LVMODE can be driven from 3-5V logic outputs directly, perhaps through a 100k isolation resistor to limit the noise coupling from the MCU to the analog circuitry.

The 5kOhm potentiometer needs to be trimmed for maximum output impedance of the current pump. This is done by repeatedly flipping the “TRIM/OP” switch, and observing the change in voltage on the voltmeter M1 as the switch is flipped back and forth. When the trim is done properly, the voltage will not change when switching between the TRIM/OP positions. This trimming has to be done only once, since it’s independent of operating voltage, but the trimming procedure must be carried out at battery voltage of 6V minimum. Once trimming is done, the switch should be left in the OP position.

Q1 + U1b are a 280uA current source. This produces 0.13V drop across R2, and ensures that the current pump’s input is always positive. Note that a current source’s output impedance is very high: Q1’s drain (pin 3) acts like a resistor of several MOhms, paralleled with an ideal current sink. Thus, this circuit introduces the necessary offset voltage to set the operating point (0A value) of the primary current pump, but otherwise doesn’t affect the gains, output impedance, nor DC CMRR of said pump.

D1 and D2 drop about 1V and raise the op-amp’s common mode voltage when operating at higher supply voltages. Below 8-10V, the Arduino code uses Q2 to bypass the diodes.

R8 || C2 are the load, and convert current into voltage that’s then measured by the voltmeter M1 (during trimming) and by the A/D converter of the Arduino.

U1 a with R3, R4, R5, R6, R7 and R10 form the Improved Howland Current Pump, with +/-210uA output range around the operating point, full scale, for the shunt’s full scale +/-0.1V sense voltage.

R10 is the 470Ohm resistor on the output of the op amp - I forgot to mark it with a reference number.

C1 stabilizes the op-amp. It could be reduced to 5pF.

Q1 and Q2 are 2N7000 N-channel low-power mosfets, typically used for signal switching.

This approach makes sense for LM358, but it’s not universal. An op-amp with common mode voltage extending to VCC, like TL072, could use a simpler current source circuit. A rail-to-rail input/output amplifier could use either approach of course.

As far as layout goes, symmetry and compactness is key. There’s no point to duplicating the output branch, since it couples more to the output than to the inputs, and thus I crossed it out. There’s also possibly not much point to duplicating the current source parasitics, since they couple mostly to low impedance nodes of the shunt. But the remainder of the circuit should be symmetric to maintain symmetry of parasitic capacitances. It could also be laid a bit tighter than I drew below. Probably a dummy trimmer set to midpoint would be a good idea in the top branch, even though on the layout below I’ve shorted out the dummy trimmer footprint with a trace. The nodes on the op-amp input are extremely sensitive to asymmetric impedances, and the trimmers are large enough to couple nicely to adjacent components and shielding.

It’d take some experimentation, but the idea below would be a starting point, and convey how it could be done.

• Where between a terrible and awful idea would it be to (ab)use the body diode of the mosfet instead of the separate diodes? (Obviously depends on the voltage drop of said diode.)
– TLW
Commented Sep 9, 2022 at 1:38

The simplest method is to scrap all chips (except your MCU of course) and just create a pair of voltage dividers to ground either side of your shunt and measure the two voltages with two ADC inputs on your MCU - then subtract one from the other in software.

You don't have "bidirectional voltage", just two different voltages, and you want to know the difference between them, either positive or negative.

To reduce quiescent current consumption you can make your voltage dividers switchable by adding P-channel MOSFETs (and N-channel to drive them) like this:

simulate this circuit – Schematic created using CircuitLab

Size your RTx and RBx resistors to give the suitable voltage for your MCU's ADC inputs, while keeping the impedance of them low enough.

• Using 5k6 and 150k, I would have steps of approx 30mV with 10 bit adc. Even if I made a shunt with 100mV/A it would give a very poor resolution. I haven't specified, but it would be best if it had at least 100mA resolution, I was hoping for better.
– Sebi
Commented Feb 20, 2022 at 20:21

It is only a simulation.

I don't know the "sensitivity" of this circuit to the relative "values" of the resistors. To study in-depth!

Here is my proposed solution. Cheap, effective, easy

All values calculated for 0,16V/Amp 15k trimpot adjust the 2,5V offset for uController ADC input 500 ohms trimpot adjust for fine Zero Amp output to 2,5V Furthermore the Zero and 0.16V/A are also adjustable in software. Valid for bidirectional current output. 2,5V being the Zero current output.

• This looks very promising. And the part is cheap, offers quad channels, and is available at the moment.
– Sebi
Commented Feb 20, 2022 at 21:17
• You'll want matched pairs of precision 10k resistors for this circuit, to ensure that both dividers have exactly the same ratio. Otherwise your measurement will be off by a fair bit. Commented Feb 20, 2022 at 21:40
• The above circuit update render unnecessary to match the 4 10k reesistors Commented Feb 20, 2022 at 22:19