main/task_ds18b20.c

changeset 0
b74b0e4902c3
child 4
6d1f512cd074
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main/task_ds18b20.c	Sat Oct 20 13:23:15 2018 +0200
@@ -0,0 +1,252 @@
+/**
+ * @file task_ds18b20.c
+ * @brief Task that reads the DS18B20 sensors on two one-wire busses.
+ *        The task can also be compiled with simulated sensors.
+ */
+
+
+#include "owb.h"
+#include "owb_rmt.h"
+#include "ds18b20.h"
+#include "config.h"
+
+
+#ifdef CONFIG_TEMP_SENSORS_ONEWIRE
+#define GPIO_DS18B20_MLT     (CONFIG_ONE_WIRE_MLT)
+#define GPIO_DS18B20_HLT     (CONFIG_ONE_WIRE_HLT)
+#define MAX_DEVICES          (8)
+#define DS18B20_RESOLUTION   (DS18B20_RESOLUTION_12_BIT)
+#define SAMPLE_PERIOD        (2000)   // milliseconds
+#endif
+
+#ifdef CONFIG_TEMP_SENSORS_SIMULATOR
+#define SAMPLE_PERIOD        (750)    // milliseconds
+
+float               	Fake_MLT = 18.90;
+float			Fake_HLT = 18.70;
+#endif
+
+static const char	*TAG = "task_ds18b20";
+
+SemaphoreHandle_t	xSemaphoreDS18B20 = NULL;
+DS18B20_State		*ds18b20_state;
+
+
+/*
+ * Task to read temperature sensors.
+ */
+void task_ds18b20(void *pvParameter)
+{
+#ifdef CONFIG_TEMP_SENSORS_ONEWIRE
+    int			num_devices = 0;
+    float		readings = 0;
+    bool		found = false;
+    DS18B20_ERROR	errors = 0;
+    TickType_t		last_wake_time = xTaskGetTickCount();
+
+    ESP_LOGI(TAG, "Starting DS18B20 sensors");
+    ds18b20_state = malloc(sizeof(DS18B20_State));
+    ds18b20_state->mlt_valid = ds18b20_state->hlt_valid = false;
+    ds18b20_state->mlt_temperature = ds18b20_state->hlt_temperature = 0.0;
+    ds18b20_state->mlt_error = ds18b20_state->hlt_error = DS18B20_ERR_NOSENSOR;
+
+    /*
+     * Initialize the MLT and HLT one-wire busses.
+     */
+    OneWireBus *owb_mlt;
+    OneWireBus *owb_hlt;
+    owb_rmt_driver_info rmt_driver_info_mlt;
+    owb_rmt_driver_info rmt_driver_info_hlt;
+    owb_mlt = owb_rmt_initialize(&rmt_driver_info_mlt, GPIO_DS18B20_MLT, RMT_CHANNEL_1, RMT_CHANNEL_0);
+    owb_hlt = owb_rmt_initialize(&rmt_driver_info_hlt, GPIO_DS18B20_HLT, RMT_CHANNEL_3, RMT_CHANNEL_2);
+    owb_use_crc(owb_mlt, true);                     // enable CRC check for ROM code
+    owb_use_crc(owb_hlt, true); 
+
+    DS18B20_Info * ds18b20_info = ds18b20_malloc();
+
+    /*
+     * Task loop forever.
+     */
+    while (1) {
+
+	last_wake_time = xTaskGetTickCount();
+
+	num_devices = 0;
+	OneWireBus_SearchState mlt_search_state = {0};
+	found = false;
+	owb_search_first(owb_mlt, &mlt_search_state, &found);
+	while (found) {
+	    ++num_devices;
+	    owb_search_next(owb_mlt, &mlt_search_state, &found);
+	}
+
+	if (num_devices == 1) {
+	    ds18b20_init_solo(ds18b20_info, owb_mlt);			// 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_mlt);
+	    ds18b20_wait_for_conversion(ds18b20_info);
+
+	    errors = ds18b20_read_temp(ds18b20_info, &readings);
+
+	    if (xSemaphoreTake(xSemaphoreDS18B20, 25) == pdTRUE) {
+	    	if (errors == DS18B20_OK) {
+		    ds18b20_state->mlt_error = DS18B20_ERR_NONE;
+		    ds18b20_state->mlt_valid = true;
+		    ds18b20_state->mlt_temperature = readings;
+	    	} else {
+		    if (errors == DS18B20_ERROR_CRC)
+		    	ds18b20_state->mlt_error = DS18B20_ERR_CRC;
+		    if (errors == DS18B20_ERROR_OWB)
+		    	ds18b20_state->mlt_error = DS18B20_ERR_READ;
+		    if (errors == DS18B20_ERROR_DEVICE)
+		    	ds18b20_state->mlt_error = DS18B20_ERR_READ;
+		    ds18b20_state->mlt_valid = false;
+		    ds18b20_state->mlt_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->mlt_error = DS18B20_ERR_NOSENSOR;
+	    	else
+		    ds18b20_state->mlt_error = DS18B20_ERR_TOOMANY;
+	    	ds18b20_state->mlt_valid = false;
+	    	ds18b20_state->mlt_temperature = 0.0;
+		xSemaphoreGive(xSemaphoreDS18B20);
+	    }
+	} // if num_devices == 1
+
+	num_devices = 0;
+	OneWireBus_SearchState hlt_search_state = {0};
+	found = false;
+	owb_search_first(owb_hlt, &hlt_search_state, &found);
+	while (found) {
+	    ++num_devices;
+	    owb_search_next(owb_hlt, &hlt_search_state, &found);
+	}
+
+	if (num_devices == 1) {
+	    ds18b20_init_solo(ds18b20_info, owb_hlt);                   // only one device on bus
+	    ds18b20_use_crc(ds18b20_info, true);                        // enable CRC check for temperature readings
+	    ds18b20_set_resolution(ds18b20_info, DS18B20_RESOLUTION);
+
+	    // Read temperatures more efficiently by starting conversions on all devices at the same time
+	    ds18b20_convert_all(owb_hlt);
+	    ds18b20_wait_for_conversion(ds18b20_info);
+	
+	    errors = ds18b20_read_temp(ds18b20_info, &readings);
+	
+	    if (xSemaphoreTake(xSemaphoreDS18B20, 25) == pdTRUE) {
+	    	if (errors == DS18B20_OK) {
+		    ds18b20_state->hlt_error = DS18B20_ERR_NONE;
+		    ds18b20_state->hlt_valid = true;
+		    ds18b20_state->hlt_temperature = readings;
+	    	} else {
+		    if (errors == DS18B20_ERROR_CRC)
+		    	ds18b20_state->hlt_error = DS18B20_ERR_CRC;
+		    if (errors == DS18B20_ERROR_OWB)
+		    	ds18b20_state->hlt_error = DS18B20_ERR_READ;
+		    if (errors == DS18B20_ERROR_DEVICE)
+		    	ds18b20_state->hlt_error = DS18B20_ERR_READ;
+		    ds18b20_state->hlt_valid = false;
+		    ds18b20_state->hlt_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->hlt_error = DS18B20_ERR_NOSENSOR;
+	    	else
+		    ds18b20_state->hlt_error = DS18B20_ERR_TOOMANY;
+	    	ds18b20_state->hlt_valid = false;
+	    	ds18b20_state->hlt_temperature = 0.0;
+		xSemaphoreGive(xSemaphoreDS18B20);
+	    }
+	} // if num_devices == 1
+
+#if 0
+	printf("MLT  %.3f  %d err %s, HLT  %.3f,  %d err %s\n",
+		ds18b20_state->mlt_temperature, ds18b20_state->mlt_error, (ds18b20_state->mlt_valid) ? "valid":" N/A ",
+		ds18b20_state->hlt_temperature, ds18b20_state->hlt_error, (ds18b20_state->hlt_valid) ? "valid":" N/A ");
+#endif
+	vTaskDelayUntil(&last_wake_time, SAMPLE_PERIOD / portTICK_PERIOD_MS);
+    }
+#endif
+
+#ifdef CONFIG_TEMP_SENSORS_SIMULATOR
+
+    float		Plate_MLT = 18.90;
+    extern int		MLT_pin, HLT_pin;
+
+    ESP_LOGI(TAG, "Starting Fake sensors");
+    ds18b20_state = malloc(sizeof(DS18B20_State));
+    ds18b20_state->mlt_valid = ds18b20_state->hlt_valid = true;
+    ds18b20_state->mlt_temperature = 18.90;
+    ds18b20_state->hlt_temperature = 18.70;
+    ds18b20_state->mlt_error = ds18b20_state->hlt_error = DS18B20_ERR_NONE;
+
+    /*
+     * Task loop forever. Update the temperatures each 750 mSeconds.
+     */
+    while (1) {
+
+	/*
+	 * Make this fake heater a bit more real by using a simulated heatplate.
+	 * We heatup that plate and then transfer the heat to the water.
+	 * That way we get a nice overshoot like in real life.
+	 */
+	if (MLT_pin) {
+	    if (Plate_MLT < 250.0)
+		Plate_MLT += SAMPLE_PERIOD * 0.001;   // Simulate plate upto 250 degrees
+	} else {
+	    if (Plate_MLT > Fake_MLT)
+		Plate_MLT -= SAMPLE_PERIOD * 0.00002 * (Plate_MLT - Fake_MLT);
+	}
+	// If plate is hotter then the water with a offset so that cooling later works.
+	if (Plate_MLT > (Fake_MLT + 5.0)) {
+	    if (Fake_MLT < 100.05)
+		Fake_MLT += SAMPLE_PERIOD * 0.000001 * (Plate_MLT - Fake_MLT);
+	}
+	// Allways loose heat to the air
+	if (Fake_MLT > 16.0) {
+	    Fake_MLT -= SAMPLE_PERIOD * 0.00000010 * (Fake_MLT - 16.0);
+	}
+
+	if ((equipment.SSR2 == SSR2_HLT_SHARE) || (equipment.SSR2 == SSR2_HLT_IND)) {
+	    /*
+	     * There is a HLT function configured.
+	     */
+	    if (HLT_pin) {
+	    	if (Fake_HLT < 100.05)
+		    Fake_HLT += SAMPLE_PERIOD * 0.000055;
+	    } else {
+	    	if (Fake_HLT > 16.0)
+		    Fake_HLT -= SAMPLE_PERIOD * 0.00000006 * (Fake_HLT - 16.0);
+	    }
+	}
+
+	if (xSemaphoreTake(xSemaphoreDS18B20, 25) == pdTRUE) {
+	    ds18b20_state->mlt_temperature = ((int)(Fake_MLT * 16)) / 16.0;
+	    ds18b20_state->hlt_temperature = ((int)(Fake_HLT * 16)) / 16.0;
+	    xSemaphoreGive(xSemaphoreDS18B20);
+	}
+
+	vTaskDelay(SAMPLE_PERIOD / portTICK_PERIOD_MS);
+    }
+
+#endif
+}
+
+

mercurial