Fri, 07 Apr 2023 14:31:17 +0200
The esp-idf-lib apds9930 component is now working. In nvsio stop logging not updated values. Store gain and aglbit values in nvs.
/** * @file task_apds9930.c * @brief The FreeRTOS task to query the APDS9930 sensor. */ #include "config.h" static const char *TAG = "task_apds9930"; SemaphoreHandle_t xSemaphoreAPDS9930 = NULL; ///< Semaphore APDS9930 task EventGroupHandle_t xEventGroupAPDS9930; ///< Events APDS9930 task APDS9930_State *apds9930_state; ///< Public state for other tasks float ambient_light; uint16_t ch0 = 0; uint16_t ch1 = 1; uint16_t ALS_maxcount; ///< Maximum ADC value uint16_t ALS_mincount; ///< Threshold to increase gain extern apds9930_t apds9930_dev; const int TASK_APDS9930_REQUEST_DONE = BIT0; ///< All requests are done. const int TASK_APDS9930_REQUEST_LIGHT = BIT1; ///< Request Ambient Light void request_apds9930(void) { xEventGroupClearBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_DONE); xEventGroupSetBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_LIGHT); } bool ready_apds9930(void) { if (xEventGroupGetBits(xEventGroupAPDS9930) & TASK_APDS9930_REQUEST_DONE) return true; return false; } /* * Task to read APDS9930 sensor on request. */ void task_apds9930(void *pvParameter) { int tries; esp_err_t err = ESP_OK; uint8_t l_gain, l_aglbit; ESP_LOGI(TAG, "Starting task APDS9930 sda=%d scl=%d", CONFIG_I2C_MASTER_SDA, CONFIG_I2C_MASTER_SCL); apds9930_state = malloc(sizeof(APDS9930_State)); apds9930_state->valid = false; apds9930_state->fake = (apds9930_dev.i2c_dev.addr == 0) ? true:false; apds9930_state->address = apds9930_dev.i2c_dev.addr; apds9930_state->error = APDS9930_ERR_NONE; /* Gain settings are saved in NVS for quick startup. */ l_gain = nvsio_read_u8((char *)"l_gain"); l_aglbit = nvsio_read_u8((char *)"l_aglbit"); ESP_LOGI(TAG, "gain %d agl: %d", l_gain, l_aglbit); // Calculate these for auto gain scaling. ALS_maxcount = (256 - APDS9930_DEFAULT_ATIME) * 1024; ALS_mincount = ALS_maxcount / 64; /* event handler and event group for this task */ xEventGroupAPDS9930 = xEventGroupCreate(); EventBits_t uxBits; /* * Task loop forever. */ ESP_LOGI(TAG, "Starting loop APDS9930 sensor 0x%02x %d", apds9930_state->address, apds9930_state->fake); while (1) { uxBits = xEventGroupWaitBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_LIGHT, pdFALSE, pdFALSE, portMAX_DELAY ); if (uxBits & TASK_APDS9930_REQUEST_LIGHT) { if (! apds9930_state->fake) { /* Real sensor is present */ if (l_gain > 3) l_gain = 0; ESP_ERROR_CHECK(apds9930_enableLightSensor(&apds9930_dev, false)); // Does apds9930_enablePower() too. ESP_ERROR_CHECK(apds9930_disableProximitySensor(&apds9930_dev)); ESP_ERROR_CHECK(apds9930_setAmbientLightGain(&apds9930_dev, l_gain)); ESP_ERROR_CHECK(apds9930_setAmbientGainLevel(&apds9930_dev, l_aglbit)); vTaskDelay(200 / portTICK_PERIOD_MS); tries = 6; err = ESP_OK; while (tries) { if (err == ESP_OK) { err = apds9930_readCh0Light(&apds9930_dev, &ch0); if (err == ESP_OK) { err = apds9930_readCh1Light(&apds9930_dev, &ch1); } } if (err != ESP_OK) { ESP_LOGE(TAG, "read APDS-9930 values error '%s'", esp_err_to_name(err)); break; } ambient_light = apds9930_floatAmbientToLux(&apds9930_dev, ch0, ch1); /* * Check ranges */ if (((ch0 == ALS_maxcount) || (ch1 == ALS_maxcount)) && ((l_gain > 0) || (l_aglbit == 0))) { /* Looks like an internal overflow */ if (l_gain > 0) { l_gain--; } else { l_aglbit = 1; } apds9930_setAmbientLightGain(&apds9930_dev, l_gain); apds9930_setAmbientGainLevel(&apds9930_dev, l_aglbit); vTaskDelay(200 / portTICK_PERIOD_MS); ESP_LOGI(TAG, "Gain decreased to %d AGL: %d", l_gain, l_aglbit); } else if ((ch0 < ALS_mincount) && (ch1 < ALS_mincount) && (l_gain < 3)) { /* Looks like low resolution of the ADC. */ if ((l_gain == 0) && l_aglbit) { l_aglbit = 0; } else { l_gain++; } apds9930_setAmbientLightGain(&apds9930_dev, l_gain); apds9930_setAmbientGainLevel(&apds9930_dev, l_aglbit); vTaskDelay(200 / portTICK_PERIOD_MS); ESP_LOGI(TAG, "Gain increased to %d AGL: %d", l_gain, l_aglbit); } else { if ((ch0 == ALS_maxcount) || (ch1 == ALS_maxcount)) { ambient_light = -1; } else if (l_aglbit) { ambient_light = ambient_light / 0.1666; } nvsio_write_u8((char *)"l_gain", l_gain); nvsio_write_u8((char *)"l_aglbit", l_aglbit); ESP_LOGI(TAG, "Ambient: %.2f Ch0: %d Ch1: %d Gain: %d AGL: %d", ambient_light, ch0, ch1, l_gain, l_aglbit); break; } tries--; } if (tries == 0) { ESP_LOGW(TAG, "tries = 0"); } apds9930_disableLightSensor(&apds9930_dev); apds9930_disablePower(&apds9930_dev); if (xSemaphoreTake(xSemaphoreAPDS9930, 25) == pdTRUE) { if (err == ESP_OK) { apds9930_state->error = APDS9930_ERR_NONE; apds9930_state->valid = true; apds9930_state->ambient_light = ambient_light; apds9930_state->gain = l_gain; apds9930_state->aglbit = l_aglbit; } else { apds9930_state->error = APDS9930_ERR_READ; apds9930_state->valid = false; apds9930_state->ambient_light = 12.34; apds9930_state->gain = 2; apds9930_state->aglbit = 0; } xSemaphoreGive(xSemaphoreAPDS9930); } } else { /* Use fake values */ if (xSemaphoreTake(xSemaphoreAPDS9930, 25) == pdTRUE) { apds9930_state->error = APDS9930_ERR_NONE; apds9930_state->valid = true; apds9930_state->ambient_light = 12.34; apds9930_state->gain = 2; apds9930_state->aglbit = 0; xSemaphoreGive(xSemaphoreAPDS9930); } } xEventGroupClearBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_LIGHT); xEventGroupSetBits(xEventGroupAPDS9930, TASK_APDS9930_REQUEST_DONE); #if 0 ESP_LOGI(TAG, " Light: %.2f, gain: %d, error: %d", apds9930_state->ambient_light, apds9930_state->gain, apds9930_state->error); #endif } } }