main/task_ds18b20.c

Tue, 08 Oct 2019 12:00:31 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Tue, 08 Oct 2019 12:00:31 +0200
changeset 0
88d965579617
child 2
c0184362d48c
permissions
-rw-r--r--

Initial import of the CO2 meter application.

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


#define GPIO_DS18B20_BUS	(CONFIG_ONE_WIRE_BUS)
#define MAX_DEVICES		(8)
#define DS18B20_RESOLUTION	(DS18B20_RESOLUTION_12_BIT)
#define SAMPLE_PERIOD		(2000)   // milliseconds


static const char		*TAG = "task_ds18b20";
static const char		*dsErrors[] = { "Ok", "No sensor", "Too many sensors", "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			num_devices = 0;
    float		readings = 0;
    bool		found = false;
    DS18B20_ERROR	errors = 0;

    ESP_LOGI(TAG, "Starting DS18B20 sensors");
    ds18b20_state = malloc(sizeof(DS18B20_State));
    ds18b20_state->bottle_valid = false;
    ds18b20_state->bottle_temperature = 0.0;
    ds18b20_state->bottle_error = DS18B20_ERR_NOSENSOR;

    /* event handler and event group for the wifi driver */
    xEventGroupDS18B20 = xEventGroupCreate();

    /*
     * Initialize the MLT and HLT one-wire busses.
     */
    OneWireBus *owb_bottle;
    owb_rmt_driver_info rmt_driver_info_bottle;
    owb_bottle = owb_rmt_initialize(&rmt_driver_info_bottle, GPIO_DS18B20_BUS, RMT_CHANNEL_1, RMT_CHANNEL_0);
    owb_use_crc(owb_bottle, true);                     // enable CRC check for ROM code

    DS18B20_Info * ds18b20_info = ds18b20_malloc();
    EventBits_t uxBits;

    /*
     * Task loop forever.
     */
    while (1) {

	uxBits = xEventGroupWaitBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_TEMPS, pdFALSE, pdFALSE, portMAX_DELAY );

	if (uxBits & TASK_DS18B20_REQUEST_TEMPS) {
	    num_devices = 0;
	    OneWireBus_SearchState bottle_search_state = {0};
	    found = false;
	    owb_search_first(owb_bottle, &bottle_search_state, &found);
	    while (found) {
	    	++num_devices;
	    	owb_search_next(owb_bottle, &bottle_search_state, &found);
	    }

	    if (num_devices == 1) {
	    	ds18b20_init_solo(ds18b20_info, owb_bottle);		// 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_bottle);
	    	ds18b20_wait_for_conversion(ds18b20_info);

	    	errors = ds18b20_read_temp(ds18b20_info, &readings);

	    	if (xSemaphoreTake(xSemaphoreDS18B20, 25) == pdTRUE) {
	    	    if (errors == DS18B20_OK) {
		    	ds18b20_state->bottle_error = DS18B20_ERR_NONE;
		    	ds18b20_state->bottle_valid = true;
		    	ds18b20_state->bottle_temperature = readings;
	    	    } else {
		    	if (errors == DS18B20_ERROR_CRC)
		    	   ds18b20_state->bottle_error = DS18B20_ERR_CRC;
		    	if (errors == DS18B20_ERROR_OWB)
		    	    ds18b20_state->bottle_error = DS18B20_ERR_READ;
		    	if (errors == DS18B20_ERROR_DEVICE)
		    	    ds18b20_state->bottle_error = DS18B20_ERR_READ;
		    	ds18b20_state->bottle_valid = false;
		    	ds18b20_state->bottle_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->bottle_error = DS18B20_ERR_NOSENSOR;
	    	    else
		    	ds18b20_state->bottle_error = DS18B20_ERR_TOOMANY;
	    	    ds18b20_state->bottle_valid = false;
	    	    ds18b20_state->bottle_temperature = 0.0;
		    xSemaphoreGive(xSemaphoreDS18B20);
	    	}
	    } // if num_devices == 1
	
	    xEventGroupClearBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_TEMPS);
	    xEventGroupSetBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_DONE);
#if 1
	    ESP_LOGI(TAG, "Temperature %.3f %s", ds18b20_state->bottle_temperature, dsErrors[ds18b20_state->bottle_error]);
#endif
	}
	vTaskDelay( (TickType_t)10);
    }
}

mercurial