data ready interrupt in hdc2010.

I’m trying to interface with the HDC2010 sensor, which uses the I2C protocol. I’ve successfully done this using the polling method, but now I want to implement it using the Data Ready (DRDY) interrupt method. I’ve connected the INT1 pin of the sensor to a GPIO pin on my microcontroller. When I manually trigger the interrupt, it correctly enters the interrupt service routine. However, it’s not automatically generating interrupts when new data is available.

 

#include <zephyr/kernel.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/sys/printk.h>
#include <zephyr/drivers/gpio.h>
#define I2C_NODE DT_NODELABEL(hdc2010)

// config reg
#define CONFIG_REG 0X0E
#define MEASUREMENT_CONFIG 0x0F

// who i am reg
#define DEVICE_ID_L 0xFE
#define DEVICE_ID_H 0xFF

// menu id
#define MENU_ID_L 0xFC
#define MENU_ID_H 0xFD

// reading temp reg
#define TEMP_L 0X00
#define TEMP_H 0X01

// config interrupt pin
#define INTERRUPT_CONFIG 0x07

// init flag
int initFlag = 0;
// init temp flag
int tempFlag = 0;
// init hum flag
int humFlag = 0;

uint8_t config[2] = {CONFIG_REG, 0x80};

#define SW0_NODE DT_ALIAS(sw5)
int temp;
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);
static const struct i2c_dt_spec hdc2010 = I2C_DT_SPEC_GET(I2C_NODE);

int dataReady = 0;
static struct gpio_callback button_cb_data;

// who am i
int readDeviceId(const struct i2c_dt_spec *hdc2010, uint16_t *id, uint16_t *id1)
{
        int ret;
        // first reading device id
        uint8_t reg[2] = {DEVICE_ID_L, DEVICE_ID_H};
        uint8_t device_id[2] = {DEVICE_ID_L, DEVICE_ID_H};
        ret = i2c_write_read_dt(hdc2010, &reg[0], 1, &device_id[0], 1);
        if (ret)
        {
                printk("device id error\n");
                return -1;
        }
        ret = i2c_write_read_dt(hdc2010, &reg[1], 1, &device_id[1], 1);
        if (ret)
        {
                printk("device id error\n");
                return -1;
        }
        *id = (device_id[1] << 8) | device_id[0];
        // second reading menu id
        reg[0] = MENU_ID_L;
        reg[1] = MENU_ID_H;
        ret = i2c_write_read_dt(hdc2010, &reg[0], 1, &device_id[0], 1);
        if (ret)
        {
                printk("menu id error\n");
                return -1;
        }
        ret = i2c_write_read_dt(hdc2010, &reg[1], 1, &device_id[1], 1);
        if (ret)
        {
                printk("menu id error");
                return -1;
        }
        *id1 = (device_id[1] << 8) | device_id[0];
        printk("%x %x device id and menu id\n", *id, *id1);
        return 0;
}
// init
int hdc2010Init(const struct i2c_dt_spec *hdc2010)
{
        uint8_t oldConfig;
        int ret;
        if (initFlag)
        {
                return 0;
        }

        uint8_t tempReg[2] = {CONFIG_REG, 0};

        ret = i2c_write_read_dt(hdc2010, &tempReg[0], 1, &oldConfig, 1);
        if (ret)
        {
                printk("writing in reg problem\n");
                return -1;
        }
        uint8_t newConfig = oldConfig | 7 << 4;
        config[1] = newConfig;
        ret = i2c_write_dt(hdc2010, config, sizeof(config));
        if (ret != 0)
        {
                printk("soft reseting is fail\n");
                return -1;
        }

        /*
        Bits 2 and 1 of the MEASUREMENT_CONFIG register controls
        the measurement mode
        */
        // Upper two bits of the MEASUREMENT_CONFIG register controls the temperature resolution
        // default value is 14
        // Bit 0 of the MEASUREMENT_CONFIG register can be used to trigger measurements

        config[0] = MEASUREMENT_CONFIG;
        config[1] = 0X4b;
        ret = i2c_write_dt(hdc2010, config, sizeof(config));
        if (ret != 0)
        {
                printk("setup measurement config failed \n");
                return -1;
        }
        initFlag = 1;
        tempFlag = 1;
        return 0;
}

// deinit hdc2010
int hdc2010DeInit()
{
        tempFlag = 0;
        humFlag = 0;
        initFlag = 0;
        return 0;
}
// reading values for sensor temperature
int Hdc2010ReadingTemperature(const struct i2c_dt_spec *hdc2010, int *val)
{
        int ret;
        volatile uint16_t temp;
        float intermediate, value;
        hdc2010Init(hdc2010);
        uint8_t tempReg[2] = {TEMP_L, TEMP_H};
        uint8_t reading[2];
        ret = i2c_write_read_dt(hdc2010, &tempReg[0], 1, &reading[0], 1);
        if (ret)
        {
                printk("failed at reading temperature\n");
                return -1;
        }
        ret = i2c_write_read_dt(hdc2010, &tempReg[1], 1, &reading[1], 1);
        if (ret)
        {
                printk("failed at reading temperature\n");
                return -1;
        }
        temp = (reading[1] << 8) | reading[0];
        intermediate = temp / 65536.0;
        intermediate = intermediate * 165;
        value = intermediate - 40.00;
        *val = value;
        printk("%0.2f C\n", value);
        hdc2010DeInit();
        return 0;
}

int hdc_enable_interrupt(const struct i2c_dt_spec *hdc2010)
{
        uint8_t oldConfig;
        int ret;
        uint8_t tempReg[2] = {CONFIG_REG, 0};

        ret = i2c_write_read_dt(hdc2010, &tempReg[0], 1, &oldConfig, 1);
        if (ret)
        {
                printk("reading in reg problem int\n");
                return -1;
        }
        uint8_t newConfig = oldConfig | 1 << 2; // setting intEn pin in config reg
        tempReg[1] = newConfig;

        ret = i2c_write_dt(hdc2010, tempReg, sizeof(tempReg));
        if (ret)
        {
                printk("setting int pin is not set\n");
                return -1;
        }
        return ret;
}
// setting up polarity for interrupt
int hdc2010_setInterruptPolarity(const struct i2c_dt_spec *hdc2010, int polarity)
{
        uint8_t oldConfig;
        int ret;
        uint8_t tempReg[2] = {CONFIG_REG, 0};

        ret = i2c_write_read_dt(hdc2010, &tempReg[0], 1, &oldConfig, 1);
        if (ret)
        {
                printk("writing in reg problem\n");
                return -1;
        }
        uint16_t newConfig;
        if (polarity)
        {
                newConfig = oldConfig | 1 << 1; // setting polarity of pin active high
        }
        else
        {
                newConfig = oldConfig & ~(1 << 1); // setting polarity of pin active low
        }
        tempReg[1] = newConfig;

        ret = i2c_write_dt(hdc2010, tempReg, sizeof(tempReg));
        if (ret)
        {
                printk("setting int pin is not set\n");
                return -1;
        }
        return ret;
}
// trigger reading
int triggerMeasurement(const struct i2c_dt_spec *hdc2010)
{
        uint8_t oldConfig;
        int ret;
        uint8_t tempReg[2] = {MEASUREMENT_CONFIG, 0};

        ret = i2c_write_read_dt(hdc2010, &tempReg[0], 1, &oldConfig, 1);
        if (ret)
        {
                printk("writing in reg problem\n");
                return -1;
        }
        uint8_t newConfig = oldConfig | 1 << 0; // setting start measurement
        tempReg[1] = newConfig;

        ret = i2c_write_dt(hdc2010, tempReg, sizeof(tempReg));
        if (ret)
        {
                printk("setting int pin is not set\n");
                return -1;
        }
        return 0;
}
// setting up drdy bit
int hdc2010_enableDRDYInterrupt(const struct i2c_dt_spec *hdc2010)
{
        uint8_t config;
        int ret;
        uint8_t tempReg[2] = {INTERRUPT_CONFIG, 0};

        ret = i2c_write_read_dt(hdc2010, &tempReg[0], 1, &config, 1);
        if (ret)
        {
                printk("writing in reg problem\n");
                return -1;
        }
        uint8_t newConfig = config | 1 << 7; // setting intEn pin in config reg
        tempReg[1] = newConfig;

        ret = i2c_write_dt(hdc2010, tempReg, sizeof(tempReg));
        if (ret)
        {
                printk("setting int pin is not set\n");
                return -1;
        }
        return 0;
}

// setting up interrupt drdy
int HDC2010_Enable_DRDY_Interrupt(const struct i2c_dt_spec *hdc2010, int polarity)
{

        int ret = hdc2010_enableDRDYInterrupt(hdc2010);
        ret = hdc_enable_interrupt(hdc2010);
        if (ret)
        {
                printk("hdc2010 enable interrupt error\n");
                return -1;
        }
        ret = hdc2010_setInterruptPolarity(hdc2010, polarity);
        if (ret)
        {
                printk("hdc2010 enabling polarity error\n");
        }
        ret = triggerMeasurement(hdc2010);

        return 0;
}

void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
        dataReady = 1;
        printk("interrupt triggered\n");
        /// Hdc2010ReadingTemperature(&hdc2010, &temp);
        //  triggerMeasurement(&hdc2010);
}
int main(void)
{
        int ret;
        if (!device_is_ready(button.port))
        {
                printk("inti problem\n");
                return;
        }
        //    static const struct i2c_dt_spec hdc2010 = I2C_DT_SPEC_GET(I2C_NODE);
        if (!device_is_ready(hdc2010.bus))
        {
                printk("device is not ready\n");
                return 0;
        }

        // sensor init part is here
        ret = hdc2010Init(&hdc2010);
        if (ret)
        {
                printk("hdc2010 sensor init failed\n");
                return -1;
        }

        printk("init completed\n");
        ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
        ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE);
        if (ret)
        {
                printk("error\n");
                return 0;
        }
        // // temp part
        uint8_t tempReg[2] = {MEASUREMENT_CONFIG, 0};
        uint8_t oldConfig;
        ret = i2c_write_read_dt(&hdc2010, &tempReg[0], 1, &oldConfig, 1);
        if (ret)
        {
                printk("writing in reg problem\n");
                return -1;
        }
        printk("%x measurement\n", oldConfig);
        tempReg[0] = CONFIG_REG;
        oldConfig;
        ret = i2c_write_read_dt(&hdc2010, &tempReg[0], 1, &oldConfig, 1);
        if (ret)
        {
                printk("writing in reg problem\n");
                return -1;
        }

        printk("%x config\n", oldConfig);

        gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
        gpio_add_callback(button.port, &button_cb_data);
        int temp;

        ret = HDC2010_Enable_DRDY_Interrupt(&hdc2010, 0);
        if (ret)
        {
                printk("error\n");
                return 0;
        }
        tempReg[0] = INTERRUPT_CONFIG;
        ret = i2c_write_read_dt(&hdc2010, &tempReg[0], 1, &oldConfig, 1);
        if (ret)
        {
                printk("writing in reg problem\n");
                return -1;
        }
        printk("%x DRDY BIT\n", oldConfig);
        while (1)
        {
                k_msleep(1000);
        }
        return 0;
}

this is code i have written , drivers were not available in zephyr so i have to wrote them, see if there is problem.

&i2c0 {
    status = "okay";
    hdc2010: hdc2010@40 {
        compatible = "i2c-device";
        status = "okay";
        reg = <0x40>;
    };
};
/ {
    buttons {
        compatible = "gpio-keys";
        button5: button_5 {
            gpios = <&gpio0 4 (GPIO_PULL_UP | GPIO_ACTIVE_HIGH)>;

        };

    };
    aliases{
        sw5=&button5;
    };

};
 
and this is my overlay file.

Related