main/task_ds18b20.c

Sun, 14 Jun 2020 14:53:06 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sun, 14 Jun 2020 14:53:06 +0200
changeset 57
232f318a6b51
parent 55
43362bb8f3c0
child 61
a322cfcff6b8
permissions
-rw-r--r--

Code cleanup, doxygen comments added.

/**
 * @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

extern uint32_t			err_temp;

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, "Start 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_LOGD(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;
			    err_temp++;
			} 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;
			    err_temp++;
			} 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);
	}
    }
}

mercurial