Issue with MAX30208 Sensor: No Interrupt Signal on GPIO0 Pin in Xiao ble nrf52840 board and programming by using zepkhyr ncs v2.6.1 vscode sofware.

Issue: No Interrupt Signal on GPIO0 Pin of MAX30208 Sensor with Xiao BLE nRF52840 Using Zephyr NCS v2.6.1

I was write a code for max302078 sensor driver but in this i want to use the feature which a alarm feature or called as interrupt in max30208 microcontroller to genarte an interrupt when the temperature value goes to high to set predefine value in alarm register then the gpio0 pin in max30208 sensor want to genrate a low signal but in my case after doing internal pullup through microcontroller the gpio pin is always in low state or logical 0;

so , I am encountering an issue with the MAX30208 temperature sensor connected to the Xiao BLE nRF52840 microcontroller, where the GPIO0 pin is supposed to generate an interrupt signal. Despite configuring the sensor and the GPIO pin as specified in the datasheet and programming it using Zephyr NCS v2.6.1, the interrupt signal on GPIO0 is not being generated as expected.

Details:

  • Sensor: MAX30208
  • Microcontroller: Xiao BLE nRF52840
  • Programming Framework: Zephyr NCS v2.6.1
  • Expected Behavior: GPIO0 should generate an interrupt when the temperature exceeds the predefined alarm thresholds.
  • Actual Behavior: GPIO0 remains in a low state (logic 0) and does not transition to a high state (logic 1), indicating no interrupt signal is generated.

Steps Taken:

  1. Configuration:

    • Configured the MAX30208 sensor with alarm thresholds.
    • Enabled the internal pull-up resistor on GPIO0.
    • Set the appropriate interrupt enable bits and GPIO0_MODE in the sensor registers.
    • when i use only pull up of gpio in devicetree is like below
    • &i2c1 {
          status = "okay";
          pinctrl-0 = <&i2c1_default>;
          max30208: max30208@50 {
              compatible = "i2c-device";
              status = "okay";
              reg = <0x50>;
          };
      };
      
      &pinctrl {
          i2c1_default: i2c1_default {
              group1 {
                  psels = <NRF_PSEL(TWIM_SDA, 0, 4)>,
                          <NRF_PSEL(TWIM_SCL, 0, 5)>;
                  bias-disable;
              };
          };
      };
      
      / {
          max_gpio {
              compatible = "gpio-keys";
              // debounce-interval-ms = <1000>;
              max_gpio0: max_gpio0 {
                  gpios = <&gpio0 2 GPIO_PULL_UP>;
              };
          };
      };
  2. Code Implementation:

    • Configured the GPIO0 pin as an input with an internal pull-up resistor using Zephyr NCS v2.6.1.
    • #include <zephyr/kernel.h>
      #include <zephyr/device.h>
      #include <zephyr/devicetree.h>
      #include <zephyr/drivers/gpio.h>
      #include <zephyr/logging/log.h>
      #include "max30208.h"
      
      LOG_MODULE_REGISTER(temp_max_xiao);
      
      // I2C node
      #define I2C_NODE DT_NODELABEL(max30208)
      #define GPIO_NODE DT_NODELABEL(max_gpio0)
      
      static const struct i2c_dt_spec max30208 = I2C_DT_SPEC_GET(I2C_NODE);
      static const struct gpio_dt_spec max30208_gpio = GPIO_DT_SPEC_GET(GPIO_NODE, gpios);
      // static struct gpio_callback max30208_gpio_cb_data;
      
      // void triggred(const struct device *port, struct gpio_callback *cb, gpio_port_pins_t pins)
      // {
      //         LOG_INF("Temperature alarm triggered");
      //         uint8_t button_state = gpio_pin_get_dt(&max30208_gpio);
      //         LOG_INF("bt2 = %d", button_state);
      // }
      
      int8_t gpio_trigger(void)
      {
              int ret;
      
              if (!device_is_ready(max30208_gpio.port))
              {
                      LOG_ERR("I2C bus is not ready!");
                      return -1;
              }
      
              ret = gpio_pin_configure_dt(&max30208_gpio, GPIO_INPUT);
              if (ret < 0)
              {
                      return -1;
              }
      
              // ret = gpio_pin_interrupt_configure_dt(&max30208_gpio, GPIO_INT_LEVEL_INACTIVE); // rising edge
              // if (ret < 0)
              // {
              //         LOG_INF("Failed to configure interrupt");
              //         return -1;
              // }
      
              // gpio_init_callback(&max30208_gpio_cb_data, triggred, BIT(max30208_gpio.pin));
      
              // ret = gpio_add_callback(max30208_gpio.port, &max30208_gpio_cb_data);
              // if (ret < 0)
              // {
              //         LOG_INF("Failed to add callback");
              //         return -1;
              // }
      
              return 0;
      }
      
      int32_t max30208_get_AlarmHigh(const struct i2c_dt_spec *spec, uint8_t *temp)
      {
              int32_t ret;
      
              ret = read_register(spec, ALARM_HIGH_MSB, temp);
              if (ret < 0)
              {
                      LOG_ERR("Failed to read ALARM_HIGH_MSB");
                      return -1;
              }
              return 0;
      }
      
      int32_t max30208_set_AlarmHigh(const struct i2c_dt_spec *spec, uint8_t *temp)
      {
              int32_t ret;
              uint8_t reg[2] = {ALARM_HIGH_MSB, temp[0]};
              ret = write_register(spec, reg);
              if (ret < 0)
              {
                      LOG_ERR("Failed to write ALARM_HIGH_MSB");
                      return -1;
              }
              reg[0] = ALARM_HIGH_LSB;
              reg[1] = temp[1];
              ret = write_register(spec, reg);
              if (ret < 0)
              {
                      LOG_ERR("Failed to write ALARM_HIGH_MSB");
                      return -1;
              }
              return 0;
      }
      
      int8_t alarm_high_setup(uint8_t *reg_AH)
      {
              int ret;
              uint8_t ret_AH[2] = {0X00};
              ret = max30208_get_AlarmHigh(&max30208, ret_AH);
              if (ret < 0)
              {
                      LOG_ERR("Failed to read alarm high");
                      return -1;
              }
              LOG_INF("Alarm high: 0x%02x%02x", ret_AH[0], ret_AH[1]);
              ret = max30208_set_AlarmHigh(&max30208, reg_AH);
              if (ret < 0)
              {
                      LOG_ERR("Failed to write alarm high");
                      return -1;
              }
      
              ret = max30208_get_AlarmHigh(&max30208, ret_AH);
              if (ret < 0)
              {
                      LOG_ERR("Failed to read alarm high");
                      return -1;
              }
              LOG_INF("Alarm high: 0x%02x%02x", ret_AH[0], ret_AH[1]);
              return 0;
      }
      
      int32_t max30208_get_AlarmLow(const struct i2c_dt_spec *spec, uint8_t *value)
      {
              int8_t ret;
              ret = read_register(spec, ALARM_LOW_MSB, value);
              if (ret < 0)
              {
                      LOG_ERR("Failed to read ALARM_LOW_MSB");
                      return -1;
              }
              return 0;
      }
      
      int32_t max30208_set_AlarmLow(const struct i2c_dt_spec *spec, uint8_t *temp)
      {
              int32_t ret;
              uint8_t reg[2] = {ALARM_LOW_MSB, temp[0]};
              ret = write_register(spec, reg);
              if (ret < 0)
              {
                      LOG_ERR("Failed to write ALARM_LOW_MSB");
                      return -1;
              }
              reg[0] = ALARM_LOW_LSB;
              reg[1] = temp[1];
              ret = write_register(spec, reg);
              if (ret < 0)
              {
                      LOG_ERR("Failed to write ALARM_LOW_MSB");
                      return -1;
              }
              return 0;
      }
      
      int8_t alarm_low_setup(uint8_t *reg_AL)
      {
              int8_t ret;
              uint8_t ret_AL[2] = {0X00};
              ret = max30208_get_AlarmLow(&max30208, ret_AL);
              if (ret < 0)
              {
                      LOG_ERR("Failed to read alarm low");
                      return -1;
              }
              ret = max30208_set_AlarmLow(&max30208, reg_AL);
              if (ret < 0)
              {
                      LOG_ERR("Failed to write alarm low");
                      return -1;
              }
              ret = max30208_get_AlarmLow(&max30208, ret_AL);
              if (ret < 0)
              {
                      LOG_ERR("Failed to read alarm low");
                      return -1;
              }
              return 0;
      }
      
      int32_t max30208_enable_interrupts(const struct i2c_dt_spec *spec)
      {
              int32_t ret;
      
              uint8_t reg[2] = {INTERRUPT_CONF, 0x06}; // Enable TEMP_LO and TEMP_HI interrupts
              ret = write_register(spec, reg);
              if (ret < 0)
              {
                      LOG_ERR("Failed to enable interrupts");
                      return -1;
              }
              return 0;
      }
      
      int32_t max30208_get_GPIOSetup(const struct i2c_dt_spec *spec, uint8_t *value)
      {
              int32_t ret;
              ret = read_register(spec, GPIO_SETUP, value);
              if (ret < 0)
              {
                      LOG_ERR("Failed to read ALARM_LOW_MSB");
                      return -1;
              }
              return 0;
      }
      
      int32_t max30208_configure_gpio(const struct i2c_dt_spec *spec)
      {
              int32_t ret;
              uint8_t reg[2] = {GPIO_SETUP, 0x03}; // Configure GPIO0 as interrupt output
              ret = write_register(spec, reg);
              if (ret < 0)
              {
                      LOG_ERR("Failed to configure GPIO");
                      return -1;
              }
              return 0;
      }
      
      int32_t max30208_set_GPIOControl(const struct i2c_dt_spec *spec)
      {
              int32_t ret;
              uint8_t ret_GPCL[1] = {0X00};
              ret = read_register(&max30208, GPIO_CONTROL, ret_GPCL);
              if (ret < 0)
              {
                      LOG_ERR("Failed to read GPIO control");
                      return -1;
              }
              LOG_INF("GPIO Control: 0x%02x", ret_GPCL[0]);
      
              uint8_t reg[2] = {GPIO_CONTROL, 0x01};
              ret = write_register(spec, reg);
              if (ret < 0)
              {
                      LOG_ERR("Failed to set GPIO control");
                      return -1;
              }
      
              ret = read_register(&max30208, GPIO_CONTROL, ret_GPCL);
              if (ret < 0)
              {
                      LOG_ERR("Failed to read GPIO control");
                      return -1;
              }
              LOG_INF("GPIO Control: 0x%02x", ret_GPCL[0]);
              return 0;
      }
      
      int main(void)
      {
              int8_t ret;
              uint8_t part_id;
              uint8_t button_state;
              float temp;
              float temperatureF;
              uint8_t htem_status = 0x00;
              if (!device_is_ready(max30208.bus))
              {
                      LOG_ERR("I2C bus is not ready!");
                      return -1;
              }
      
              ret = gpio_trigger();
              if (ret < 0)
              {
                      LOG_ERR("Failed to configure GPIO");
                      return -1;
              }
      
              // Check Part ID
              ret = read_part_id(&max30208, &part_id);
              if (ret < 0 || part_id != PART_IDENTIFIER_VAL)
              {
                      LOG_ERR("Failed to read part ID or ID mismatch. Expected: 0x%02x, Read: 0x%02x", PART_IDENTIFIER_VAL, part_id);
                      return -1;
              }
              LOG_INF("Part ID: 0x%02x", part_id);
      
              // Initialize sensor
              ret = max30208_init(&max30208);
              if (ret < 0)
              {
                      LOG_ERR("Failed to initialize MAX30208");
                      return -1;
              }
      
              ret = max30208_configure_gpio(&max30208);
              if (ret < 0)
              {
                      LOG_ERR("Failed to configure GPIO");
                      return -1;
              }
      
              ret = max30208_enable_interrupts(&max30208);
              if (ret < 0)
              {
                      LOG_ERR("Failed to enable interrupts");
                      return -1;
              }
      
              ret = max30208_set_GPIOControl(&max30208);
              if (ret < 0)
              {
                      LOG_ERR("Failed to set GPIO control");
                      return -1;
              }
      
              uint8_t reg_AL[2] = {0x19, 0x00};
              ret = alarm_low_setup(reg_AL);
              if (ret < 0)
              {
                      LOG_ERR("Failed to set alarm low");
                      return -1;
              }
      
              uint8_t reg_AH[2] = {0x1A, 0xE0};
              ret = alarm_high_setup(reg_AH);
              if (ret < 0)
              {
                      LOG_ERR("Failed to set alarm high");
                      return -1;
              }
      
              while (1)
              {
                      // Trigger temperature conversion
                      ret = MAX30208_Trigger_Conversion(&max30208);
                      if (ret < 0)
                      {
                              LOG_ERR("Failed to trigger conversion");
                              return -1;
                      }
                      // Delay to allow conversion to complete
                      k_msleep(100);
      
                      // Read temperature
                      ret = read_temp(&max30208, &temp);
                      if (ret < 0)
                      {
                              LOG_ERR("Failed to read temperature");
                              return -1;
                      }
                      // Convert to Fahrenheit
                      temperatureF = max30208_toFahrenheit(temp);
                      LOG_INF("Temperaturec: %.2f °C\t||\tTemperaturef: %.2f °F", temp, temperatureF);
      
                      ret = read_status(&max30208, &htem_status);
                      if (ret < 0)
                      {
                              LOG_ERR("Failed to read status");
                              return -1;
                      }
                      LOG_INF("Status: 0x%02x", htem_status);
      
                      button_state = gpio_pin_get_dt(&max30208_gpio);
                      LOG_INF("bt = %d", button_state);
      
                      // Wait before next measurement
                      k_msleep(DELAY);
              }
              return 0;
      }
      
  3. Testing:

    • Verified the temperature readings and confirmed they exceed the set alarm thresholds.
    • Observed the GPIO0 pin state using a logic analyzer and confirmed it remains low.
    • this is result when i use only pull up in devicetree
    • this is result when i use  pull up and gpio_active_low in devicetree

Attachments:

I have attached the relevant code, the datasheet for the MAX30208 sensor, and the logic analyzer data for further analysis. Any guidance or assistance in resolving this issue would be greatly appreciated.

Thank you for your support.

Parents Reply Children
Related