diff -r 000000000000 -r b74b0e4902c3 main/task_ds18b20.c --- /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 +} + +