max30102.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #include "max30102.h"
  2. static const char *TAG = "max30102";
  3. #define MAX30102_I2C_SCL 2 // GPIO number used for I2C master clock
  4. #define MAX30102_I2C_SDA 3 // GPIO number used for I2C master data
  5. #define MAX30102_I2C_NUM 0 // I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip
  6. #define MAX30102_I2C_FREQ_HZ 50000 // I2C master clock frequency
  7. #define MAX30102_I2C_TX_BUF_DISABLE 0 // I2C master doesn't need buffer
  8. #define MAX30102_I2C_RX_BUF_DISABLE 0
  9. #define MAX30102_I2C_TIMEOUT_MS 1000
  10. #define MAX30102_GPIO_INT 7 // GPIO number used for MAX30102 int
  11. // | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | WRITE ADDRESS | READ ADDRESS |
  12. // | 1 | 0 | 1 | 0 | 1 | 1 | 1 | R/W| 0xAE | 0xAF |
  13. #define MAX30102_ADDR 0x57 // I2C device MAX30102's 7-bit address
  14. #define MAX30102_PART_ID_REG_ADDR 0xff
  15. static xQueueHandle gpio_evt_queue = NULL;
  16. /**
  17. * @brief init the i2c port for MAX30102
  18. */
  19. static esp_err_t max30102_i2c_init()
  20. {
  21. int i2c_master_port = MAX30102_I2C_NUM;
  22. i2c_config_t conf = {
  23. .mode = I2C_MODE_MASTER,
  24. .sda_io_num = MAX30102_I2C_SDA,
  25. .scl_io_num = MAX30102_I2C_SCL,
  26. .sda_pullup_en = GPIO_PULLUP_ENABLE,
  27. .scl_pullup_en = GPIO_PULLUP_ENABLE,
  28. .master.clk_speed = MAX30102_I2C_FREQ_HZ,
  29. };
  30. i2c_param_config(i2c_master_port, &conf);
  31. return i2c_driver_install(i2c_master_port, conf.mode, MAX30102_I2C_RX_BUF_DISABLE, MAX30102_I2C_TX_BUF_DISABLE, 0);
  32. }
  33. /**
  34. * @brief Read a sequence of bytes from a MAX30102 registers
  35. */
  36. static esp_err_t max30102_register_read(uint8_t reg_addr, uint8_t *data, size_t len)
  37. {
  38. return i2c_master_write_read_device(MAX30102_I2C_NUM, MAX30102_ADDR, &reg_addr, 1, data, len, MAX30102_I2C_TIMEOUT_MS / portTICK_RATE_MS);
  39. }
  40. /**
  41. * @brief Write a byte to a MAX30102 register
  42. */
  43. static esp_err_t max30102_register_write_byte(uint8_t reg_addr, uint8_t data)
  44. {
  45. int ret;
  46. uint8_t write_buf[2] = {reg_addr, data};
  47. ret = i2c_master_write_to_device(MAX30102_I2C_NUM, MAX30102_ADDR, write_buf, sizeof(write_buf), MAX30102_I2C_TIMEOUT_MS / portTICK_RATE_MS);
  48. return ret;
  49. }
  50. void gpio_intr_task()
  51. {
  52. uint8_t byte[6];
  53. int data[2];
  54. uint8_t io_num;
  55. for(;;) {
  56. if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
  57. ESP_ERROR_CHECK(max30102_register_read(0x07, &byte, 6));
  58. data[0] = ((byte[0]<<16 | byte[1]<<8 | byte[2]) & 0x03ffff);
  59. data[1] = ((byte[3]<<16 | byte[4]<<8 | byte[5]) & 0x03ffff);
  60. printf("Red: %d, IR: %d\n", data[1], data[0]);
  61. }
  62. }
  63. }
  64. static void IRAM_ATTR gpio_isr_handler(void* arg)
  65. {
  66. uint32_t gpio_num = (uint32_t) arg;
  67. xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
  68. }
  69. /**
  70. * @brief init the gpio intr for MAX30102
  71. */
  72. static esp_err_t max30102_gpio_intr_init()
  73. {
  74. gpio_config_t io_conf = {};
  75. io_conf.intr_type = GPIO_INTR_NEGEDGE;
  76. io_conf.mode = GPIO_MODE_INPUT;
  77. io_conf.pin_bit_mask = (1ULL<<MAX30102_GPIO_INT);
  78. io_conf.pull_down_en = 0;
  79. io_conf.pull_up_en = 1;
  80. ESP_ERROR_CHECK(gpio_config(&io_conf));
  81. //create a queue to handle gpio event from isr
  82. gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
  83. //start gpio task
  84. xTaskCreate(gpio_intr_task, "gpio_intr_task", 2048, NULL, 10, NULL);
  85. //install gpio isr service
  86. gpio_install_isr_service(0);
  87. //hook isr handler for specific gpio pin
  88. gpio_isr_handler_add(MAX30102_GPIO_INT, gpio_isr_handler, (void*) MAX30102_GPIO_INT);
  89. return ESP_OK;
  90. }
  91. void get_temp()
  92. {
  93. uint8_t byte[2];
  94. float temp;
  95. ESP_ERROR_CHECK(max30102_register_write_byte(0x21, 0x01));
  96. vTaskDelay(100 / portTICK_RATE_MS);
  97. ESP_ERROR_CHECK(max30102_register_read(0x1f, &byte[0], 1));
  98. ESP_ERROR_CHECK(max30102_register_read(0x20, &byte[1], 1));
  99. temp = (int8_t)(byte[0]) + byte[1] * 0.0625;
  100. printf("Temp: %f\n", temp);
  101. // FIFO
  102. ESP_ERROR_CHECK(max30102_register_write_byte(0x04, 0x00)); // clear FIFO Write Pointer
  103. ESP_ERROR_CHECK(max30102_register_write_byte(0x05, 0x00)); // clear FIFO Overflow Counter
  104. ESP_ERROR_CHECK(max30102_register_write_byte(0x06, 0x00)); // clear FIFO Read Pointer
  105. // clear PPG_RDY ! Cannot receive the first interrupt without clearing !
  106. uint8_t data;
  107. ESP_ERROR_CHECK(max30102_register_read(0x00, &data, 1));
  108. ESP_ERROR_CHECK(max30102_register_read(0x01, &data, 1));
  109. }
  110. void max30102_init()
  111. {
  112. ESP_ERROR_CHECK(max30102_i2c_init());
  113. ESP_LOGI(TAG, "MAX30102 I2C initialized successfully");
  114. max30102_gpio_intr_init();
  115. ESP_LOGI(TAG, "MAX30102 GPIO INTR initialized successfully");
  116. // reset
  117. ESP_ERROR_CHECK(max30102_register_write_byte(0x09, 0x40));
  118. vTaskDelay(100 / portTICK_RATE_MS);
  119. // Interrupt Enable
  120. ESP_ERROR_CHECK(max30102_register_write_byte(0x02, 0xc0)); // enable interrupts: A_FULL: FIFO Almost Full Flag and PPG_RDY: New FIFO Data Ready
  121. ESP_ERROR_CHECK(max30102_register_write_byte(0x03, 0x02)); // enable interrupt: DIE_TEMP_RDY: Internal Temperature Ready Flag
  122. // FIFO
  123. ESP_ERROR_CHECK(max30102_register_write_byte(0x04, 0x00)); // clear FIFO Write Pointer
  124. ESP_ERROR_CHECK(max30102_register_write_byte(0x05, 0x00)); // clear FIFO Overflow Counter
  125. ESP_ERROR_CHECK(max30102_register_write_byte(0x06, 0x00)); // clear FIFO Read Pointer
  126. // FIFO Configuration
  127. ESP_ERROR_CHECK(max30102_register_write_byte(0x08, 0x0f)); // SMP_AVE = 0b000: 1 averaging, FIFO_ROLLOVER_EN = 0, FIFO_A_FULL = 0xf
  128. // Mode Configuration
  129. ESP_ERROR_CHECK(max30102_register_write_byte(0x09, 0x03)); // MODE = 0b011: SpO2 mode
  130. // SpO2 Configuration
  131. ESP_ERROR_CHECK(max30102_register_write_byte(0x0a, 0x47)); // SPO2_ADC_RGE = 0b10: 8192, SPO2_SR = 0b001: 100 SAMPLES PER SECOND,
  132. // LED_PW = 0b11: PULSE WIDTH 411, ADC RESOLUTION 18
  133. // LED Pulse Amplitude
  134. ESP_ERROR_CHECK(max30102_register_write_byte(0x0c, 0x50)); // LED1_PA(red) = 0x24, LED CURRENT 16mA
  135. ESP_ERROR_CHECK(max30102_register_write_byte(0x0d, 0x50)); // LED2_PA(IR) = 0x24, LED CURRENT 16mA
  136. ESP_ERROR_CHECK(max30102_register_write_byte(0x10, 0x50)); // PILOT_PA = 0x24, LED CURRENT 16mA
  137. // clear PPG_RDY ! Cannot receive the first interrupt without clearing !
  138. uint8_t data;
  139. ESP_ERROR_CHECK(max30102_register_read(0x00, &data, 1));
  140. ESP_LOGI(TAG, "Interrupt Status 1: 0x%x", data);
  141. ESP_ERROR_CHECK(max30102_register_read(0x01, &data, 1));
  142. ESP_LOGI(TAG, "Interrupt Status 2: 0x%x", data);
  143. }