Sat, 14 Mar 2020 15:52:04 +0100
Added function comment
/** * @file task_ds18b20.c * @brief The FreeRTOS task to query the DS18B20 sensors on the * one-wire bus. * 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) ///< GPIO pin for the one-wire bus. #define DS18B20_RESOLUTION (DS18B20_RESOLUTION_12_BIT) ///< Desired DS18B20 resolution. static const char *TAG = "task_ds18b20"; static const char *dsErrors[] = { "Ok", "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 i, num_devices = 0; bool found = false; EventBits_t uxBits; ESP_LOGI(TAG, "Starting DS18B20 sensors"); ds18b20_state = malloc(sizeof(DS18B20_State)); ds18b20_state->valid = false; ds18b20_state->num_sensors = 0; for (i = 0; i < DS18B20_MAX; i++) { ds18b20_state->sensor[i].temperature = 0.0; ds18b20_state->sensor[i].rom_code[0] = '\0'; ds18b20_state->sensor[i].error = DS18B20_ERR_READ; } /* * event handler and event group for the one-wire bus */ xEventGroupDS18B20 = xEventGroupCreate(); /* * Initialize the one-wire bus. */ owb_rmt_driver_info rmt_driver_info_bottle; OneWireBus *owb = owb_rmt_initialize(&rmt_driver_info_bottle, GPIO_DS18B20_BUS, RMT_CHANNEL_1, RMT_CHANNEL_0); owb_use_crc(owb, true); /* * Task loop forever. */ while (1) { uxBits = xEventGroupWaitBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_TEMPS, pdFALSE, pdFALSE, portMAX_DELAY ); if (uxBits & TASK_DS18B20_REQUEST_TEMPS) { ESP_LOGI(TAG, "Requested DS18B20 readings"); OneWireBus_ROMCode device_rom_codes[DS18B20_MAX] = {0}; num_devices = 0; OneWireBus_SearchState search_state = {0}; found = false; owb_search_first(owb, &search_state, &found); while (found) { char rom_code_s[17]; owb_string_from_rom_code(search_state.rom_code, rom_code_s, sizeof(rom_code_s)); rom_code_s[16] = '\0'; #if 0 ESP_LOGI(TAG, " %d : %s %d\n", num_devices + 1, rom_code_s, strlen(rom_code_s)); #endif device_rom_codes[num_devices] = search_state.rom_code; strncpy(ds18b20_state->sensor[num_devices].rom_code, rom_code_s, 17); ++num_devices; owb_search_next(owb, &search_state, &found); } if (num_devices) { /* * Create DS18B20 devices on the bus */ DS18B20_Info * devices[DS18B20_MAX] = {0}; for (i = 0; i < num_devices; ++i) { DS18B20_Info * ds18b20_info = ds18b20_malloc(); // heap allocation devices[i] = ds18b20_info; if (num_devices == 1) { ds18b20_init_solo(ds18b20_info, owb); // only one device on bus } else { ds18b20_init(ds18b20_info, owb, device_rom_codes[i]); // associate with bus and device } 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); ds18b20_wait_for_conversion(devices[0]); // Read the results immediatly after conversion. float readings[DS18B20_MAX] = { 0 }; DS18B20_ERROR errors[DS18B20_MAX] = { 0 }; for (i = 0; i < num_devices; ++i) { errors[i] = ds18b20_read_temp(devices[i], &readings[i]); } // Process the results with a locked semaphore if (xSemaphoreTake(xSemaphoreDS18B20, 25) == pdTRUE) { ds18b20_state->valid = true; for (i = 0; i < num_devices; ++i) { if (errors[i] != DS18B20_OK) { if (errors[i] == DS18B20_ERROR_CRC) ds18b20_state->sensor[i].error = DS18B20_ERR_CRC; else ds18b20_state->sensor[i].error = DS18B20_ERR_READ; // All other errors ds18b20_state->valid = false; ds18b20_state->sensor[i].temperature = 0.0; } else if (readings[i] == 85.0) { // Error value ds18b20_state->sensor[i].error = DS18B20_ERR_READ; ds18b20_state->valid = false; ds18b20_state->sensor[i].temperature = 0.0; } else { ds18b20_state->sensor[i].error = DS18B20_ERR_NONE; ds18b20_state->sensor[i].temperature = readings[i]; } #if 1 ESP_LOGI(TAG, "Temperature %d %s %.4f %s", i, ds18b20_state->sensor[i].rom_code, ds18b20_state->sensor[i].temperature, dsErrors[ds18b20_state->sensor[i].error]); #endif } ds18b20_state->num_sensors = num_devices; xSemaphoreGive(xSemaphoreDS18B20); } else { ESP_LOGE(TAG, "Missed lock 1"); } } else { ESP_LOGW(TAG, "No temperature sensors found."); } /* * Set the remainder of the ds18b20 entries */ if (xSemaphoreTake(xSemaphoreDS18B20, 25) == pdTRUE) { ds18b20_state->num_sensors = num_devices; for (i = num_devices; i < DS18B20_MAX; i++) { ds18b20_state->sensor[i].temperature = 0.0; ds18b20_state->sensor[i].rom_code[0] = '\0'; ds18b20_state->sensor[i].error = DS18B20_ERR_READ; } xSemaphoreGive(xSemaphoreDS18B20); } else { ESP_LOGE(TAG, "Missed lock 2"); } xEventGroupClearBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_TEMPS); xEventGroupSetBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_DONE); } } }