/*=================================================================
Primeira Versão da Programação do Dosador de Liquidos
Sobre: Primeiro programa para o controle do dosador de liquidos,
com as principais funções de operação.
Versão: 1.0
in.: 01.08.2024
fim: --.--.----
by: losr || <pL>
=================================================================*/
//============ Inclusão das Bibliotecas ============//
#include "Wire.h" // Comunicação I2C
#include <dht.h> // Sensor de Temperatura e Umidade do Ar DHT22
//#include <Ultrassonic.h> // Sensor Ultrassônico HC-SR04
#include <LiquidCrystal_I2C.h> // Display LCD 20x4
//============ Manuseio das Bibliotecas ============//
//HC_SR04 sensor_hc_sr04(triggerPin, echoPin); // Configura os pinos sensor ultrassônico, sint.: 'nomeSensor(Trigger, Echo)'
dht sensor_dht22; // Cria o objeto sensor dht22
LiquidCrystal_I2C lcd(0x27, 20, 4); // Cria o objeto lcd
//============ Mapeamento de Hardware ============//
// ----- INPUTS ----- //
#define triggerPin 10 // Trigger
#define echoPin 11 // Echo
#define dht22Pin 5 // DHT22
#define cntPin A0 // Contador
#define sigPin A1 // Sinal
// ----- INPUTS PULLUP ----- //
#define btnDown 1 // PB0 D8 Botão de Ligar e Desligar Sistema de Venda
#define btnUp (1 << 1) // PB1 D9 Botão Down
#define btnEnter (1 << 4) // PB4 D12 Botão Enter
#define btnBuy (1 << 7) // PD7 D7 Botão de compra
// ----- OUTPUTS ----- //
#define peltierPin 2 // Célula Peltier
#define coolerFunPin 3 // Ventoinha
#define bombaPin 4 // Bomba Peristáltica
//----- Definições para PinMode Geral ------//
#define num_pins_in 5 // Constante Total de Entradas
#define num_pins_out 3 // Constante Total de Saídas
int lista_io[2][(5)] = { // Lista de I/O
{ // Outputs
peltierPin, coolerFunPin, bombaPin
},
{ // Inputs
triggerPin, echoPin, dht22Pin, cntPin, sigPin
}
};
//============ Variavéis Globais ============//
boolean btnEnter_func = 0x00;
unsigned char gapTime = 78,
t_enter;
int menu, submenu, subnum, linha_flag;
const int menu_max = 4,
linha_max = 3;
char* telas[menu_max] = {
"Config. Peltier",
"Config. Vendas",
"Exibir Valores",
"Iniciar Vendas"
};
char* txt_estados[] = {
"Ligar",
"Desligar",
"ON",
"OFF"
};
char* sub_menus[menu_max][5] = {
{
"Estado: ",
"Intervalo temp.",
"Coolers: ",
" peltier"
},
{
"Valor",
"Caixa"
},
{
"Temp: ",
"Peltier: ",
"Coolers: "
}
};
//============ Declaração das Funções ============//
void bootProcess(); // Animação de Inicialização
void attLcd(); // Atualização do Display LCD
void controle(); // Navegação
//============ Interrupção ============//
ISR (TIMER1_OVF_vect) // "Interrup Service Routine" - ISR
{
TCNT1 = 0x06; // Reinicializa Timer0
if (submenu) {
if (btnEnter_func) t_enter++;
if (t_enter >= gapTime) {
t_enter = 0;
submenu = 0;
menu = 0;
subnum = 0;
linha_flag = 0;
attLcd();
}
}
}
//======================= SETUP =======================//
void setup()
{
cli(); // Desliga Interrupções
TCNT1 = 0x06; // Inicia Timer0 para contar até 50
TCCR1B = 0x03; // Prescaler 1:64
TIMSK1 = 0x01; // Habilita interrupção do Timer0
sei(); // Liga Interrupções
// Base de tempo principal: 62.5E-9 * 64 * 250 = 1ms
Serial.begin(9600);
for (int i = 0; i < num_pins_out; i++) pinMode(lista_io[0][i], OUTPUT); // Definindo os pinos de saída
for (int i = 0; i < num_pins_in; i++) pinMode(lista_io[1][i], INPUT); // Definindo os pinos de entrada
DDRB &= ~btnUp;
DDRB &= ~btnDown;
DDRB &= ~btnEnter;
DDRD &= ~btnBuy;
PORTB |= btnUp;
PORTB |= btnDown;
PORTB |= btnEnter;
PORTD |= btnBuy;
lcd.init(); // Iniciar a comunicação com o display já conectado
lcd.backlight(); // Ligar a luz de fundo do display
lcd.clear(); // Limpar a tela do display
// bootProcess();
attLcd();
}
void loop() {
controle();
}
//============ Definição das Funções ============//
void controle()
{
static boolean btnEnter_flag = 0x00,
btnUp_flag = 0x00,
btnDown_flag = 0x00,
btnBuy_flag = 0x00;
if (!(PINB & btnEnter)) {
btnEnter_func = 0x01;
btnEnter_flag = 0x01;
}
if (!(PINB & btnUp)) btnUp_flag = 0x01;
if (!(PINB & btnDown)) btnDown_flag = 0x01;
if (!(PIND & btnBuy)) btnBuy_flag = 0x01;
if ((PINB & btnEnter) && btnEnter_flag) {
btnEnter_flag = 0x00;
btnEnter_func = 0x00;
t_enter = 0;
submenu = 1;
linha_flag = 0;
attLcd();
}
if ((PINB & btnUp) && btnUp_flag)
{
btnUp_flag = 0x00;
if (!submenu) {
if (menu < menu_max - 1) { // Se menu for menor que o menu max
menu++; // Aumentar menu
if (linha_flag < linha_max) linha_flag++; // Aumenta a flag da pos de linha
attLcd(); // Atualiza LCD
}
} else if (linha_flag < linha_max - 1) {
subnum++;
if (linha_flag < linha_max - 1) linha_flag++;
attLcd();
}
}
if ((PINB & btnDown) && btnDown_flag) {
btnDown_flag = 0x00;
if (!submenu) {
if (menu > 0) { // Se menu for menor que o menu max
menu--; // Aumentar menu
if (linha_flag > 0) linha_flag--; // Aumenta a flag da pos de linha
attLcd(); // Atualiza LCD
}
} else if (linha_flag > 0) {
subnum--;
if (linha_flag > 0) linha_flag--;
attLcd();
}
}
if ((PIND & btnBuy) && btnBuy_flag) {
btnBuy_flag = 0x00;
}
}
void attLcd() {
lcd.clear();
lcd.setCursor(0, 0);
switch (submenu) // Comutar submenu
{
case 0: // Caso 0
switch (linha_flag)
{
case 0:
lcd.print("> "); // Imprime "> " na 1° linha
lcd.print(telas[menu]); // Imprime tela com valor do menu atual
lcd.setCursor(0, 1); // Troca a linha
lcd.print(" ");
lcd.print(telas[menu + 1]);
lcd.setCursor(0, 2); // Troca a linha
lcd.print(" ");
lcd.print(telas[menu + 2]);
lcd.setCursor(0, 3); // Troca a linha
lcd.print(" ");
lcd.print(telas[menu + 3]);
break;
case 1:
lcd.print(" "); // Imprime "> " na 1° linha
lcd.print(telas[menu - 1]); // Imprime tela com valor do menu atual
lcd.setCursor(0, 1); // Troca a linha
lcd.print("> ");
lcd.print(telas[menu]);
lcd.setCursor(0, 2); // Troca a linha
lcd.print(" ");
lcd.print(telas[menu + 1]);
lcd.setCursor(0, 3); // Troca a linha
lcd.print(" ");
lcd.print(telas[menu + 2]);
break;
case 2:
lcd.print(" "); // Imprime "> " na 1° linha
lcd.print(telas[menu - 2]); // Imprime tela com valor do menu atual
lcd.setCursor(0, 1); // Troca a linha
lcd.print(" ");
lcd.print(telas[menu - 1]);
lcd.setCursor(0, 2); // Troca a linha
lcd.print("> ");
lcd.print(telas[menu]);
lcd.setCursor(0, 3); // Troca a linha
lcd.print(" ");
lcd.print(telas[menu + 1]);
break;
case 3:
lcd.print(" "); // Imprime "> " na 1° linha
lcd.print(telas[menu - 3]); // Imprime tela com valor do menu atual
lcd.setCursor(0, 1); // Troca a linha
lcd.print(" ");
lcd.print(telas[menu - 2]);
lcd.setCursor(0, 2); // Troca a linha
lcd.print(" ");
lcd.print(telas[menu - 1]);
lcd.setCursor(0, 3); // Troca a linha
lcd.print("> ");
lcd.print(telas[menu]);
break;
}
break;
// nova parte do código
case 1:
switch (linha_flag)
{
case 0:
lcd.print("v "); // Imprime "V " na 1° linha
lcd.print(telas[menu]); // Imprime tela com valor do menu atual
lcd.setCursor(1, 1); // Troca a linha
lcd.print("> ");
lcd.print(sub_menus[menu][subnum]);
lcd.setCursor(1, 2); // Troca a linha
lcd.print(" ");
lcd.print(sub_menus[menu][subnum + 1]);
lcd.setCursor(1, 3); // Troca a linha
lcd.print(" ");
lcd.print(sub_menus[menu][subnum + 2]);
break;
case 1:
lcd.print("v "); // Imprime "V " na 1° linha
lcd.print(telas[menu]); // Imprime tela com valor do menu atual
lcd.setCursor(1, 1); // Troca a linha
lcd.print(" ");
lcd.print(sub_menus[menu][subnum - 1]);
lcd.setCursor(1, 2); // Troca a linha
lcd.print("> ");
lcd.print(sub_menus[menu][subnum]);
lcd.setCursor(1, 3); // Troca a linha
lcd.print(" ");
lcd.print(sub_menus[menu][subnum + 1]);
break;
case 2:
lcd.print("v "); // Imprime "V " na 1° linha
lcd.print(telas[menu]); // Imprime tela com valor do menu atual
lcd.setCursor(1, 1); // Troca a linha
lcd.print(" ");
lcd.print(sub_menus[menu][subnum - 2]);
lcd.setCursor(1, 2); // Troca a linha
lcd.print(" ");
lcd.print(sub_menus[menu][subnum - 1]);
lcd.setCursor(1, 3); // Troca a linha
lcd.print("> ");
lcd.print(sub_menus[menu][subnum]);
break;
}
break;
// fim da nova parte do código
}
Serial.print("Menu: "); Serial.print(menu + 1);
Serial.print(" Submenu: "); Serial.print(submenu);
Serial.print(" Linha: "); Serial.println(linha_flag + 1);
}
// Animação de Inicialização (Repetirá uma Única Vez)
void bootProcess()
{
lcd.init(); // Iniciar a comunicação com o display já conectado
lcd.backlight(); // Ligar a luz de fundo do display
lcd.clear(); // Limpar a tela do display
for (int i = 0; i < 16; i ++) {
if ((i % 4 == 0)) {
lcd.clear(); // Limpar a tela do display
lcd.setCursor(0, 1);
lcd.print(" Ligando");
} else lcd.print(".");
delay(500);
}
lcd.clear();
lcd.setCursor(0, 1);
lcd.print(" DOSADORA");
lcd.setCursor(0, 2);
lcd.print(" AUTOMATICA");
delay(3000);
lcd.clear();
}