main/co2meter.c

Sun, 14 Jun 2020 22:35:24 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sun, 14 Jun 2020 22:35:24 +0200
changeset 58
e949f41034eb
parent 57
232f318a6b51
child 59
52d9405474e1
permissions
-rw-r--r--

Lower loglevel for one message.

/**
 * @file co2meter.c
 * @brief co2meter project.
 */

#include "config.h"

static const char *TAG = "co2meter";


const esp_app_desc_t                    *app_desc = NULL;               ///< Application description
int					Main_Loop1 = ML1_INIT;		///< Loop 1 init
int					num_sensors = 0;		///< Detected DS18B20 sensors
static TaskHandle_t			xTaskDS18B20 = NULL;
static TaskHandle_t			xTaskADC = NULL;
static TaskHandle_t			xTaskWifi = NULL;
static TaskHandle_t			xTaskMQTT = NULL;
static TaskHandle_t			xTaskUser = NULL;

extern unit_t				units[3];			///< Pressure test units
extern SemaphoreHandle_t		xSemaphoreUnits;		///< Units lock semaphore
extern DS18B20_State            	*ds18b20_state;         	///< DS18B20 state
extern SemaphoreHandle_t        	xSemaphoreDS18B20;      	///< DS18B20 lock semaphore
extern ADC_State                	*adc_state;             	///< ADC state
extern SemaphoreHandle_t        	xSemaphoreADC;          	///< ADC lock semaphore
extern SemaphoreHandle_t		xSemaphoreWiFi;
extern WIFI_State			*wifi_state;			///< WiFi state
extern EventGroupHandle_t		xEventGroupUser;
extern int				count_pub;			///< Published MQTT messages in transit
extern uint32_t				AlarmTimer;			///< Alarm timer
extern uint32_t				err_connect;			///< Connect error counter


/**
 * @brief Main program entry
 */
void app_main()
{
    esp_err_t           ret;

    Main_Loop1 = ML1_INIT;
    app_desc = esp_ota_get_app_description();
    /*
     * event handler and event group for the user interface
     */
    xEventGroupUser = xEventGroupCreate();
    user_cold();

    /*
     * Initialize NVS
     */
    ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    /*
     * Setup SPIFFS filesystem
     */
    ESP_LOGI(TAG, "Initializing SPIFFS");
    esp_vfs_spiffs_conf_t conf = {
        .base_path = "/spiffs",
        .partition_label = NULL,
        .max_files = 5,
        .format_if_mount_failed = true
    };

    /*
     * Use settings defined above to initialize and mount SPIFFS filesystem.
     * Note: esp_vfs_spiffs_register is an all-in-one convenience function.
     */
    ret = esp_vfs_spiffs_register(&conf);

    if (ret != ESP_OK) {
        if (ret == ESP_FAIL) {
            ESP_LOGE(TAG, "Failed to mount or format filesystem");
        } else if (ret == ESP_ERR_NOT_FOUND) {
            ESP_LOGE(TAG, "Failed to find SPIFFS partition");
        } else {
            ESP_LOGE(TAG, "Failed to initialize SPIFFS (%d)", ret);
        }
        return; // Stop application.
    }

    size_t total = 0, used = 0;
    ret = esp_spiffs_info(NULL, &total, &used);
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to get SPIFFS partition information");
        return; // Stop application.
    } else {
        ESP_LOGI(TAG, "Partition size: %d, used: %d - %d%%", total, used, (used * 100) / total);
    }

    // Just to debug, list the /spiffs filesystem.
#if 0
    DIR *dir = opendir("/spiffs");
    struct dirent* de = readdir(dir);
    while (de) {
        if (de->d_type == DT_REG) {
            printf("F ");
        }
        if (de->d_type == DT_DIR) {
            printf("D ");
        }
        printf("%s\n", de->d_name);
        de = readdir(dir);
    }
    closedir(dir);
#endif

    /*
     * Read or create configuration
     */
    read_config();
    read_units();

    /*
     * Create FreeRTOS tasks
     */
    xSemaphoreDS18B20 = xSemaphoreCreateMutex();
    xSemaphoreADC = xSemaphoreCreateMutex();
    xSemaphoreUnits = xSemaphoreCreateMutex();

    xTaskCreate(&task_user,    "task_user",     4096, NULL,10, &xTaskUser);
    xTaskCreate(&task_ds18b20, "task_ds18b20",  2560, NULL, 8, &xTaskDS18B20);
    xTaskCreate(&task_adc,     "task_adc",      2560, NULL, 8, &xTaskADC);
    esp_log_level_set("MQTT_CLIENT", ESP_LOG_ERROR);
    xTaskCreate(&task_mqtt,    "task_mqtt",     4096, NULL, 5, &xTaskMQTT);
    esp_log_level_set("wifi", ESP_LOG_ERROR);
    xTaskCreate(&task_wifi,    "task_wifi",     4096, NULL, 3, &xTaskWifi);
    vTaskDelay(10 / portTICK_PERIOD_MS);
    int wait = 150;
    while (wait) {
	if (ready_WiFi()) {
		ESP_LOGI(TAG, "Online in %.1f seconds", (150 - wait) / 10.0);
        	wait = 0;
        } else {
		wait--;
		if (wait < 1)
			ESP_LOGE(TAG, "Timeout network connection");
	}
	vTaskDelay(100 / portTICK_PERIOD_MS);
    }

    /*
     * Main application loop.
     */
    while (1) {

	ESP_LOGI(TAG, "Entered Main loop");

	/* Measure process */
	while (1) {
	    switch (Main_Loop1) {
		case ML1_INIT:
		    status_WiFi();
		    Main_Loop1 = ML1_CONNECT;
		    request_ds18b20();
		    request_adc();
		    AlarmTimer = 30;
		    if (! ready_WiFi()) { /* If WiFi was lost, try a new connection */
			ESP_LOGI(TAG, "Try WiFi restore");
			request_WiFi();
			err_connect++;
		    }
		    break;

		case ML1_CONNECT:
                    if (ready_WiFi()) {
                        Main_Loop1 = ML1_MQTT_CONNECT;
			user_refresh();
			if (! ready_mqtt())
			    connect_mqtt(true);
		    }
                    break;

		case ML1_MQTT_CONNECT:
		    if (ready_ds18b20() && ready_adc()) {
			Main_Loop1 = ML1_WAITCON;

			uint32_t temp[DS18B20_MAX];
			int state[DS18B20_MAX], i;
			char rom_code[DS18B20_MAX][17];
			for (i = 0; i < DS18B20_MAX; i++) {
			    temp[i] = 0;
			    state[i] = 0;
			    rom_code[i][0] = '\0';
			}
			/* Copy results from all connected DS18B20 sensors */
			num_sensors = 0;
			if (xSemaphoreTake(xSemaphoreDS18B20, 10) == pdTRUE) {
			    num_sensors = ds18b20_state->num_sensors;
			    for (i = 0; i < num_sensors; i++) {
			    	temp[i] = (ds18b20_state->sensor[i].temperature * 1000);
			    	state[i] = (ds18b20_state->sensor[i].error == 0) ? 0:1;
			    	strncpy(rom_code[i], ds18b20_state->sensor[i].rom_code, 17);
			    	rom_code[i][16] = '\0';
			    }
        		    xSemaphoreGive(xSemaphoreDS18B20);
    			} else {
			    ESP_LOGE(TAG, "ML1_MQTT_CONNECT DS18B20 lock error");
			}

			/* Copy measured data and calculate results */
			for (i = 0; i < 3; i++) {
			    if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) {
				/* Search configured temperature sensor for this unit */
				for (int j = 0; j < num_sensors; j++) {
				    if (strcmp(rom_code[j], units[i].temperature_rom_code) == 0) {
					units[i].temperature = temp[j];
					units[i].temperature_state = state[j];
					units[i].alarm = 0;
					if (state[j])
                                    	    units[i].alarm |= ALARM_SYS_TEMPERATURE & ALARM_UNIT_TEMPERATURE;
					break;
				    }
				}

				/* Get the ADC results */
			    	if (xSemaphoreTake(xSemaphoreADC, 10) == pdTRUE) {
				    units[i].pressure_state = adc_state->Pressure[i].error;
				    units[i].pressure_channel = adc_state->Pressure[i].channel;
				    units[i].pressure_voltage = adc_state->Pressure[i].voltage;
				    if (units[i].pressure_state || units[i].pressure_voltage < 80)
					units[i].alarm |= ALARM_UNIT_PRESSURE;
				    int P = (units[i].pressure_voltage / (adc_state->Batt_voltage / 1000) - units[i].pressure_zero) * 14; // in bar
				    if (P < 0)
				    	P = 0;
				    units[i].pressure = P;
				    ESP_LOGI(TAG, "%d vb:%.3f vp:%.3f zero:%d scale:%3d mbar:%4d alm: %d t:%6.3f %s",
					i, adc_state->Batt_voltage / 1000.0, units[i].pressure_voltage / 1000.0, units[i].pressure_zero, 
					units[i].pressure_voltage / (adc_state->Batt_voltage / 1000) - units[i].pressure_zero, P, units[i].alarm,
					units[i].temperature / 1000.0, units[i].temperature_rom_code);
				    xSemaphoreGive(xSemaphoreADC);
			    	} else {
				    ESP_LOGE(TAG, "ML1_MQTT_CONNECT ADC[%d] lock error", i);
				}
				xSemaphoreGive(xSemaphoreUnits);
			    } else {
                            	ESP_LOGE(TAG, "ML1_MQTT_CONNECT units[%d] lock error", i);
                            }
			}
			if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) {
			    write_units();
			    xSemaphoreGive(xSemaphoreUnits);
			} else {
			    ESP_LOGE(TAG, "ML1_MQTT_CONNECT write_units lock error");
			}
			user_refresh();
		    }
		    break;

		case ML1_WAITCON:
		    if (ready_mqtt())
			Main_Loop1 = ML1_SEND;
		    break;

		case ML1_SEND:
		    publishNode();
		    publishUnits();
		    publishLogs();
		    Main_Loop1 = ML1_WAITACK;
		    break;

		case ML1_WAITACK:
		    if (count_pub == 0) { // Wait until all published messages are sent.
			ESP_LOGD(TAG, "Main loop: Done, user busy: %s", user_busy() ? "true":"false");
                        Main_Loop1 = ML1_DONE;
                        user_refresh();
		    }
		    break;

		case ML1_DONE:
		    /* Wait here until the timer resets the loop */
		    AlarmTimer = 0;
		    break;
	    }
	    vTaskDelay(10 / portTICK_PERIOD_MS);
	}

	Main_Loop1 = ML1_INIT;
    }
}

mercurial