Mon, 29 Oct 2018 11:32:03 +0100
README update
/** * @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" #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 }