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, ®[0], 1, &device_id[0], 1);
if (ret)
{
printk("device id error\n");
return -1;
}
ret = i2c_write_read_dt(hdc2010, ®[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, ®[0], 1, &device_id[0], 1);
if (ret)
{
printk("menu id error\n");
return -1;
}
ret = i2c_write_read_dt(hdc2010, ®[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.
