/* Kookabus-01 reader for Linux (Raspberry Pi, Jetson, any board with /dev/i2c-N). * * gcc -O2 -o kookabus kookabus.c && ./kookabus /dev/i2c-1 0x40 * * Prints one line a second. Exits non-zero when the pack falls below the cut-off, * so a shell loop or systemd unit can stop the load. */ #include #include #include #include #include #include #include #define R_SHUNT 0.005 /* ohm; trim against a multimeter if current reads off */ #define I_LSB 0.0005 /* A per CURRENT bit */ #define CONFIG 0x4527 /* 16-sample average, 1.1 ms conversions, continuous */ #define V_CUTOFF (5 * 3.0) static int fd; static void wr(uint8_t reg, uint16_t val) { uint8_t b[3] = { reg, val >> 8, val & 0xFF }; if (write(fd, b, 3) != 3) { perror("i2c write"); exit(2); } } static uint16_t rd(uint8_t reg) { uint8_t b[2]; if (write(fd, ®, 1) != 1 || read(fd, b, 2) != 2) { perror("i2c read"); exit(2); } return (b[0] << 8) | b[1]; } int main(int argc, char **argv) { const char *dev = argc > 1 ? argv[1] : "/dev/i2c-1"; int addr = argc > 2 ? (int)strtol(argv[2], NULL, 0) : 0x40; if ((fd = open(dev, O_RDWR)) < 0 || ioctl(fd, I2C_SLAVE, addr) < 0) { perror(dev); return 2; } if (rd(0xFE) != 0x5449) { fprintf(stderr, "no INA226 at 0x%02x\n", addr); return 2; } wr(0x00, CONFIG); wr(0x05, (uint16_t)(0.00512 / (I_LSB * R_SHUNT) + 0.5)); /* 2048 */ for (;;) { double v = rd(0x02) * 0.00125; double i = (int16_t)rd(0x04) * I_LSB; double p = rd(0x03) * 25 * I_LSB; printf("%6.2f V %6.3f A %6.1f W\n", v, i, p); fflush(stdout); if (v < V_CUTOFF) { fprintf(stderr, "pack below %.1f V, stop the load\n", V_CUTOFF); return 1; } sleep(1); } }