dosificador-atmel/Dosificador_LCD2004_4buttons/Dosificador_LCD2004_4buttons.ino

1077 lines
36 KiB
Arduino
Raw Normal View History

2021-03-15 23:01:21 -06:00
/*****************************************
* Dosificador_LCD2004_4buttons *
* 15/03/2021 *
* Versión 0.1.0 *
* koneko.mx *
*****************************************/
#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
/**************************************************
* Definición de Constantes
**************************************************/
2022-06-18 15:10:35 -05:00
// 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 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
2021-03-15 23:01:21 -06:00
/**************************************************
* Debug
* Define DEBUG_SERIAL_ENABLE to enable debug serial.
* Comment it to disable debug serial.
**************************************************/
2022-06-18 15:10:35 -05:00
//#define DEBUG_SERIAL_ENABLE
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
#define dbSerial Serial
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
#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
2021-03-15 23:01:21 -06:00
/**************************************************
* ENVIRONMENT VARIABLES
**************************************************/
2022-06-18 15:10:35 -05:00
// 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;
2021-03-15 23:01:21 -06:00
uint32_t button_pressed_millis;
uint8_t release_button;
2022-06-18 15:10:35 -05:00
uint8_t dispenser_status;
uint32_t dispenser_status_time_millis;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
uint8_t menu_section;
uint8_t menu_status;
uint8_t menu_cursor_var;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
uint8_t setup_var[3];
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
uint32_t last_change_menu_millis;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
// LCD2004 Render
LiquidCrystal_I2C lcd(LCD_I2C_ADDRESS, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
String menu[] = {
"SENSIBILIDAD BOTON",
"AL PRESIONAR BOTON",
"AL MANTENER PRESIO",
"RETARDO AL INICIAR",
"TIEMPO DOSIFICACION",
"VALORES DE FABRICA",
"REINICIAR",
"SALIR",
};
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
String status[] = {
"EN ESPERA",
"DETECTANDO",
"DOSIFICARA",
"DOSIFICANDO",
"BLOQUEADO",
};
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
String text_info[] = {
"MODO 1",
"MODO 2",
"MODO 3",
"RESTAURAR",
"REINICAR",
"CANCELAR",
};
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
boolean refresh_lcd_menu;
uint32_t blink_millis;
2021-03-15 23:01:21 -06:00
/**************************************************
* FRONT PANEL OF CONFIGURATIONS
**************************************************/
2022-06-18 15:10:35 -05:00
// 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_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_SENSITIVITY_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_LAG);
}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;
}
}
2021-03-15 23:01:21 -06:00
/**************************************************
* LCD2004 rendering
**************************************************/
2022-06-18 15:10:35 -05:00
// 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();
}
}
2021-03-15 23:01:21 -06:00
/**************************************************
* DOSAGE PROCESS
**************************************************/
2022-06-18 15:10:35 -05:00
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;
}
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
continue_dosing_process();
}
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
void start_dosing_process()
{
/*
Modo 1:
Modo 2:
Modo 3:
*/
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
/*
if(press_button_mode == 3 &&
dispenser_status != DISPENSER_IDLE &&
dispenser_status_time_millis >= button_pressed_millis &&
release_button == 0){
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
dispenser_status = DISPENSER_DOSING;
dispenser_status_time_millis = 0;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
serialPrint("Proceso detenido");
serialPrintln(millis());
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
}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);
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
release_button = 1;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
serialPrint("Iniciando proceso ");
serialPrintln(millis());
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
}else if(press_button_mode == 2){
dispenser_status = DISPENSER_RESTART;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
release_button = 1;
}
*/
switch(press_button_mode){
case 1:
dispenser_status = DISPENSER_RESTART;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
serialPrintln("Modo 1 ");
break;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
case 2:
dispenser_status = DISPENSER_RESTART;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
serialPrintln("Modo 2 ");
break;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
case 3:
dispenser_status = DISPENSER_RESTART;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
serialPrintln("Modo 3 ");
break;
}
}
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
void continue_dosing_process()
{
switch(dispenser_status){
case DISPENSER_RESTART:
digitalWrite(RELAY_PIN, RELAY_LOW);
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
dispenser_status = DISPENSER_LAG;
dispenser_status_time_millis = millis() + ((uint32_t) lag_time_decseg * 100);
break;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
case DISPENSER_LAG:
if(millis() >= dispenser_status_time_millis){
dispenser_status = DISPENSER_DOSING;
dispenser_status_time_millis = millis() + ((uint32_t) dosing_time_decseg * 100);
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
digitalWrite(RELAY_PIN, RELAY_HIGH);
}
break;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
case DISPENSER_DOSING:
if(millis() >= dispenser_status_time_millis){
dispenser_status = button_pressed_millis == 0? DISPENSER_IDLE: DISPENSER_BLOCK;
dispenser_status_time_millis = 0;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
digitalWrite(RELAY_PIN, RELAY_LOW);
}
break;
2021-03-15 23:01:21 -06:00
2022-06-18 15:10:35 -05:00
case DISPENSER_BLOCK:
if(button_pressed_millis == 0)
dispenser_status = DISPENSER_IDLE;
break;
}
}
2021-03-15 23:01:21 -06:00
/**************************************************
* Setup & Loops
**************************************************/
2022-06-18 15:10:35 -05:00
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();
}