#include #include #include "driver/i2c.h" #include "embedded_display.c" #include "esp_log.h" #include "i2c.c" #define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/ #define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */ #define ACK_VAL 0x0 /*!< I2C ack value */ #define NACK_VAL 0x1 /*!< I2C nack value */ #define I2C_MASTER_NUM CONFIG_I2C_NUM #define APDS_9930_ADDRESS 0x39 #define APDS_9930_CMD_REPEATED 0x80 // 命令重复地址 #define APDS_9930_CMD_AUTO_INCREMENT 0x90 // 命令自动递增地址 // ----------------------------------- 描述 默认值 #define APDS_9930_REG_ENABLE 0x00 // 状态和中断的启用 0x00 #define APDS_9930_REG_ATIME 0x01 // ALS ADC 时间 0xff #define APDS_9930_REG_PTIME 0x02 // Proximity ADC 时间 0xff #define APDS_9930_REG_WTIME 0x03 // Wait 时间 0xff #define APDS_9930_REG_PPULSE 0x0e // Proximity 脉冲计数 0x00 #define APDS_9930_REG_CONTROL 0x0f // 增益控制 0x00 #define APDS_9930_REG_Ch0DATAL 0x14 // Ch0 ADC Low data 0x00 #define APDS_9930_REG_Ch0DATAH 0x15 // Ch0 ADC High data 0x00 #define APDS_9930_REG_Ch1DATAL 0x16 // Ch1 ADC Low data 0x00 #define APDS_9930_REG_Ch1DATAH 0x17 // Ch1 ADC High data 0x00 #define APDS_9930_REG_PDATAL 0x18 // Proximity ADC Low data 0x00 #define APDS_9930_REG_PDATAH 0x19 // Proximity ADC High data 0x00 #define APDS_9930_REG_OFFSET 0x1e // Proximity 偏移 -- #define APDS_9930_ATIME_VALUE 0xff // 2.7 ms – minimum ALS integration time #define APDS_9930_WTIME_VALUE 0xff // 2.7 ms – minimum Wait time #define APDS_9930_PTIME_VALUE 0xff // 2.7 ms – minimum Prox integration time #define APDS_9930_PPULSE_VALUE 0x08 // Minimum prox pulse count #define APDS_9930_CONTROL_VALUE \ 0b00101010 // LED 100mA, Proximity Diode Ch1, // Proximity 4X, ALS 16 X #define APDS_9930_ENABLE_VALUE 0b01000111 #define APDS_9930_OFFSET_VALUE 0x8f #define AMBIENT_LIGHT_TAG "ambient-light" static int8_t is_apds_9930_online = 0; esp_err_t apds_9930_write(uint8_t command, uint8_t data) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, APDS_9930_ADDRESS << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN); i2c_master_write_byte(cmd, command, ACK_CHECK_EN); i2c_master_write_byte(cmd, data, ACK_CHECK_EN); i2c_master_stop(cmd); esp_err_t error = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); if (error != ESP_OK) { ESP_LOGW(AMBIENT_LIGHT_TAG, "write failed. %d", error); } return error; } esp_err_t apds_9930_write_word(uint8_t command, uint8_t data_l, uint8_t data_h) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, APDS_9930_ADDRESS << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN); i2c_master_write_byte(cmd, command, ACK_CHECK_EN); i2c_master_write_byte(cmd, data_l, ACK_CHECK_EN); i2c_master_write_byte(cmd, data_h, ACK_CHECK_EN); i2c_master_stop(cmd); esp_err_t error = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); if (error != ESP_OK) { ESP_LOGW(AMBIENT_LIGHT_TAG, "write failed. %d", error); } return error; } esp_err_t apds_9930_read(uint8_t command, uint8_t* data) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, APDS_9930_ADDRESS << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN); i2c_master_write_byte(cmd, command, ACK_CHECK_EN); i2c_master_start(cmd); i2c_master_write_byte(cmd, APDS_9930_ADDRESS << 1 | I2C_MASTER_READ, ACK_CHECK_EN); i2c_master_read_byte(cmd, data, NACK_VAL); i2c_master_stop(cmd); esp_err_t error = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); if (error != ESP_OK) { ESP_LOGW(AMBIENT_LIGHT_TAG, "write failed. %d", error); } return error; } esp_err_t apds_9930_read_word(uint8_t command, uint8_t* data_l, uint8_t* data_h) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, APDS_9930_ADDRESS << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN); i2c_master_write_byte(cmd, command, ACK_CHECK_EN); i2c_master_start(cmd); i2c_master_write_byte(cmd, APDS_9930_ADDRESS << 1 | I2C_MASTER_READ, ACK_CHECK_EN); i2c_master_read_byte(cmd, data_l, ACK_VAL); i2c_master_read_byte(cmd, data_h, NACK_VAL); i2c_master_stop(cmd); esp_err_t error = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS); i2c_cmd_link_delete(cmd); if (error != ESP_OK) { ESP_LOGW(AMBIENT_LIGHT_TAG, "write failed. %d", error); } return error; } void ambient_light_fetch(void* arg) { ESP_LOGI(AMBIENT_LIGHT_TAG, "ambient_light_fetch"); esp_err_t error; uint16_t als_ch0_raw; uint16_t als_ch1_raw; uint16_t proximity_raw; char als_ch0_str[10]; char als_ch1_str[10]; char proximity_str[10]; uint8_t als_ch0_buffer[] = {0, 0}; uint8_t als_ch1_buffer[] = {0, 0}; uint8_t proximity_buffer[] = {0, 0}; uint8_t enable_value; display_fill_rect(0, 2, 128, 8, 0x00); for (;;) { // Proximity error = apds_9930_read_word(APDS_9930_CMD_AUTO_INCREMENT | APDS_9930_REG_PDATAL, &(proximity_buffer[1]), &(proximity_buffer[0])); if (error != ESP_OK) { ESP_LOGW(AMBIENT_LIGHT_TAG, "read failed. %x", error); } else { proximity_raw = proximity_buffer[0] << 8 | proximity_buffer[1]; sprintf(proximity_str, "Prox: % 4d ", proximity_raw); display_print8_str(8, 2, proximity_str); ESP_LOGD(AMBIENT_LIGHT_TAG, "Prox: %d %x, %x %x", proximity_raw, proximity_raw, proximity_buffer[0], proximity_buffer[1]); } // als ch0 error = apds_9930_read_word( APDS_9930_CMD_AUTO_INCREMENT | APDS_9930_REG_Ch0DATAL, &(als_ch0_buffer[1]), &(als_ch0_buffer[0])); if (error != ESP_OK) { ESP_LOGW(AMBIENT_LIGHT_TAG, "read failed. %x", error); } else { als_ch0_raw = als_ch0_buffer[0] << 8 | als_ch0_buffer[1]; sprintf(als_ch0_str, "Ch0: % 5d ", als_ch0_raw); display_print8_str(8, 4, als_ch0_str); ESP_LOGD(AMBIENT_LIGHT_TAG, "ALS Ch0: %d, %x", als_ch0_raw, als_ch0_raw); } // als ch1 // error = apds_9930_read_word( // APDS_9930_CMD_AUTO_INCREMENT | APDS_9930_REG_Ch1DATAL, // &(als_ch1_buffer[1]), &(als_ch1_buffer[0])); // if (error != ESP_OK) { // ESP_LOGW(AMBIENT_LIGHT_TAG, "read failed. %x", error); // } else { // als_ch1_raw = als_ch1_buffer[0] << 8 | als_ch1_buffer[1]; // sprintf(als_ch1_str, "Ch1: % 5d ", als_ch1_raw); // display_print8_str(8, 6, als_ch1_str); // ESP_LOGD(AMBIENT_LIGHT_TAG, "ALS Ch1: %d, %x", als_ch1_raw, // als_ch1_raw); // } vTaskDelay(pdMS_TO_TICKS(1000)); } display_fill_rect(0, 2, 128, 8, 0x00); } void ambient_light_auto_fetch() { if (is_apds_9930_online == 0) { return; } xTaskCreate(ambient_light_fetch, "ambient-light", 2048, NULL, 10, NULL); } void ambient_light_init() { if (i2c_check_slave_exists(APDS_9930_ADDRESS)) { is_apds_9930_online = 1; } else { is_apds_9930_online = 0; return; } ESP_LOGI(AMBIENT_LIGHT_TAG, "Initializing APDS-9930"); // esp_log_level_set(AMBIENT_LIGHT_TAG, ESP_LOG_ERROR); ESP_ERROR_CHECK(apds_9930_write(APDS_9930_CMD_REPEATED | APDS_9930_REG_ATIME, APDS_9930_ATIME_VALUE)); ESP_ERROR_CHECK(apds_9930_write(APDS_9930_CMD_REPEATED | APDS_9930_REG_PTIME, APDS_9930_PTIME_VALUE)); ESP_ERROR_CHECK(apds_9930_write(APDS_9930_CMD_REPEATED | APDS_9930_REG_PPULSE, APDS_9930_PPULSE_VALUE)); ESP_ERROR_CHECK(apds_9930_write( APDS_9930_CMD_REPEATED | APDS_9930_REG_CONTROL, APDS_9930_CONTROL_VALUE)); ESP_ERROR_CHECK(apds_9930_write(APDS_9930_CMD_REPEATED | APDS_9930_REG_OFFSET, APDS_9930_OFFSET_VALUE)); ESP_ERROR_CHECK(apds_9930_write(APDS_9930_CMD_REPEATED | APDS_9930_REG_ENABLE, APDS_9930_ENABLE_VALUE)); }