main/task_ds18b20.c

Sat, 14 Mar 2020 13:07:02 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 14 Mar 2020 13:07:02 +0100
changeset 47
1ab1f4a8c328
parent 44
e52d11b8f252
child 55
43362bb8f3c0
permissions
-rw-r--r--

Version 0.2.2 Changed to use a permanent network and WiFi connection. Removed three mainloop stages. Removed MQTT sequence counter that was not used. Update WiFi rssi status during eacht measure cycle. Changed FreeRTOS schedulng to 500 Hz.

/**
 * @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);
	}
    }
}

mercurial