LIFE LOG(ここにはあなたのブログ名)

作業日誌 う靴

気ままにコンピュータ関連の備忘録などを書きます...。

ZYNQボード(ZYJZGW)でINA219モジュールを使ってi2c通信で電流・電圧値を取得する

はじめに

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, &reg, 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により無事、計測できている。

補足