main/task_ds18b20.c

Sat, 06 Jun 2020 13:28:46 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 06 Jun 2020 13:28:46 +0200
changeset 77
66c77497d86d
parent 4
6d1f512cd074
child 88
7f02dbee58d0
permissions
-rw-r--r--

Changed the recipe database so that it is expandable, version 2. More mash fields and allow 16 steps. Allow 20 Additions. Removed separate mash steps from the state machine, the steps are moved to the runtime data. There is no fixed step number for mashout anymore. There is no fixed step for mash-in anymore, just use the first step and heat to the infusion temperature. After malt add, switch to the normal step temperature. Implemented decoction steps.

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

mercurial