From ea3541008f780b1a70e578d2914bfe2518c94c1a Mon Sep 17 00:00:00 2001 From: Ivan Li Date: Sun, 5 Feb 2023 23:09:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=8E=AF=E5=A2=83=E5=85=89=E4=B8=8E?= =?UTF-8?q?=E6=8E=A5=E8=BF=91=E4=BC=A0=E6=84=9F=E5=99=A8=E6=8E=A5=E5=85=A5?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 +- main/CMakeLists.txt | 2 +- main/ambient_light.c | 203 ++++++++++++++++++++++++++++++++++++++++ main/embedded_display.c | 11 +++ main/main.c | 5 +- main/temperature.c | 9 +- 6 files changed, 226 insertions(+), 7 deletions(-) create mode 100644 main/ambient_light.c diff --git a/.vscode/settings.json b/.vscode/settings.json index 8a66b05..1bef50e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -45,6 +45,7 @@ "led_strip.h": "c", "esp_event.h": "c", "string.h": "c", - "i2c.h": "c" + "i2c.h": "c", + "esp_log.h": "c" } } diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index dcc2372..6d157e0 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,2 +1,2 @@ -idf_component_register(SRCS "temperature.c" "embedded_display.c" "ui.c" "mqtt.c" "main.c" "wifi.c" "light.c" "mqtt.c" +idf_component_register(SRCS "ambient_light.c" "temperature.c" "embedded_display.c" "ui.c" "mqtt.c" "main.c" "wifi.c" "light.c" "mqtt.c" INCLUDE_DIRS ".") \ No newline at end of file diff --git a/main/ambient_light.c b/main/ambient_light.c new file mode 100644 index 0000000..261907f --- /dev/null +++ b/main/ambient_light.c @@ -0,0 +1,203 @@ +#include +#include + +#include "driver/i2c.h" +#include "embedded_display.c" + +#include "esp_log.h" + +#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" + +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_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(100)); + } + display_fill_rect(0, 2, 128, 8, 0x00); +} + +void ambient_light_auto_fetch() { + xTaskCreate(ambient_light_fetch, "ui_input_event", 2048, NULL, 10, NULL); +} + +void ambient_light_init() { + // esp_log_level_set(AMBIENT_LIGHT_TAG, ESP_LOG_DEBUG); + 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)); +} diff --git a/main/embedded_display.c b/main/embedded_display.c index 5fd0c89..c8f739c 100644 --- a/main/embedded_display.c +++ b/main/embedded_display.c @@ -38,6 +38,17 @@ void display_fill(uint8_t bmpData) { } } } +void display_fill_rect(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, + uint8_t bmpData) { + for (int y = y0; y < y1; y++) { + i2cWriteCommand(0xB0 + y); + i2cWriteCommand(0x01); + i2cWriteCommand(0x10); + for (int x = x0; x < x1; x++) { + i2cWriteData(bmpData); + } + } +} void display_set_pos(uint8_t x, uint8_t y) { i2cWriteCommand(0xB0 + y); diff --git a/main/main.c b/main/main.c index 6223157..ba6850c 100644 --- a/main/main.c +++ b/main/main.c @@ -1,3 +1,4 @@ +#include "ambient_light.c" #include "driver/i2c.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" @@ -44,8 +45,10 @@ void app_main(void) { light_init_strip(); init_i2c(); init_display(); - auto_fetch_temperature(); display_print8_str(0, 0, "Ambient Light"); + ambient_light_init(); + ambient_light_auto_fetch(); + auto_fetch_temperature(); init_ui(); xTaskCreate(publish_ui_input, "ui_input_event", 2048, NULL, 10, NULL); vTaskDelay(pdMS_TO_TICKS(10)); diff --git a/main/temperature.c b/main/temperature.c index 9fe3fad..f2ed1e1 100644 --- a/main/temperature.c +++ b/main/temperature.c @@ -26,6 +26,7 @@ void fetch_temperature(void* arg) { float temperature = DEFAULT_TEMPERATURE; char temperature_str[10]; uint8_t temperature_buffer[] = {0, 0}; + display_fill_rect(0, 0, 128, 2, 0x00); for (;;) { i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_master_start(cmd); @@ -59,13 +60,13 @@ void fetch_temperature(void* arg) { temperature = (temperature_buffer[0] << 3 | temperature_buffer[1] >> 5) * 0.125; } - sprintf(temperature_str, "Temp: %.3f ", temperature); + sprintf(temperature_str, "Temp: %2.3f", temperature); } - - display_print8_str(8, 2, temperature_str); + display_print8_str(8, 0, temperature_str); } - vTaskDelay(pdMS_TO_TICKS(1000)); + vTaskDelay(pdMS_TO_TICKS(500)); } + display_fill_rect(0, 0, 128, 2, 0x00); } void auto_fetch_temperature() {