/***************************************** * Dosificador_LCD2004_4buttons * * 15/03/2021 * * Versión 0.1.0 * * koneko.mx * *****************************************/ #include #include /************************************************** * Definición de Constantes **************************************************/ // LCD2004 I2C #define LCD_I2C_ADDRESS 0x27 // PINOUT #define RELAY_PIN A2 #define DOSING_BUTTON_PIN A1 #define SETTINGS_BUTTONS_PIN A0 /************************************************** * BOTONES **************************************************/ #define SETTING_BUTTON_IN_VAL 14 #define SETTING_BUTTON_UP_VAL 41 #define SETTING_BUTTON_DOWN_VAL 66 #define SETTING_BUTTON_OUT_VAL 89 #define SETTING_BUTTON_TOLERANCE_READ 5 #define SETTING_BUTTON_CONFIRMATION_REPEATS_MILLIS 5 #define SETTING_BUTTON_DELAY_MILLIS 350 // 4-button configuration uint16_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; /************************************************** * MENÚ **************************************************/ // BLOQUES DE MEMORIA EEPROM #define BUTTON_SENSITIVITY_EEPROM_ADDRESS 0 #define DISPENSER_MODE_EEPROM_ADDRESS 1 #define LAG_TIME_MIN_EEPROM_ADDRESS 2 // Minutos, tiempo de retraso #define LAG_TIME_SEG_EEPROM_ADDRESS 3 // Segundo, tiempo de retraso #define LAG_TIME_DEC_EEPROM_ADDRESS 4 // Décimas de segundo, tiempo de retraso #define DOSING_TIME_MIN_EEPROM_ADDRESS 5 // Minutos, tiempo dosificación #define DOSING_TIME_SEG_EEPROM_ADDRESS 6 // Segundos, tiempo dosificación #define DOSING_TIME_DEC_EEPROM_ADDRESS 7 // Décimas de segundo, tiempo dosificación // FACTORY SETTINGS #define BUTTON_SENSITIVITY_DEFAULT_VALUE 10 #define DISPENSER_MODE_DEFAULT_VALUE 2 #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 OUT_OF_MENU 0 #define ALL_SETTINGS 0 // POSITION MENU #define IN_SENSITIVITY_BUTTON 1 #define IN_DISPENSER_MODE 2 #define IN_LAG 3 #define IN_DOSING 4 #define IN_FACTORY_RESET 5 #define IN_RESTART 6 #define IN_EXIT 7 #define VIEW 0 #define UPDATE 1 #define POSITION_ONE 0 #define POSITION_TWO 1 #define POSITION_THREE 2 // text_info[] index #define DISPENSER_MODE 0 #define BELT_MODE 1 #define FACTORY_RESET 2 #define RESTART 3 #define CANCEL 4 // MENU & LCD #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 // MODE EEPROM DISPENSER #define DISPENSER_MODE_VALUE 1 #define BELT_MODE_VALUE 2 // RELAY STATUS #define RELAY_HIGH HIGH #define RELAY_LOW LOW // SENSOR STATUS #define SENSOR_UNLOCK 0 #define SENSOR_LOCK 1 #define SENSOR_ACTIVATED LOW // SENSOR ACTIVATION BUFFER SIZE #define SENSOR_BUFFER_SIZE 25 /************************************************** * 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 **************************************************/ // Configuraciones del dosificador uint16_t button_sensitivity_millis; uint8_t dispenser_mode; uint16_t lag_time_decseg; uint16_t dosing_time_decseg; // Momento del bloqueo del sensor uint32_t sensor_lock_millis; // Registro del sensor uint8_t last_sensor_status = SENSOR_UNLOCK; uint8_t relay_activation_pointer; uint32_t relay_activation_millis_ini[SENSOR_BUFFER_SIZE]; uint32_t relay_activation_millis_end[SENSOR_BUFFER_SIZE]; // Estado del Relevador uint8_t relay_state = RELAY_LOW; // Estado del dosificador uint8_t dispenser_status; uint32_t dispenser_status_time_millis; // Navegación de menú uint8_t setup_var[3]; uint8_t menu_section; uint8_t menu_status; uint8_t menu_cursor_var; uint32_t blink_millis; uint32_t last_change_menu_millis; boolean refresh_lcd_menu; // LCD2004 Render LiquidCrystal_I2C lcd(LCD_I2C_ADDRESS, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); String menu[] = { "SENSIBILIDAD SENSOR", "MODO DE TRABAJO", "RETARDO AL INICIAR", "TIEMPO DOSIFICACION", "VALORES DE FABRICA", "REINICIAR", "SALIR", }; String status[] = { "EN ESPERA", "DETECTANDO", "DOSIFICARA", "DOSIFICANDO", "BLOQUEADO", }; String text_info[] = { "DOSIFICADOR", "BANDA TRANSPORTADOR", "RESTAURAR", "REINICAR", "CANCELAR", }; /************************************************** * FRONT PANEL OF CONFIGURATIONS **************************************************/ // button methods and memory spaces void loop_settings_panel_buttons() { // Leemos valor analogo del botón uint16_t button_value = analogRead(SETTINGS_BUTTONS_PIN); // Comprobamos el valor obtenido con un rago de tolerancia SETTING_BUTTON_TOLERANCE_READ for (uint16_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(uint16_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_DISPENSER_MODE: if(menu_status == VIEW) menu_status = UPDATE; else if(++menu_cursor_var > POSITION_ONE) save_setting(IN_DISPENSER_MODE); 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_DISPENSER_MODE: if(menu_status == VIEW){ load_menu_variables(IN_SENSITIVITY_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_DISPENSER_MODE); }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){ dispenser_mode == DISPENSER_MODE_VALUE? load_menu_variables(IN_DOSING): load_menu_variables(IN_LAG); }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_RESTART); 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_DISPENSER_MODE); }else{ // UPDATE setup_var[0] = setup_var[0] <= 1 ? 10 : --setup_var[0]; } break; case IN_DISPENSER_MODE: 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){ dispenser_mode == DISPENSER_MODE_VALUE? load_menu_variables(IN_DOSING): 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_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_DISPENSER_MODE: EEPROM.write(DISPENSER_MODE_EEPROM_ADDRESS, setup_var[0]); load_setting(IN_DISPENSER_MODE); serialPrintln("Save dispenser_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(DISPENSER_MODE_EEPROM_ADDRESS, DISPENSER_MODE_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]){ for (int i = 0; i < SENSOR_BUFFER_SIZE; ++i){ relay_activation_pointer = 0; relay_activation_millis_ini[i] = 0; relay_activation_millis_end[i] = 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_DISPENSER_MODE); 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_DISPENSER_MODE: dispenser_mode = EEPROM.read(DISPENSER_MODE_EEPROM_ADDRESS); serialPrint("dispenser_mode: "); serialPrintln(dispenser_mode); break; case IN_LAG: lag_time_decseg = (EEPROM.read(LAG_TIME_MIN_EEPROM_ADDRESS) * 600) + (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_DISPENSER_MODE: setup_var[0] = EEPROM.read(DISPENSER_MODE_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_DISPENSER_MODE: switch(setup_var[0]){ case DISPENSER_MODE_VALUE: lcd.print(fill_string_ws(text_info[DISPENSER_MODE], 20)); break; case BELT_MODE_VALUE: lcd.print(fill_string_ws(text_info[BELT_MODE], 20)); 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(dispenser_mode == DISPENSER_MODE_VALUE? process_time(): "--:--", 8, 1)); break; case DISPENSER_BLOCK: 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_FACTORY_RESET: case IN_RESTART: lcd.setCursor(3,1); break; case IN_DISPENSER_MODE: lcd.setCursor(0,1); break; } lcd.cursor(); } } /************************************************** * DOSAGE PROCESS **************************************************/ void loop_dosage_process() { dispenser_status = DISPENSER_IDLE; // Se a activado el Sensor if(digitalRead(DOSING_BUTTON_PIN) == SENSOR_ACTIVATED){ if(sensor_lock_millis == 0) sensor_lock_millis = millis(); // Se supero el button_sensitivity_millis if(last_sensor_status == SENSOR_UNLOCK && millis() >= (sensor_lock_millis + button_sensitivity_millis)){ // Registramos en Inicio de Proceso de dosifiación relay_activation_millis_ini[relay_activation_pointer] = millis() + (lag_time_decseg * 100); // En modo Dosificador if(dispenser_mode == DISPENSER_MODE_VALUE) relay_activation_millis_end[relay_activation_pointer] = relay_activation_millis_ini[relay_activation_pointer] + (dosing_time_decseg * 100); last_sensor_status = SENSOR_LOCK; } if(dispenser_mode == DISPENSER_MODE_VALUE && relay_activation_millis_end[relay_activation_pointer] == 0){ dispenser_status = DISPENSER_BLOCK; } }else if(last_sensor_status == SENSOR_LOCK){ if(dispenser_mode == DISPENSER_MODE_VALUE){ relay_activation_millis_ini[relay_activation_pointer] = 0; relay_activation_millis_end[relay_activation_pointer] = 0; }else{ relay_activation_millis_end[relay_activation_pointer++] = millis() + (lag_time_decseg * 100); // Si supera el tamaño del buffer vamos al inicio del buffer if(relay_activation_pointer >= SENSOR_BUFFER_SIZE) relay_activation_pointer = 0; } sensor_lock_millis = 0; last_sensor_status = SENSOR_UNLOCK; } // Determinamos el estado del Relevador relay_state = RELAY_LOW; if(dispenser_mode == DISPENSER_MODE_VALUE){ // Depuramos if(relay_activation_millis_end[relay_activation_pointer] > 0 && millis() >= relay_activation_millis_end[relay_activation_pointer]){ relay_activation_millis_ini[relay_activation_pointer] = 0; relay_activation_millis_end[relay_activation_pointer] = 0; } // Existe periodo de dosificación if(relay_activation_millis_ini[relay_activation_pointer] > 0) { // Revisamos si se debe encender el Dosificador if(millis() >= relay_activation_millis_ini[relay_activation_pointer]){ dispenser_status = DISPENSER_DOSING; dispenser_status_time_millis = relay_activation_millis_end[relay_activation_pointer]; relay_state = RELAY_HIGH; // Aun no comienza dosificación }else{ dispenser_status = DISPENSER_LAG; dispenser_status_time_millis = relay_activation_millis_ini[relay_activation_pointer]; } } }else{ for (int i = 0; i < SENSOR_BUFFER_SIZE; ++i){ // Depuramos el Buffer if(relay_activation_millis_end[i] > 0 && millis() >= relay_activation_millis_end[i]){ relay_activation_millis_ini[i] = 0; relay_activation_millis_end[i] = 0; } if(relay_activation_millis_ini[i] > 0){ // Revisamos en el Buffer si se debe encender el Dosificador if(millis() >= relay_activation_millis_ini[i]){ dispenser_status = DISPENSER_DOSING; dispenser_status_time_millis = 0; relay_state = RELAY_HIGH; // Aun no comienza dosificación }else if (relay_state == RELAY_LOW){ dispenser_status = DISPENSER_LAG; dispenser_status_time_millis = relay_activation_millis_ini[i]; } } } } // Aplicamos cambios en el estado del relevador digitalWrite(RELAY_PIN, relay_state); /* dispenser_status_time_millis dispenser_status = DISPENSER_IDLE; dispenser_status = DISPENSER_LAG; dispenser_status = DISPENSER_DOSING; dispenser_status = DISPENSER_BLOCK; // Determinamos el estado del Dosificador if(dispenser_mode == DISPENSER_MODE_VALUE){ }else{ } for (int i = 0; i < SENSOR_BUFFER_SIZE; ++i){ serialPrint(i); serialPrint(") "); serialPrint(relay_activation_millis_ini[i]); serialPrint(", "); serialPrint(relay_activation_millis_end[i]); serialPrint(" - "); serialPrintln((relay_activation_millis_end[i] - relay_activation_millis_ini[i])); } serialPrintln(""); serialPrintln(""); serialPrintln(""); */ } /************************************************** * Setup & Loops **************************************************/ void setup() { pinMode(RELAY_PIN, OUTPUT); pinMode(DOSING_BUTTON_PIN, INPUT_PULLUP); pinMode(SETTINGS_BUTTONS_PIN, INPUT_PULLUP); // Salida Serial serialBegin(115200); 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(); }