From d510d15b99ff7b8421f3fb112fe908484884c369 Mon Sep 17 00:00:00 2001
From: Arturo Corro <arturo@koneko.mx>
Date: Tue, 19 Jul 2022 00:29:14 -0500
Subject: [PATCH] =?UTF-8?q?Pi=C3=B1as=20Update?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../Dosificador_LCD2004_4buttons.ino          | 2094 ++++++++---------
 1 file changed, 1047 insertions(+), 1047 deletions(-)

diff --git a/Dosificador_LCD2004_4buttons/Dosificador_LCD2004_4buttons.ino b/Dosificador_LCD2004_4buttons/Dosificador_LCD2004_4buttons.ino
index 719a1d5..f924ec4 100644
--- a/Dosificador_LCD2004_4buttons/Dosificador_LCD2004_4buttons.ino
+++ b/Dosificador_LCD2004_4buttons/Dosificador_LCD2004_4buttons.ino
@@ -1,1047 +1,1047 @@
-/*****************************************
-*   Dosificador_LCD2004_4buttons         *
-*   15/03/2021                           *
-*   Versión 0.1.0                        *
-*   koneko.mx                            *
-*****************************************/
-
-#include <EEPROM.h>
-#include <LiquidCrystal_I2C.h>
-
-/**************************************************
-* Definición de Constantes
-**************************************************/
-	// LCD2004 I2C
-	#define LCD_I2C_ADDRESS 0x27
-
-	// PINOUT
-	#define RELAY_PIN			  4
-	#define DOSING_BUTTON_PIN	  3
-	#define SETTINGS_BUTTONS_PIN A2
-
-	// BUTTON SETTINGS
-	#define SETTING_BUTTON_IN_VAL   15
-	#define SETTING_BUTTON_OUT_VAL  92
-	#define SETTING_BUTTON_UP_VAL   42
-	#define SETTING_BUTTON_DOWN_VAL 67
-
-	#define SETTING_BUTTON_TOLERANCE_READ				 2
-	#define SETTING_BUTTON_CONFIRMATION_REPEATS_MILLIS	80
-	#define SETTING_BUTTON_DELAY_MILLIS				   450
-
-	// BLOQUES DE MEMORIA EEPROM 
-	#define BUTTON_SENSITIVITY_EEPROM_ADDRESS 0
-	#define PRESS_BUTTON_EEPROM_ADDRESS		  1
-	#define HOLD_DOWN_BUTTON_EEPROM_ADDRESS	  2
-	#define LAG_TIME_MIN_EEPROM_ADDRESS		  3 // Minutos, tiempo de retraso
-	#define LAG_TIME_SEG_EEPROM_ADDRESS		  4 // Segundo, tiempo de retraso
-	#define LAG_TIME_DEC_EEPROM_ADDRESS		  5 // Décimas de segundo, tiempo de retraso
-	#define DOSING_TIME_MIN_EEPROM_ADDRESS	  6 // Minutos, tiempo dosificación
-	#define DOSING_TIME_SEG_EEPROM_ADDRESS	  7 // Segundos, tiempo dosificación
-	#define DOSING_TIME_DEC_EEPROM_ADDRESS	  8 // Décimas de segundo, tiempo dosificación
-
-	// FACTORY SETTINGS
-	#define BUTTON_SENSITIVITY_DEFAULT_VALUE  9
-	#define PRESS_BUTTON_DEFAULT_VALUE		  3
-	#define HOLD_DOWN_BUTTON_DEFAULT_VALUE	  1
-	#define LAG_TIME_MIN_DEFAULT_VALUE		  0 // Minutos, tiempo de retraso
-	#define LAG_TIME_SEG_DEFAULT_VALUE		  3 // Segundo, tiempo de retraso
-	#define LAG_TIME_DEC_DEFAULT_VALUE		  5 // Décimas de segundo, tiempo de retraso
-	#define DOSING_TIME_MIN_DEFAULT_VALUE	  1 // Minutos, tiempo dosificación
-	#define DOSING_TIME_SEG_DEFAULT_VALUE	 10 // Segundos, tiempo dosificación
-	#define DOSING_TIME_DEC_DEFAULT_VALUE	  9 // Décimas de segundo, tiempo dosificación
-
-	// SETTINGS MENU
-	#define ALL_SETTINGS 0
-	#define OUT_OF_MENU  0
-
-	#define IN_SENSITIVITY_BUTTON 1
-	#define IN_PRESS_BUTTON 	  2
-	#define IN_HOLD_DOWN_BUTTON	  3
-	#define IN_LAG 				  4
-	#define IN_DOSING 			  5
-	#define IN_FACTORY_RESET 	  6
-	#define IN_RESTART 			  7
-	#define IN_EXIT 			  8
-
-	#define VIEW   0
-	#define UPDATE 1
-
-	#define POSITION_ONE   0
-	#define POSITION_TWO   1
-	#define POSITION_THREE 2
-
-	#define MODE_1		  0
-	#define MODE_2		  1
-	#define MODE_3		  2
-	#define FACTORY_RESET 3
-	#define RESTART		  4
-	#define CANCEL		  5
-
-	#define AUTO_EXIT_MENU_MILLIS	   15000
-	#define BLINK_MILLIS				1600
-	#define LCD_PROCESS_REFRESH_MILLIS   333
-
-	// DISPENSER
-	#define DISPENSER_RESTART	10
-	#define DISPENSER_IDLE		 0
-	#define DISPENSER_DETECTING  1
-	#define DISPENSER_LAG		 2
-	#define DISPENSER_DOSING	 3
-	#define DISPENSER_BLOCK		 4
-
-	// STATUS RELAY
-	#define RELAY_HIGH HIGH
-	#define RELAY_LOW  LOW
-
-	// STATUS BUTTON
-	#define DOSING_BUTTON_PUSH 0
-	#define DOSING_BUTTON_IDLE 1
-
-
-/**************************************************
-* Debug
-* Define DEBUG_SERIAL_ENABLE to enable debug serial.
-* Comment it to disable debug serial.
-**************************************************/
-	//#define DEBUG_SERIAL_ENABLE
-
-	#define dbSerial Serial
-
-	#ifdef DEBUG_SERIAL_ENABLE
-		#define serialPrint(a)		dbSerial.print(a)
-		#define serialPrintln(a)	dbSerial.println(a)
-		#define serialBegin(a)		dbSerial.begin(a)
-		#define serialBeginWhile(a) while(!dbSerial) delay(1)
-	#else
-		#define serialPrint(a)		do{}while(0)
-		#define serialPrintln(a)	do{}while(0)
-		#define serialBegin(a)		do{}while(0)
-		#define serialBeginWhile(a)	do{}while(0)
-	#endif
-
-
-/**************************************************
-* ENVIRONMENT VARIABLES
-**************************************************/
-	// Dosing
-	uint16_t button_sensitivity_millis;
-	uint8_t  press_button_mode;
-	uint8_t  hold_down_button_mode;
-	uint16_t lag_time_decseg;
-	uint16_t dosing_time_decseg;
-
-    uint32_t button_pressed_millis;
-    uint8_t  release_button;
-
-	uint8_t  dispenser_status;
-	uint32_t dispenser_status_time_millis;
-
-	// 4-button configuration 
-	uint8_t  button_values[] = {SETTING_BUTTON_IN_VAL, SETTING_BUTTON_OUT_VAL, SETTING_BUTTON_UP_VAL, SETTING_BUTTON_DOWN_VAL};
-	uint32_t _bt[sizeof(button_values)]; // millis
-	uint32_t confirmation_repeats_millis;
-
-	uint8_t menu_section;
-	uint8_t menu_status;
-	uint8_t menu_cursor_var;
-
-	uint8_t setup_var[3];
-
-	uint32_t last_change_menu_millis;
-
-
-	// LCD2004 Render
-	LiquidCrystal_I2C lcd(LCD_I2C_ADDRESS, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
-
-	String menu[] = {
-		"SENSIBILIDAD BOTON",
-		"AL PRESIONAR BOTON",
-		"AL MANTENER PRESIO",
-		"RETARDO AL INICIAR",
-		"TIEMPO DOSIFICACION",
-		"VALORES DE FABRICA",
-		"REINICIAR",
-		"SALIR",
-	};
-
-	String status[] = {
-		"EN ESPERA",
-		"DETECTANDO",
-		"DOSIFICARA",
-		"DOSIFICANDO",
-		"BLOQUEADO",
-	};
-
-	String text_info[] = {
-		"MODO 1",
-		"MODO 2",
-		"MODO 3",
-		"RESTAURAR",
-		"REINICAR",
-		"CANCELAR",
-	};
-
-	boolean  refresh_lcd_menu;
-	uint32_t blink_millis;
-
-
-/**************************************************
-* FRONT PANEL OF CONFIGURATIONS
-**************************************************/
-	// button methods and memory spaces
-	void loop_settings_panel_buttons()
-	{
-		// Leemos valor analogo del botón
-		uint8_t button_value = analogRead(SETTINGS_BUTTONS_PIN);
-
-		// Comprobamos el valor obtenido con un rago de tolerancia SETTING_BUTTON_TOLERANCE_READ
-		for (uint8_t i = 0; i < sizeof button_values / sizeof button_values[0]; i++) {
-			if(button_values[i] >= (button_value - SETTING_BUTTON_TOLERANCE_READ) && button_values[i] <= (button_value + SETTING_BUTTON_TOLERANCE_READ))
-				button_value = button_values[i];
-		}
-
-		//Valoramos si se presiono un botón y ejecutamos el metodo correspondiente
-		switch(button_value) {
-			case SETTING_BUTTON_IN_VAL:
-				if(millis() >= _bt[0] + SETTING_BUTTON_DELAY_MILLIS) {
-					if(confirmation_repeats_millis == 0)
-						confirmation_repeats_millis = millis() + SETTING_BUTTON_CONFIRMATION_REPEATS_MILLIS;
-
-					if(millis() > confirmation_repeats_millis){
-						action_button(SETTING_BUTTON_IN_VAL);
-
-						_bt[0] = millis();
-					}
-				}
-				break;
-
-			case SETTING_BUTTON_OUT_VAL:
-				if(millis() >= _bt[1] + SETTING_BUTTON_DELAY_MILLIS) {
-					if(confirmation_repeats_millis == 0)
-						confirmation_repeats_millis = millis() + SETTING_BUTTON_CONFIRMATION_REPEATS_MILLIS;
-
-					if(millis() > confirmation_repeats_millis){
-						action_button(SETTING_BUTTON_OUT_VAL);
-
-						_bt[1] = millis();
-					}
-				}
-				break;
-
-			case SETTING_BUTTON_UP_VAL:
-				if(millis() >= _bt[2] + SETTING_BUTTON_DELAY_MILLIS) {
-					if(confirmation_repeats_millis == 0)
-						confirmation_repeats_millis = millis() + SETTING_BUTTON_CONFIRMATION_REPEATS_MILLIS;
-
-					if(millis() > confirmation_repeats_millis){
-						action_button(SETTING_BUTTON_UP_VAL);
-
-						_bt[2] = millis();
-					}
-				}
-				break;
-
-			case SETTING_BUTTON_DOWN_VAL:
-				if(millis() >= _bt[3] + SETTING_BUTTON_DELAY_MILLIS) {
-					if(confirmation_repeats_millis == 0)
-						confirmation_repeats_millis = millis() + SETTING_BUTTON_CONFIRMATION_REPEATS_MILLIS;
-
-					if(millis() > confirmation_repeats_millis){
-						action_button(SETTING_BUTTON_DOWN_VAL);
-
-						_bt[3] = millis();
-					}
-				}
-				break;
-
-			default:
-				confirmation_repeats_millis = 0;
-		}
-
-		// Verificamos y salimos del menú si a pasan AUTO_EXIT_MENU_MILLIS
-		if((menu_section != OUT_OF_MENU) && (millis() >= last_change_menu_millis + AUTO_EXIT_MENU_MILLIS)){
-			load_menu_variables(OUT_OF_MENU);
-
-			refresh_lcd_menu = true;
-
-			serialPrintln("AUTO_EXIT_MENU_MILLIS");
-		}
-	}
-
-	void action_button(uint8_t button_value)
-	{
-		switch(button_value) {
-			case SETTING_BUTTON_IN_VAL:
-				switch(menu_section) {
-					case OUT_OF_MENU:
-						load_menu_variables(IN_SENSITIVITY_BUTTON);
-						break;
-
-					case IN_SENSITIVITY_BUTTON:
-						if(menu_status == VIEW)
-							menu_status = UPDATE;
-
-						else if(++menu_cursor_var > POSITION_ONE)
-							save_setting(IN_SENSITIVITY_BUTTON);
-						break;
-
-					case IN_PRESS_BUTTON:
-						if(menu_status == VIEW)
-							menu_status = UPDATE;
-
-						else if(++menu_cursor_var > POSITION_ONE)
-							save_setting(IN_PRESS_BUTTON);
-						break;
-
-					case IN_HOLD_DOWN_BUTTON:
-						if(menu_status == VIEW)
-							menu_status = UPDATE;
-
-						else if(++menu_cursor_var > POSITION_ONE)
-							save_setting(IN_HOLD_DOWN_BUTTON);
-						break;
-
-					case IN_LAG:
-						if(menu_status == VIEW)
-							menu_status = UPDATE;
-
-						else if(++menu_cursor_var > POSITION_THREE)
-							save_setting(IN_LAG);
-						break;
-
-					case IN_DOSING:
-						if(menu_status == VIEW)
-							menu_status = UPDATE;
-
-						else if(++menu_cursor_var > POSITION_THREE)
-							save_setting(IN_DOSING);
-						break;
-
-					case IN_FACTORY_RESET:
-						if(menu_status == VIEW)
-							menu_status = UPDATE;
-
-						else if(++menu_cursor_var > POSITION_ONE)
-							save_setting(IN_FACTORY_RESET);
-						break;
-
-					case IN_RESTART:
-						if(menu_status == VIEW)
-							menu_status = UPDATE;
-
-						else if(++menu_cursor_var > POSITION_ONE)
-							save_setting(IN_RESTART);
-						break;
-
-					case IN_EXIT:
-						load_menu_variables(OUT_OF_MENU);
-						break;
-				}
-				break;
-
-			case SETTING_BUTTON_OUT_VAL:
-				switch(menu_status){
-					case VIEW:
-						load_menu_variables(OUT_OF_MENU);
-						break;
-
-					case UPDATE:
-						if(menu_cursor_var == 0)
-							load_menu_variables(menu_section);
-						else
-							menu_cursor_var--;
-				}
-				break;
-
-			case SETTING_BUTTON_UP_VAL:
-				switch(menu_section) {
-					case OUT_OF_MENU:
-						load_menu_variables(IN_RESTART);
-						break;
-
-					case IN_SENSITIVITY_BUTTON:
-						if(menu_status == VIEW){
-							load_menu_variables(IN_EXIT);
-
-						}else{ // UPDATE
-							setup_var[0] = setup_var[0] >= 10 ? 1 : ++setup_var[0];
-						}
-						break;
-
-					case IN_PRESS_BUTTON:
-						if(menu_status == VIEW){
-							load_menu_variables(IN_SENSITIVITY_BUTTON);
-
-						}else{ // UPDATE
-							setup_var[0] = setup_var[0] <= 1 ? 3 : --setup_var[0];
-						}
-						break;
-
-					case IN_HOLD_DOWN_BUTTON:
-						if(menu_status == VIEW){
-							load_menu_variables(IN_PRESS_BUTTON);
-
-						}else{ // UPDATE
-							setup_var[0] = setup_var[0] <= 1 ? 2 : --setup_var[0];
-						}
-						break;
-
-					case IN_LAG:
-						if(menu_status == VIEW){
-							load_menu_variables(IN_PRESS_BUTTON);
-
-						}else{ // UPDATE
-							if(menu_cursor_var == POSITION_ONE)
-								setup_var[0] = setup_var[0] >= 60 ? 0 : ++setup_var[0]; // Minutos
-
-							else if(menu_cursor_var == POSITION_TWO)
-								setup_var[1] = setup_var[1] >= 59 ? 0 : ++setup_var[1]; // Segundo
-
-							else if(menu_cursor_var == POSITION_THREE)
-								setup_var[2] = setup_var[2] >= 9 ? 0 : ++setup_var[2]; // Decimas de segundo
-						}
-						break;
-
-					case IN_DOSING:
-						if(menu_status == VIEW){
-							load_menu_variables(IN_LAG);
-
-						}else{ // UPDATE
-							if(menu_cursor_var == POSITION_ONE)
-								setup_var[0] = setup_var[0] >= 60 ? 0 : ++setup_var[0]; // Minutos
-
-							else if(menu_cursor_var == POSITION_TWO)
-								setup_var[1] = setup_var[1] >= 59 ? 0 : ++setup_var[1]; // Segundo
-
-							else if(menu_cursor_var == POSITION_THREE)
-								setup_var[2] = setup_var[2] >= 9 ? 0 : ++setup_var[2]; // Decimas de segundo
-						}
-						break;
-
-					case IN_FACTORY_RESET:
-						if(menu_status == VIEW){
-							load_menu_variables(IN_DOSING);
-
-						}else{ // UPDATE
-							setup_var[0] = setup_var[0] >= 1 ? 0 : ++setup_var[0];
-						}
-						break;
-
-					case IN_RESTART:
-						if(menu_status == VIEW){
-							load_menu_variables(IN_FACTORY_RESET);
-
-						}else{ // UPDATE
-							setup_var[0] = setup_var[0] >= 1 ? 0 : ++setup_var[0];
-						}
-						break;
-
-					case IN_EXIT:
-						load_menu_variables(IN_FACTORY_RESET);
-						break;
-				}
-				break;
-
-			case SETTING_BUTTON_DOWN_VAL:
-				switch(menu_section) {
-					case OUT_OF_MENU:
-						load_menu_variables(IN_SENSITIVITY_BUTTON);
-						break;
-
-					case IN_SENSITIVITY_BUTTON:
-						if(menu_status == VIEW){
-							load_menu_variables(IN_PRESS_BUTTON);
-
-						}else{ // UPDATE
-							setup_var[0] = setup_var[0] <= 1 ? 10 : --setup_var[0];
-						}
-						break;
-
-					case IN_PRESS_BUTTON:
-						if(menu_status == VIEW){
-							load_menu_variables(IN_LAG);
-
-						}else{ // UPDATE
-							setup_var[0] = setup_var[0] >= 3 ? 1 : ++setup_var[0];
-						}
-						break;
-
-					case IN_HOLD_DOWN_BUTTON:
-						if(menu_status == VIEW){
-							load_menu_variables(IN_LAG);
-
-						}else{ // UPDATE
-							setup_var[0] = setup_var[0] >= 2 ? 1 : ++setup_var[0];
-						}
-						break;
-
-					case IN_LAG:
-						if(menu_status == VIEW){
-							load_menu_variables(IN_DOSING);
-
-						}else{ // UPDATE
-							if(menu_cursor_var == POSITION_ONE)
-								setup_var[0] = setup_var[0] <= 0 ? 60 : --setup_var[0]; // Minutos
-
-							else if(menu_cursor_var == POSITION_TWO)
-								setup_var[1] = setup_var[1] <= 0 ? 59 : --setup_var[1]; // Segundo
-
-							else if(menu_cursor_var == POSITION_THREE)
-								setup_var[2] = setup_var[2] <= 0 ? 9 : --setup_var[2]; // Decimas de segundo
-						}
-						break;
-
-					case IN_DOSING:
-						if(menu_status == VIEW){
-							load_menu_variables(IN_FACTORY_RESET);
-
-						}else{ // UPDATE
-							if(menu_cursor_var == POSITION_ONE)
-								setup_var[0] = setup_var[0] <= 0 ? 60 : --setup_var[0]; // Minutos
-
-							else if(menu_cursor_var == POSITION_TWO)
-								setup_var[1] = setup_var[1] <= 0 ? 59 : --setup_var[1]; // Segundo
-
-							else if(menu_cursor_var == POSITION_THREE)
-								setup_var[2] = setup_var[2] <= 0 ? 9 : --setup_var[2]; // Decimas de segundo
-						}
-						break;
-
-					case IN_FACTORY_RESET:
-						if(menu_status == VIEW){
-							load_menu_variables(IN_RESTART);
-
-						}else{ // UPDATE
-							setup_var[0] = setup_var[0] <= 0 ? 1 : --setup_var[0];
-						}
-						break;
-
-					case IN_RESTART:
-						if(menu_status == VIEW){
-							load_menu_variables(IN_EXIT);
-
-						}else{ // UPDATE
-							setup_var[0] = setup_var[0] <= 0 ? 1 : --setup_var[0];
-						}
-						break;
-
-					case IN_EXIT:
-						load_menu_variables(IN_SENSITIVITY_BUTTON);
-						break;
-				}
-				break;
-		}
-
-		refresh_lcd_menu = true;
-		last_change_menu_millis = millis();
-
-		serialPrint("button_value: ");
-		serialPrintln(button_value);
-
-		serialPrint("menu_section: ");
-		serialPrint(menu_section);
-		serialPrint(", menu_status: ");
-		serialPrint(menu_status);
-		serialPrint(", menu_cursor_var: ");
-		serialPrint(menu_cursor_var);
-		serialPrint(", setup_var[0]: ");
-		serialPrint(setup_var[0]);
-		serialPrint(", setup_var[1]: ");
-		serialPrint(setup_var[1]);
-		serialPrint(", setup_var[2]: ");
-		serialPrintln(setup_var[2]);
-	}
-
-	void save_setting(uint8_t _setting)
-	{
-		menu_status     = VIEW;
-		menu_cursor_var = POSITION_ONE;
-
-		switch(_setting){
-			case IN_SENSITIVITY_BUTTON:
-				EEPROM.write(BUTTON_SENSITIVITY_EEPROM_ADDRESS, setup_var[0]);
-
-				load_setting(IN_SENSITIVITY_BUTTON);
-
-				serialPrintln("Save button_sensitivity_millis");
-				break;
-
-			case IN_PRESS_BUTTON:
-				EEPROM.write(PRESS_BUTTON_EEPROM_ADDRESS, setup_var[0]);
-
-				load_setting(IN_PRESS_BUTTON);
-
-				serialPrintln("Save press_button_mode");
-				break;
-
-			case IN_HOLD_DOWN_BUTTON:
-				EEPROM.write(HOLD_DOWN_BUTTON_EEPROM_ADDRESS, setup_var[0]);
-
-				load_setting(IN_HOLD_DOWN_BUTTON);
-
-				serialPrintln("Save hold_down_button_mode");
-				break;
-
-			case IN_LAG:
-				EEPROM.write(LAG_TIME_MIN_EEPROM_ADDRESS, setup_var[0]);
-				EEPROM.write(LAG_TIME_SEG_EEPROM_ADDRESS, setup_var[1]);
-				EEPROM.write(LAG_TIME_DEC_EEPROM_ADDRESS, setup_var[2]);
-
-				load_setting(IN_LAG);
-
-				serialPrintln("Save lag_time");
-				break;
-
-			case IN_DOSING:
-				EEPROM.write(DOSING_TIME_MIN_EEPROM_ADDRESS, setup_var[0]);
-				EEPROM.write(DOSING_TIME_SEG_EEPROM_ADDRESS, setup_var[1]);
-				EEPROM.write(DOSING_TIME_DEC_EEPROM_ADDRESS, setup_var[2]);
-
-				load_setting(IN_DOSING);
-
-				serialPrintln("Save dosing_time");
-				break;
-
-			case IN_FACTORY_RESET:
-				if(setup_var[0]){
-					EEPROM.write(BUTTON_SENSITIVITY_EEPROM_ADDRESS, BUTTON_SENSITIVITY_DEFAULT_VALUE);
-					EEPROM.write(PRESS_BUTTON_EEPROM_ADDRESS, PRESS_BUTTON_DEFAULT_VALUE);
-					EEPROM.write(HOLD_DOWN_BUTTON_EEPROM_ADDRESS, HOLD_DOWN_BUTTON_DEFAULT_VALUE);
-					EEPROM.write(LAG_TIME_MIN_EEPROM_ADDRESS, LAG_TIME_MIN_DEFAULT_VALUE);
-					EEPROM.write(LAG_TIME_SEG_EEPROM_ADDRESS, LAG_TIME_SEG_DEFAULT_VALUE);
-					EEPROM.write(LAG_TIME_DEC_EEPROM_ADDRESS, LAG_TIME_DEC_DEFAULT_VALUE);
-					EEPROM.write(DOSING_TIME_MIN_EEPROM_ADDRESS, DOSING_TIME_MIN_DEFAULT_VALUE);
-					EEPROM.write(DOSING_TIME_SEG_EEPROM_ADDRESS, DOSING_TIME_SEG_DEFAULT_VALUE);
-					EEPROM.write(DOSING_TIME_DEC_EEPROM_ADDRESS, DOSING_TIME_DEC_DEFAULT_VALUE);
-
-					load_setting(ALL_SETTINGS);
-					load_menu_variables(OUT_OF_MENU);
-
-					serialPrintln("Restore factory settings");
-				}
-				break;
-
-			case IN_RESTART:
-				if(setup_var[0]){
-					dispenser_status 			 = DISPENSER_DOSING;
-					dispenser_status_time_millis = 0;
-
-					load_menu_variables(OUT_OF_MENU);
-
-					serialPrintln("Restart");
-				}
-				break;
-		}
-	}
-
-	void load_setting(uint8_t _setting)
-	{
-		switch(_setting){
-			case ALL_SETTINGS:
-				load_setting(IN_SENSITIVITY_BUTTON);
-				load_setting(IN_PRESS_BUTTON);
-				load_setting(IN_HOLD_DOWN_BUTTON);
-				load_setting(IN_LAG);
-				load_setting(IN_DOSING);
-				break;
-
-			case IN_SENSITIVITY_BUTTON:
-				button_sensitivity_millis = 1100 - (EEPROM.read(BUTTON_SENSITIVITY_EEPROM_ADDRESS) * 110);
-
-				serialPrint("button_sensitivity_millis: ");
-				serialPrintln(button_sensitivity_millis);
-				break;
-
-			case IN_PRESS_BUTTON:
-				press_button_mode = EEPROM.read(PRESS_BUTTON_EEPROM_ADDRESS);
-
-				serialPrint("press_button_mode: ");
-				serialPrintln(press_button_mode);
-				break;
-
-			case IN_HOLD_DOWN_BUTTON:
-				hold_down_button_mode = EEPROM.read(HOLD_DOWN_BUTTON_EEPROM_ADDRESS);
-
-				serialPrint("hold_down_button_mode: ");
-				serialPrintln(hold_down_button_mode);
-				break;
-
-			case IN_LAG:
-				lag_time_decseg = (EEPROM.read(LAG_TIME_SEG_EEPROM_ADDRESS) * 10) + EEPROM.read(LAG_TIME_DEC_EEPROM_ADDRESS);
-
-				serialPrint("lag_time_decseg: ");
-				serialPrintln(lag_time_decseg);
-				break;
-
-			case IN_DOSING:
-				dosing_time_decseg = (EEPROM.read(DOSING_TIME_MIN_EEPROM_ADDRESS) * 600) + (EEPROM.read(DOSING_TIME_SEG_EEPROM_ADDRESS) * 10) + EEPROM.read(DOSING_TIME_DEC_EEPROM_ADDRESS);
-
-				serialPrint("dosing_time_decseg: ");
-				serialPrintln(dosing_time_decseg);
-				break;
-		}
-	}
-
-	void load_menu_variables(uint8_t _menu_section)
-	{
-		menu_section 	= _menu_section;
-		menu_status     = VIEW;
-		menu_cursor_var = POSITION_ONE;
-
-		switch(_menu_section){
-			case OUT_OF_MENU:
-			case IN_FACTORY_RESET:
-			case IN_RESTART:
-				setup_var[0] = 0;
-				setup_var[1] = 0;
-				setup_var[2] = 0;
-				break;
-
-			case IN_SENSITIVITY_BUTTON:
-				setup_var[0] = EEPROM.read(BUTTON_SENSITIVITY_EEPROM_ADDRESS);
-				break;
-
-			case IN_PRESS_BUTTON:
-				setup_var[0] = EEPROM.read(PRESS_BUTTON_EEPROM_ADDRESS);
-				break;
-
-			case IN_HOLD_DOWN_BUTTON:
-				setup_var[0] = EEPROM.read(HOLD_DOWN_BUTTON_EEPROM_ADDRESS);
-				break;
-
-			case IN_LAG:
-				setup_var[0] = EEPROM.read(LAG_TIME_MIN_EEPROM_ADDRESS); // Minutos
-				setup_var[1] = EEPROM.read(LAG_TIME_SEG_EEPROM_ADDRESS); // Segundos
-				setup_var[2] = EEPROM.read(LAG_TIME_DEC_EEPROM_ADDRESS); // Decimas de segundo
-				break;
-
-			case IN_DOSING:
-				setup_var[0] = EEPROM.read(DOSING_TIME_MIN_EEPROM_ADDRESS); // Minutos
-				setup_var[1] = EEPROM.read(DOSING_TIME_SEG_EEPROM_ADDRESS); // Segundos
-				setup_var[2] = EEPROM.read(DOSING_TIME_DEC_EEPROM_ADDRESS); // Decimas de segundo
-				break;
-		}
-	}
-
-
-/**************************************************
-* LCD2004 rendering
-**************************************************/
-	// Helpers
-	String fill_string_ws(String _text_info, uint8_t _length, uint8_t _first_spaces = 0, String _char = " ")
-	{
-		if(_text_info.length() >= _length)
-			return _text_info.substring(0, _length);
-
-		for(uint8_t i = 0; _first_spaces > i; i++)
-			if(_text_info.length() < _length)
-				_text_info = _char + _text_info;
-
-		while(_text_info.length() < _length)
-			_text_info = _text_info + _char;
-	
-		return _text_info;
-	}
-
-	String min_seg_dec_to_string(uint8_t _min, uint8_t _seg, uint8_t _dec)
-	{
-		String min = String(_min < 10? "0": "") + String(_min);
-		String seg = String(_seg < 10? "0": "") + String(_seg);
-
-		return min  + ":" + seg  + "." + String(_dec);
-	}
-
-	String process_time()
-	{
-		String process_time_string = "0";
-
-		if(dispenser_status_time_millis - millis()){
-			uint32_t min = (dispenser_status_time_millis - millis()) / 60000;
-			uint16_t seg = ((dispenser_status_time_millis - millis()) - (min * 60000)) / 1000;
-			uint8_t dec = ((dispenser_status_time_millis - millis()) - (min * 60000) - (seg * 1000)) / 100;
-
-			String _min = min >= 1? String(min) + ":": "";
-			String _seg = (min >= 1 && seg <= 9? "0": "") + String(seg);
-
-			process_time_string = _min + _seg + "." + String(dec);
-		}
-
-		serialPrintln(process_time_string);
-
-		return process_time_string;
-	}
-
-
-	// Methods
-	void loop_screen_rendering()
-	{
-		if(refresh_lcd_menu){
-			print_lcd_menu();
-
-			refresh_lcd_menu = false;
-		}
-
-		if(millis() % LCD_PROCESS_REFRESH_MILLIS == 0){
-			print_lcd_process();
-			setCursor_lcd_menu();
-		}
-	}
-
-	void print_lcd_menu()
-	{
-		lcd.noCursor();
-
-	    // Menú de configuraciones
-	    lcd.setCursor(0, 0);
-
-	    menu_section == OUT_OF_MENU?
-			lcd.print(fill_string_ws("", 20)):
-			lcd.print(fill_string_ws(menu[menu_section -1], 20));
-
-		// Detalles de configuraciones
-		lcd.setCursor(0, 1);
-
-		switch(menu_section){
-			case OUT_OF_MENU:
-				lcd.print(fill_string_ws("", 20));
-				break;
-
-			case IN_SENSITIVITY_BUTTON:
-				lcd.print(fill_string_ws(fill_string_ws(String(setup_var[0]), 2, 1, "0"), 20, 3));
-				break;
-
-			case IN_PRESS_BUTTON:
-			case IN_HOLD_DOWN_BUTTON:
-				switch(setup_var[0]){
-					case 1:
-						lcd.print(fill_string_ws(text_info[MODE_1], 20, 3));
-						break;
-
-					case 2:
-						lcd.print(fill_string_ws(text_info[MODE_2], 20, 3));
-						break;
-
-					case 3:
-						lcd.print(fill_string_ws(text_info[MODE_3], 20, 3));
-						break;
-				}
-				break;
-
-			case IN_LAG:
-			case IN_DOSING:
-				lcd.print(fill_string_ws(min_seg_dec_to_string(setup_var[0], setup_var[1], setup_var[2]), 20, 3));
-				break;
-
-			case IN_FACTORY_RESET:
-				if(menu_status == UPDATE){
-					setup_var[0]?
-						lcd.print(fill_string_ws(text_info[FACTORY_RESET], 20, 3)):
-						lcd.print(fill_string_ws(text_info[CANCEL], 20, 3));
-
-				}else
-					lcd.print(fill_string_ws("", 20));
-				break;
-
-			case IN_RESTART:
-				if(menu_status == UPDATE){
-					setup_var[0]?
-						lcd.print(fill_string_ws(text_info[RESTART], 20, 3)):
-						lcd.print(fill_string_ws(text_info[CANCEL], 20, 3));
-
-				}else
-					lcd.print(fill_string_ws("", 20));
-				break;
-		}
-
-		// Limpiamos línea de proceso
-		if(menu_status == UPDATE){
-			lcd.setCursor(0, 2);
-			lcd.print(fill_string_ws("", 20));
-
-			lcd.setCursor(0, 3);
-			lcd.print(fill_string_ws("", 20));
-		}
-	}
-
-	void print_lcd_process()
-	{
-		if(menu_section == OUT_OF_MENU || menu_status == VIEW){
-			lcd.setCursor(0, 2);
-
-			lcd.print(status[dispenser_status]);
-
-			switch(dispenser_status){
-				case DISPENSER_IDLE:
-					if(millis() >= blink_millis)
-						blink_millis = millis() + (BLINK_MILLIS * 2);
-					
-					lcd.print(fill_string_ws(blink_millis - millis() >= BLINK_MILLIS? "": "***", 11, 2));
-					break;
-
-				case DISPENSER_LAG:
-					lcd.print(fill_string_ws(process_time(), 8, 2));
-					break;
-
-				case DISPENSER_DOSING:
-					lcd.print(fill_string_ws(process_time(), 8, 1));
-					break;
-
-				case DISPENSER_BLOCK:
-					//lcd.print(fill_string_ws(process_time(), 8, 1));
-					break;
-			}
-		}
-	}
-
-	void setCursor_lcd_menu()
-	{
-		if(menu_status == UPDATE){
-			switch(menu_section){
-				case OUT_OF_MENU:
-					break;
-
-				case IN_LAG:
-				case IN_DOSING:
-					// Posicionamos el cursos, para la edición
-					if(menu_cursor_var == POSITION_ONE)
-						lcd.setCursor(3,1);
-
-					else if(menu_cursor_var == POSITION_TWO)
-						lcd.setCursor(6,1);
-
-					else if(menu_cursor_var == POSITION_THREE)
-						lcd.setCursor(9,1);
-					break;
-
-				case IN_SENSITIVITY_BUTTON:
-				case IN_PRESS_BUTTON:
-				case IN_HOLD_DOWN_BUTTON:
-				case IN_FACTORY_RESET:
-				case IN_RESTART:
-					lcd.setCursor(3,1);
-					break;
-			}
-
-			lcd.cursor();
-		}
-	}
-
-
-/**************************************************
-* DOSAGE PROCESS
-**************************************************/
-	void loop_dosage_process()
-	{
-		if(digitalRead(DOSING_BUTTON_PIN) == DOSING_BUTTON_PUSH){
-			if(button_pressed_millis == 0)
-				button_pressed_millis = millis();
-
-				// Se supero el button_sensitivity_millis
-				if (millis() >= (button_pressed_millis + button_sensitivity_millis))
-					start_dosing_process();
-
-		}else{
-
-			release_button = 0;
-			button_pressed_millis = 0;
-		}
-
-		continue_dosing_process();
-	}
-
-	void start_dosing_process()
-	{
-
-
-
-		if(press_button_mode == 3 &&
-			dispenser_status != DISPENSER_IDLE &&
-			dispenser_status_time_millis >= button_pressed_millis &&
-			release_button == 0){
-
-			dispenser_status 			 = DISPENSER_DOSING;
-			dispenser_status_time_millis = 0;
-
-			serialPrint("Proceso detenido");
-			serialPrintln(millis());
-
-
-		}else if((press_button_mode == 1 || press_button_mode == 3) && dispenser_status == DISPENSER_IDLE){
-			dispenser_status 			 = DISPENSER_LAG;
-			dispenser_status_time_millis = millis() + ((uint32_t) lag_time_decseg * 100);
-
-			release_button = 1;
-
-			serialPrint("Iniciando proceso ");
-			serialPrintln(millis());
-
-		}else if(press_button_mode == 2){
-			dispenser_status = DISPENSER_RESTART;
-
-			release_button = 1;
-		}
-	}
-
-	void continue_dosing_process()
-	{
-		switch(dispenser_status){
-			case DISPENSER_RESTART:
-				digitalWrite(RELAY_PIN, RELAY_LOW);
-
-				dispenser_status 			 = DISPENSER_LAG;
-				dispenser_status_time_millis = millis() + ((uint32_t) lag_time_decseg * 100);
-				break;
-
-			case DISPENSER_LAG:
-				if(millis() >= dispenser_status_time_millis){
-					dispenser_status 			 = DISPENSER_DOSING;
-					dispenser_status_time_millis = millis() + ((uint32_t) dosing_time_decseg * 100);
-
-					digitalWrite(RELAY_PIN, RELAY_HIGH);
-				}
-				break;
-
-			case DISPENSER_DOSING:
-				if(millis() >= dispenser_status_time_millis){
-					dispenser_status 			 = button_pressed_millis == 0? DISPENSER_IDLE: DISPENSER_BLOCK;
-					dispenser_status_time_millis = 0;
-
-					digitalWrite(RELAY_PIN, RELAY_LOW);
-				}
-				break;
-
-			case DISPENSER_BLOCK:
-				if(button_pressed_millis == 0)
-					dispenser_status = DISPENSER_IDLE;
-				break;
-		}
-	}
-
-
-/**************************************************
-* Setup & Loops
-**************************************************/
-	void setup()
-	{
-		pinMode(RELAY_PIN, OUTPUT);
-		pinMode(DOSING_BUTTON_PIN, INPUT_PULLUP);
-		pinMode(SETTINGS_BUTTONS_PIN, INPUT_PULLUP);
-
-		// Salida Serial
-		serialBegin(9600);
-		serialBeginWhile();
-
-		// Cargamos configuraciones de la EEPROM a la ram
-		load_setting(ALL_SETTINGS);
-
-		//Iniciamos la pantalla
-		lcd.begin(20, 4);
-	}
-
-	void loop()
-	{
-		loop_settings_panel_buttons();
-		loop_dosage_process();
-		loop_screen_rendering();
-	}
+/*****************************************
+*   Dosificador_LCD2004_4buttons         *
+*   15/03/2021                           *
+*   Versión 0.1.0                        *
+*   koneko.mx                            *
+*****************************************/
+
+#include <EEPROM.h>
+#include <LiquidCrystal_I2C.h>
+
+/**************************************************
+* Definición de Constantes
+**************************************************/
+	// LCD2004 I2C
+	#define LCD_I2C_ADDRESS 0x27
+
+	// PINOUT
+	#define RELAY_PIN			  4
+	#define DOSING_BUTTON_PIN	  3
+	#define SETTINGS_BUTTONS_PIN A2
+
+	// BUTTON SETTINGS
+	#define SETTING_BUTTON_IN_VAL   15
+	#define SETTING_BUTTON_OUT_VAL  92
+	#define SETTING_BUTTON_UP_VAL   42
+	#define SETTING_BUTTON_DOWN_VAL 67
+
+	#define SETTING_BUTTON_TOLERANCE_READ				 2
+	#define SETTING_BUTTON_CONFIRMATION_REPEATS_MILLIS	80
+	#define SETTING_BUTTON_DELAY_MILLIS				   450
+
+	// BLOQUES DE MEMORIA EEPROM 
+	#define BUTTON_SENSITIVITY_EEPROM_ADDRESS 0
+	#define PRESS_BUTTON_EEPROM_ADDRESS		  1
+	#define HOLD_DOWN_BUTTON_EEPROM_ADDRESS	  2
+	#define LAG_TIME_MIN_EEPROM_ADDRESS		  3 // Minutos, tiempo de retraso
+	#define LAG_TIME_SEG_EEPROM_ADDRESS		  4 // Segundo, tiempo de retraso
+	#define LAG_TIME_DEC_EEPROM_ADDRESS		  5 // Décimas de segundo, tiempo de retraso
+	#define DOSING_TIME_MIN_EEPROM_ADDRESS	  6 // Minutos, tiempo dosificación
+	#define DOSING_TIME_SEG_EEPROM_ADDRESS	  7 // Segundos, tiempo dosificación
+	#define DOSING_TIME_DEC_EEPROM_ADDRESS	  8 // Décimas de segundo, tiempo dosificación
+
+	// FACTORY SETTINGS
+	#define BUTTON_SENSITIVITY_DEFAULT_VALUE  9
+	#define PRESS_BUTTON_DEFAULT_VALUE		  3
+	#define HOLD_DOWN_BUTTON_DEFAULT_VALUE	  1
+	#define LAG_TIME_MIN_DEFAULT_VALUE		  0 // Minutos, tiempo de retraso
+	#define LAG_TIME_SEG_DEFAULT_VALUE		  3 // Segundo, tiempo de retraso
+	#define LAG_TIME_DEC_DEFAULT_VALUE		  5 // Décimas de segundo, tiempo de retraso
+	#define DOSING_TIME_MIN_DEFAULT_VALUE	  1 // Minutos, tiempo dosificación
+	#define DOSING_TIME_SEG_DEFAULT_VALUE	 10 // Segundos, tiempo dosificación
+	#define DOSING_TIME_DEC_DEFAULT_VALUE	  9 // Décimas de segundo, tiempo dosificación
+
+	// SETTINGS MENU
+	#define ALL_SETTINGS 0
+	#define OUT_OF_MENU  0
+
+	#define IN_SENSITIVITY_BUTTON 1
+	#define IN_PRESS_BUTTON 	  2
+	#define IN_HOLD_DOWN_BUTTON	  3
+	#define IN_LAG 				  4
+	#define IN_DOSING 			  5
+	#define IN_FACTORY_RESET 	  6
+	#define IN_RESTART 			  7
+	#define IN_EXIT 			  8
+
+	#define VIEW   0
+	#define UPDATE 1
+
+	#define POSITION_ONE   0
+	#define POSITION_TWO   1
+	#define POSITION_THREE 2
+
+	#define MODE_1		  0
+	#define MODE_2		  1
+	#define MODE_3		  2
+	#define FACTORY_RESET 3
+	#define RESTART		  4
+	#define CANCEL		  5
+
+	#define AUTO_EXIT_MENU_MILLIS	   15000
+	#define BLINK_MILLIS				1600
+	#define LCD_PROCESS_REFRESH_MILLIS   333
+
+	// DISPENSER
+	#define DISPENSER_RESTART	10
+	#define DISPENSER_IDLE		 0
+	#define DISPENSER_DETECTING  1
+	#define DISPENSER_LAG		 2
+	#define DISPENSER_DOSING	 3
+	#define DISPENSER_BLOCK		 4
+
+	// STATUS RELAY
+	#define RELAY_HIGH HIGH
+	#define RELAY_LOW  LOW
+
+	// STATUS BUTTON
+	#define DOSING_BUTTON_PUSH 0
+	#define DOSING_BUTTON_IDLE 1
+
+
+/**************************************************
+* Debug
+* Define DEBUG_SERIAL_ENABLE to enable debug serial.
+* Comment it to disable debug serial.
+**************************************************/
+	//#define DEBUG_SERIAL_ENABLE
+
+	#define dbSerial Serial
+
+	#ifdef DEBUG_SERIAL_ENABLE
+		#define serialPrint(a)		dbSerial.print(a)
+		#define serialPrintln(a)	dbSerial.println(a)
+		#define serialBegin(a)		dbSerial.begin(a)
+		#define serialBeginWhile(a) while(!dbSerial) delay(1)
+	#else
+		#define serialPrint(a)		do{}while(0)
+		#define serialPrintln(a)	do{}while(0)
+		#define serialBegin(a)		do{}while(0)
+		#define serialBeginWhile(a)	do{}while(0)
+	#endif
+
+
+/**************************************************
+* ENVIRONMENT VARIABLES
+**************************************************/
+	// Dosing
+	uint16_t button_sensitivity_millis;
+	uint8_t  press_button_mode;
+	uint8_t  hold_down_button_mode;
+	uint16_t lag_time_decseg;
+	uint16_t dosing_time_decseg;
+
+    uint32_t button_pressed_millis;
+    uint8_t  release_button;
+
+	uint8_t  dispenser_status;
+	uint32_t dispenser_status_time_millis;
+
+	// 4-button configuration 
+	uint8_t  button_values[] = {SETTING_BUTTON_IN_VAL, SETTING_BUTTON_OUT_VAL, SETTING_BUTTON_UP_VAL, SETTING_BUTTON_DOWN_VAL};
+	uint32_t _bt[sizeof(button_values)]; // millis
+	uint32_t confirmation_repeats_millis;
+
+	uint8_t menu_section;
+	uint8_t menu_status;
+	uint8_t menu_cursor_var;
+
+	uint8_t setup_var[3];
+
+	uint32_t last_change_menu_millis;
+
+
+	// LCD2004 Render
+	LiquidCrystal_I2C lcd(LCD_I2C_ADDRESS, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
+
+	String menu[] = {
+		"SENSIBILIDAD BOTON",
+		"AL PRESIONAR BOTON",
+		"AL MANTENER PRESIO",
+		"RETARDO AL INICIAR",
+		"TIEMPO DOSIFICACION",
+		"VALORES DE FABRICA",
+		"REINICIAR",
+		"SALIR",
+	};
+
+	String status[] = {
+		"EN ESPERA",
+		"DETECTANDO",
+		"DOSIFICARA",
+		"DOSIFICANDO",
+		"BLOQUEADO",
+	};
+
+	String text_info[] = {
+		"MODO 1",
+		"MODO 2",
+		"MODO 3",
+		"RESTAURAR",
+		"REINICAR",
+		"CANCELAR",
+	};
+
+	boolean  refresh_lcd_menu;
+	uint32_t blink_millis;
+
+
+/**************************************************
+* FRONT PANEL OF CONFIGURATIONS
+**************************************************/
+	// button methods and memory spaces
+	void loop_settings_panel_buttons()
+	{
+		// Leemos valor analogo del botón
+		uint8_t button_value = analogRead(SETTINGS_BUTTONS_PIN);
+
+		// Comprobamos el valor obtenido con un rago de tolerancia SETTING_BUTTON_TOLERANCE_READ
+		for (uint8_t i = 0; i < sizeof button_values / sizeof button_values[0]; i++) {
+			if(button_values[i] >= (button_value - SETTING_BUTTON_TOLERANCE_READ) && button_values[i] <= (button_value + SETTING_BUTTON_TOLERANCE_READ))
+				button_value = button_values[i];
+		}
+
+		//Valoramos si se presiono un botón y ejecutamos el metodo correspondiente
+		switch(button_value) {
+			case SETTING_BUTTON_IN_VAL:
+				if(millis() >= _bt[0] + SETTING_BUTTON_DELAY_MILLIS) {
+					if(confirmation_repeats_millis == 0)
+						confirmation_repeats_millis = millis() + SETTING_BUTTON_CONFIRMATION_REPEATS_MILLIS;
+
+					if(millis() > confirmation_repeats_millis){
+						action_button(SETTING_BUTTON_IN_VAL);
+
+						_bt[0] = millis();
+					}
+				}
+				break;
+
+			case SETTING_BUTTON_OUT_VAL:
+				if(millis() >= _bt[1] + SETTING_BUTTON_DELAY_MILLIS) {
+					if(confirmation_repeats_millis == 0)
+						confirmation_repeats_millis = millis() + SETTING_BUTTON_CONFIRMATION_REPEATS_MILLIS;
+
+					if(millis() > confirmation_repeats_millis){
+						action_button(SETTING_BUTTON_OUT_VAL);
+
+						_bt[1] = millis();
+					}
+				}
+				break;
+
+			case SETTING_BUTTON_UP_VAL:
+				if(millis() >= _bt[2] + SETTING_BUTTON_DELAY_MILLIS) {
+					if(confirmation_repeats_millis == 0)
+						confirmation_repeats_millis = millis() + SETTING_BUTTON_CONFIRMATION_REPEATS_MILLIS;
+
+					if(millis() > confirmation_repeats_millis){
+						action_button(SETTING_BUTTON_UP_VAL);
+
+						_bt[2] = millis();
+					}
+				}
+				break;
+
+			case SETTING_BUTTON_DOWN_VAL:
+				if(millis() >= _bt[3] + SETTING_BUTTON_DELAY_MILLIS) {
+					if(confirmation_repeats_millis == 0)
+						confirmation_repeats_millis = millis() + SETTING_BUTTON_CONFIRMATION_REPEATS_MILLIS;
+
+					if(millis() > confirmation_repeats_millis){
+						action_button(SETTING_BUTTON_DOWN_VAL);
+
+						_bt[3] = millis();
+					}
+				}
+				break;
+
+			default:
+				confirmation_repeats_millis = 0;
+		}
+
+		// Verificamos y salimos del menú si a pasan AUTO_EXIT_MENU_MILLIS
+		if((menu_section != OUT_OF_MENU) && (millis() >= last_change_menu_millis + AUTO_EXIT_MENU_MILLIS)){
+			load_menu_variables(OUT_OF_MENU);
+
+			refresh_lcd_menu = true;
+
+			serialPrintln("AUTO_EXIT_MENU_MILLIS");
+		}
+	}
+
+	void action_button(uint8_t button_value)
+	{
+		switch(button_value) {
+			case SETTING_BUTTON_IN_VAL:
+				switch(menu_section) {
+					case OUT_OF_MENU:
+						load_menu_variables(IN_SENSITIVITY_BUTTON);
+						break;
+
+					case IN_SENSITIVITY_BUTTON:
+						if(menu_status == VIEW)
+							menu_status = UPDATE;
+
+						else if(++menu_cursor_var > POSITION_ONE)
+							save_setting(IN_SENSITIVITY_BUTTON);
+						break;
+
+					case IN_PRESS_BUTTON:
+						if(menu_status == VIEW)
+							menu_status = UPDATE;
+
+						else if(++menu_cursor_var > POSITION_ONE)
+							save_setting(IN_PRESS_BUTTON);
+						break;
+
+					case IN_HOLD_DOWN_BUTTON:
+						if(menu_status == VIEW)
+							menu_status = UPDATE;
+
+						else if(++menu_cursor_var > POSITION_ONE)
+							save_setting(IN_HOLD_DOWN_BUTTON);
+						break;
+
+					case IN_LAG:
+						if(menu_status == VIEW)
+							menu_status = UPDATE;
+
+						else if(++menu_cursor_var > POSITION_THREE)
+							save_setting(IN_LAG);
+						break;
+
+					case IN_DOSING:
+						if(menu_status == VIEW)
+							menu_status = UPDATE;
+
+						else if(++menu_cursor_var > POSITION_THREE)
+							save_setting(IN_DOSING);
+						break;
+
+					case IN_FACTORY_RESET:
+						if(menu_status == VIEW)
+							menu_status = UPDATE;
+
+						else if(++menu_cursor_var > POSITION_ONE)
+							save_setting(IN_FACTORY_RESET);
+						break;
+
+					case IN_RESTART:
+						if(menu_status == VIEW)
+							menu_status = UPDATE;
+
+						else if(++menu_cursor_var > POSITION_ONE)
+							save_setting(IN_RESTART);
+						break;
+
+					case IN_EXIT:
+						load_menu_variables(OUT_OF_MENU);
+						break;
+				}
+				break;
+
+			case SETTING_BUTTON_OUT_VAL:
+				switch(menu_status){
+					case VIEW:
+						load_menu_variables(OUT_OF_MENU);
+						break;
+
+					case UPDATE:
+						if(menu_cursor_var == 0)
+							load_menu_variables(menu_section);
+						else
+							menu_cursor_var--;
+				}
+				break;
+
+			case SETTING_BUTTON_UP_VAL:
+				switch(menu_section) {
+					case OUT_OF_MENU:
+						load_menu_variables(IN_RESTART);
+						break;
+
+					case IN_SENSITIVITY_BUTTON:
+						if(menu_status == VIEW){
+							load_menu_variables(IN_EXIT);
+
+						}else{ // UPDATE
+							setup_var[0] = setup_var[0] >= 10 ? 1 : ++setup_var[0];
+						}
+						break;
+
+					case IN_PRESS_BUTTON:
+						if(menu_status == VIEW){
+							load_menu_variables(IN_SENSITIVITY_BUTTON);
+
+						}else{ // UPDATE
+							setup_var[0] = setup_var[0] <= 1 ? 3 : --setup_var[0];
+						}
+						break;
+
+					case IN_HOLD_DOWN_BUTTON:
+						if(menu_status == VIEW){
+							load_menu_variables(IN_PRESS_BUTTON);
+
+						}else{ // UPDATE
+							setup_var[0] = setup_var[0] <= 1 ? 2 : --setup_var[0];
+						}
+						break;
+
+					case IN_LAG:
+						if(menu_status == VIEW){
+							load_menu_variables(IN_PRESS_BUTTON);
+
+						}else{ // UPDATE
+							if(menu_cursor_var == POSITION_ONE)
+								setup_var[0] = setup_var[0] >= 60 ? 0 : ++setup_var[0]; // Minutos
+
+							else if(menu_cursor_var == POSITION_TWO)
+								setup_var[1] = setup_var[1] >= 59 ? 0 : ++setup_var[1]; // Segundo
+
+							else if(menu_cursor_var == POSITION_THREE)
+								setup_var[2] = setup_var[2] >= 9 ? 0 : ++setup_var[2]; // Decimas de segundo
+						}
+						break;
+
+					case IN_DOSING:
+						if(menu_status == VIEW){
+							load_menu_variables(IN_LAG);
+
+						}else{ // UPDATE
+							if(menu_cursor_var == POSITION_ONE)
+								setup_var[0] = setup_var[0] >= 60 ? 0 : ++setup_var[0]; // Minutos
+
+							else if(menu_cursor_var == POSITION_TWO)
+								setup_var[1] = setup_var[1] >= 59 ? 0 : ++setup_var[1]; // Segundo
+
+							else if(menu_cursor_var == POSITION_THREE)
+								setup_var[2] = setup_var[2] >= 9 ? 0 : ++setup_var[2]; // Decimas de segundo
+						}
+						break;
+
+					case IN_FACTORY_RESET:
+						if(menu_status == VIEW){
+							load_menu_variables(IN_DOSING);
+
+						}else{ // UPDATE
+							setup_var[0] = setup_var[0] >= 1 ? 0 : ++setup_var[0];
+						}
+						break;
+
+					case IN_RESTART:
+						if(menu_status == VIEW){
+							load_menu_variables(IN_FACTORY_RESET);
+
+						}else{ // UPDATE
+							setup_var[0] = setup_var[0] >= 1 ? 0 : ++setup_var[0];
+						}
+						break;
+
+					case IN_EXIT:
+						load_menu_variables(IN_FACTORY_RESET);
+						break;
+				}
+				break;
+
+			case SETTING_BUTTON_DOWN_VAL:
+				switch(menu_section) {
+					case OUT_OF_MENU:
+						load_menu_variables(IN_SENSITIVITY_BUTTON);
+						break;
+
+					case IN_SENSITIVITY_BUTTON:
+						if(menu_status == VIEW){
+							load_menu_variables(IN_PRESS_BUTTON);
+
+						}else{ // UPDATE
+							setup_var[0] = setup_var[0] <= 1 ? 10 : --setup_var[0];
+						}
+						break;
+
+					case IN_PRESS_BUTTON:
+						if(menu_status == VIEW){
+							load_menu_variables(IN_LAG);
+
+						}else{ // UPDATE
+							setup_var[0] = setup_var[0] >= 3 ? 1 : ++setup_var[0];
+						}
+						break;
+
+					case IN_HOLD_DOWN_BUTTON:
+						if(menu_status == VIEW){
+							load_menu_variables(IN_LAG);
+
+						}else{ // UPDATE
+							setup_var[0] = setup_var[0] >= 2 ? 1 : ++setup_var[0];
+						}
+						break;
+
+					case IN_LAG:
+						if(menu_status == VIEW){
+							load_menu_variables(IN_DOSING);
+
+						}else{ // UPDATE
+							if(menu_cursor_var == POSITION_ONE)
+								setup_var[0] = setup_var[0] <= 0 ? 60 : --setup_var[0]; // Minutos
+
+							else if(menu_cursor_var == POSITION_TWO)
+								setup_var[1] = setup_var[1] <= 0 ? 59 : --setup_var[1]; // Segundo
+
+							else if(menu_cursor_var == POSITION_THREE)
+								setup_var[2] = setup_var[2] <= 0 ? 9 : --setup_var[2]; // Decimas de segundo
+						}
+						break;
+
+					case IN_DOSING:
+						if(menu_status == VIEW){
+							load_menu_variables(IN_FACTORY_RESET);
+
+						}else{ // UPDATE
+							if(menu_cursor_var == POSITION_ONE)
+								setup_var[0] = setup_var[0] <= 0 ? 60 : --setup_var[0]; // Minutos
+
+							else if(menu_cursor_var == POSITION_TWO)
+								setup_var[1] = setup_var[1] <= 0 ? 59 : --setup_var[1]; // Segundo
+
+							else if(menu_cursor_var == POSITION_THREE)
+								setup_var[2] = setup_var[2] <= 0 ? 9 : --setup_var[2]; // Decimas de segundo
+						}
+						break;
+
+					case IN_FACTORY_RESET:
+						if(menu_status == VIEW){
+							load_menu_variables(IN_RESTART);
+
+						}else{ // UPDATE
+							setup_var[0] = setup_var[0] <= 0 ? 1 : --setup_var[0];
+						}
+						break;
+
+					case IN_RESTART:
+						if(menu_status == VIEW){
+							load_menu_variables(IN_EXIT);
+
+						}else{ // UPDATE
+							setup_var[0] = setup_var[0] <= 0 ? 1 : --setup_var[0];
+						}
+						break;
+
+					case IN_EXIT:
+						load_menu_variables(IN_SENSITIVITY_BUTTON);
+						break;
+				}
+				break;
+		}
+
+		refresh_lcd_menu = true;
+		last_change_menu_millis = millis();
+
+		serialPrint("button_value: ");
+		serialPrintln(button_value);
+
+		serialPrint("menu_section: ");
+		serialPrint(menu_section);
+		serialPrint(", menu_status: ");
+		serialPrint(menu_status);
+		serialPrint(", menu_cursor_var: ");
+		serialPrint(menu_cursor_var);
+		serialPrint(", setup_var[0]: ");
+		serialPrint(setup_var[0]);
+		serialPrint(", setup_var[1]: ");
+		serialPrint(setup_var[1]);
+		serialPrint(", setup_var[2]: ");
+		serialPrintln(setup_var[2]);
+	}
+
+	void save_setting(uint8_t _setting)
+	{
+		menu_status     = VIEW;
+		menu_cursor_var = POSITION_ONE;
+
+		switch(_setting){
+			case IN_SENSITIVITY_BUTTON:
+				EEPROM.write(BUTTON_SENSITIVITY_EEPROM_ADDRESS, setup_var[0]);
+
+				load_setting(IN_SENSITIVITY_BUTTON);
+
+				serialPrintln("Save button_sensitivity_millis");
+				break;
+
+			case IN_PRESS_BUTTON:
+				EEPROM.write(PRESS_BUTTON_EEPROM_ADDRESS, setup_var[0]);
+
+				load_setting(IN_PRESS_BUTTON);
+
+				serialPrintln("Save press_button_mode");
+				break;
+
+			case IN_HOLD_DOWN_BUTTON:
+				EEPROM.write(HOLD_DOWN_BUTTON_EEPROM_ADDRESS, setup_var[0]);
+
+				load_setting(IN_HOLD_DOWN_BUTTON);
+
+				serialPrintln("Save hold_down_button_mode");
+				break;
+
+			case IN_LAG:
+				EEPROM.write(LAG_TIME_MIN_EEPROM_ADDRESS, setup_var[0]);
+				EEPROM.write(LAG_TIME_SEG_EEPROM_ADDRESS, setup_var[1]);
+				EEPROM.write(LAG_TIME_DEC_EEPROM_ADDRESS, setup_var[2]);
+
+				load_setting(IN_LAG);
+
+				serialPrintln("Save lag_time");
+				break;
+
+			case IN_DOSING:
+				EEPROM.write(DOSING_TIME_MIN_EEPROM_ADDRESS, setup_var[0]);
+				EEPROM.write(DOSING_TIME_SEG_EEPROM_ADDRESS, setup_var[1]);
+				EEPROM.write(DOSING_TIME_DEC_EEPROM_ADDRESS, setup_var[2]);
+
+				load_setting(IN_DOSING);
+
+				serialPrintln("Save dosing_time");
+				break;
+
+			case IN_FACTORY_RESET:
+				if(setup_var[0]){
+					EEPROM.write(BUTTON_SENSITIVITY_EEPROM_ADDRESS, BUTTON_SENSITIVITY_DEFAULT_VALUE);
+					EEPROM.write(PRESS_BUTTON_EEPROM_ADDRESS, PRESS_BUTTON_DEFAULT_VALUE);
+					EEPROM.write(HOLD_DOWN_BUTTON_EEPROM_ADDRESS, HOLD_DOWN_BUTTON_DEFAULT_VALUE);
+					EEPROM.write(LAG_TIME_MIN_EEPROM_ADDRESS, LAG_TIME_MIN_DEFAULT_VALUE);
+					EEPROM.write(LAG_TIME_SEG_EEPROM_ADDRESS, LAG_TIME_SEG_DEFAULT_VALUE);
+					EEPROM.write(LAG_TIME_DEC_EEPROM_ADDRESS, LAG_TIME_DEC_DEFAULT_VALUE);
+					EEPROM.write(DOSING_TIME_MIN_EEPROM_ADDRESS, DOSING_TIME_MIN_DEFAULT_VALUE);
+					EEPROM.write(DOSING_TIME_SEG_EEPROM_ADDRESS, DOSING_TIME_SEG_DEFAULT_VALUE);
+					EEPROM.write(DOSING_TIME_DEC_EEPROM_ADDRESS, DOSING_TIME_DEC_DEFAULT_VALUE);
+
+					load_setting(ALL_SETTINGS);
+					load_menu_variables(OUT_OF_MENU);
+
+					serialPrintln("Restore factory settings");
+				}
+				break;
+
+			case IN_RESTART:
+				if(setup_var[0]){
+					dispenser_status 			 = DISPENSER_DOSING;
+					dispenser_status_time_millis = 0;
+
+					load_menu_variables(OUT_OF_MENU);
+
+					serialPrintln("Restart");
+				}
+				break;
+		}
+	}
+
+	void load_setting(uint8_t _setting)
+	{
+		switch(_setting){
+			case ALL_SETTINGS:
+				load_setting(IN_SENSITIVITY_BUTTON);
+				load_setting(IN_PRESS_BUTTON);
+				load_setting(IN_HOLD_DOWN_BUTTON);
+				load_setting(IN_LAG);
+				load_setting(IN_DOSING);
+				break;
+
+			case IN_SENSITIVITY_BUTTON:
+				button_sensitivity_millis = 1100 - (EEPROM.read(BUTTON_SENSITIVITY_EEPROM_ADDRESS) * 110);
+
+				serialPrint("button_sensitivity_millis: ");
+				serialPrintln(button_sensitivity_millis);
+				break;
+
+			case IN_PRESS_BUTTON:
+				press_button_mode = EEPROM.read(PRESS_BUTTON_EEPROM_ADDRESS);
+
+				serialPrint("press_button_mode: ");
+				serialPrintln(press_button_mode);
+				break;
+
+			case IN_HOLD_DOWN_BUTTON:
+				hold_down_button_mode = EEPROM.read(HOLD_DOWN_BUTTON_EEPROM_ADDRESS);
+
+				serialPrint("hold_down_button_mode: ");
+				serialPrintln(hold_down_button_mode);
+				break;
+
+			case IN_LAG:
+				lag_time_decseg = (EEPROM.read(LAG_TIME_SEG_EEPROM_ADDRESS) * 10) + EEPROM.read(LAG_TIME_DEC_EEPROM_ADDRESS);
+
+				serialPrint("lag_time_decseg: ");
+				serialPrintln(lag_time_decseg);
+				break;
+
+			case IN_DOSING:
+				dosing_time_decseg = (EEPROM.read(DOSING_TIME_MIN_EEPROM_ADDRESS) * 600) + (EEPROM.read(DOSING_TIME_SEG_EEPROM_ADDRESS) * 10) + EEPROM.read(DOSING_TIME_DEC_EEPROM_ADDRESS);
+
+				serialPrint("dosing_time_decseg: ");
+				serialPrintln(dosing_time_decseg);
+				break;
+		}
+	}
+
+	void load_menu_variables(uint8_t _menu_section)
+	{
+		menu_section 	= _menu_section;
+		menu_status     = VIEW;
+		menu_cursor_var = POSITION_ONE;
+
+		switch(_menu_section){
+			case OUT_OF_MENU:
+			case IN_FACTORY_RESET:
+			case IN_RESTART:
+				setup_var[0] = 0;
+				setup_var[1] = 0;
+				setup_var[2] = 0;
+				break;
+
+			case IN_SENSITIVITY_BUTTON:
+				setup_var[0] = EEPROM.read(BUTTON_SENSITIVITY_EEPROM_ADDRESS);
+				break;
+
+			case IN_PRESS_BUTTON:
+				setup_var[0] = EEPROM.read(PRESS_BUTTON_EEPROM_ADDRESS);
+				break;
+
+			case IN_HOLD_DOWN_BUTTON:
+				setup_var[0] = EEPROM.read(HOLD_DOWN_BUTTON_EEPROM_ADDRESS);
+				break;
+
+			case IN_LAG:
+				setup_var[0] = EEPROM.read(LAG_TIME_MIN_EEPROM_ADDRESS); // Minutos
+				setup_var[1] = EEPROM.read(LAG_TIME_SEG_EEPROM_ADDRESS); // Segundos
+				setup_var[2] = EEPROM.read(LAG_TIME_DEC_EEPROM_ADDRESS); // Decimas de segundo
+				break;
+
+			case IN_DOSING:
+				setup_var[0] = EEPROM.read(DOSING_TIME_MIN_EEPROM_ADDRESS); // Minutos
+				setup_var[1] = EEPROM.read(DOSING_TIME_SEG_EEPROM_ADDRESS); // Segundos
+				setup_var[2] = EEPROM.read(DOSING_TIME_DEC_EEPROM_ADDRESS); // Decimas de segundo
+				break;
+		}
+	}
+
+
+/**************************************************
+* LCD2004 rendering
+**************************************************/
+	// Helpers
+	String fill_string_ws(String _text_info, uint8_t _length, uint8_t _first_spaces = 0, String _char = " ")
+	{
+		if(_text_info.length() >= _length)
+			return _text_info.substring(0, _length);
+
+		for(uint8_t i = 0; _first_spaces > i; i++)
+			if(_text_info.length() < _length)
+				_text_info = _char + _text_info;
+
+		while(_text_info.length() < _length)
+			_text_info = _text_info + _char;
+	
+		return _text_info;
+	}
+
+	String min_seg_dec_to_string(uint8_t _min, uint8_t _seg, uint8_t _dec)
+	{
+		String min = String(_min < 10? "0": "") + String(_min);
+		String seg = String(_seg < 10? "0": "") + String(_seg);
+
+		return min  + ":" + seg  + "." + String(_dec);
+	}
+
+	String process_time()
+	{
+		String process_time_string = "0";
+
+		if(dispenser_status_time_millis - millis()){
+			uint32_t min = (dispenser_status_time_millis - millis()) / 60000;
+			uint16_t seg = ((dispenser_status_time_millis - millis()) - (min * 60000)) / 1000;
+			uint8_t dec = ((dispenser_status_time_millis - millis()) - (min * 60000) - (seg * 1000)) / 100;
+
+			String _min = min >= 1? String(min) + ":": "";
+			String _seg = (min >= 1 && seg <= 9? "0": "") + String(seg);
+
+			process_time_string = _min + _seg + "." + String(dec);
+		}
+
+		serialPrintln(process_time_string);
+
+		return process_time_string;
+	}
+
+
+	// Methods
+	void loop_screen_rendering()
+	{
+		if(refresh_lcd_menu){
+			print_lcd_menu();
+
+			refresh_lcd_menu = false;
+		}
+
+		if(millis() % LCD_PROCESS_REFRESH_MILLIS == 0){
+			print_lcd_process();
+			setCursor_lcd_menu();
+		}
+	}
+
+	void print_lcd_menu()
+	{
+		lcd.noCursor();
+
+	    // Menú de configuraciones
+	    lcd.setCursor(0, 0);
+
+	    menu_section == OUT_OF_MENU?
+			lcd.print(fill_string_ws("", 20)):
+			lcd.print(fill_string_ws(menu[menu_section -1], 20));
+
+		// Detalles de configuraciones
+		lcd.setCursor(0, 1);
+
+		switch(menu_section){
+			case OUT_OF_MENU:
+				lcd.print(fill_string_ws("", 20));
+				break;
+
+			case IN_SENSITIVITY_BUTTON:
+				lcd.print(fill_string_ws(fill_string_ws(String(setup_var[0]), 2, 1, "0"), 20, 3));
+				break;
+
+			case IN_PRESS_BUTTON:
+			case IN_HOLD_DOWN_BUTTON:
+				switch(setup_var[0]){
+					case 1:
+						lcd.print(fill_string_ws(text_info[MODE_1], 20, 3));
+						break;
+
+					case 2:
+						lcd.print(fill_string_ws(text_info[MODE_2], 20, 3));
+						break;
+
+					case 3:
+						lcd.print(fill_string_ws(text_info[MODE_3], 20, 3));
+						break;
+				}
+				break;
+
+			case IN_LAG:
+			case IN_DOSING:
+				lcd.print(fill_string_ws(min_seg_dec_to_string(setup_var[0], setup_var[1], setup_var[2]), 20, 3));
+				break;
+
+			case IN_FACTORY_RESET:
+				if(menu_status == UPDATE){
+					setup_var[0]?
+						lcd.print(fill_string_ws(text_info[FACTORY_RESET], 20, 3)):
+						lcd.print(fill_string_ws(text_info[CANCEL], 20, 3));
+
+				}else
+					lcd.print(fill_string_ws("", 20));
+				break;
+
+			case IN_RESTART:
+				if(menu_status == UPDATE){
+					setup_var[0]?
+						lcd.print(fill_string_ws(text_info[RESTART], 20, 3)):
+						lcd.print(fill_string_ws(text_info[CANCEL], 20, 3));
+
+				}else
+					lcd.print(fill_string_ws("", 20));
+				break;
+		}
+
+		// Limpiamos línea de proceso
+		if(menu_status == UPDATE){
+			lcd.setCursor(0, 2);
+			lcd.print(fill_string_ws("", 20));
+
+			lcd.setCursor(0, 3);
+			lcd.print(fill_string_ws("", 20));
+		}
+	}
+
+	void print_lcd_process()
+	{
+		if(menu_section == OUT_OF_MENU || menu_status == VIEW){
+			lcd.setCursor(0, 2);
+
+			lcd.print(status[dispenser_status]);
+
+			switch(dispenser_status){
+				case DISPENSER_IDLE:
+					if(millis() >= blink_millis)
+						blink_millis = millis() + (BLINK_MILLIS * 2);
+					
+					lcd.print(fill_string_ws(blink_millis - millis() >= BLINK_MILLIS? "": "***", 11, 2));
+					break;
+
+				case DISPENSER_LAG:
+					lcd.print(fill_string_ws(process_time(), 8, 2));
+					break;
+
+				case DISPENSER_DOSING:
+					lcd.print(fill_string_ws(process_time(), 8, 1));
+					break;
+
+				case DISPENSER_BLOCK:
+					//lcd.print(fill_string_ws(process_time(), 8, 1));
+					break;
+			}
+		}
+	}
+
+	void setCursor_lcd_menu()
+	{
+		if(menu_status == UPDATE){
+			switch(menu_section){
+				case OUT_OF_MENU:
+					break;
+
+				case IN_LAG:
+				case IN_DOSING:
+					// Posicionamos el cursos, para la edición
+					if(menu_cursor_var == POSITION_ONE)
+						lcd.setCursor(3,1);
+
+					else if(menu_cursor_var == POSITION_TWO)
+						lcd.setCursor(6,1);
+
+					else if(menu_cursor_var == POSITION_THREE)
+						lcd.setCursor(9,1);
+					break;
+
+				case IN_SENSITIVITY_BUTTON:
+				case IN_PRESS_BUTTON:
+				case IN_HOLD_DOWN_BUTTON:
+				case IN_FACTORY_RESET:
+				case IN_RESTART:
+					lcd.setCursor(3,1);
+					break;
+			}
+
+			lcd.cursor();
+		}
+	}
+
+
+/**************************************************
+* DOSAGE PROCESS
+**************************************************/
+	void loop_dosage_process()
+	{
+		if(digitalRead(DOSING_BUTTON_PIN) == DOSING_BUTTON_PUSH){
+			if(button_pressed_millis == 0)
+				button_pressed_millis = millis();
+
+				// Se supero el button_sensitivity_millis
+				if (millis() >= (button_pressed_millis + button_sensitivity_millis))
+					start_dosing_process();
+
+		}else{
+
+			release_button = 0;
+			button_pressed_millis = 0;
+		}
+
+		continue_dosing_process();
+	}
+
+	void start_dosing_process()
+	{
+
+
+
+		if(press_button_mode == 3 &&
+			dispenser_status != DISPENSER_IDLE &&
+			dispenser_status_time_millis >= button_pressed_millis &&
+			release_button == 0){
+
+			dispenser_status 			 = DISPENSER_DOSING;
+			dispenser_status_time_millis = 0;
+
+			serialPrint("Proceso detenido");
+			serialPrintln(millis());
+
+
+		}else if((press_button_mode == 1 || press_button_mode == 3) && dispenser_status == DISPENSER_IDLE){
+			dispenser_status 			 = DISPENSER_LAG;
+			dispenser_status_time_millis = millis() + ((uint32_t) lag_time_decseg * 100);
+
+			release_button = 1;
+
+			serialPrint("Iniciando proceso ");
+			serialPrintln(millis());
+
+		}else if(press_button_mode == 2){
+			dispenser_status = DISPENSER_RESTART;
+
+			release_button = 1;
+		}
+	}
+
+	void continue_dosing_process()
+	{
+		switch(dispenser_status){
+			case DISPENSER_RESTART:
+				digitalWrite(RELAY_PIN, RELAY_LOW);
+
+				dispenser_status 			 = DISPENSER_LAG;
+				dispenser_status_time_millis = millis() + ((uint32_t) lag_time_decseg * 100);
+				break;
+
+			case DISPENSER_LAG:
+				if(millis() >= dispenser_status_time_millis){
+					dispenser_status 			 = DISPENSER_DOSING;
+					dispenser_status_time_millis = millis() + ((uint32_t) dosing_time_decseg * 100);
+
+					digitalWrite(RELAY_PIN, RELAY_HIGH);
+				}
+				break;
+
+			case DISPENSER_DOSING:
+				if(millis() >= dispenser_status_time_millis){
+					dispenser_status 			 = button_pressed_millis == 0? DISPENSER_IDLE: DISPENSER_BLOCK;
+					dispenser_status_time_millis = 0;
+
+					digitalWrite(RELAY_PIN, RELAY_LOW);
+				}
+				break;
+
+			case DISPENSER_BLOCK:
+				if(button_pressed_millis == 0)
+					dispenser_status = DISPENSER_IDLE;
+				break;
+		}
+	}
+
+
+/**************************************************
+* Setup & Loops
+**************************************************/
+	void setup()
+	{
+		pinMode(RELAY_PIN, OUTPUT);
+		pinMode(DOSING_BUTTON_PIN, INPUT_PULLUP);
+		pinMode(SETTINGS_BUTTONS_PIN, INPUT_PULLUP);
+
+		// Salida Serial
+		serialBegin(9600);
+		serialBeginWhile();
+
+		// Cargamos configuraciones de la EEPROM a la ram
+		load_setting(ALL_SETTINGS);
+
+		//Iniciamos la pantalla
+		lcd.begin(20, 4);
+	}
+
+	void loop()
+	{
+		loop_settings_panel_buttons();
+		loop_dosage_process();
+		loop_screen_rendering();
+	}