main/task_ds18b20.c

changeset 0
88d965579617
child 2
c0184362d48c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/task_ds18b20.c	Tue Oct 08 12:00:31 2019 +0200
@@ -0,0 +1,152 @@
+/**
+ * @file task_ds18b20.c
+ * @brief The FreeRTOS task to query the DS18B20 sensors on one or two
+ *        one-wire busses. Each bus must have only one sensor. That way
+ *        we don't need to care about the DS18B20 internal ROM address.
+ *        The task will update the DS18B20_State structure.
+ */
+
+
+#include "owb.h"
+#include "owb_rmt.h"
+#include "ds18b20.h"
+#include "config.h"
+
+
+#define GPIO_DS18B20_BUS	(CONFIG_ONE_WIRE_BUS)
+#define MAX_DEVICES		(8)
+#define DS18B20_RESOLUTION	(DS18B20_RESOLUTION_12_BIT)
+#define SAMPLE_PERIOD		(2000)   // milliseconds
+
+
+static const char		*TAG = "task_ds18b20";
+static const char		*dsErrors[] = { "Ok", "No sensor", "Too many sensors", "CRC error", "Read error" };
+
+SemaphoreHandle_t		xSemaphoreDS18B20 = NULL;	///< Semaphire DS18B20 task
+EventGroupHandle_t		xEventGroupDS18B20;		///< Events DS18B20 task
+DS18B20_State			*ds18b20_state;			///< Public state for other tasks
+
+
+const int TASK_DS18B20_REQUEST_TEMPS = BIT0;			///< Request temperature measurements
+const int TASK_DS18B20_REQUEST_DONE = BIT1;			///< Request is completed
+
+
+
+void request_ds18b20(void)
+{
+    xEventGroupClearBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_DONE);
+    xEventGroupSetBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_TEMPS);
+}
+
+
+
+bool ready_ds18b20(void)
+{
+    if (xEventGroupGetBits(xEventGroupDS18B20) & TASK_DS18B20_REQUEST_DONE)
+        return true;
+    return false;
+}
+
+
+
+/*
+ * Task to read temperature sensors on request.
+ */
+void task_ds18b20(void *pvParameter)
+{
+    int			num_devices = 0;
+    float		readings = 0;
+    bool		found = false;
+    DS18B20_ERROR	errors = 0;
+
+    ESP_LOGI(TAG, "Starting DS18B20 sensors");
+    ds18b20_state = malloc(sizeof(DS18B20_State));
+    ds18b20_state->bottle_valid = false;
+    ds18b20_state->bottle_temperature = 0.0;
+    ds18b20_state->bottle_error = DS18B20_ERR_NOSENSOR;
+
+    /* event handler and event group for the wifi driver */
+    xEventGroupDS18B20 = xEventGroupCreate();
+
+    /*
+     * Initialize the MLT and HLT one-wire busses.
+     */
+    OneWireBus *owb_bottle;
+    owb_rmt_driver_info rmt_driver_info_bottle;
+    owb_bottle = owb_rmt_initialize(&rmt_driver_info_bottle, GPIO_DS18B20_BUS, RMT_CHANNEL_1, RMT_CHANNEL_0);
+    owb_use_crc(owb_bottle, true);                     // enable CRC check for ROM code
+
+    DS18B20_Info * ds18b20_info = ds18b20_malloc();
+    EventBits_t uxBits;
+
+    /*
+     * Task loop forever.
+     */
+    while (1) {
+
+	uxBits = xEventGroupWaitBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_TEMPS, pdFALSE, pdFALSE, portMAX_DELAY );
+
+	if (uxBits & TASK_DS18B20_REQUEST_TEMPS) {
+	    num_devices = 0;
+	    OneWireBus_SearchState bottle_search_state = {0};
+	    found = false;
+	    owb_search_first(owb_bottle, &bottle_search_state, &found);
+	    while (found) {
+	    	++num_devices;
+	    	owb_search_next(owb_bottle, &bottle_search_state, &found);
+	    }
+
+	    if (num_devices == 1) {
+	    	ds18b20_init_solo(ds18b20_info, owb_bottle);		// only one device on bus
+	    	ds18b20_use_crc(ds18b20_info, true);			// enable CRC check for temperature readings
+	    	ds18b20_set_resolution(ds18b20_info, DS18B20_RESOLUTION);	// returns true if ok.
+
+	    	// Read temperatures more efficiently by starting conversions on all devices at the same time
+	    	ds18b20_convert_all(owb_bottle);
+	    	ds18b20_wait_for_conversion(ds18b20_info);
+
+	    	errors = ds18b20_read_temp(ds18b20_info, &readings);
+
+	    	if (xSemaphoreTake(xSemaphoreDS18B20, 25) == pdTRUE) {
+	    	    if (errors == DS18B20_OK) {
+		    	ds18b20_state->bottle_error = DS18B20_ERR_NONE;
+		    	ds18b20_state->bottle_valid = true;
+		    	ds18b20_state->bottle_temperature = readings;
+	    	    } else {
+		    	if (errors == DS18B20_ERROR_CRC)
+		    	   ds18b20_state->bottle_error = DS18B20_ERR_CRC;
+		    	if (errors == DS18B20_ERROR_OWB)
+		    	    ds18b20_state->bottle_error = DS18B20_ERR_READ;
+		    	if (errors == DS18B20_ERROR_DEVICE)
+		    	    ds18b20_state->bottle_error = DS18B20_ERR_READ;
+		    	ds18b20_state->bottle_valid = false;
+		    	ds18b20_state->bottle_temperature = 0.0;
+	    	    }
+		    xSemaphoreGive(xSemaphoreDS18B20);
+	    	}
+
+	    } else {
+	    	/*
+	    	 * Zero or more then one device, this is an error.
+	    	 */
+	    	if (xSemaphoreTake(xSemaphoreDS18B20, 25) == pdTRUE) {
+	    	    if (num_devices == 0)
+		    	ds18b20_state->bottle_error = DS18B20_ERR_NOSENSOR;
+	    	    else
+		    	ds18b20_state->bottle_error = DS18B20_ERR_TOOMANY;
+	    	    ds18b20_state->bottle_valid = false;
+	    	    ds18b20_state->bottle_temperature = 0.0;
+		    xSemaphoreGive(xSemaphoreDS18B20);
+	    	}
+	    } // if num_devices == 1
+	
+	    xEventGroupClearBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_TEMPS);
+	    xEventGroupSetBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_DONE);
+#if 1
+	    ESP_LOGI(TAG, "Temperature %.3f %s", ds18b20_state->bottle_temperature, dsErrors[ds18b20_state->bottle_error]);
+#endif
+	}
+	vTaskDelay( (TickType_t)10);
+    }
+}
+

mercurial