Closed Darkextratoasty closed 10 months ago
Thanks for the questions, it will take several days before I have time to investigate, need to check if I still have such sensor somewhere.
A quick look showed a TODO note in the .cpp so I label it as bug to give it some priority.
had a brief moment in the datasheet.
INA.setShuntADC(0x03); //set resolution to 12 bits
INA.setShuntADC(0x0F); //set samples to 128
Only the second call is needed, when setting the samples the resolution is always 12 bit (given the duration).
I will implement 4 additional functions (and add some documentation)
bool setBusResolution(uint8_t bits); // 9..12 otherwise false
bool setBusSamples(uint8_t value); // value = 0..7 => 2^value samples
bool setShuntResolution(uint8_t bits); // 9..12 otherwise false
bool setShuntSamples(uint8_t value); // value = 0..7 => 2^value samples
Expect a develop branch later today I do not have time to setup hardware, so if you have time to test it would be appreciated.
@Darkextratoasty
Looking at you code, I saw
Wire.setClock(800000);
Can you change it to 100000?
Datasheet states it should be supported (see below) but these are often only under ideal circumstances.
The INA219 supports the transmission protocol for fast (1- to 400-kHz) and high-speed (1-kHz to 2.56-MHz) modes. All data bytes are transmitted most significant byte first.
If the write to the register fails, it uses the default bits and samples => 84 microseconds and that is what you saw.
it only takes ~85uS to take the measurement, meaning it's actually on 9 bits and 1 sample.
This could be verified by trying to read back the setting. Can you add
Serial.println( INA.getShuntADC(), HEX);
Note to myself: add checking for the writeRegister() calls.
Created the develop branch with the four new functions - https://github.com/RobTillaart/INA219/tree/develop It includes the checking of the writeRegister() calls. PR will be made asap.
Going through the code this morning did not reveal any code bug (absence of proof != proof of absence)
First off, thank you for being so quick to respond and helpful.
I tested a few different INA219 breakout board, a few different I2C cables, and a few different microcontrollers just to be sure it isn't a hardware issue.
First changed the clock speed to 100KHz while still on the master branch. The 85uS turns into about 520uS and changing the value fed into setShuntADC()
still has no effect on the time. getShuntADC()
seems to be indicating that the register is writing correctly however.
After moving to the develop branch, I used
INA.setShuntResolution(9);
Serial.println(INA.getShuntADC(), HEX);
which printed out 0
as expected and took about 520uS for an INA.getCurrent()
action. I then changed the resolution to 12
INA.setShuntResolution(12);
Serial.println(INA.getShuntADC(), HEX);
which printed 3
and took 520uS to get current. Setting the samples to 1
INA.setShuntResolution(12);
INA.setShuntSamples(1);
Serial.println(INA.getShuntADC(), HEX);
printed 9
and took 520uS. Setting samples to 7 (128 samples)
INA.setShuntResolution(12);
INA.setShuntSamples(7);
Serial.println(INA.getShuntADC(), HEX);
prints F
and still takes about 520uS.
So the getShuntADC()
is indicating that the register is being correctly written, but the time it takes to perform a reading doesn't match up. I'm wondering if perhaps the actual time it's taking to make a measurement is changing, but the time that I'm seeing with getCurrent()
is only the time it takes to read the latest measurement from a buffer on the INA219. I tried looping as fast as possible 100 times, reading the current with getCurrent()
each time, which ran through in about 52mS, indicating each reading still took around 520uS. However, it's possible the actual value is only updating every ~62mS (for 12bit 128sample), and I'm just reading the same value over and over. I plan to test this out, but first I need to come up with a load that changes current fast enough for it to change within 520uS. I'll update when I get that rigged up, hopefully today.
@Darkextratoasty
Interesting line in the datasheet. It mentions the resolution and samples are for the shunt VOLTAGE register. (idem for BUS voltage register)
You are timing getCurrent(), so can you try to time getShuntVoltage()?
To be continued..
It appears that my guess was correct, the INA219 will let you read as fast as the I2C bus can go, but the values will only update at the rate determined by the resolution and number of samples. I made a simple quickly changing load using a resistive load connected to a mosfet that's driven by another arduino running a sped up "fade" example sketch. This is the sketch I used to read the INA219 to test this (on an esp32 board this time):
#include "INA219.h"
#include "Wire.h"
INA219 INA(0x40);
void setup(void) {
Serial.begin(115200);
delay(7000);
Serial.print("\n\n\n\n\n\nINA219_LIB_VERSION: ");
Serial.println(INA219_LIB_VERSION);
Wire.begin();
Wire.setClock(100000);
if (!INA.begin() ) {
Serial.println("could not connect. Fix and Reboot");
}
INA.setMaxCurrentShunt(3.2, 0.1);
INA.setGain(8);
INA.setShuntResolution(9);
// INA.setShuntSamples(7);
Serial.print("getShuntADC result: 0x0");
Serial.println(INA.getShuntADC(), HEX);
float current[512] = {0};
unsigned long start = micros();
for(int i = 0; i < 512; i++) {
current[i] = INA.getCurrent_mA();
}
unsigned long end = micros();
Serial.print("Time total: \t"); Serial.print((end-start)/1000); Serial.print("mS \tTime per reading: \t"); Serial.print((end-start)/512); Serial.println("uS");
Serial.println();
Serial.println("Current: \t");// Serial.print(current, 4); Serial.print("A \t");
for(int i = 0; i < 32; i++) {
for(int j = 0; j < 16; j++) {
Serial.print(current[(i*16) + j]);
Serial.print(" \t");
}
Serial.println();
}
Serial.println();
}
void loop(void) {}
With resolution set to 9
and samples unset, the sample time should be 84uS, while the I2C read time is about 600uS (esp32 is apparently slower than RP2040), so I would expect to see a different value for each reading. The output shows just that:
INA219_LIB_VERSION: 0.2.1
getShuntADC result: 0x00
Time total: 307mS Time per reading: 599uS
Current:
263.87 263.87 263.87 395.51 502.93 503.32 502.93 106.15 503.32 502.15 502.54 503.91 9.86 503.91 502.54 503.32
502.54 303.42 503.91 503.32 503.32 502.93 504.30 503.32 502.54 503.32 502.54 502.54 502.93 503.32 503.32 502.93
502.54 503.32 503.32 502.93 499.71 503.32 503.32 502.54 502.54 503.32 502.93 -0.39 501.76 -1.17 107.52 0.00
-0.39 0.00 0.00 0.39 -0.39 -0.39 -0.78 -0.78 -0.39 0.00 -0.39 0.00 0.39 0.39 0.39 0.00
-0.78 0.88 -0.39 0.00 0.39 0.39 214.45 -0.39 0.00 -0.39 -0.78 530.96 -0.39 0.00 -0.39 0.00
426.07 -0.39 0.39 0.39 0.39 0.00 201.27 -0.39 -0.39 0.88 0.39 -7.81 0.39 0.00 51.07 -1.17
0.00 0.00 -0.78 314.06 -0.39 0.00 -0.78 -0.78 505.08 0.39 0.00 0.39 0.00 503.32 0.00 -0.39
-0.39 0.00 -0.39 502.15 -0.39 -0.39 0.39 -0.78 422.36 -0.39 -0.39 244.92 -0.39 212.40 0.00 0.39
475.00 0.00 -8.59 -0.39 0.39 504.30 -0.39 0.88 0.39 0.00 502.54 0.00 0.00 -0.39 -0.39 0.00
501.37 0.88 0.39 -0.39 0.00 500.98 -0.39 0.39 429.39 0.39 500.59 -0.78 0.39 523.54 -0.39 412.50
-0.39 0.00 504.30 0.00 206.64 0.39 -0.39 502.54 502.54 0.00 1.27 -0.39 0.39 502.15 0.39 -0.39
-1.56 0.39 501.37 -1.17 -0.39 337.99 0.39 500.98 -0.39 -0.39 505.47 0.00 501.37 0.88 0.39 503.32
0.00 502.15 -0.39 0.39 0.39 502.54 -0.39 519.04 -0.39 -0.39 500.98 0.00 305.86 69.63 -0.39 500.59
0.39 107.52 349.51 -0.39 500.59 0.00 0.39 505.47 -0.78 501.76 0.00 0.39 503.32 0.00 502.54 1.27
0.00 0.00 501.76 0.00 503.32 -0.39 0.39 502.54 -0.39 502.54 166.70 0.00 501.76 -0.39 525.29 444.14
-0.39 502.93 0.00 307.91 503.91 -0.39 502.54 0.39 96.78 501.37 -0.39 502.15 0.00 0.00 -0.39 500.98
-0.39 502.54 -1.17 0.39 501.37 0.39 504.30 275.78 0.00 501.37 0.00 503.91 505.47 -0.78 501.76 -0.39
503.91 503.32 -0.39 501.76 -0.78 505.86 503.32 0.00 502.54 502.54 -0.78 318.16 501.37 0.00 503.32 62.99
100.10 501.76 -0.39 503.91 377.83 -0.39 500.59 -0.39 504.30 505.86 0.00 502.15 -0.39 503.32 502.93 -0.78
501.76 -0.39 502.93 502.54 0.88 502.54 502.54 0.00 502.54 502.15 0.39 502.54 157.32 502.54 501.76 0.39
503.91 469.63 310.74 500.98 0.00 503.32 505.08 212.79 501.76 -0.78 503.91 502.93 0.39 502.93 0.39 502.93
501.37 0.39 0.39 502.54 1.66 503.32 501.76 0.00 503.32 257.32 502.54 500.98 -0.78 504.30 506.64 502.15
501.37 -0.39 503.91 504.30 502.54 500.98 0.00 503.32 502.15 412.11 501.76 0.00 502.93 501.37 501.37 213.28
502.54 209.08 502.54 501.76 2.54 502.93 352.73 502.15 501.76 0.39 502.54 505.86 502.15 501.76 -1.17 503.32
503.91 502.54 501.76 0.39 503.91 502.93 502.54 503.32 0.39 502.54 501.76 501.76 502.54 503.32 364.26 503.32
501.76 412.89 503.91 453.61 502.93 501.76 202.05 503.32 504.30 503.32 502.54 4.20 502.93 503.32 502.54 502.93
0.00 502.54 502.93 504.30 502.54 0.39 503.32 503.32 501.76 503.32 502.93 333.01 502.93 501.76 503.32 503.91
626.86 502.93 502.54 503.32 502.93 503.91 502.54 503.32 422.75 502.93 503.32 501.76 502.93 203.81 503.32 503.32
502.54 503.32 -1.95 -1.95 502.93 502.54 503.32 503.32 285.25 502.54 503.32 503.32 503.32 504.30 503.32 503.32
503.32 503.32 502.93 502.93 503.32 503.32 503.32 534.67 503.32 0.39 0.00 502.93 0.39 0.00 0.00 104.59
104.59 -0.39 -0.39 0.00 0.00 212.01 0.00 0.39 -0.39 0.39 99.22 -0.39 0.00 0.39 0.39 -1.17
0.39 0.00 -0.39 0.39 0.39 0.39 0.39 0.00 0.00 0.39 0.00 0.00 0.00 212.01 -0.39 0.00
With resolution set to 12
(setShuntResolution()
commented out) and samples set to 2
(4 samples), the sample time should be 2130uS, while the I2C read time is 600uS, so I would expect the same value 3-4 times. The actual result is closer to 4-5 times, but close enough:
INA219_LIB_VERSION: 0.2.1
getShuntADC result: 0x0A
Time total: 307mS Time per reading: 599uS
Current:
433.98 433.98 442.77 442.77 442.77 442.77 442.77 444.82 444.82 444.82 444.82 459.77 459.77 459.77 459.77 470.70
470.70 470.70 470.70 470.70 458.59 458.59 458.59 458.59 464.06 464.06 464.06 464.06 464.06 469.92 469.92 469.92
469.92 473.05 473.05 473.05 473.05 485.06 485.06 485.06 485.06 485.06 493.85 493.85 493.85 493.85 509.28 509.28
509.28 509.28 494.24 494.24 494.24 494.24 494.24 311.82 311.82 311.82 311.82 5.37 5.37 5.37 5.37 12.21
12.21 12.21 12.21 12.21 18.55 18.55 18.55 18.55 38.38 38.38 38.38 38.38 38.38 38.38 38.38 38.38
38.38 28.52 28.52 28.52 28.52 35.35 35.35 35.35 35.35 35.35 41.80 41.80 41.80 41.80 45.31 45.31
45.31 45.31 51.66 51.66 51.66 51.66 51.66 61.82 61.82 61.82 61.82 77.73 77.73 77.73 77.73 68.85
68.85 68.85 68.85 68.85 71.19 71.19 71.19 71.19 77.64 77.64 77.64 77.64 77.64 81.05 81.05 81.05
81.05 87.89 87.89 87.89 87.89 94.73 94.73 94.73 94.73 94.73 111.04 111.04 111.04 111.04 97.95 97.95
97.95 97.95 104.39 104.39 104.39 104.39 104.39 112.89 112.89 112.89 112.89 117.29 117.29 117.29 117.29 117.29
125.88 125.88 125.88 125.88 133.89 133.89 133.89 133.89 140.23 140.23 140.23 140.23 140.23 130.96 130.96 130.96
130.96 140.53 140.53 140.53 140.53 151.86 151.86 151.86 151.86 151.86 150.49 150.49 150.49 150.49 161.91 161.91
161.91 161.91 166.89 166.89 166.89 166.89 166.89 188.96 188.96 188.96 188.96 170.02 170.02 170.02 170.02 170.02
176.37 176.37 176.37 176.37 183.20 183.20 183.20 183.20 189.55 189.55 189.55 189.55 189.55 197.75 197.75 197.75
197.75 206.45 206.45 206.45 206.45 223.24 223.24 223.24 223.24 223.24 203.22 203.22 203.22 203.22 214.26 214.26
214.26 214.26 214.26 216.41 216.41 216.41 216.41 224.71 224.71 224.71 224.71 225.98 225.98 225.98 225.98 225.98
238.96 238.96 238.96 238.96 253.22 253.22 253.22 253.22 239.16 239.16 239.16 239.16 239.16 246.78 246.78 246.78
246.78 252.54 252.54 252.54 252.54 260.55 260.55 260.55 260.55 260.55 262.50 262.50 262.50 262.50 278.32 278.32
278.32 278.32 278.32 294.73 294.73 294.73 294.73 275.20 275.20 275.20 275.20 285.84 285.84 285.84 285.84 285.84
288.38 288.38 288.38 288.38 299.41 299.41 299.41 299.41 298.63 298.63 298.63 298.63 298.63 320.70 320.70 320.70
320.70 325.10 325.10 325.10 325.10 325.10 312.01 312.01 312.01 312.01 321.87 321.87 321.87 321.87 326.95 326.95
326.95 326.95 326.95 331.74 331.74 331.74 331.74 334.47 334.47 334.47 334.47 354.49 354.49 354.49 354.49 354.49
357.52 357.52 357.52 357.52 350.98 350.98 350.98 350.98 351.37 351.37 351.37 351.37 351.37 362.50 362.50 362.50
362.50 364.75 364.75 364.75 364.75 364.75 372.85 372.85 372.85 372.85 388.67 388.67 388.67 388.67 397.27 397.27
397.27 397.27 397.27 383.59 383.59 383.59 383.59 387.21 387.21 387.21 387.21 398.34 398.34 398.34 398.34 398.34
403.61 403.61 403.61 403.61 408.20 408.20 408.20 408.20 425.10 425.10 425.10 425.10 425.10 429.59 429.59 429.59
429.59 422.66 422.66 422.66 422.66 422.66 424.90 424.90 424.90 424.90 434.08 434.08 434.08 434.08 433.59 433.59
433.59 433.59 433.59 444.43 444.43 444.43 444.43 458.50 458.50 458.50 458.50 468.65 468.65 468.65 468.65 468.65
458.59 458.59 458.59 458.59 463.87 463.87 463.87 463.87 463.87 470.12 470.12 470.12 470.12 475.00 475.00 475.00
475.00 477.73 477.73 477.73 477.73 477.73 483.01 483.01 483.01 483.01 503.52 503.52 503.52 503.52 490.82 490.82
490.82 490.82 490.82 496.68 496.68 496.68 496.68 206.05 206.05 206.05 206.05 5.47 5.47 5.47 5.47 5.47
11.91 11.91 11.91 11.91 22.07 22.07 22.07 22.07 22.07 38.28 38.28 38.28 38.28 26.27 26.27 26.27
Finally, with samples set to 7
(128 samples), the sample time should be 68.1mS, while the I2C read time is 600uS, so I would expect the same value ~115 times. I didn't bother counting the result, but it appears close enough:
INA219_LIB_VERSION: 0.2.1
getShuntADC result: 0x0F
Time total: 307mS Time per reading: 599uS
Current:
274.71 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81
278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81
278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81
278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81
278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81
278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81
278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81 278.81
341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70
341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70
341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70
341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70
341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70
341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70
341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 341.70 361.62
361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62
361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62
361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62
361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62
361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62
361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62
361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 361.62 96.97 96.97
96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97
96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97
96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97
96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97
96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97
96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97 96.97
All this to say, the register set is working correctly (I suspect the master branch library was also working correctly, I'll test that out soon), but the INA219 will let you read old values as fast as the I2C bus can go.
Per your most recent comment, getCurrent()
and getShuntVoltage()
yield the same results with respect to the timing.
Yep, the master branch library was fine, setShuntADC()
works as intended.
That is an amazing analysis, well done. In short one configures the internal read process, the values in the registers are "just" the last valid values. Tomorrow I will think how to describe this in the readme.md file, Again thanks for your tests and work, really appreciated 👍
This is for now the updated section that will be in the readme.md.
Note: The internal conversions runs in the background in the INA219. If a conversion is finished the measured value is stored in the appropriate register. The last obtained values can always be read from the registers, so they will not block. Result can be that you get the very same value if no new data is available yet. This is especially true if you increase the number of samples. (See also discussion in #11).
Using more samples reduces the noise level, but one will miss the faster changes in voltage or current. Depending on your project needs you can choose one over the other.
As a rule of thumb on could take the time between two I2C communication time for reading a register as an upper limit. This would give a fresh reading every time. NB it is always possible to average readings fetched from the device.
Use one of these three so set bus resolution and sampling.
Use one of these three so set shunt resolution and sampling.
mask = both resolution + averaging multiple samples. minus - == don't care
bit mask | value | resolution | samples | conversion time |
---|---|---|---|---|
0-00 | 0 / 4 | 9 bit | 1 sample | 84 μs |
0-01 | 1 / 5 | 10 bit | 1 sample | 148 μs |
0-10 | 2 / 6 | 11 bit | 1 sample | 276 μs |
0-11 | 3 / 7 | 12 bit | 1 sample | 532 μs |
1000 | 8 | 12 bit | 1 sample | 532 μs |
1001 | 9 | 12 bit | 2 samples | 1.06 ms |
1010 | 10 | 12 bit | 4 samples | 2.13 ms |
1011 | 11 | 12 bit | 8 samples | 4.26 ms |
1100 | 12 | 12 bit | 16 samples | 8.51 ms |
1101 | 13 | 12 bit | 32 samples | 17.02 ms |
1110 | 14 | 12 bit | 64 samples | 34.05 ms |
1111 | 15 | 12 bit | 128 samples | 68.10 ms |
That is a very clear description, thanks you for your work developing and maintaining this library
I will merge the PR / branch in a few minutes, Thank you for helping to analyze and the insightful learn moment!
Merged and released 0.2.1 version, so I close this issue.
I'm a bit confused on how to set the bits for the resolution and averaging using the
setBusADC()
andsetShuntADC()
functions. From reading the datasheet, it seems to me that I need to first set the resolution using the 0x00 through 0x03 options, then I need to set the averaging samples using the 0x08 through 0x0F options. So to set the shunt ADC resolution to 12 bits and 128 samples, I would use:However, if I then measure the amount of time it takes to perform a current reading, which should take about 70mS, it only takes ~85uS to take the measurement, meaning it's actually on 9 bits and 1 sample. I've also tried just using 0x0F, but that has the same result. No matter what I feed into the
setShuntADC()
function (as long as it's <=0x0F) the time it takes to do a measurement doesn't change. Here's the example code that shows this:Am I completely misunderstanding how to use these functions?