RobTillaart / INA226

Arduino library for INA226 power sensor
MIT License
54 stars 14 forks source link

Bus voltage error grows linearly up to 0.5V when measuring 35V #30

Closed zalexzperez closed 9 months ago

zalexzperez commented 11 months ago

Just got an INA226 board from China. Used the demo plotter file and edited it to only display bus voltage measurements.

Riden RD6006P precise power supply to apply voltages from 0 to 35V at the Vbus pin. UNI-T multimeter confirms the accuracy of the power supply (down to 0.01V at all applied voltages).

Here's a table with the measurements: Set (V) Max measurement (V)
0 0.03
0.5 0.51
1 1.02
1.5 1.53
2 2.03
3 3.05
4 4.06
5 5.08
10 10.15
15 15.23
20 20.3
25 25.38
30 30.46
35 35.53

What causes this offset error? Is there a way to prevent it? Edit: on further analysis, the measured values correspond to a +1.51% error.

Thanks

RobTillaart commented 11 months ago

Thanks for the issue, will try to handle it this week.

RobTillaart commented 11 months ago

(got some thoughts, so a quick share)

Dont know what causes the offset, the only explanation I can come up with is a (systematic) deviation of the shunt.

Can you do a measurement without anything connected? So no voltage at all? It could indicate some noise.

Can you print the measurements with 4 decimals, especially to get see if the error is linear over the range or not.


Thinking out loud to prevent it? Assuming it is an error in the shunt, you could try to change the setup of 1Amp 0.002 ohm to 1 Amp 0.00197 ohm in the sketch. Can you give that a try? Let me know the results.

Another option could be to add correction factors in the library to be able to adjust the precision of the library. For that we need to know if the error is (almost) linear. If the error is not linear, it is always possible to use multimap (another library by me) to correct the values (slower as it adds an extra layer of math).

zalexzperez commented 11 months ago

Assuming it is an error in the shunt, you could try to change the setup of 1Amp 0.002 ohm

The included resistor in the module is 0.1Ohms (R100), I left that detail out as I wasn't attempting to measure current.

I wasn't passing any current through the shunt resistor, I was only applying the 0-35V voltage at the Vbus pin when performing those measurements, no loads connected.

Nevertheless, I just tried measuring current. The load in the circuit is a 100 Ohm 1/4W resistor, power supply voltage varied between 0.5 and 4.5V. For instance, at 3V, multimeter measured 29.2mA while the sensor reports 32.05mA. At 1.5V, multimeter measured 14.55mA while sensor reports 15.95mA. I see there's a ~10% constant error on the reported current values.

The shunt resistor is quite close to the rated value. I measured 2.9mV (multimeter) across it while 29.2mA were flowing, so R=2.9/29.2=0.0993Ohms, almost 0.1Ohms. I also used someone's library and the reported currents get very close to the expected ones by using a 0.90918 correction factor. It also has the same 1.5% error on the Vbus measurements.

RobTillaart commented 11 months ago

Given that the other library gives same/ similar error is a sign that the (systematic) error is in the hardware.

As the sensor makes measurements it needs to have a reference voltage. This is often based upon the voltage the sensor gets to power up.

What is the voltage the sensor gets? 5.000V ? What happens to the measurements if you vary that voltage? E.g make it 4.900V?

zalexzperez commented 11 months ago

I was powering it from the host MCU's LDO 3.3V output (FireBeetle 2 ESP32-E)

I just tried powering it from a separate power supply using 3.3V. When measuring 30V, sensor reports 30.436V at 3.3V. When decreasing Vcc all the way to 1.8V, sensor reports 30.426V. That made hardly a difference. Lower voltages than 1.8V shut down the device.

RobTillaart commented 11 months ago

I just tried powering it from a separate power supply using 3.3V. When measuring 30V, sensor reports 30.436V at 3.3V. When decreasing Vcc all the way to 1.8V, sensor reports 30.426V. That made hardly a difference. Lower voltages than 1.8V shut down the device.

OK, that indicates the sensor uses an internal reference, so we can exclude that as source of the deviation.

The shunt resistor is quite close to the rated value. I measured 2.9mV (multimeter) across it while 29.2mA were flowing, so R=2.9/29.2=0.0993Ohms, almost 0.1Ohms.

Note that 0,0993 Ohm and 0.1 Ohm differ a vert little in absolute terms, but relative it is still about 0.7% (which equals only half of the 1.5% error)

zalexzperez commented 11 months ago

Note that 0,0993 Ohm and 0.1 Ohm differ a vert little in absolute terms, but relative it is still about 0.7% (which equals only half of the 1.5% error)

But the shunt resistor is not used at all when measuring the Vbus voltage... Or is it?

RobTillaart commented 11 months ago

image

Looking at the diagram in the datasheet (Texas Instruments august 2015) it is not.

Just got an INA226 board from China.

Don't know if your China board uses a genuine TI sensor or some replica with other specs. I have seen other non-genuine sensors that just failed to meet the specs of the datasheet. So that is a possible cause that cannot be excluded.

Thinking out loud

With your Riden RD6006P precise power supply, what is the smallest step you can set?

The INA226 should be able to see 36V in 65536 steps ==> steps of about 0.5 mV So if you can see that generate and see that difference one could test if the internal ADC is indeed 16 bit.

RobTillaart commented 11 months ago

FYI, there are quite a bit of tech docs - https://www.ti.com/product/INA226#tech-docs For the library I only used the datasheet, but the others might have some interesting data. I will add this link in the readme.md

RobTillaart commented 11 months ago

Can you set setAverage(7) to see if readings get better? (probably slower).

RobTillaart commented 11 months ago

Have you tried setBusVoltageConversionTime(7) ?

zalexzperez commented 11 months ago

With your Riden RD6006P precise power supply, what is the smallest step you can set?

It's 0.001V image

The INA226 should be able to see 36V in 65536 steps ==> steps of about 0.5 mV

Actually, the bus voltage accuracy is 1.25mV: image

So, I performed some more measurements, this time I applied 0.010V to 0.030V. Then from 0.050 to 0.054V and finally 20.000 to 20.008 in 0.002V (2mV) increments. The INA measurements min and max values come from 100+ printed values (at least 20 seconds of data printing for each set value).

Set value [V] Multimeter [mV] INA226 min[V] INA226 max[V]
0,010 9,54 0,00000 0,01875
0,012 11,52 0,00000 0,02125
0,014 13,5 0,00250 0,02125
0,016 15,45 0,00000 0,02125
0,018 17,43 0,00500 0,02875
0,020 19,42 0,00500 0,03000
0,022 21,38 0,00750 0,03250
0,024 23,4 0,00875 0,03625
0,026 25,35 0,00750 0,03625
0,028 27,32 0,00875 0,03500
0,030 29,26 0,01500 0,03750
- - - -
0,050 49,65 0,03125 0,06625
0,052 51,63 0,04125 0,06250
0,054 53,61 0,04000 0,06250
- - - -
20,000 - 20,29000 20,30750
20,002 - 20,29375 20,31125
20,004 - 20,29375 20,31000
20,006 - 20,30125 20,31225
20,008 - 20,30125 20,31250

Have you tried setBusVoltageConversionTime(7) ?

I just tried it. 35V at Vbus pin, sensor reports min: 35.525V and max: 35.5275V

RobTillaart commented 11 months ago

Thanks for al these measurements, really appreciated. Although it does not give clues about the why of the deviation, they show detailed behavior on accuracy / precision.

RobTillaart commented 11 months ago

Note to myself: These kind of test sketches could be worthy to include as examples.

zalexzperez commented 11 months ago

I deleted my previous message as I was announcing good news because I had tried a third library and thought it was finally giving the correct bus voltage. But it was just an old sketch running with a correction factor applied, sorry about that!

RobTillaart commented 11 months ago

Maybe the 1.5% deviation is a accuracy problem and not a precision one.

Suppose I will implement corrections, how many would the library need?

These have typical the form of y = ax + b for linear correction. For power two linear corrections, I times V, will generate a quadratic one.

RobTillaart commented 11 months ago

Pasted your measurements of the first post in spreadsheet to determine the correction formula. This formula came out

f(x) = 0.98529147 * x - 0.00633941587;

The maximum error is at 0 == 0.0231 Not counting in zero, the max error == 0.00625

As the b offset is rather small, (with some trial an error) this formula is almost equally good.

f(x) = 0,98495 * x;

drawback of both formulas is that they "fail around zero"

(notice that 0.9845 +0.0151 =~100% so there is a clear relation with your 1.51%

RobTillaart commented 11 months ago

Maybe the 1.5% deviation is a accuracy problem and not a precision one.

Dived into the datasheet, and section 7.4.1 Averaging and Conversion Time Considerations and beyond describes how to optimize the measurements and minimize noise.

RobTillaart commented 11 months ago

@zalexzperez Any progress to report? or questions or other libraries?

zalexzperez commented 11 months ago

Well,

I asked Wolfgang Ewald (owner of another INA226 library) about the issue and he replied his modules don't have such error. He also suggested I may have a fake one. Nevertheless, since I'll build a custom PCB, I'll definitely get the genuine sensor and we'll find out if the error's still there or not.

Anyway, using a correction factor of 0.98525, 16 averages with 8244us bus conversion time gives me a good-enough precision of 5mV lower than the actual voltage in the use range that I will use this for (car battery voltage reading). I still have to see how it behaves inside of a car, though.


Since you asked about other questions, I hope you don't mind my asking here about something else. I've been busy trying to understand the calibration register and how it can supposedly increase the current resolution. But first, let me inform you that the shunt voltage reading doesn't have a voltage error like the bus voltage does.

The datasheet states: "The highest resolution for the Current Register (04h) can be obtained by using the smallest allowable Current_LSB based on the maximum expected current"

So I started using the formulas trying to see how a lower expected current could give a higher current resolution, but didn't see how that was possible: Ohm's law dictates that the minimum measurable current increment should only depend on the shunt voltage LSB and the shunt resistor value: 2.5uV/R_shunt. If the shunt resistor is 0.1Ohms, the minimum current increment will be 2.5E-6/0.1=25uA.

Now, we'll see if a lower "expected current" gives a higher current resolution or not with an example with two "maximum expected current" values and a real load current of 200.025mA.

Current_LSB is rounded to 12.5uA/bit (0.4/2^15), giving a CAL register = 4096. Current register will be (8001X4096)/2048 = 16002. The measured current will be 16002 x 12.5E-6= 200.025mA.

As seen, both max expected current values result in the same measured current value. So I'm wondering what is the purpose of current_LSB parameter.

edit: I also found that using a lower expected current value can even give a worse precision. I observed Current_LSB must be a number such that the resulting CAL register ends up being a multiple of 2048, otherwise the current register will not be a whole number.

RobTillaart commented 11 months ago

When making a measurement with any device you have a number of specifications

The calibration value of the INA226 defines the step size of the measurements a.k.a. the current_lsb (precision). If the current_lsb is smaller, the possible range is also smaller. These go hand in hand. And yes there are settings that overlap and work well for different uses.

Suppose you have a 20A sensor and you know that you will never have more than 6 A. You can change the calibration value to get a smaller current_LSB and thus a higher precision. However this can only be obtained by having more samples (averaging etc). Note that a lower current_lsb is also more sensitive to noise. So in practice you need to do your math and do experiments to maximize the quality of the measurements if you want to go beyond 4 significant digits. Details are in the datasheet.

RobTillaart commented 11 months ago

Your example (0.8A and 0.4 A) misses the point as the real value is a multiple of the highest currentLSB

Use a real load current of 200.015mA.

Max A = 0.8 CAL register = 2048. it will measure 8001 => 200.025mA. (deviates 10 uA)

Max A = 0.4 CAL register = 4096. it will measure 16001 => 200.012.5mA. (deviates 2.5 uA so more precise than above.

you could do the math for A = 250 mA and it might be even closer.

zalexzperez commented 11 months ago
  • Which library does Wolfgang Ewald use? Can he confirm this one is working properly?

https://github.com/wollewald/INA226_WE I contacted him through a blog post and he said his modules don't exhibit the error.

it will measure 16001 => 200.012.5mA. (deviates 2.5 uA so more precise than above.

But how exactly can the current register be 16001? Shunt voltage register is 8001 for both max expected currents, as this measurement is independent from the calibration.
So when the max expected current is 0.4, the current register should be (8001 x 4096) / 2048 = 16002 ! And for each voltage register bit increase, the current register will increase by two, due to the 4096/2048 ratio...

RobTillaart commented 11 months ago

From datasheet:

image

So when the max expected current is 0.4, the current register should be (8001 x 4096) / 2048 = 16002

Your math is correct if there was only a single measurement, however the sensor can make multiple and average them. Otherwise it would indeed not make sense.

I also don't know if the internal math is 16 bit or 32 bit as your calculation assumes. Only if I had more time (and hardware) to investigate such details.

RobTillaart commented 10 months ago

@zalexzperez Any progress to report?

zalexzperez commented 10 months ago

Nothing else to report. I have to finish designing my PCB and it's going to take some time before I can test the sensor. I'll report my findings once that time comes.

RobTillaart commented 9 months ago

@zalexzperez Any progress to report?

zalexzperez commented 9 months ago

@RobTillaart

Hello, yes, and it's good news! I received my custom ESP32-S3 based PCBs and made some testing. Since I'm not using the standard pins for i2C with the S3, I used Wire.setPins() prior to calling Wire.begin();

The problem is gone. No more need to use a correction factor. At 35V I'm measuring 35.006V, at 5V it's 5.000V, at 14.456V it's exactly 14.456V.

Here's the genuine INA226 chip from LCSC: image

And here's the INA226 from the AliExpress module: image

I even went and desoldered the fake chip and put a good one in its place, to be able to test the module with an older ESP32-E microcontroller and the results are good, just like with the S3 board.

RobTillaart commented 9 months ago

Good to hear the issue is solved,

Thanks for reporting and the images!

pedroke commented 7 months ago

Hi guys, I have to confirm the issue. I have 4 pieces from China, ordered each from different seller and on different date... Each piece reports different voltages, with pretty obvious error. I've been already asking on TI forum, but just here I found the final confirmation those are really fakes :( Thanks for your efforts... we should spread this info...

RobTillaart commented 7 months ago

Thanks for your addition.