e eu pudesse fazer um botão de "retorno de tela" ou "saída" da tela que estivar vou deixa minha programação para maior esclarecimentos.
DESCRIÇÃO DO PROGRAMA: Ele possui um menu principal contidos pela Tela_Principa(); Tela_Principal_2(); Tela_Principal_3(); Tela_Principal_4(), onde a Tela_Principal_2(), terá um subMenu, logo toda as vezes que entrar em qualquer item do subMenu queria retor a tela anterior quando necessário, porém não consigo, como faço? em vermelho coloquei um pequena parte que tentei fazer o retorno mas sem exito .
#include <openGLCD.h>// inclusão da biblioteca GLCD
#define BOT_UP 43 //botao 1 no pino digital 43#define BOT_DOWN 42 //botao 2 no pino digital 42
#define BOT_ANT 46 //botao 5 no pino digital 46#define BOT_PROX 48 //botao 6 no pino digital 48
#define BOT_F1 50 //botao 5 no pino digital 46#define BOT_F2 51 //botao 6 no pino digital 48
#define select 45 //botao 3 no pino digital 45#define SAIR 44 //botao 4 no pino digital 44
//#define BOT_ESC //44
#define CILINDRO_H 47 //Saída para Cilindro horizontal,pino digital 47#define CILINDRO_V 49 //Saída para Cilindro Vertical,pino digital 49#define CILINDRO_A 39 //Saída para Cilindro Alimentador,pino digital 39#define CILINDRO_D 41 //Saída para Cilindro Datador,pino digital 41#define RESISTENCIA_V 30 //Saída para Cilindro Alimentador,pino digital 30#define RESISTENCIA_H 31 //Saída para Cilindro Horizontal,pino digital 31#define RESISTENCIA_D 2 //Saída para Cilindro Datador,pino digital 2#define MOTOR_P 3 //Saída para Cilindro Datador,pino digital 3//////////////////////////////////////////////////////////////////////////////////////////////////////////////// --- Funções Principais ---void changeMenu(); //Função para modificar o menu atualvoid dispMenu(); //Função para mostrar o menu atual//----Funções Principal do Menu-----void Tela_Principa(); //Função do menu1, {1->Funcao Manual;2->Funcao Auto; 3->Configuracao}void Tela_Principal_2(); //Função do menu2, 1->Funcao Manualvoid Tela_Principal_3(); //Função do menu3, 2->Funcao Autovoid Tela_Principal_4(); //Função do menu4, 3->Configuracao
//----------------- Funções Auxiliares do Sub menu, referente a função menu Tela_Principal_2 ---------------------------void dispSubMenu4(); //Função do sub menu4 void readSelect(char option); //Função de Leitura do botão select para seleção de subMenusvoid subMenu4_1(); //Função para subMenu4_1void subMenu4_2(); //Função para subMenu4_2void subMenu4_3(); //Função para subMenu4_3void subMenu4_4(); //Função para subMenu4_4
// --- Variáveis Globais ---char menu = 0x01; //Variável para selecionar o menu onde será direcionado ao casechar subMenu4 = 0x01; //Variável para selecionar o Submenu onde será direcionado ao casechar set1 = 0x00, set2 = 0x00; //Controle dos cilindros da máquinaboolean t_botao_up, t_botao_down,t_botao_ant, t_botao_prox, t_botao_f1,t_botao_f2, t_select, t_sair;//Flags para armazenar o estado dos botões
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////void setup(){ GLCD.Init(); // Pinagem correspondente do display p/ o Arduino(ver tabela) GLCD.SelectFont(System5x7); // tamanho da fonte a ser selecionada pinMode(BOT_UP, INPUT); //Configura entrada do botão 1, CIMA pinMode(BOT_DOWN, INPUT); //Configura entrada do botão 2, BAIXO pinMode(select, INPUT); //Configura entrada do botão 3, SELECIONAR pinMode(SAIR, INPUT); //Configura entrada do botão 4, SAIR pinMode(BOT_ANT, INPUT); //Configura entrada do botão 5, FUNÇÃO 1 pinMode(BOT_PROX, INPUT); //Configura entrada do botão 6, FUNÇÃO 2 pinMode(BOT_F1, INPUT); //Configura entrada do botão 5, FUNÇÃO 1 pinMode(BOT_F2, INPUT); //Configura entrada do botão 6, FUNÇÃO 2 pinMode(CILINDRO_H, OUTPUT); //Configura saída para Cilindro Horizontal pinMode(CILINDRO_V, OUTPUT); //Configura saída para Cilindro Vertical pinMode(CILINDRO_A, OUTPUT); //Configura saída para Cilindro Alimentador pinMode(CILINDRO_D, OUTPUT); //Configura saída para Cilindro Datador pinMode(RESISTENCIA_V, OUTPUT); //Configura saída para Resistência Vertical pinMode(RESISTENCIA_H, OUTPUT); //Configura saída para Resistência Horizontal pinMode(RESISTENCIA_D, OUTPUT); //Configura saída para Resistência Datador pinMode(MOTOR_P, OUTPUT); //Configura saída do Motor Puxador
pinMode(CILINDRO_H, LOW); //Configura do estado de saída para Cilindro Horizontal pinMode(CILINDRO_V, LOW); //Configura do estado de saída para Cilindro Vertical pinMode(CILINDRO_A, LOW); //Configura do estado de saída para Cilindro Alimentador pinMode(CILINDRO_D, LOW); //Configura do estado de saída para Cilindro Datador pinMode(RESISTENCIA_V, LOW); //Configura saída para Resistência Vertical pinMode(RESISTENCIA_H, LOW); //Configura saída para Resistência Horizontal pinMode(RESISTENCIA_D, LOW); //Configura saída para Resistência Datador pinMode(MOTOR_P, LOW); //Configura saída para o Motor Puxador////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// t_botao_up = 0x00; //limpa flag do botão up(botão CIMA) t_botao_down = 0x00; //limpa flag do botão down(botão BAIXO) t_select = 0x00; //limpa flag do botão enter; (botão SELECIONAR) t_sair = 0x00; //limpa flag do botão esc; (botão SAIR) t_botao_ant = 0x00; //limpa flag do botão esc; (botão anterior) t_botao_prox = 0x00; //limpa flag do botão esc; (botão próximo) t_botao_f1 = 0x00; //limpa flag do botão esc; (botão função 1) t_botao_f2 = 0x00; //limpa flag do botão esc; (botão função 2)///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// } void loop(){ changeMenu(); dispMenu(); }//----------------------------------Início da configuração dos Botões up e down para o Menu principal---------------------------------------------------------------------------------void changeMenu(){ if(!digitalRead(BOT_UP)) t_botao_up = 0x01; //Botão up pressionado? Seta flag if(!digitalRead(BOT_DOWN)) t_botao_down = 0x01; //Botão down pressionado? Seta flag if(digitalRead(BOT_UP) && t_botao_up) //Botão up solto e flag setada? { //Sim... t_botao_up = 0x00; //Limpa flag GLCD.ClearScreen(); //Limpa display menu++; //Incrementa menu if(menu > 0x04) menu = 0x01; //Se menu maior que 4, volta a ser 1 } //Fim BOT_UP if(digitalRead(BOT_DOWN) && t_botao_down) //Botão down solto e flag setada? { //Sim... t_botao_down = 0x00; //Limpa flag GLCD.ClearScreen(); //Limpa display menu--; //Decrementa menu if(menu < 0x01) menu = 0x04; //Se menu menor que 1, volta a ser 4 } //Fim Botao down } void dispMenu(){ switch(menu) //Controle da variável menu { case 0x01: //Caso 1 Tela_Principa(); //Chama a Tela inicial break; //break case 0x02: //Caso 2 Tela_Principal_2(); //Chama a Tela inicial apenas com um item do menu a qual deseja selecionar break; //break case 0x03: //Caso 4 Tela_Principal_3(); //Chama a Tela inicial apenas com um item do menu a qual deseja selecionar break; //break case 0x04: //Caso 4 Tela_Principal_4(); //Chama a Tela inicial apenas com um item do menu a qual deseja selecionar break; //break } }//----------------------------------- Finalização da configuração dos Botões e do Menu principal----------------------------------------------------------------------------------------- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////----------------------------------------------Início da Telas do Menu Princial--------------------------------------------------------------------------------------------------------- void Tela_Principa() // Tela inicial do menu{ GLCD.CursorToXY(35,0); //(Coluna x Linha) GLCD.print("Pressione");
GLCD.CursorToXY(2,11); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual "); //Escrita no LCD GLCD.CursorToXY(2,22); GLCD.Puts("2->Funcao Auto");
GLCD.CursorToXY(2,32); GLCD.Puts("3->Configuracao");
GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); //padrão da que possa ser exibino no LCD.} //end data_hora
void Tela_Principal_2(){ GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); //padrão da que possa ser exibino no LCD. */ // GLCD.ClearScreen(); dispSubMenu4(); //Segue abaixo }/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //------------------------------------------- INICIO DO SUB MENU PARA TELA PRINCIPLA 2-----------------------------------------------------------------------------------------------------//----------------------------------Início da configuração dos Botões Anterior e Proximo para o Sub Menu principal---------------------------------------------------------------------------------void dispSubMenu4() //Mostra o sub menu atual para o menu 4{ if(!digitalRead(BOT_ANT)) t_botao_ant = 0x01; //Botão Anterior pressionado? Seta flag if(!digitalRead(BOT_PROX)) t_botao_prox = 0x01; //Botão Próximo pressionado? Seta flag if(digitalRead(BOT_ANT) && t_botao_ant) //Botão Anterior solto e flag setada?*/ { //Sim... t_botao_ant = 0x00; //Limpa flag subMenu4++; //incrementa subMenu4 if(subMenu4 > 4) subMenu4 = 0x01; //se maior que 4, volta a ser 1 } //Fim Botão Anterior if(digitalRead(BOT_PROX) && t_botao_prox) //Botão Botão Próximo e flag setada? { //Sim... t_botao_prox = 0x00; //Limpa flag subMenu4--; //decrementa subMenu4 if(subMenu4 < 1) subMenu4 = 0x04; //se menor que 1, volta a ser 4 } //end butM
switch(subMenu4) //Controle da variável subMenu { case 0x01: //Caso 1 GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD
GLCD.CursorToXY(8,8); //Posiciona cursor na coluna e linha GLCD.print(">> Manual 1"); GLCD.CursorToXY(8,18); //Posiciona cursor na coluna e linha GLCD.print("Manual 2 "); GLCD.CursorToXY(8,28); //Posiciona cursor na coluna e linha GLCD.print("Manual 3 "); GLCD.CursorToXY(8,38); //Posiciona cursor na coluna e linha GLCD.print("Manual 4 "); GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC");/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// if(!digitalRead(SAIR)) t_sair = 0x01; //Botão up pressionado? Seta flag subMenu4 = 0x01; if(digitalRead(SAIR) && t_sair && subMenu4) { t_sair = 0x00; // digitalWrite(RESISTENCIA_V, HIGH); dispSubMenu4();
} ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// readSelect(1); //Lê botão select com parâmetro 1 break; //break case 0x02: //Caso 2 GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD
GLCD.CursorToXY(8,8); //Posiciona cursor na coluna e linha GLCD.print("Manual 1 "); GLCD.CursorToXY(8,18); //Posiciona cursor na coluna e linha GLCD.print(">> Manual 2"); GLCD.CursorToXY(8,28); //Posiciona cursor na coluna e linha GLCD.print("Manual 3 "); GLCD.CursorToXY(8,38); //Posiciona cursor na coluna e linha GLCD.print("Manual 4 "); GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); readSelect(2); //Lê botão select com parâmetro 2 break; //break case 0x03: //Caso 3 GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD
GLCD.CursorToXY(8,8); //Posiciona cursor na coluna e linha GLCD.print("Manual 1 "); GLCD.CursorToXY(8,18); //Posiciona cursor na coluna e linha GLCD.print("Manual 2 "); GLCD.CursorToXY(8,28); //Posiciona cursor na coluna e linha GLCD.print(">> Manual 3"); GLCD.CursorToXY(8,38); //Posiciona cursor na coluna e linha GLCD.print("Manual 4 "); GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); readSelect(3); //Lê botão select com parâmetro 3 break; //break
case 0x04: //Caso 4
GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD
GLCD.CursorToXY(8,8); //Posiciona cursor na coluna e linha GLCD.print("Manual 1 "); GLCD.CursorToXY(8,18); //Posiciona cursor na coluna e linha GLCD.print("Manual 2 "); GLCD.CursorToXY(8,28); //Posiciona cursor na coluna e linha GLCD.print("Manual 3 "); GLCD.CursorToXY(8,38); //Posiciona cursor na coluna e linha GLCD.print(">> Manual 4"); GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); readSelect(4); //Lê botão select com parâmetro 4 break; } //Fim switch menu
} //Fim dispMenu
void readSelect(char option) //Leitura do botão select para seleção de subMenus{ if(!digitalRead(select)) t_select = 0x01; //Botão select pressionado? Seta flag if(digitalRead(select) && t_select) //Botão select solto e flag setada? { //Sim... GLCD.ClearScreen(); t_select = 0x00; //Limpa flag
GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD GLCD.CursorToXY(8,8); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print(">> Funcao Manual 1"); //Escrita no LCD GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC");
switch(option) { case 0x01: subMenu4_1(); break; case 0x02: subMenu4_2(); break; case 0x03: subMenu4_3(); break;
case 0x04: subMenu4_4(); break; } //end switch option } //end if
} //end readSelect
void subMenu4_1() //Início dos Submenu{ while(1) { //--------------------------------Início da configuração dos Botões Função 1 e 2 para o Sub Menu principal, Cilindros Vertical e Horizontal------------------------------------------------
if(!digitalRead(BOT_F1)) t_botao_f1 = 0x01; //Botão Função 1 pressionado? Seta flagif(!digitalRead(BOT_F2)) t_botao_f2 = 0x01; //Botão Função 2 pressionado? Seta flag if(digitalRead(BOT_F1) && t_botao_f1) //Botão Função 1 solto e flag setada? { //Sim... t_botao_f1 = 0x00; //Limpa flag set1++; //Incrementa set1 if(set1 > 2) set1 = 0x01; //Se maior que 2, volta a ser 1 switch(set1) //Controle do set1 { case 0x01: //Caso 1
GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD GLCD.CursorToXY(8,8); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print(">> Funcao Manual 1");
GLCD.CursorToXY(12,18); //Posiciona cursor na coluna e linha GLCD.print("Cilindro Vertical"); GLCD.CursorToXY(48,26); //Posiciona cursor na coluna e linha GLCD.print("OFF/ "); //Mostrador (apenas ilustrativo......) digitalWrite(CILINDRO_H, LOW); //Avança Cilindro GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC");
break; //Break case 0x02: //Caso 2
GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD GLCD.CursorToXY(8,8); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print(">> Funcao Manual 1");
GLCD.CursorToXY(12,18); //Posiciona cursor na coluna e linha GLCD.print("Cilindro Vertical"); GLCD.CursorToXY(48,26); //Posiciona cursor na coluna e linha GLCD.print(" /ON"); //Mostrador (apenas ilustrativo......) digitalWrite(CILINDRO_H, HIGH); //Recua Cilindro GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); break; //Break } //Fim switch set1 } //Fim Função 1 if(digitalRead(BOT_F2) && t_botao_f2) //Botão Função 2 solto e flag setada? { //Sim... t_botao_f2 = 0x00; //Limpa flag set2++; //Incrementa set2 if(set2 > 2) set2 = 0x01; //Se maior que 2, volta a ser 1 switch(set2) //Controle do set2 { case 0x01: //Caso 1 GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD GLCD.CursorToXY(8,8); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print(">> Funcao Manual 1"); GLCD.CursorToXY(8,36); //Posiciona cursor na coluna e linha GLCD.print("Cilindro Horizontal "); GLCD.CursorToXY(48,44); //Posiciona cursor na coluna e linha GLCD.print("OFF/ "); //Mostrador (apenas ilustrativo......) digitalWrite(CILINDRO_V, LOW); //Avança cilindro GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); break; //Break case 0x02: //Caso 2 GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD GLCD.CursorToXY(8,8); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print(">> Funcao Manual 1"); GLCD.CursorToXY(8,36); //Posiciona cursor na coluna e linha GLCD.print("Cilindro Horizontal "); GLCD.CursorToXY(48,44); //Posiciona cursor na coluna e linha GLCD.print(" /ON"); //Mostrador (apenas ilustrativo......) */ digitalWrite(CILINDRO_V, HIGH); //Recua cilindro GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); break; //Break} //Fim switch set1 } //Fim d0 Botão Função 2 } //Fim do while(1) } //Fim subMenu4_1
void subMenu4_2(){ while(1) {if(!digitalRead(BOT_F1)) t_botao_f1 = 0x01; //Botão Função 1 pressionado? Seta flagif(!digitalRead(BOT_F2)) t_botao_f2 = 0x01; //Botão Função 2 pressionado? Seta flag if(digitalRead(BOT_F1) && t_botao_f1) //Botão Função 1 solto e flag setada? { //Sim... t_botao_f1 = 0x00; //Limpa flag set1++; //Incrementa set1 if(set1 > 2) set1 = 0x01; //Se maior que 2, volta a ser 1 switch(set1) //Controle do set1 { case 0x01: //Caso 1
GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD
GLCD.CursorToXY(6,8); //Posiciona cursor na coluna e linha GLCD.print("Cilindro Alimentador"); GLCD.CursorToXY(48,18); //Posiciona cursor na coluna e linha GLCD.print("ON/ "); //Mostrador (apenas ilustrativo......) digitalWrite(CILINDRO_A, HIGH); //Avança Cilindro GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); break; //Break case 0x02: //Caso 2
GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD
GLCD.CursorToXY(6,8); //Posiciona cursor na coluna e linha GLCD.print("Cilindro Alimentador"); GLCD.CursorToXY(48,18); //Posiciona cursor na coluna e linha GLCD.print(" /OFF"); //Mostrador (apenas ilustrativo......) digitalWrite(CILINDRO_A, LOW); //Recua Cilindro GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); break; //Break } //Fim switch set1 } //Fim Função 1 if(digitalRead(BOT_F2) && t_botao_f2) //Botão Função 2 solto e flag setada? { //Sim... t_botao_f2 = 0x00; //Limpa flag set2++; //Incrementa set2 if(set2 > 2) set2 = 0x01; //Se maior que 2, volta a ser 1 switch(set2) //Controle do set2 { case 0x01: //Caso 1 GLCD.CursorToXY(18,28); //Posiciona cursor na coluna e linha GLCD.print("Cilindro Datador "); GLCD.CursorToXY(48,38); //Posiciona cursor na coluna e linha GLCD.print("ON/ "); //Mostrador (apenas ilustrativo......) digitalWrite(CILINDRO_D, HIGH); //Avança cilindro GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); break; //Break case 0x02: //Caso 2 GLCD.CursorToXY(18,28); //Posiciona cursor na coluna e linha GLCD.print("Cilindro Datador "); GLCD.CursorToXY(48,38); //Posiciona cursor na coluna e linha GLCD.print(" /OFF"); //Mostrador (apenas ilustrativo......) */ digitalWrite(CILINDRO_D, LOW); //Recua cilindro GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); break; //Break} //Fim switch set1 } //Fim d0 Botão Função 2 } //Fim do while(1) } //Fim subMenu4_2void subMenu4_3(){ while(1) {if(!digitalRead(BOT_F1)) t_botao_f1 = 0x01; //Botão Função 1 pressionado? Seta flagif(!digitalRead(BOT_F2)) t_botao_f2 = 0x01; //Botão Função 2 pressionado? Seta flag if(digitalRead(BOT_F1) && t_botao_f1) //Botão Função 1 solto e flag setada? { //Sim... t_botao_f1 = 0x00; //Limpa flag set1++; //Incrementa set1 if(set1 > 2) set1 = 0x01; //Se maior que 2, volta a ser 1 switch(set1) //Controle do set1 { case 0x01: //Caso 1
GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD
GLCD.CursorToXY(4,8); //Posiciona cursor na coluna e linha GLCD.print("Resistencia Vertical "); GLCD.CursorToXY(48,18); //Posiciona cursor na coluna e linha GLCD.print("ON/ "); //Mostrador (apenas ilustrativo......) digitalWrite(RESISTENCIA_V, HIGH); //Liga Resistencia Vertical GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); break; //Break case 0x02: //Caso 2
GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD
GLCD.CursorToXY(4,8); //Posiciona cursor na coluna e linha GLCD.print("Resistencia Vertical "); GLCD.CursorToXY(48,18); //Posiciona cursor na coluna e linha GLCD.print(" /OFF"); //Mostrador (apenas ilustrativo......) digitalWrite(RESISTENCIA_V, LOW); //Desliga Resistencia Vertical GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); break; //Break } //Fim switch set1 } //Fim Função 1 if(digitalRead(BOT_F2) && t_botao_f2) //Botão Função 2 solto e flag setada? { //Sim... t_botao_f2 = 0x00; //Limpa flag set2++; //Incrementa set2 if(set2 > 2) set2 = 0x01; //Se maior que 2, volta a ser 1 switch(set2) //Controle do set2 { case 0x01: //Caso 1 GLCD.CursorToXY(2,28); //Posiciona cursor na coluna e linha GLCD.print("Resistencia Horizont. "); GLCD.CursorToXY(48,38); //Posiciona cursor na coluna e linha GLCD.print("ON/ "); //Mostrador (apenas ilustrativo......) digitalWrite(RESISTENCIA_H, HIGH); //Liga Resistencia Horizontal GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); break; //Break case 0x02: //Caso 2 GLCD.CursorToXY(2,28); //Posiciona cursor na coluna e linha GLCD.print("Resistencia Horizont. "); GLCD.CursorToXY(48,38); //Posiciona cursor na coluna e linha GLCD.print(" /OFF"); //Mostrador (apenas ilustrativo......) */ digitalWrite(RESISTENCIA_H, LOW); //Desliga Resistencia Horizontal GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); break; //Break} //Fim switch set1 } //Fim d0 Botão Função 2 } //Fim do while(1) } //Fim subMenu4_3void subMenu4_4(){ while(1) {if(!digitalRead(BOT_F1)) t_botao_f1 = 0x01; //Botão Função 1 pressionado? Seta flagif(!digitalRead(BOT_F2)) t_botao_f2 = 0x01; //Botão Função 2 pressionado? Seta flag if(digitalRead(BOT_F1) && t_botao_f1) //Botão Função 1 solto e flag setada? { //Sim... t_botao_f1 = 0x00; //Limpa flag set1++; //Incrementa set1 if(set1 > 2) set1 = 0x01; //Se maior que 2, volta a ser 1 switch(set1) //Controle do set1 { case 0x01: //Caso 1
GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD
GLCD.CursorToXY(8,8); //Posiciona cursor na coluna e linha GLCD.print("Resistencia Datador "); GLCD.CursorToXY(48,18); //Posiciona cursor na coluna e linha GLCD.print("ON/ "); //Mostrador (apenas ilustrativo......) digitalWrite(RESISTENCIA_D, HIGH); //Liga Resistencia do Datador GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); break; //Break case 0x02: //Caso 2
GLCD.CursorToXY(0,0); //Posição na matriz(1- MENU) do LCD(localização) GLCD.print("1->Funcao Manual"); //Escrita no LCD
GLCD.CursorToXY(8,8); //Posiciona cursor na coluna e linha GLCD.print("Resistencia Datador "); GLCD.CursorToXY(48,18); //Posiciona cursor na coluna e linha GLCD.print(" /OFF"); //Mostrador (apenas ilustrativo......) digitalWrite(RESISTENCIA_D, LOW); //Desliga Resistencia do Datador GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); break; //Break } //Fim switch set1 } //Fim Função 1 if(digitalRead(BOT_F2) && t_botao_f2) //Botão Função 2 solto e flag setada? { //Sim... t_botao_f2 = 0x00; //Limpa flag set2++; //Incrementa set2 if(set2 > 2) set2 = 0x01; //Se maior que 2, volta a ser 1 switch(set2) //Controle do set2 { case 0x01: //Caso 1 GLCD.CursorToXY(32,28); //Posiciona cursor na coluna e linha GLCD.print("Motor Puxador "); GLCD.CursorToXY(48,38); //Posiciona cursor na coluna e linha GLCD.print("ON/ "); //Mostrador (apenas ilustrativo......) digitalWrite(MOTOR_P, HIGH); //Liga do Motor do Puxador GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); break; //Break case 0x02: //Caso 2 GLCD.CursorToXY(32,28); //Posiciona cursor na coluna e linha GLCD.print("Motor Puxador "); GLCD.CursorToXY(48,38); //Posiciona cursor na coluna e linha GLCD.print(" /OFF"); //Mostrador (apenas ilustrativo......) */ digitalWrite(MOTOR_P, LOW); //Desliga do Motor do Puxador GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); break; //Break} //Fim switch set1 } //Fim d0 Botão Função 2 } //Fim do while(1) } //Fim subMenu4_4//--------------------------------------------Finalização do Sub menu da Tela Principal_2(), existente no Menu principal-------------------------------------------------------------------/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //--------------------------------------------Continaução do Menu Principla com as Tela Principal_3(), Tela Principal_4()-------------------------------------------------------------------void Tela_Principal_3(){ GLCD.CursorToXY(2,11); //Posiciona cursor na coluna e linha GLCD.Puts("2->Funcao Auto"); //Mostrador (apenas ilustrativo......)
GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); //padrão da que possa ser exibino no LCD.*/ }
void Tela_Principal_4(){ GLCD.CursorToXY(2,22); //Posiciona cursor na coluna e linha GLCD.Puts("3->Configuracao"); //Mostrador (apenas ilustrativo......)
GLCD.DrawLine(0,52,127,52); //linha desenhada prox. do roda pé GLCD.CursorToXY(2,55); //Posição na matriz(ENTER) do LCD(localização) GLCD.Puts("ENTER"); GLCD.CursorToXY(109,55); //Posição na matriz(ESC) do LCD(localização), todos seguem esse GLCD.Puts("ESC"); //padrão da que possa ser exibino no LCD.*/
}
…
stou apanhando com o código C
17:59
EuDo Arduino?
Leonardo Borges da Silvasim
EuQue tipo de robo?
Leonardo Borges da Silvamontei ele com duas rodas com motores DC
com uma ponte h
e um sonar
fiz os motores funcionarem
e o sonar tambem
mais não consigo criar a variavel que faz ele desviar das coisas
18:01
Leonardo Borges da Silvacriei um tópico
EuCom o sensor é possível saber a que distância está o obstáculo?
Leonardo Borges da Silvasim
fiz um topico com algumas fotos e o código que estou tentando utilizar
Primeiro Projeto Arduino, Dúvidas
18:04
EuEntão vc. precisa de 2 variáveis para controle a atual e a anterior, quando a atual for menor que a anterior, você deve comparar com o outro sensor. Se as variaveis atuais dos 2 sensores estiverem menores que a anterior, significa que o robo está se aproximando de um obstáculo sem chance de desviar. você deve retornar os 2 motores, se um dos lados estiver a atual maior que a anterior, significa que ali há um espaço de escape. deve acionar o motor do lado contrário e vice-versa.
18:06
EuVocê está usando sensores sonares?
Leonardo Borges da Silvasim
entendi o que vc me explicou
EuConsegue ter a medida de distância com eles?
Leonardo Borges da Silvamais não consigo colocar isso em C
consigo
EuVocê tem quantos sensores?
Leonardo Borges da Silva1 só
18:08
EuEntão o máximo que pode fazer é tentar desviar para um só lado, e torcer para que haja espaço, ou então refazer o teste de distância e virar para o outro lado, ou dar marcha a ré.
Leonardo Borges da Silvaé esse aqui o sensor
http://www.robocore.net/modules.php?name=GR_LojaVirtual&prod=190
você pode me mostrar um exemplo ?
se não for te trapalhar é claro
EuEu tenho um sensor desses aqui, mas ainda não o usei para este tipo de aplicação. Mas vc. entendeu a lógica que lhe expliquei?
Espere que vou lá ver se é igual ao meu.
Leonardo Borges da Silvaentendi a lógica
mais como não entendo muito da linguagem
tenho dificuldades em digitar o código
18:12
EuEspere que vou dar uma olhada no manual.
Leonardo Borges da SilvaOk muito Obrigado
18:14
EuA conecção com o Arduino está TTL ou PWM?
Leonardo Borges da SilvaPWM
18:16
EuEntre os motores e as rodas qual está sendo a redução?
18:18
Leonardo Borges da Silvanão esta especificado
eu comprei a base pronta
http://lojabrasilrobotics.blogspot.com.br/2011/10/plataforma-robotica-w-r14500.html
é essa aqui
eu abri um topico e coloquei algumas fotos
18:20
EuVc. chegou a ver isso: http://letsmakerobots.com/node/5629
Leonardo Borges da Silvaolhei sim
18:22
Leonardo Borges da Silvamais não entedi
entendi**
18:22
EuEste é o exemplo indicado lá no site do sensor. O meu é diferente do seu, não tem tantos pinos.
Leonardo Borges da Silvahummm entendi
você viu o código que eu fiz e não deu certo ?
EuAinda não vc. não passou o link. Veja como este tipo de robo e comporta:http://blog.makezine.com/2009/03/05/mr-green-an-arduino-robot/
18:27
Leonardo Borges da Silvaaqui o post
http://labdegaragem.com/forum/topics/primeiro-projeto-arduino-d-vidas?commentId=6223006%3AComment%3A173742&xg_source=msg_com_forum
EuVeja que o sensor é movido de um lado para o outro para que ele "veja" se há escapatória quando está em vias de se chocar com algo.
Leonardo Borges da Silvaeu vi esse video
EuColocou isso no seu?
Leonardo Borges da Silvaestava focando nesse projeto porem sem o LCD e o Buzzer
http://ferpinheiro.wordpress.com/2012/03/09/criando-robo-com-arduino-parte-iv-montando-o-robo/
EuIsso poupa ter que colocar mais de um sensor no robo.
Vou lá no link que me passou.
Leonardo Borges da Silvaok obrigado
18:30
Leonardo Borges da Silvaum rapaz deixou um exemplo vc viu ?
18:42
EuSe vc. não alterou este código, está tentando usar o pino 5 para 2 coisas diferentes:
int URTRIG=5; // PWM trigger pin int E1 = 4; int M1 = 5;
URTRIG e M1 são diferentes certo?
Pode ser por isso que seu motor não está parando de girar.
Leonardo Borges da Silvasim o M1 é o motor
URTRIG é do sonar
verdade não tinha reparado nisso
EuAltera lá e testa.
Leonardo Borges da Silvaok vou fazer issoagora
18:45
EuOutra, procure usar um padrão de nomes que inclua o uso do IO. Tipo variáveis de pinos de entrada inicie com "I_" (input) e variáveis de pinos de saídas inicie com "O_" (outputs), isso evita estas dúvidas.
I_Sensor = Input do sensor.
O_M1 = Saída de acionamento do motor 1.
Entendeu?
Leonardo Borges da Silvaentendi
18:49
EuIsolando o que cada pino faz, acho que agora fica mais fácil. Leia novamente o que o Jonatas escreveu. Não dá para pular etapas, se não começar pelo Blink...vai faltar coisas no meio do caminho.
18:51
EuLeia a distância do sensor, e acione os motores de acordo com a lógica que vc. deseja que seja executada para que o robo não saia "batendo" em tudo por aí.
Leonardo Borges da Silvavou tentar aqui
EuMas importante: Os delays entre leituras e acionamentos tem que ser bem pensados, verifique as reduções entre os motores e as rodas e "equilibre" de acordo.
18:53
EuTipo: Leia o sensor, mostre a distância, execute um delay( tempo) e faça um acionamento "lento" para que vc. possa entender em que parte do programa o que está ocorrendo está sendo executado. quando tiver tudo redondo, aí retire ou remarque os delays. Já que o Arduino é "pobre" em debug.
Acha que daqui pra frente vai?
Leonardo Borges da Silvaeu alterei o pino mais não aconteceu nada
acho que vou começar do zero
como eu consigo "testar" tipo
18:56
Leonardo Borges da Silvauma variavel
que eu consiga falar para o motor ligar com certa distancia
que o sonar me retornar
acho que assim eu entendendo um exemplo consiga o restante
18:56
Euif ( position <= 50){ faça alguma coisa...// delay(10);
};
verifique se vc. não está "mandando" sinal digital onde se espera um acionamento analógico.
Leonardo Borges da Silvaok vou tentar fazer esse teste
19:01
EuAfinal o controle dos motores está por PWM né?
19:02
EuEntão nos pinos dos motores tem que ser AnalogWrite!
Leonardo Borges da Silvanossa verdade
EuAí se uma hora vc. manda Digital outra hora vc. manda Analog fica difícil...
Leonardo Borges da Silvanão preciso do PLL
EuAí o motor não para, ou despara...ou repara...
19:05
EuIsso são "detalhezinhos" que todo programador deve ter no "sangue"....senão imagine quando aparecer coisas "complicadas"????....rsrsrsss...
Leonardo Borges da Silvahauhauahuauh verdade
to terminando aqui ai posso te enviar para vc dar uma olhada ?
19:07
EuNão tenho como testar aqui. Vou ver se copio este tópico lá e vc. coloca como resposta.
…
eferência para seu Sistema atual e suas futuras implementações. E depois de publicado este, irei fazer uma pequena melhoria em termos de desempenho na precisão do processo de medir o Fluxo (ou a RPM de algo em um Sistema), e publicarei aqui também.
Não deixe de ler todo o texto, pois há considerações importantes nele.
Lembrando que este tópico é praticamente uma continuação de outro do J. Leonardo, onde publiquei uma implementação inicial, e que está neste link: "Medição Vazão 1"
Mas antes, comentando sobre as fotos do seu Sistema, ficou bem legal, e tem até uma personalização identificando o equipamento ("Hidrômetro Digital"). Vi também que o módulo Bluetooth HC-05 já está conectado no Sistema, e sobre isto, comento no final do post.
Como de costume, quando possível implemento também uma simulação, o que permite que aqueles que não tem o Hardware em mãos, possam testar, fazer experimentações, e aprender com isso.
Para a simulação, aproveitei o Sistema que eu já tinha publicado antes naquele seu outro tópico. Apenas tive que acrescentar no Hardware, a parte dos dois Botões de Controle e dos dois LEDs de sinalização de alertas. Também fiz um pequeno ajuste no circuito que "emula" o Sensor de Fluxo, a fim de que ele tivesse uma faixa de ajuste da "Vazão" mais de acordo com a faixa que vc está usando. O arquivo para simulação no Proteus está anexado no final do post.
Então começando pela simulação, o circuito pode ser visto na figura a seguir:
(clique na figura para "zoom")
Na figura a seguir, pode-se ver o resultado após quase 14 segundos de simulação (este tempo é "virtual").
(clique na figura para "zoom")
No Display LCD é exibida a informação conforme selecionada via Botões de controle "Up" e "Down", e no Terminal do Arduino são "printados" dados a cada segundo (ou seja, a cada vez que é obtida uma nova amostragem da Vazão).
Nota-se que além da Vazão "instantânea", também é "printado" no Terminal do Arduino, a Vazão Média (sobre a qual falo mais adiante), a qual vai aumentando até praticamente se igualar ao valor instantâneo (como esperado).
Mas após isso, eu aumentei em "TP10" (o Trimpot para ajuste do Fluxo), para que a Vazão ficasse acima do Limite (que é 1 L/minuto).
O tempo necessário para detectar a Vazão Limite é de 5 minutos conforme o J. Leonardo especificou, ou seja, a Vazão tem que ficar acima do Limite por 5 minutos para que seja emitido um alerta. Porém, apenas na simulação eu diminui este tempo para 1 minuto, para não ter que esperar muito para ver o resultado.
E este resultado pode ser visto na figura a seguir, que mostra ligado o LED vermelho "Alerta Vazão":
(clique na figura para "zoom")
Nota-se também que pelo tempo decorrido, que novamente o valor da Vazão Média praticamente já igualou a Vazão instantânea.
Agora falando sobre o código, cujo link para download está no final do post.
Um ponto importante a salientar, é que o Sistema calcula continuamente a Vazão Média, e usa esse valor como referência para determinar se a Vazão Limite (no caso, 1 L/minuto) foi excedida (claro, após se manter assim por tempo determinado). Isso é necessário porque a Vazão "instantânea" terá variações, o que poderá impedir o Sistema de detectar o limite e emitir um alerta. Exemplo: a Vazão Limite é de 2 L/minuto e a Vazão instantânea está em 2,1 L/min a algum tempo, mas cai por 3 segundos para 1,9 L/min, e em seguida volta a subir indo para 2,3 L/min. Neste caso, quando a Vazão caiu momentaneamente para 1,9 L/min, isto interromperia a contagem de tempo para emissão de um alerta, o que seria um problema caso essas quedas ficassem ocorrendo e impedindo o alerta de ser emitido. Usando a Vazão Média, diminui-se a possibilidade desse problema, uma vez que variações momentâneas na Vazão, terão efeito menor no valor da Vazão Média.
No código, você pode determinar quantas amostras irão compor a Vazão Média, conforme mostro mais adiante.
Além de usar a Vazão Média para o alerta, o código também tem uma tolerância para o valor da Vazão Limite, sendo esta tolerância sempre "para baixo" (já que não teria sentido ser também "para cima"). Exemplo: se a Vazão Limite é de 2 L/min, e a tolerância é definida para 10%, então o Sistema considera como valor limite efetivo, os 2 L/min menos 10% de 2 L/min. Ou seja, 2 - 0.1 x 2 = 1,8 L/minuto. A tolerância pode ser facilmente alterada no código (como mostro adiante), e caso não se deseje utilizá-la basta então especificar uma tolerância de 0%.
A verificação para alerta de Vazão Limite, é temporizada, ou seja, é feita em intervalos de tempo. No código, este intervalo de tempo está especificado em segundos (como mostro logo adiante). Como resultado, esta temporização também ajuda a minimizar alertas errôneos, uma vez que pequenas variações podem até ser ignoradas pelo Sistema. Exemplo: a Vazão Média está próxima ao limite mas abaixo dele, e fica acima desse limite por 5 segundos, voltando a ficar abaixo em seguida, e como isso ocorre entre dois intervalos de verificação, a variação acaba não sendo detectada (mas seria, se fosse efetiva e ficasse mais tempo acima do limite).
Outros detalhes de definições no código, são descritos a seguir na ordem que eles aparecem no próprio código. Lembrando que logo no início do código, estão definidos os parâmetros mais significativos e que são normalmente os mais alterados em implementações diversas. A quantidade de parâmetros é um pouco extensa, e além das definições de parâmetros constantes, há também algumas variáveis/flags importantes para o funcionamento do Sistema. No texto a seguir, descrevo os tais parâmetros mais significativos e aponto algumas funções mais relevantes para o Sistema.
A figura a seguir, mostra a definição dos fatores para cálculo da Vazão "instantânea" e da conta de água.
(clique na figura para "zoom")
O "fator_Vazão" permite o cálculo da Vazão "instantânea" em mili-Litros por segundo. Assim no código, para se obter a Vazão em Litros por minuto, basta multiplicar a Vazão instantânea por 60 (já que 60 segundos= 1 minuto) e dividir por 1000 (já que 1000 mili-Litros = 1 Litro).
Na figura a seguir, são mostrados os parâmetros usados para determinar se o Sistema deve emitir um alerta de Vazão acima de um limite definido. A figura é auto-explicativa, uma vez que os comentários no código descrevem cada parâmetro e explicam como são usados.
(clique na figura para "zoom")
O Sistema emite também um alerta quando o consumo total (o fluxo total acumulado), ultrapassa um limite estabelecido. A figura a seguir, mostra a definição deste limite, em metros cúbicos:
(clique na figura para "zoom")
Observar que como o fluxo é sempre cumulativo, não é necessário tratamento especial (como calcular um valor médio) para se detectar um limiar e consequentemente emitir um alerta.
Além de mensagem no Display LCD, dois LEDs são usados para sinalizar o alerta de Vazão Limite e alerta de fluxo total acumulado. A figura a seguir mostra as definições para uso destes LEDs no Sistema:
(clique na figura para "zoom")
Sinalizar através de LED é uma forma eficiente de emitir um alerta (alertas auditivos geralmente são mais eficientes, mas nem sempre são os mais adequados devido ao "barulho" resultante). Mas é preciso considerar a cor usada para o alerta visual, neste caso a cor da luz que os LEDs emitem. Eu projetei Equipamentos Eletro-Médicos por 25 anos, e conheço bem as normas relacionadas a alertas naqueles equipamentos (normas compulsórias neste caso), onde alertas visuais devem se restringir a cores como "amarelo", "laranja", "vermelho", e tons semelhantes. Ou seja, não tem sentido sinalizar um alerta com uma cor como "verde" ou "azul" (ou mesmo "branco"). Aqui neste tópico não estamos tratando de equipamentos médicos, mas observem que o bom senso do uso das cores também se aplica de forma muito natural para sinalizarmos alertas.
Para selecionar a informação exibida no Display, são usados dois Botões chamados de "Up" e "Down". Acredito que apenas um Botão seria suficiente para esta função, mas o J. Leonardo optou por dois. Mas além disso, um Botão a mais permite mais opções de uso, e isso certamente será necessário se as funcionalidades do código forem expandidas por quem assim desejar (é bem provável que um terceiro e um quarto Botão sejam bem vindos). Os dois Botões são definidos conforme mostra a figura a seguir:
(clique na figura para "zoom")
Como o Sistema é originalmente para o Arduino UNO (ou seja, com Processador "AVR"), o código automaticamente ligará o Resistor de Pullup interno no pino dos Botões, caso o Nível Lógico de acionamento (com nome "logica_Botao_ON" na figura anterior) seja "LOW", assim dispensando um Pullup externo. Lembrando que o Pullup interno do AVR tem um valor com alta-tolerância, podendo ir de 20 kΩ a 50 kΩ (depende da tensão de alimentação, sendo que tensões mais altas neste caso implicam em impedâncias mais baixas, pois são usados MOSFETs para "construir" os Resistores de pullup). Caso o código seja usado em Sistemas com outros Processadores que permitam também "Pulldown" (como ESP32, STM32, Arduino Due, etc), então pode-se usar a mesma técnica para ligar automaticamente ou o "Pullup" ou o "PullDown" (ou mesmo nenhum deles, caso se especifique que um Resistor externo esteja sendo usado).
Para eliminar o "bouncing" (ou trepidação mecânica) resultante do acionamento de um Botão, e assim impedir acionamentos errôneos consecutivos, o Sistema implementa um "tempo de debouncing". Assim quando um Botão é acionado, o Sistema ignora qualquer outro acionamento no mesmo botão, pelo "tempo de debouncing", e isso faz com que a trepidação mecânica não tenha efeito. Como existem Botões de todo tipo no mercado e com maior ou menor trepidação mecânica, é preciso definir qual o tempo de "debouncing" a ser utilizado no Sistema, e isto pode ser visto na figura a seguir:
(clique na figura para "zoom")
Por razões óbvias, este tempo está especificado em unidades de mili-segundos. O tempo de 100 [ms] definido na figura anterior, é geralmente mais que suficiente mesmo para os "piores" Botões, mas pode-se diminuir ou aumentar o mesmo caso seja desejado. Este tempo não tem efeito na detecção imediata do Botão, ou seja, quando um Botão é acionado ele será imediatamente detectado. Claro, se o tempo for especificado como "0" (zero), então o "tempo de debouncing" não terá efeito (ou seja, as trepidações mecânicas no acionamento provocarão diversos acionamentos).
Como já dito, o Sistema emite dois alertas: um de Vazão Limite e um alerta de Fluxo acumulado (um "alerta de consumo" total). Para ambos, há LEDs específicos para emissão de alerta visual. O alerta de Vazão Limite também é exibido periodicamente no Display (conforme descrito mais adiante). Caso seja desejado emitir outras formas de alerta, pode-se testar as Flags específicas para cada um dos dois alertas. Estas Flags são variáveis do tipo "bool" (ou "boolean"), e assumem o valor "true" ou o valor "false". Quando um alerta é emitido, a Flag respectiva vai ao valor "true". As variáveis correspondentes a estas Flags, são definidas conforme mostrado na figura a seguir:
(clique na figura para "zoom")
Logo, estas Flags podem ser testadas a qualquer momento e em qualquer ponto do código, para se saber se o alerta correspondente foi emitido. Lembrando que o consumo acumulado só aumenta, e portanto quando fica além do limite definido para alerta, este alerta passa a ser constante, ou seja, o LED de alerta fica permanentemente ligado e a Flag de alerta passa a ficar em "true" (e não volta mais para "false").
Também como dito antes, o Sistema calcula continuamente a Vazão Média em Litros por minuto, e para isso ele mantém um registro das últimas "N" amostras da Vazão instantânea. Esta quantidade "N" é definida conforme mostrado na figura a seguir:
(clique na figura para "zoom")
A Vazão Média será então o resultado do somatório das últimas "N" amostras, dividido pelo valor "N". No código este total de registros está definido como sendo 10 (dez), mas pode ser alterado conforme desejado (lembrando que quanto maior a quantidade de registros, mais memória RAM é usada para manter estes registros, e mais tempo o Sistema gasta para fazer os cálculos da Vazão Média).
Nota: a página do post não comporta o restante do texto, então estou continuando logo a seguir:
…
Adicionado por Elcids Chagas ao 1:09 em 20 novembro 2020