main/task_apds9930.c

changeset 12
bb72d448e282
child 16
b3e96bbe4ce4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/task_apds9930.c	Mon Apr 03 16:07:34 2023 +0200
@@ -0,0 +1,186 @@
+/**
+ * @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 = 0, l_aglbit = 0;
+
+    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;
+
+    /* 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 */
+		apds9930_enablePower(&apds9930_dev);
+		apds9930_enableLightSensor(&apds9930_dev, false);
+		apds9930_disableProximitySensor(&apds9930_dev);
+		if (xSemaphoreTake(xSemaphoreAPDS9930, 25) == pdTRUE) {
+		    l_gain = apds9930_state->gain;
+		    l_aglbit = apds9930_state->aglbit;
+		    xSemaphoreGive(xSemaphoreAPDS9930);
+		}
+		if (l_gain > 3)
+		    l_gain = 0;
+		apds9930_setAmbientLightGain(&apds9930_dev, l_gain);
+		apds9930_setAmbientGainLevel(&apds9930_dev, l_aglbit);
+		vTaskDelay(200 / portTICK_PERIOD_MS);
+		tries = 6;
+		err = ESP_OK;
+
+		while (tries) {
+		    err = apds9930_readAmbientLightLux(&apds9930_dev, &ambient_light);
+		    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;
+		    }
+
+		    /*
+		     * 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;
+			}
+			ESP_LOGI(TAG, "Ambient: %.3f  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 1
+	    ESP_LOGI(TAG, "  Light: %.2f, gain: %d, error: %d", apds9930_state->ambient_light, apds9930_state->gain, apds9930_state->error);
+#endif
+	}
+    }
+}

mercurial