Skip to content

Commit 68f1f83

Browse files
Improve ina260 example (#771)
Set the config register. Fix issue with overflow.
1 parent 3085c7f commit 68f1f83

1 file changed

Lines changed: 65 additions & 11 deletions

File tree

i2c/ina260_i2c/ina260_i2c.c

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,53 @@
1010
#define POWER_REGISTER 0x03
1111
#define I2C_ADDRESS 0x40
1212

13-
#define ByteSwap(u) (uint16_t)((u << 8)|(u >> 8))
13+
#define CONFIG_REGISTER 0x00
1414

1515
#ifndef RTC_CLOCK_SRC_GPIO_OUT
1616
#define RTC_CLOCK_SRC_GPIO_OUT 21
1717
#endif
1818

19+
// Averaging: number of samples the INA260 averages in hardware before updating
20+
// its registers (CONFIG register AVG field, bits 11:9). More = quieter readings
21+
// but slower updates. Helpful for low sleep currents.
22+
// Allowed values: 1, 4, 16, 64, 128, 256, 512, 1024.
23+
#define AVG_SAMPLES 128
24+
25+
#if AVG_SAMPLES == 1
26+
#define AVG_FIELD 0
27+
#elif AVG_SAMPLES == 4
28+
#define AVG_FIELD 1
29+
#elif AVG_SAMPLES == 16
30+
#define AVG_FIELD 2
31+
#elif AVG_SAMPLES == 64
32+
#define AVG_FIELD 3
33+
#elif AVG_SAMPLES == 128
34+
#define AVG_FIELD 4
35+
#elif AVG_SAMPLES == 256
36+
#define AVG_FIELD 5
37+
#elif AVG_SAMPLES == 512
38+
#define AVG_FIELD 6
39+
#elif AVG_SAMPLES == 1024
40+
#define AVG_FIELD 7
41+
#else
42+
#error "AVG_SAMPLES must be one of: 1, 4, 16, 64, 128, 256, 512, 1024"
43+
#endif
44+
45+
// CONFIG register value:
46+
// bit 15 reset (0)
47+
// bits 11:9 AVG = samples averaged
48+
// bits 8:6 VBUSCT, 5:3 ISHCT = conversion times (left at default 0b100 = 1.1 ms)
49+
// bits 2:0 MODE = 0b111 (continuous shunt + bus)
50+
#define CONFIG_VALUE ( ((AVG_FIELD & 0x7) << 9) \
51+
| (0x4 << 6) /* VBUSCT 1.1 ms */ \
52+
| (0x4 << 3) /* ISHCT 1.1 ms */ \
53+
| 0x7 ) /* continuous shunt + bus */
54+
55+
// Swap the byte order of a 16-bit value (INA260 returns big-endian over I2C).
56+
static inline uint16_t byte_swap(uint16_t u) {
57+
return (uint16_t)((u << 8) | (u >> 8));
58+
}
59+
1960
// Read register value
2061
static uint16_t read_reg(uint8_t reg) {
2162
// Set the register address
@@ -27,7 +68,15 @@ static uint16_t read_reg(uint8_t reg) {
2768
ret = i2c_read_blocking(i2c_default, I2C_ADDRESS, (uint8_t*)&data, 2, false);
2869
assert(ret == 2);
2970
if (ret != 2) return 0;
30-
return ByteSwap(data);
71+
return byte_swap(data);
72+
}
73+
74+
// Write a 16-bit register value
75+
static void write_reg(uint8_t reg, uint16_t value) {
76+
uint8_t buf[3] = { reg, (uint8_t)(value >> 8), (uint8_t)(value & 0xFF) };
77+
int ret = i2c_write_blocking(i2c_default, I2C_ADDRESS, buf, 3, false);
78+
assert(ret == 3);
79+
(void)ret;
3180
}
3281

3382
int main() {
@@ -53,23 +102,28 @@ int main() {
53102
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
54103
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
55104

105+
// Configure averaging + continuous mode (see CONFIG_VALUE above).
106+
write_reg(CONFIG_REGISTER, CONFIG_VALUE);
107+
56108
hard_assert(status_led_init());
57109
while(true) {
58110
status_led_set_state(true);
59111

60-
// Read current and convert to mA
61-
float ma = read_reg(CURRENT_REGISTER) * 1.250f;
62-
if (ma > 15000) ma = 0;
63-
// Read the voltage
112+
// Read current and convert to mA. The CURRENT register is signed
113+
// (two's complement), so cast through int16_t before scaling -- otherwise
114+
// small negative or near-zero readings wrap to a huge positive number.
115+
float ma = (int16_t)read_reg(CURRENT_REGISTER) * 1.25f;
116+
// Read the voltage (1.25 mV/LSB, unsigned)
64117
float v = read_reg(VOLTAGE_REGISTER) * 0.00125f;
65-
// Read power and convert to mW
66-
uint16_t mw = read_reg(POWER_REGISTER) * 10;
67-
118+
// Read power and convert to mW (10 mW/LSB). Use 32-bit: register x 10
119+
// exceeds uint16_t range.
120+
uint32_t mw = (uint32_t)read_reg(POWER_REGISTER) * 10;
121+
68122
// Display results
69-
printf("current: %.2f mA voltage: %.2f V power: %u mW\n", ma, v, mw);
123+
printf("current: %.2f mA voltage: %.2f V power: %lu mW\n", ma, v, (unsigned long)mw);
70124

71125
status_led_set_state(false);
72126
sleep_ms(1000);
73127
}
74128
return 0;
75-
}
129+
}

0 commit comments

Comments
 (0)