Initial code for the rotary switch and some menus. Changed default pushbutton pin from 12 to 14 and swapped the rotary pins. Disabled always create a new units file, it should be safe to keep it now.

Wed, 30 Oct 2019 23:21:46 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Wed, 30 Oct 2019 23:21:46 +0100
changeset 16
e38ffa806e84
parent 15
83314e7b1b4a
child 17
f9eca4a55911

Initial code for the rotary switch and some menus. Changed default pushbutton pin from 12 to 14 and swapped the rotary pins. Disabled always create a new units file, it should be safe to keep it now.

main/Kconfig.projbuild file | annotate | diff | comparison | revisions
main/co2meter.c file | annotate | diff | comparison | revisions
main/config.c file | annotate | diff | comparison | revisions
main/config.h file | annotate | diff | comparison | revisions
main/task_mqtt.c file | annotate | diff | comparison | revisions
sdkconfig file | annotate | diff | comparison | revisions
--- a/main/Kconfig.projbuild	Sat Oct 26 14:05:17 2019 +0200
+++ b/main/Kconfig.projbuild	Wed Oct 30 23:21:46 2019 +0100
@@ -64,7 +64,7 @@
     config ROT_ENC_SW_GPIO
 	int "Rotary Encoder push switch GPIO number"
 	range 0 39
-	default 12
+	default 14
 	help
 		GPIO number (IOxx) from which to sample the Rotary Push function output and to
 		wakeup the ESP from deep sleep.
--- a/main/co2meter.c	Sat Oct 26 14:05:17 2019 +0200
+++ b/main/co2meter.c	Wed Oct 30 23:21:46 2019 +0100
@@ -11,15 +11,14 @@
 #define ROT_ENC_A_GPIO		(CONFIG_ROT_ENC_A_GPIO)
 #define ROT_ENC_B_GPIO		(CONFIG_ROT_ENC_B_GPIO)
 #define ROT_ENC_SW_GPIO		(CONFIG_ROT_ENC_SW_GPIO)
+#define INACTIVITY		480					///< Time in 250 mSec units.
+
+#define RESET_AT		0		///< Set to a positive non-zero number to reset the position if this value is exceeded
 
 
-#define ENABLE_HALF_STEPS	false		///< Set to true to enable tracking of rotary encoder at half step resolution
-#define RESET_AT		0		///< Set to a positive non-zero number to reset the position if this value is exceeded
-#define FLIP_DIRECTION		false		///< Set to true to reverse the clockwise/counterclockwise sense
-
-
-int					Main_Loop1 = MAIN_LOOP1_INIT;	///< Loop 1 init
+int					Main_Loop1 = ML1_INIT;		///< Loop 1 init
 int					Main_Loop2 = -1;		///< Loop 2 invalid
+int					New_Loop2 = ML2_DONE;		///< Loop 2 new state
 bool                            	System_TimeOk = false;          ///< System time status
 time_t                          	now;                            ///< Current time
 struct tm                       	timeinfo;                       ///< Current time structure
@@ -29,9 +28,10 @@
 static TaskHandle_t			xTaskADC = NULL;
 static TaskHandle_t			xTaskWifi = NULL;
 static TaskHandle_t			xTaskMQTT = NULL;
-const esp_app_desc_t			*app_desc = NULL;
-u8g2_t					u8g2;				///<  A structure which will contain all the data for one display
-
+const esp_app_desc_t			*app_desc = NULL;		///< Application description
+u8g2_t					u8g2;				///< A structure which will contain all the data for one display
+rotary_encoder_info_t			rinfo = { 0 };			///< Rotary encoder record
+static int				PushDuration = 0;		///< Duration of the pushed button
 
 extern unit_t				units[3];			///< Pressure test units
 extern SemaphoreHandle_t		xSemaphoreUnits;		///< Units lock semaphore
@@ -39,12 +39,16 @@
 extern SemaphoreHandle_t        	xSemaphoreDS18B20;      	///< DS18B20 lock semaphore
 extern ADC_State                	*adc_state;             	///< ADC state
 extern SemaphoreHandle_t        	xSemaphoreADC;          	///< ADC lock semaphore
-extern int				count_pub;
+extern int				count_pub;			///< Published MQTT messages in transit
+static xQueueHandle			gpio_evt_queue = NULL;		///< Rotary pushbutton queue
+static int				usertimer = 0;			///< User inactive timeout
 
 
-void screen_main(float t, float p1, float p2, float p3)
+
+void screen_main()
 {
     char	buf[65];
+    int		i;
 
     u8g2_ClearBuffer(&u8g2);
     u8g2_DrawHLine(&u8g2, 0, 14, 128);
@@ -53,26 +57,99 @@
     u8g2_uint_t w = u8g2_GetStrWidth(&u8g2, buf);
     u8g2_DrawStr(&u8g2, (128 - w) / 2,12, buf);
 
-    u8g2_SetFont(&u8g2, u8g2_font_t0_22b_tf);
-    sprintf(buf, "%.1f °C", t);
-    w = u8g2_GetUTF8Width(&u8g2, buf);
-    u8g2_DrawUTF8(&u8g2, (128 - w) / 2,40, buf);
-    u8g2_SetFont(&u8g2, u8g2_font_t0_18b_tf);
+    if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) {
+
+    	u8g2_SetFont(&u8g2, u8g2_font_t0_22b_tf);
+    	sprintf(buf, "%.1f °C", units[0].temperature / 1000.0);
+    	w = u8g2_GetUTF8Width(&u8g2, buf);
+    	u8g2_DrawUTF8(&u8g2, (128 - w) / 2,40, buf);
+    	u8g2_SetFont(&u8g2, u8g2_font_t0_18b_tf);
+
+	for (i = 0; i < 3; i++) {
+    	    sprintf(buf, "%.1f", units[i].pressure / 1000.0);
+    	    w = u8g2_GetUTF8Width(&u8g2, buf);
+    	    u8g2_DrawUTF8(&u8g2, ((42 - w) / 2) + i * 43,63, buf);
+	}
+	xSemaphoreGive(xSemaphoreUnits);
+    }
+    u8g2_SendBuffer(&u8g2);
+    u8g2_SetPowerSave(&u8g2, 0); // wake up display
+}
+
+
+
+void screen_unit(int no)
+{
+    char        buf[65];
+
+    u8g2_ClearBuffer(&u8g2);
+    u8g2_DrawHLine(&u8g2, 0, 14, 128);
+    u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr);
+    sprintf(buf, "Unit %d", no + 1);
+    u8g2_uint_t w = u8g2_GetStrWidth(&u8g2, buf);
+    u8g2_DrawStr(&u8g2, (128 - w) / 2,12, buf);
+
+    if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) {
+
+    	u8g2_SetFont(&u8g2, u8g2_font_t0_22b_tf);
+    	sprintf(buf, "%.1f °C", units[no].temperature / 1000.0);
+    	w = u8g2_GetUTF8Width(&u8g2, buf);
+    	u8g2_DrawUTF8(&u8g2, (128 - w) / 2,40, buf);
+//    	u8g2_SetFont(&u8g2, u8g2_font_t0_18b_tf);
+
+    	sprintf(buf, "%.2f bar", units[no].pressure / 1000.0);
+    	w = u8g2_GetUTF8Width(&u8g2, buf);
+    	u8g2_DrawUTF8(&u8g2, (128 - w) / 2,63, buf);
 
-    sprintf(buf, "%.1f", p1);
-    w = u8g2_GetUTF8Width(&u8g2, buf);
-    u8g2_DrawUTF8(&u8g2, ((42 - w) / 2),63, buf);
+	xSemaphoreGive(xSemaphoreUnits);
+    }
+    u8g2_SendBuffer(&u8g2);
+    u8g2_SetPowerSave(&u8g2, 0); // wake up display
+}
+
+
+
+void screen_unit_setup(int no, int sub)
+{
+    char        buf[65];
+
+    u8g2_ClearBuffer(&u8g2);
+    u8g2_DrawHLine(&u8g2, 0, 14, 128);
+    u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr);
+    sprintf(buf, "Unit %d setup", no + 1);
+    u8g2_uint_t w = u8g2_GetStrWidth(&u8g2, buf);
+    u8g2_DrawStr(&u8g2, (128 - w) / 2,12, buf);
 
-    sprintf(buf, "%.1f", p2);
-    w = u8g2_GetUTF8Width(&u8g2, buf);
-    u8g2_DrawUTF8(&u8g2, ((42 - w) / 2) + 43,63, buf);
+    if (sub == 0)
+	u8g2_SetFont(&u8g2, u8g2_font_t0_15b_tr);
+    else
+	u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr);
+    sprintf(buf, "Mode      %s", units[no].mode ? "ON":"OFF");
+    u8g2_DrawStr(&u8g2,2,28, buf);
+
+    if (sub == 1)
+        u8g2_SetFont(&u8g2, u8g2_font_t0_15b_tr);
+    else
+        u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr);
+    sprintf(buf, "Calibrate");
+    u8g2_DrawStr(&u8g2,2,40, buf);
 
-    sprintf(buf, "%.1f", p3);
-    w = u8g2_GetUTF8Width(&u8g2, buf);
-    u8g2_DrawUTF8(&u8g2, ((42 - w) / 2) + 86,63, buf);
+    if (sub == 2)
+        u8g2_SetFont(&u8g2, u8g2_font_t0_15b_tr);
+    else
+        u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr);
+    sprintf(buf, "T.sensor  ");
+    u8g2_DrawStr(&u8g2,2,52, buf);
+
+    if (sub == 3)
+        u8g2_SetFont(&u8g2, u8g2_font_t0_15b_tr);
+    else
+        u8g2_SetFont(&u8g2, u8g2_font_t0_15_tr);
+    sprintf(buf, "Return");
+    u8g2_DrawStr(&u8g2,2,64, buf);
 
     u8g2_SendBuffer(&u8g2);
-    u8g2_SetPowerSave(&u8g2, 0); // wake up display
+    u8g2_SetPowerSave(&u8g2, 0);
 }
 
 
@@ -84,32 +161,78 @@
     u8g2_DrawStr(&u8g2,2,24,e2);
     u8g2_SendBuffer(&u8g2);
     u8g2_SetPowerSave(&u8g2, 0);
+}
 
+
+
+/*
+ * Interrupt service routine for the rotary pushbutton.
+ */
+static void IRAM_ATTR gpio_isr_handler(void* arg)
+{
+    uint32_t gpio_num = (uint32_t) arg;
+    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
 }
 
 
 
+/*
+ * GPIO queue task. See if there is a rotary pushbutton event in the queue.
+ */
+static void gpio_task(void* arg)
+{
+    uint32_t		io_num;
+    static int64_t	pushed = 0;
+
+    for(;;) {
+        if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
+	    if (io_num == ROT_ENC_SW_GPIO) {
+		if (gpio_get_level(io_num) == 0) {
+		    pushed = esp_timer_get_time();
+		    PushDuration = 0;
+		} else if (gpio_get_level(io_num) == 1) {
+		    PushDuration = (esp_timer_get_time() - pushed) / 1000;
+		    ESP_LOGI(TAG, "GPIO rotary button intr, val: %d time: %d", gpio_get_level(io_num), PushDuration);
+		}
+	    } else {
+            	ESP_LOGE(TAG, "GPIO[%d] unknown intr, val: %d", io_num, gpio_get_level(io_num));
+	    }
+	    usertimer = INACTIVITY;
+        }
+    }
+}
+
+
+
+/*
+ * Select new menu number on a postitive or negative rotary position.
+ * Then reset the rotary position.
+ */
+static void rotate_to_menu(rotary_encoder_position_t pos, int next_menu, int prev_menu)
+{
+    if (pos > 0)
+	New_Loop2 = next_menu;
+    else if (pos < 0)
+	New_Loop2 = prev_menu;
+    ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo));
+}
+
+
 
 void app_main()
 {
     struct timeval	now;
     gettimeofday(&now, NULL);
     int			sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + (now.tv_usec - sleep_enter_time.tv_usec) / 1000;
-    int			New_Loop2 = MAIN_LOOP2_INIT;
     esp_err_t           ret;
 
-    Main_Loop1 = MAIN_LOOP1_INIT;
+    Main_Loop1 = ML1_INIT;
     Main_Loop2 = -1;
 
     switch (esp_sleep_get_wakeup_cause()) {
         case ESP_SLEEP_WAKEUP_EXT1: {
-            uint64_t wakeup_pin_mask = esp_sleep_get_ext1_wakeup_status();
-            if (wakeup_pin_mask != 0) {
-                int pin = __builtin_ffsll(wakeup_pin_mask) - 1;
-                printf("Wake up from GPIO %d\n", pin);
-            } else {
-                printf("Wake up from GPIO\n");
-            }
+	    ESP_LOGI(TAG, "Starting from deep sleep, Rotary switch pressed");
+	    New_Loop2 = ML2_INIT;
             break;
         }
         case ESP_SLEEP_WAKEUP_TIMER: {
@@ -124,12 +247,10 @@
     const int wakeup_time_sec = 55;
     ESP_LOGI(TAG, "Enabling timer wakeup, %ds", wakeup_time_sec);
     esp_sleep_enable_timer_wakeup(wakeup_time_sec * 1000000);
+    const uint64_t ext_wakeup_pin_1_mask = 1ULL << ROT_ENC_SW_GPIO;
 
-//    const int ext_wakeup_pin_1 = ROT_ENC_SW_GPIO; // 25 in example, redefine to rotary name.
-//    const uint64_t ext_wakeup_pin_1_mask = 1ULL << ext_wakeup_pin_1;
-
-//    printf("Enabling EXT1 wakeup on pins GPIO%d\n", ext_wakeup_pin_1);
-//    esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask, ESP_EXT1_WAKEUP_ANY_HIGH); // TODO: what is the logic of the rotary button.
+    ESP_LOGI(TAG, "Enabling EXT1 wakeup on pin GPIO%d", ROT_ENC_SW_GPIO);
+    esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask, ESP_EXT1_WAKEUP_ALL_LOW);
 
     // Isolate GPIO12 pin from external circuits. This is needed for modules
     // which have an external pull-up resistor on GPIO12 (such as ESP32-WROVER)
@@ -159,7 +280,6 @@
 
     u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8g2_esp32_i2c_byte_cb, u8g2_esp32_gpio_and_delay_cb);  // init u8g2 structure
     u8x8_SetI2CAddress(&u8g2.u8x8, 0x78);
-    ESP_LOGI(TAG, "u8g2_InitDisplay");
     u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this,
 
     /*
@@ -248,18 +368,24 @@
      * installed before calling rotary_encoder_register()
      */
     ESP_ERROR_CHECK(gpio_install_isr_service(0));
-    rotary_encoder_info_t rinfo = { 0 };
     ESP_ERROR_CHECK(rotary_encoder_init(&rinfo, ROT_ENC_A_GPIO, ROT_ENC_B_GPIO));
-//    ESP_ERROR_CHECK(rotary_encoder_enable_half_steps(&rinfo, ENABLE_HALF_STEPS));
-#ifdef FLIP_DIRECTION
-//    ESP_ERROR_CHECK(rotary_encoder_flip_direction(&rinfo));
-#endif
+    ESP_ERROR_CHECK(rotary_encoder_enable_half_steps(&rinfo, false));
+
+    gpio_config_t io_conf;
+    io_conf.intr_type = GPIO_PIN_INTR_ANYEDGE;
+    io_conf.pin_bit_mask = (1ULL << ROT_ENC_SW_GPIO);
+    io_conf.mode = GPIO_MODE_INPUT;
+    gpio_config(&io_conf);
+
+    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
+    xTaskCreate(gpio_task, "gpio_task", 2048, NULL, 10, NULL);
+
+    gpio_isr_handler_add(ROT_ENC_SW_GPIO, gpio_isr_handler, (void*) ROT_ENC_SW_GPIO);
 
     // Create a queue for events from the rotary encoder driver.
     // Tasks can read from this queue to receive up to date position information.
-//    QueueHandle_t event_queue = rotary_encoder_create_queue();
-//    ESP_ERROR_CHECK(rotary_encoder_set_queue(&rinfo, event_queue));
-
+    QueueHandle_t event_queue = rotary_encoder_create_queue();
+    ESP_ERROR_CHECK(rotary_encoder_set_queue(&rinfo, event_queue));
 
     /*
      * Main application loop.
@@ -267,35 +393,36 @@
     while (1) {
 
 	ESP_LOGI(TAG, "Entered app loop");
+	rotary_encoder_event_t event = { 0 };
+	int sub = 0;
 
 	/* Measure process or user input via rotary switch */
 	while (1) {
 	    switch (Main_Loop1) {
-		case MAIN_LOOP1_INIT:
+		case ML1_INIT:
 		    ESP_LOGI(TAG, "Loop timer: Init");
-		    // If configured do MAIN_LOOP1_CONNECT
-		    Main_Loop1 = MAIN_LOOP1_CONNECT;
+		    // If configured do ML1_CONNECT
+		    Main_Loop1 = ML1_CONNECT;
 		    requestWiFi_system(true);
 		    request_ds18b20();
 		    request_adc();
 		    break;
 
-		case MAIN_LOOP1_CONNECT:
+		case ML1_CONNECT:
                     if (ready_WiFi())
-                        Main_Loop1 = MAIN_LOOP1_MQTT_CONNECT;
+                        Main_Loop1 = ML1_MQTT_CONNECT;
                     break;
 
-		case MAIN_LOOP1_MQTT_CONNECT:
+		case ML1_MQTT_CONNECT:
 		    if (ready_ds18b20() && ready_adc()) {
 			connect_mqtt(true);
-			Main_Loop1 = MAIN_LOOP1_WAITCON;
+			Main_Loop1 = ML1_WAITCON;
 			ESP_LOGI(TAG, "Loop timer: Wait MQTT");
 
 			/* Get global temperature, use for all units. */
 			uint32_t temp = 0;
 			int state = 0;
 			char rom_code[17];
-			float t = 0, p1, p2, p3;
 			if (xSemaphoreTake(xSemaphoreDS18B20, 10) == pdTRUE) {
 			    temp = (ds18b20_state->sensor[0].temperature * 1000);
 			    state = (ds18b20_state->sensor[0].error == 0) ? 0:1;
@@ -303,13 +430,10 @@
 			    rom_code[16] = '\0';
         		    xSemaphoreGive(xSemaphoreDS18B20);
     			}
-			t = temp / 1000.0;
 
 			/* Copy measured data and calculate results */
 			if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) {
 			    for (int i = 0; i < 3; i++) {
-				if (i == 0)
-				    units[i].mode = 1;
 			    	units[i].temperature = temp;
 			    	units[i].temperature_state = state;
 				units[i].alarm = 0;
@@ -327,12 +451,6 @@
 				    if (P < 0)
 				    	P = 0;
 				    units[i].pressure = P;
-				    if (i == 0)
-					p1 = P / 1000.0;
-				    else if (i == 1)
-					p2 = P / 1000.0;
-				    else if (i == 2)
-					p3 = P / 1000.0;
 printf("%d volt: %d batt: %d scale: %d  bar: %d\n", i, units[i].pressure_voltage, adc_state->Batt_voltage, 
 		units[i].pressure_voltage / (adc_state->Batt_voltage / 1000) - units[i].pressure_zero, P);
 // Moet die echt op 5 volt?
@@ -343,51 +461,56 @@
 			    }
 			    write_units();
 			    xSemaphoreGive(xSemaphoreUnits);
-			    screen_main(t, p1, p2, p3);
+			    switch (Main_Loop2) {
+				case ML2_USER:	screen_main(); break;
+				case ML2_UNIT1:	screen_unit(0); break;
+				case ML2_UNIT2: screen_unit(1); break;
+				case ML2_UNIT3: screen_unit(2); break;
+			    }
 			}
 		    }
 		    break;
 
-		case MAIN_LOOP1_WAITCON:
+		case ML1_WAITCON:
 		    if (ready_mqtt())
-			Main_Loop1 = MAIN_LOOP1_SEND;
+			Main_Loop1 = ML1_SEND;
 		    break;
 
-		case MAIN_LOOP1_SEND:
+		case ML1_SEND:
 		    ESP_LOGI(TAG, "Loop timer: Send MQTT");
 		    publishNode();
 		    publishUnits();
 		    publishLogs();
-		    Main_Loop1 = MAIN_LOOP1_WAITACK;
+		    Main_Loop1 = ML1_WAITACK;
 		    break;
 
-		case MAIN_LOOP1_WAITACK:
+		case ML1_WAITACK:
 		    if (count_pub == 0) // Wait until all published messages are sent.
-			Main_Loop1 = MAIN_LOOP1_MQTT_DISCONNECT;
+			Main_Loop1 = ML1_MQTT_DISCONNECT;
 		    break;
 
-		case MAIN_LOOP1_MQTT_DISCONNECT:
+		case ML1_MQTT_DISCONNECT:
 		    ESP_LOGI(TAG, "Loop timer: Disconnect MQTT");
 		    connect_mqtt(false); // Doesn't really disconnect.
-                    Main_Loop1 = MAIN_LOOP1_DISCONNECT;
+                    Main_Loop1 = ML1_DISCONNECT;
 		    break;
 
-		case MAIN_LOOP1_DISCONNECT:
+		case ML1_DISCONNECT:
 		    if (! ready_mqtt()) {
 			ESP_LOGI(TAG, "Loop timer: WiFi off");
 		    	requestWiFi_system(false);
-		    	Main_Loop1 = MAIN_LOOP1_WIFI_OFF;
+		    	Main_Loop1 = ML1_WIFI_OFF;
 		    }
 		    break;
 
-		case MAIN_LOOP1_WIFI_OFF:
+		case ML1_WIFI_OFF:
 		    if (! ready_WiFi()) {
 			ESP_LOGI(TAG, "Loop timer: Done");
-			Main_Loop1 = MAIN_LOOP1_DONE;
+			Main_Loop1 = ML1_DONE;
 		    }
 		    break;
 
-		case MAIN_LOOP1_DONE:
+		case ML1_DONE:
 		    break;
 	    }
 
@@ -399,17 +522,54 @@
 		Main_Loop2 = New_Loop2;
 
 		switch (Main_Loop2) {
-		    case MAIN_LOOP2_INIT:
+		    case ML2_INIT:
 			ESP_LOGI(TAG, "Loop user: Init");
 //			u8g2_SetPowerSave(&u8g2, 0); // wake up display
 //			u8g2_ClearBuffer(&u8g2);
-//			New_Loop2 = MAIN_LOOP2_INACTIVE;
-			New_Loop2 = MAIN_LOOP2_DONE;
+			New_Loop2 = ML2_USER;
+			usertimer = INACTIVITY;
+			break;
+
+		    case ML2_USER:
+			ESP_LOGI(TAG, "Loop user: User mainmenu");
+			screen_main();
+			break;
+
+		    case ML2_UNIT1:
+		    case ML2_UNIT2:
+		    case ML2_UNIT3:
+			ESP_LOGI(TAG, "Loop user: Unit %d", Main_Loop2 - ML2_UNIT1);
+			screen_unit(Main_Loop2 - ML2_UNIT1);
+			break;
+
+		    case ML2_SET_WIFI:
+			ESP_LOGI(TAG, "Loop user: Setup WiFi");
 			break;
 
-		    case MAIN_LOOP2_INACTIVE:
-//			u8g2_SetPowerSave(&u8g2, 1); // powersave display
-			New_Loop2 = MAIN_LOOP2_DONE;
+		    case ML2_SET_NETWORK:
+			ESP_LOGI(TAG, "Loop user: Setup Network");
+			break;
+
+		    case ML2_SET_MQTT:
+			ESP_LOGI(TAG, "Loop user: Setup MQTT");
+			break;
+
+		    case ML2_UPDATE:
+			ESP_LOGI(TAG, "Loop user: Update");
+			break;
+
+		    case ML2_SETUP_UNIT1:
+		    case ML2_SETUP_UNIT2:
+		    case ML2_SETUP_UNIT3:
+			ESP_LOGI(TAG, "Loop user: Setup Unit %d", Main_Loop2 - ML2_SETUP_UNIT1);
+			sub = 0;
+			screen_unit_setup(Main_Loop2 - ML2_SETUP_UNIT1, sub);
+			break;
+
+		    case ML2_INACTIVE:
+			ESP_LOGI(TAG, "Loop user: Inactive");
+			u8g2_SetPowerSave(&u8g2, 1); // powersave display
+			New_Loop2 = ML2_DONE;
 			break;
 
 		    default:
@@ -418,10 +578,10 @@
 	    }
 
 	    /*
-	     * Action process.
+	     * Main user processing. Handle the rotary encoder and pushbutton.
 	     */
-	    switch (Main_Loop2) {
-	    // If wakeup from GPIO -- state machine 2
+	    if (Main_Loop2 < ML2_INACTIVE) {
+	    	// If wakeup from GPIO -- state machine 2
 		// Init OLED
 		// If not configured, start configure
 		// If configured select first unit
@@ -443,12 +603,97 @@
 		// Sensors setup menu:	DS18B20 addr	Press is assign
 		//			DS18B20 addr
 
-	    // Break if all done and inactive.
-		default:
-		    break;
+		if (xQueueReceive(event_queue, &event, 250 / portTICK_PERIOD_MS) == pdTRUE) {
+		    usertimer = INACTIVITY;
+		    switch (Main_Loop2) {
+		    	case ML2_USER:		rotate_to_menu(event.state.position, ML2_UNIT1, ML2_USER); break;
+		    	case ML2_UNIT1:		rotate_to_menu(event.state.position, ML2_UNIT2, ML2_USER); break;
+		    	case ML2_UNIT2:		rotate_to_menu(event.state.position, ML2_UNIT3, ML2_UNIT1); break;
+		    	case ML2_UNIT3:		rotate_to_menu(event.state.position, ML2_SET_WIFI, ML2_UNIT2); break;
+		    	case ML2_SET_WIFI:	rotate_to_menu(event.state.position, ML2_SET_NETWORK, ML2_UNIT3); break;
+		    	case ML2_SET_NETWORK:	rotate_to_menu(event.state.position, ML2_SET_MQTT, ML2_SET_WIFI); break;
+		    	case ML2_SET_MQTT:	rotate_to_menu(event.state.position, ML2_UPDATE, ML2_SET_NETWORK); break;
+		    	case ML2_UPDATE:	rotate_to_menu(event.state.position, ML2_UPDATE, ML2_SET_MQTT); break;
+			case ML2_SETUP_UNIT1:
+			case ML2_SETUP_UNIT2:
+			case ML2_SETUP_UNIT3:	if (event.state.position > 0) {
+						    if (sub < 3) {
+							sub++;
+							screen_unit_setup(Main_Loop2 - ML2_SETUP_UNIT1, sub);
+						    }
+						    ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo));
+						} else if (event.state.position < 0) {
+						    if (sub > 0) {
+							sub--;
+							screen_unit_setup(Main_Loop2 - ML2_SETUP_UNIT1, sub);
+						    }
+						    ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo));
+						}
+						break;
+			default:
+		    				ESP_LOGI(TAG, "Event: position %d, direction %s", event.state.position,
+                                		event.state.direction ? (event.state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW":"CCW"):"NOT_SET");
+		    }
+                } else {
+                    // Poll current position and direction
+                    rotary_encoder_state_t state = { 0 };
+                    ESP_ERROR_CHECK(rotary_encoder_get_state(&rinfo, &state));
+
+//                    ESP_LOGI(TAG, "Poll: position %d, direction %s timer %d", state.position,
+//                    state.direction ? (state.direction == ROTARY_ENCODER_DIRECTION_CLOCKWISE ? "CW" : "CCW") : "NOT_SET", usertimer);
+		    if (usertimer)
+			usertimer--;
+		    else
+			New_Loop2 = ML2_INACTIVE;
+
+                            // Reset the device
+       //                     if (RESET_AT && (state.position >= RESET_AT || state.position <= -RESET_AT)) {
+       //                         ESP_LOGI(TAG, "Reset");
+       //                         ESP_ERROR_CHECK(rotary_encoder_reset(&rinfo));
+       //                     }
+                }
 	    }
 
-	    if (Main_Loop1 == MAIN_LOOP1_DONE && Main_Loop2 == MAIN_LOOP2_DONE) 
+	    switch (Main_Loop2) {
+	    // Break if all done and inactive.
+		case ML2_UNIT1:
+		case ML2_UNIT2:
+		case ML2_UNIT3:
+			if (PushDuration) {
+			    New_Loop2 = ML2_SETUP_UNIT1 + (Main_Loop2 - ML2_UNIT1);
+			    PushDuration = 0;
+			}
+			break;
+
+		case ML2_SETUP_UNIT1:
+		case ML2_SETUP_UNIT2:
+		case ML2_SETUP_UNIT3:
+			if (PushDuration) {
+			    if (sub == 0) {
+				if (xSemaphoreTake(xSemaphoreUnits, 25) == pdTRUE) {
+				    if (units[Main_Loop2 - ML2_SETUP_UNIT1].mode)
+					units[Main_Loop2 - ML2_SETUP_UNIT1].mode = 0;
+				    else
+					units[Main_Loop2 - ML2_SETUP_UNIT1].mode = 1;
+				    write_units();
+                            	    xSemaphoreGive(xSemaphoreUnits);
+				}
+				screen_unit_setup(Main_Loop2 - ML2_SETUP_UNIT1, sub);
+				if (Main_Loop1 == ML1_DONE)
+				    Main_Loop1 = ML1_INIT;
+			    }
+			    if (sub == 3)
+				New_Loop2 = ML2_UNIT1 + (Main_Loop2 - ML2_SETUP_UNIT1);
+			    printf("sub %d  new %d\n", sub, New_Loop2);
+			    PushDuration = 0;
+			}
+			break;
+
+		default:
+			break;
+	    }
+
+	    if (Main_Loop1 == ML1_DONE && Main_Loop2 == ML2_DONE)
 	    	break;
 
 	    vTaskDelay(10 / portTICK_PERIOD_MS);
@@ -465,8 +710,8 @@
     	gettimeofday(&sleep_enter_time, NULL);
 	esp_deep_sleep_start();
 
-	Main_Loop1 = MAIN_LOOP1_INIT;
-	New_Loop2 = MAIN_LOOP2_INIT;
+	Main_Loop1 = ML1_INIT;
+	New_Loop2 = ML2_INIT;
     }
 
 }
--- a/main/config.c	Sat Oct 26 14:05:17 2019 +0200
+++ b/main/config.c	Wed Oct 30 23:21:46 2019 +0100
@@ -81,7 +81,7 @@
 void read_units() {
     uint8_t     *dst;
     uint8_t     mac_addr[8] = {0};
-    FILE        *f = fopen("/spiffs/etc/units.conft", "r");
+    FILE        *f = fopen("/spiffs/etc/units.conf", "r");
 
     if (f == NULL) {
         // No units yet, create them.
--- a/main/config.h	Sat Oct 26 14:05:17 2019 +0200
+++ b/main/config.h	Wed Oct 30 23:21:46 2019 +0100
@@ -66,17 +66,17 @@
  */
 typedef enum
 {
-    MAIN_LOOP1_INIT = 0,		///< Init fase
-    MAIN_LOOP1_CONNECT,			///< Connect WiFi
-    MAIN_LOOP1_MQTT_CONNECT,		///< Connect MQTT if WiFi
-    MAIN_LOOP1_WAITCON,			///< Wait for connection and measurements
-    MAIN_LOOP1_SEND,			///< Send MQTT node and units messages
-    MAIN_LOOP1_WAITACK,			///< MQTT messages received
-    MAIN_LOOP1_MQTT_DISCONNECT,		///< MQTT disconnect
-    MAIN_LOOP1_DISCONNECT,		///< Disconnect WiFi
-    MAIN_LOOP1_WIFI_OFF,		///< WiFi power off
-    MAIN_LOOP1_DONE			///< All done
-} MAIN_LOOP1;
+    ML1_INIT = 0,		///< Init fase
+    ML1_CONNECT,			///< Connect WiFi
+    ML1_MQTT_CONNECT,		///< Connect MQTT if WiFi
+    ML1_WAITCON,			///< Wait for connection and measurements
+    ML1_SEND,			///< Send MQTT node and units messages
+    ML1_WAITACK,			///< MQTT messages received
+    ML1_MQTT_DISCONNECT,		///< MQTT disconnect
+    ML1_DISCONNECT,		///< Disconnect WiFi
+    ML1_WIFI_OFF,		///< WiFi power off
+    ML1_DONE			///< All done
+} ML1;
 
 
 
@@ -85,18 +85,21 @@
  */
 typedef enum
 {
-    MAIN_LOOP2_INIT = 0,
-    MAIN_LOOP2_UNIT1,			///< Unit 1
-    MAIN_LOOP2_UNIT2,			///< Unit 2
-    MAIN_LOOP2_UNIT3,			///< Unit 3
-    MAIN_LOOP2_UNIT4,			///< Unit 4
-    MAIN_LOOP2_SET_WIFI,		///< WiFi stations setup
-    MAIN_LOOP2_SET_NETWORK,		///< Network setup
-    MAIN_LOOP2_SET_MQTT,		///< MQTT setup
-    MAIN_LOOP2_UPDATE,			///< Update
-    MAIN_LOOP2_INACTIVE,		///< Inactive reached, cleanup
-    MAIN_LOOP2_DONE			///< All done
-} MAIN_LOOP2;
+    ML2_INIT = 0,
+    ML2_USER,			///< User mainmenu
+    ML2_UNIT1,			///< Unit 1
+    ML2_UNIT2,			///< Unit 2
+    ML2_UNIT3,			///< Unit 3
+    ML2_SET_WIFI,		///< WiFi stations setup
+    ML2_SET_NETWORK,		///< Network setup
+    ML2_SET_MQTT,		///< MQTT setup
+    ML2_UPDATE,			///< Update
+    ML2_SETUP_UNIT1,		///< Unit 1 setup
+    ML2_SETUP_UNIT2,		///< Unit 2 setup
+    ML2_SETUP_UNIT3,		///< Unit 3 setup
+    ML2_INACTIVE,		///< Inactive reached, cleanup
+    ML2_DONE			///< All done
+} ML2;
 
 
 
--- a/main/task_mqtt.c	Sat Oct 26 14:05:17 2019 +0200
+++ b/main/task_mqtt.c	Wed Oct 30 23:21:46 2019 +0100
@@ -91,7 +91,7 @@
      */
     if (xSemaphoreTake(xSemaphorePcounter, 10) == pdTRUE) {
         count_pub++;
-printf("  up %d\n", count_pub);
+//printf("  up %d\n", count_pub);
         xSemaphoreGive(xSemaphorePcounter);
     } else {
         ESP_LOGE(TAG, "Missed lock 1");
@@ -288,7 +288,7 @@
 	    if (xSemaphoreTake(xSemaphorePcounter, 10) == pdTRUE) {
 	    	if (count_pub) {
 		    count_pub--;
-printf("down %d\n", count_pub);
+//printf("down %d\n", count_pub);
 	    	}
 		xSemaphoreGive(xSemaphorePcounter);
 	    } else {
--- a/sdkconfig	Sat Oct 26 14:05:17 2019 +0200
+++ b/sdkconfig	Wed Oct 30 23:21:46 2019 +0100
@@ -84,9 +84,9 @@
 CONFIG_I2C_MASTER_SDA=21
 CONFIG_I2C_MASTER_PORT_NUM=0
 CONFIG_I2C_MASTER_FREQUENCY=100000
-CONFIG_ROT_ENC_A_GPIO=27
-CONFIG_ROT_ENC_B_GPIO=26
-CONFIG_ROT_ENC_SW_GPIO=12
+CONFIG_ROT_ENC_A_GPIO=26
+CONFIG_ROT_ENC_B_GPIO=27
+CONFIG_ROT_ENC_SW_GPIO=14
 CONFIG_BATT_CHANNEL=4
 CONFIG_PRESSURE_1=6
 CONFIG_PRESSURE_2=7

mercurial