はじめに
INA219のモジュールをAmazonで購入しました。
今回計測する外部接続回路は、LED1つを常時点灯させたものです。
ZYNQとi2c通信するためのCコード
ina219.h
#ifndef INA219_H #define INA219_H #include <stdint.h> // INA219のI2Cアドレスとレジスタ #define INA219_ADDR 0x40 #define INA219_REG_CONFIG 0x00 #define INA219_REG_SHUNT_VOLTAGE 0x01 #define INA219_REG_BUS_VOLTAGE 0x02 #define INA219_REG_POWER 0x03 #define INA219_REG_CURRENT 0x04 #define INA219_REG_CALIBRATION 0x05 // 設定レジスタのビットマスク #define INA219_CONFIG_RESET 0x8000 #define INA219_CONFIG_BVOLTAGERANGE_32V 0x2000 #define INA219_CONFIG_GAIN_1_40MV 0x1800 #define INA219_CONFIG_BADCRES_12BIT 0x0700 #define INA219_CONFIG_SADCRES_12BIT_1S_532US 0x0018 #define INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS 0x0007 // スケーリングファクター #define CURRENT_LSB 0.025 // 1 LSB = 0.01 mA void ina219_init(int i2c_fd); void ina219_setCalibration(uint16_t cal_value); uint16_t ina219_getCurrent_raw(void); uint16_t ina219_getPower_raw(void); float ina219_getBusVoltage_V(void); float ina219_getShuntVoltage_mV(void); float ina219_getCurrent_mA(void); float ina219_getPower_mW(void); #endif // INA219_H
ina219.c
#include "ina219.h" #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <sys/ioctl.h> #include <linux/i2c-dev.h> static int i2c_fd; static void write_register(uint8_t reg, uint16_t value) { uint8_t buffer[3]; buffer[0] = reg; buffer[1] = value >> 8; buffer[2] = value & 0xFF; if (write(i2c_fd, buffer, 3) != 3) { perror("Failed to write to the i2c bus"); exit(1); } } static uint16_t read_register(uint8_t reg) { uint8_t buffer[2]; if (write(i2c_fd, ®, 1) != 1) { perror("Failed to write register address to the i2c bus"); exit(1); } if (read(i2c_fd, buffer, 2) != 2) { perror("Failed to read from the i2c bus"); exit(1); } return (buffer[0] << 8) | buffer[1]; } void ina219_init(int fd) { i2c_fd = fd; // Reset the device write_register(INA219_REG_CONFIG, INA219_CONFIG_RESET); usleep(50000); // Wait for the reset to complete // Set calibration value uint16_t cal_value = 0x409F; // Example calibration value ina219_setCalibration(cal_value); } void ina219_setCalibration(uint16_t cal_value) { write_register(INA219_REG_CALIBRATION, cal_value); } uint16_t ina219_getCurrent_raw(void) { // Set calibration register to ensure accurate reading uint16_t cal_value = 0x409F; // Example calibration value ina219_setCalibration(cal_value); return read_register(INA219_REG_CURRENT); } uint16_t ina219_getPower_raw(void) { // Set calibration register to ensure accurate reading uint16_t cal_value = 0x409F; // Example calibration value ina219_setCalibration(cal_value); return read_register(INA219_REG_POWER); } float ina219_getBusVoltage_V(void) { uint16_t value = read_register(INA219_REG_BUS_VOLTAGE); return (value >> 3) * 0.004; // Convert to volts (12-bit value to 0.004V/LSB) } float ina219_getShuntVoltage_mV(void) { uint16_t value = read_register(INA219_REG_SHUNT_VOLTAGE); return value * 0.01; // Convert to millivolts } float ina219_getCurrent_mA(void) { uint16_t raw_current = ina219_getCurrent_raw(); return raw_current * CURRENT_LSB; // Convert to milliamperes } float ina219_getPower_mW(void) { uint16_t raw_power = ina219_getPower_raw(); return raw_power * (20*CURRENT_LSB); // Convert to milliwatts } int main() { const char *i2c_device = "/dev/i2c-1"; // I2Cデバイスファイル if ((i2c_fd = open(i2c_device, O_RDWR)) < 0) { perror("Failed to open the i2c bus"); return 1; } if (ioctl(i2c_fd, I2C_SLAVE, INA219_ADDR) < 0) { perror("Failed to acquire bus access and/or talk to slave"); return 1; } // Initialize INA219 ina219_init(i2c_fd); while (1) { // Get measurements float bus_voltage = ina219_getBusVoltage_V(); float shunt_voltage = ina219_getShuntVoltage_mV(); float current = ina219_getCurrent_mA(); float power = ina219_getPower_mW(); // Print measurements printf("-------------------------------\n"); printf("Bus Voltage: %.2f V\n", bus_voltage); printf("Shunt Voltage: %.2f mV\n", shunt_voltage); printf("Current: %.2f mA\n", current); printf("Power: %.2f mW\n", power); printf("-------------------------------\n"); // Sleep for 500ms usleep(500000); } close(i2c_fd); return 0; }
動作確認
ひとまずコンパイル。
gcc ina219.c -o ina219
実行する。
sudo ./ina219
成功すると、電流・電圧値などがターミナル上に流れる。 i2cにより無事、計測できている。
補足