Sun, 16 Apr 2023 12:27:12 +0200
Preparations for BLE GATT. Added extra time after INA219 is powered on before measurement. Reduced LEDC frequency to 60 Hz, that makes the LED lights less nervous. Hardware mod on output 4, now needs external pulldown resistor.
/** * @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 } } }