Resultados da busca - %E6%81%92%E8%BE%BE%E7%99%BB%E5%BD%95%E7%94%A8%E6%88%B7%E5%90%8D%E6%98%AF%E4%BB%80%E4%B9%88%E6%84%8F%E6%80%9D%E3%80%90%E2%94%83%E5%A5%BD%E8%AE%A1%E5%88%922%E2%92%8F7%E2%92%8F01705%7B%EF%BC%B1%E3%80%91%E3%80%91
. Por isso, acho que, TALVEZ, sua dificuldade seja MUITO introdutória, pois existem 999999999999 vídeos que falam sobre isso. Entretanto, ninguém é dono do saber e, qualquer pessoa quando não sabe por onde começar, costuma perguntar a alguém, e da mesma forma, a ideia do fórum é ajudar a todos, então vamos lá. :)
Primeiro vamos do básico
- O Arduino possui 18 portas digitais (sendo que 5 delas também são analógicas - A0 até A5).
- As portas digitais realizam leituras ou escritas, enviando/recebendo um "ALTO/HIGH/'1'/5v" ou "Baixo/LOW/'0'/0v". Lembrando que a corrente máxima de saída é de 40ma, mas costumo ver o pessoal contraindicando o uso com esta corrente.
- As portas analógicas, quando definidas por código para este serviço, servem apenas para a leitura, oferecendo uma escala de 0 á 1023. (0 = 0v, 1023 = 5v).
Na programação do Arduino, temos 2 funções principais:
- Setup (configuração inicial)
- Loop (aqui o código fica girando eternamente).
Como seu objetivo é acionar 4 relés através de 4 botões, você pode utilizar 4 pinos digitais para LEITURA, e mais 4 pinos digitais para ESCRITA. Para isso, vamos definir na função "SETUP" a configuração dos pinos.
pinMode(4, INPUT); // Define o pino 4 como entrada.
pinMode(5, INPUT); // Define o pino 5 como entrada.
pinMode(6, INPUT); // Define o pino 6 como entrada.
pinMode(7, INPUT); // Define o pino 7 como entrada.
pinMode(8, OUTPUT); // Define o pino 8 como SAIDA.
pinMode(9, OUTPUT); // Define o pino 9 como SAIDA.
pinMode(10, OUTPUT); // Define o pino 10 como SAIDA.
pinMode(11, OUTPUT); // Define o pino 11 como SAIDA.
Como temos 4 pinos de saida, por padrão define-se a situação dele como "ALTO/BAIXO" a depender da ação desejada.
No seu caso, como deseja iniciar com tudo desligado, adicionaríamos mais esta linha:
digitalWrite(8, LOW); //Define como "Baixo/LOW/'0'/0v" o pino 8
digitalWrite(9, LOW); //Define como "Baixo/LOW/'0'/0v" o pino 8
digitalWrite(10, LOW); //Define como "Baixo/LOW/'0'/0v" o pino 8
digitalWrite(11, LOW); //Define como "Baixo/LOW/'0'/0v" o pino 8
A titulo de debug, você pode iniciar a serial:
Serial.begin(9600);
======== Aqui finalizam as configurações iniciais. =========
Agora vamos para a parte da função do Loop. O primeiro passo é ler os valores das entradas digitais e atribuir uma ação, para isso iremos utilizar a seguinte chamada:
if (digitalRead(4) == HIGH) { //Aqui criamos uma condição para "quando o pino 4 estiver 'alto')
digitalWrite(8, HIGH) // caso a condição seja verdadeira, definimos o pino 8 como ALTO.
Serial.println("botão 4 ON"); // visualiza no serial monitor a informação quando esta for verdadeira.
} // concluir a condição inicial
else { // Caso a condição seja falsa, ocorre uma ação diferente
digitalWrite(8, LOW) // Neste caso, o pino 8 ficará como baixo
Serial.println("botão 4 OFF"); // visualiza no serial monitor a informação quando esta for verdadeira.
} // finaliza a condição falsa
Observe que o mesmo irá ocorrer para todos os outros pinos.
Observe também que, desta forma, os pinos só ficarão como ALTOS enquanto a entrada estiver recebendo tensão. Logo, se seu botão for um pushbutton (daqueles que ele só fica habilitado enquanto estiver pressionado), será necessário que ele fique sempre pressionado para a entrada ficar em alto.
obs- Caso seja necessário que o botão se comporte como um interruptor, será necessário adaptar o código ou trocar o botão.
Sabendo disso, o próximo passo é ligar os fios e os botões. Aqui não tem mistério.
1- Os botões costumam ter 2 pinos.
2- Ligue o +5v a um destes pinos, e o outro ligue numa entrada digital. Repita o processo para todos os botões/pinos.
obs- A ligação de +5v pode ser feita de botão para botão também, entretanto, o segundo pino do botão não pode ser ligado aos outros. Cada botão deverá ir separadamente para uma entrada digital (neste caso, as entradas 4 á 7).
obs2- se quiser pode colocar um resistor para cada entrada digital, talvez promova alguma segurança (alguém aqui saberá lhe informar melhor, pois os testes que fiz, para este fim, foram muito curtos).
O próximo passo, dependerá do seu rele. Pois tem uns módulos cheio de wifi/usb/uhf/vhf/gps/nasa/dragonballZ/etc.. Se for os modelos simples de 5v, basta ligar a saída digital (8~11) na entrada de sinal de cada um deles, e o GND conectado ao Arduíno.
Ouvi falar que o relé tem um retorno... não tenho certeza. Mas qualquer vídeo que fala sobre módulos de rele irá apontar isso (pois posso estar me confundindo).
No rele, você tem: "saida normalmente aberto", "saida normalmente fechado", "entrada para alimentação". A diferença entre eles é a seguinte:
- Quando o arduino der um sinal baixo/low, o "normalmente aberto" irá fazer a ponte entre a entrada e a lampada.- Quando o arduino der um sinal alto/HIGH, o "normalmente fechado" é que irá fazer a ponte.
(obs: Alguns reles trabalham de forma inversa)
Sendo assim, você conecta o positivo (ou GND) ao rele, e o outro direto na outra ponta (positivo ou GND) (é bom realizar uma pesquisa, pois não sei se os relés funcionam como transistores (NPN/PNP).
obs- não esqueça que os relés costumam ser alimentados por uma fonte secundária.
Edit: Precisei realizar algumas edições, logo, está concluído agora: 21:15h kkkkk…
Adicionado por tiago merces ao 22:03 em 22 agosto 2020
subMenu4_1(), void subMenu4_2(), void subMenu4_3(), mas aparenta que a função while(1) não permite, tentei de tudo, agradeço muito a ajuda, segue abaixo o codigo.
#include <LiquidCrystal.h> //Biblioteca para o display LCD
// --- Mapeamento de Hardware --- #define butUp 12 //Botão para selecionar tela acima no digital 12 #define butDown 11 //Botão para selecionar tela abaixo no digital 11 #define butP 13 //Botão de ajuste mais no digital 10 #define butM 9 //Botão de ajuste menos no digital 9 #define select 8 //Botão de seleção no digital 8 #define Lamp1 A0 //Saída para lâmpada 1 no A0 (será usado como digital) #define Lamp2 A1 //Saída para lâmpada 2 no A1 (será usado como digital)
// --- Protótipo das Funções Auxiliares ---
void changeMenu(); //Função para modificar o menu atual
void dispMenu(); //Função para mostrar o menu atual void data_hora(); //Função do menu1, data e hora void temperatura(); //Função do menu2, temperatura void lights(); //Função do menu3, acionamento de lampadas void menu4(); //Função do menu4
void dispSubMenu4(); //Função do sub menu4 void readSelect(char option); //Função de Leitura do botão select para seleção de subMenus void subMenu4_1(); //Função para subMenu4_1 void subMenu4_2(); //Função para subMenu4_2 void subMenu4_3(); //Função para subMenu4_3
// --- Variáveis Globais --- char menu = 0x01; //Variável para selecionar o menu char subMenu4 = 0x01; //Variável para selecionar subMenu no menu4 char set1 = 0x00, set2 = 0x00; //Controle das lâmpadas boolean t_butUp, t_butDown, t_butP, t_butM, t_select; //Flags para armazenar o estado dos botões
// --- Hardware do LCD --- LiquidCrystal disp(7, //RS no digital 7 6, //EN no digital 6 5, //D4 no digital 5 4, //D5 no digital 4 3, //D6 no digital 3 2); //D7 no digital 2
// --- Configurações Iniciais --- void setup()
{
disp.begin(16,2); //Inicializa LCD 16 x 2
//Entrada para os botões (digitais 8 a 12) com pull-ups internos
pinMode(butUp, INPUT_PULLUP); pinMode(butDown, INPUT_PULLUP); pinMode(butP, INPUT_PULLUP); pinMode(butM, INPUT_PULLUP); pinMode(select, INPUT_PULLUP); pinMode(Lamp1, OUTPUT); //Configura saída para lâmpada 1 pinMode(Lamp2, OUTPUT); //Configura saída para lâmpara 2 t_butUp = 0x00; //limpa flag do botão Up t_butDown = 0x00; //limpa flag do botão Down t_butP = 0x00; //limpa flag do botão P t_butM = 0x00; //limpa flag do botão M t_select = 0x00; //limpa flag do botão select digitalWrite(Lamp1, LOW); //Lâmpada 1 inicia apagada digitalWrite(Lamp2, LOW); //Lâmpada 2 inicia apagada
} //end setup
// --- Loop Infinito --- void loop()
{ changeMenu(); dispMenu();
} //end loop
// --- Desenvolvimento das Funções Auxiliares --- void changeMenu() //Modifica o menu atual
{
if(!digitalRead(butUp)) t_butUp = 0x01; //Botão Up pressionado? Seta flag if(!digitalRead(butDown)) t_butDown = 0x01; //Botão Down pressionado? Seta flag if(digitalRead(butUp) && t_butUp) //Botão Up solto e flag setada?
{ //Sim...
t_butUp = 0x00; //Limpa flag disp.clear(); //Limpa display menu++; //Incrementa menu if(menu > 0x04) menu = 0x01; //Se menu maior que 4, volta a ser 1
} //end butUp
if(digitalRead(butDown) && t_butDown) //Botão Down solto e flag setada?
{ //Sim...
t_butDown = 0x00; //Limpa flag disp.clear(); //Limpa display menu--; //Decrementa menu if(menu < 0x01) menu = 0x04; //Se menu menor que 1, volta a ser 4
} //end butDown
} //end changeMenu
void dispMenu() //Mostra o menu atual
{
switch(menu) //Controle da variável menu {
case 0x01: //Caso 1
data_hora(); //Chama a função de relógio break; //break
case 0x02: //Caso 2
temperatura(); //Chama a função do termômetro break; //break
case 0x03: //Caso 3
lights(); //Chama função para acionamento de lâmpadas break; //break
case 0x04: //Caso 4
menu4(); //Chama função para o menu4 break; //break } //end switch menu
} //end dispMenu
void data_hora() //Data e Hora (menu1)
{ disp.setCursor(0,0); //Posiciona cursor na coluna 1, linha 1
disp.print("Data e Hora"); //Imprime mensagem
disp.setCursor(0,1); //Posiciona cursor na coluna 1, linha 2
// Desenvolver uma função de data e hora... disp.print("27/08/15 15:14"); //Mostrador (apenas ilustrativo......)
} //end data_hora
void temperatura() //Temperatura (menu2) { disp.setCursor(0,0); //Posiciona cursor na coluna 1, linha 1
disp.print("Temperatura"); //Imprime mensagem
disp.setCursor(1,1); //Posiciona cursor na coluna 2, linha 2
disp.print("25 Celsius"); //Mostrador (apenas ilustrativo......)
} //end temperatura()
void lights() //Acionamento de lâmpadas (menu3)
{ disp.setCursor(0,0); //Posiciona cursor na coluna 1, linha 1
disp.print("Acionar Lampadas"); //Imprime mensagem do menu 3 if(!digitalRead(butP)) t_butP = 0x01; //Botão P pressionado? Seta flag
if(!digitalRead(butM)) t_butM = 0x01; //Botão M pressionado? Seta flag if(digitalRead(butP) && t_butP) //Botão P solto e flag setada? { //Sim...
t_butP = 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
disp.setCursor(0,1); //Posiciona cursor na coluna 1, linha 2
disp.print("L1 on "); //Imprime mensagem
digitalWrite(Lamp1, HIGH); //Liga lâmpada 1
break; //Break
case 0x02: //Caso 2
disp.setCursor(0,1); //Posiciona cursor na coluna 1, linha 2
disp.print("L1 off"); //Imprime mensagem
digitalWrite(Lamp1, LOW); //Desliga lâmpada 1
break; //Break } //end switch set1 } //end butP
if(digitalRead(butM) && t_butM) //Botão D solto e flag setada?
{ //Sim...
t_butM = 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
disp.setCursor(8,1); //Posiciona cursor na coluna 8, linha 2
disp.print("L2 on "); //Imprime mensagem
digitalWrite(Lamp2, HIGH); //Liga lâmpada 2
break; //Break
case 0x02: //Caso 2
disp.setCursor(8,1); //Posiciona cursor na coluna 8, linha 2
disp.print("L2 off"); //Imprime mensagem
digitalWrite(Lamp2, LOW); //Liga lâmpada 1
break; //Break } //end switch set1 } //end butM
} //end lights
void menu4() //Função genérica para um quarto menu...
{
disp.setCursor(0,0); //Posiciona cursor na coluna 1, linha 1
disp.print("Menu 4"); //Imprime mensagem
dispSubMenu4();
} //end menu4
void dispSubMenu4() //Mostra o sub menu atual para o menu 4
{ if(!digitalRead(butP)) t_butP = 0x01; //Botão P pressionado? Seta flag
if(!digitalRead(butM)) t_butM = 0x01; //Botão M pressionado? Seta flag if(digitalRead(butP) && t_butP) //Botão P solto e flag setada?
{ //Sim...
t_butP = 0x00; //Limpa flag subMenu4++; //incrementa subMenu4 if(subMenu4 > 3) subMenu4 = 0x01; //se maior que 3, volta a ser 1 } //end butP
if(digitalRead(butM) && t_butM) //Botão D solto e flag setada?
{ //Sim...
t_butM = 0x00; //Limpa flag subMenu4--; //decrementa subMenu4 if(subMenu4 < 1) subMenu4 = 0x03; //se menor que 1, volta a ser 3 } //end butM switch(subMenu4) //Controle da variável subMenu
{
case 0x01: //Caso 1
disp.setCursor(1,1); //Posiciona cursor na coluna 2, linha 2
disp.print("Sub Menu 01"); readSelect(1); //Lê botão select com parâmetro 1
break; //break
case 0x02: //Caso 2
disp.setCursor(1,1); //Posiciona cursor na coluna 2, linha 2
disp.print("Sub Menu 02");
readSelect(2); //Lê botão select com parâmetro 2
break; //break
case 0x03: //Caso 2
disp.setCursor(1,1); //Posiciona cursor na coluna 2, linha 2
disp.print("Sub Menu 03");
readSelect(3); //Lê botão select com parâmetro 3
break; //break } //end switch menu
} //end 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...
t_select = 0x00; //Limpa flag
switch(option) {
case 0x01: subMenu4_1(); break; case 0x02: subMenu4_2(); break; case 0x03: subMenu4_3(); break;
} //end switch option } //end if
} //end readSelect
void subMenu4_1()
{
while(1)
{
disp.setCursor(0,0); //Posiciona cursor na coluna 1, linha 1
disp.print("Tarefa 1"); //Imprime mensagem
disp.setCursor(0,1); //Posiciona cursor na coluna 1, linha 2
disp.print("Em funcionamento"); //Mostrador (apenas ilustrativo......)
}
} //end subMenu4_1
void subMenu4_2()
{
while(1)
{
disp.setCursor(0,0); //Posiciona cursor na coluna 1, linha 1
disp.print("Tarefa 2"); //Imprime mensagem
disp.setCursor(0,1); //Posiciona cursor na coluna 1, linha 2
disp.print("Em funcionamento"); //Mostrador (apenas ilustrativo......)
}
} //end subMenu4_2
void subMenu4_3()
{
while(1)
{
disp.setCursor(0,0); //Posiciona cursor na coluna 1, linha 1
disp.print("Tarefa 3"); //Imprime mensagem
disp.setCursor(0,1); //Posiciona cursor na coluna 1, linha 2
disp.print("Em funcionamento"); //Mostrador (apenas ilustrativo......)
}
} //end subMenu4_3…
Adicionado por Ricardo Gomes ao 21:36 em 6 junho 2017
te tentei instala-lo usando a versão do Raspian (Linux Debian para Raspberry Pi) 2012-12-16-wheezy-raspbian, mas estava tendo muita dificuldade. Pesquisei no forum do Raspberry muitas dicas, mas o Raspian nem enxergava a interface USB.
Forum do Raspberry Pi:
http://www.raspberrypi.org/phpBB3/
Ao ler uma nova dica, alguem comentou que a nova versão do Raspian já tnha os drivers (2013-02-09-wheezy-raspbian).
Fiz a instalação e funcionou ! Eu ainda estou aprendendo LInux e foi muito legal ver todo o processo. Algumas dúvidas, mas é bem legal. Nunca fui um grande admirador do Linux. O linux ainda tem suas limitaçoes, mas com o Raspberry estou tendo muita motivação para aprende-lo.
Este foi o procedimento para configurar WIFI:
Primeiramente espetei a interface WIFI no meu HUB USB com fonte de 5V separada (veja tópicos anteriores).
Para confirmar que o Raspian enxergou a interface Asus:
pi@raspberrypi ~ $ lsusbBus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hubBus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.Bus 001 Device 004: ID 1a40:0101 Terminus Technology Inc. 4-Port HUBBus 001 Device 005: ID 0b05:1786 ASUSTek Computer, Inc. USB-N10 802.11n Network Adapter [Realtek RTL8188SU]
Beleza, agora tem que configurar a interface Wireless no Raspian. Para visualizar o arquivo de configuração de rede:
raspberrypi:~# cat /etc/network/interfacesauto loiface lo inet loopbackiface eth0 inet dhcpallow-hotplug wlan0iface wlan0 inet manualwpa-roam /etc/wpa_supplicant/wpa_supplicant.confiface default inet dhcp
Para alterar a configuração use o editor NANO, muito fácil de usar e muito melhor do que o VI (meu ponto de vista).
Veja antes o SSID e a sua senha de acesso do seu roteador de acesso à Internet.Atençao pois é sensível a letras maisculas e minusculas. Veja os endereços da rede LAN do seu roteador, se quiser alterar a configuração da rede com fio também.
No meu caso, eu também configurei a minha rede com fio para IP estático, para facilitar o uso do SSH(acesso ao terminal) e do VNC (acesso a interface grafica). Eu conectei o cabo de rede do Raspberry Pi ao meu roteador ASUS RT-N10.
$ sudo nano /etc/network/interfacesAltere o seguinte >>>
auto loiface lo inet loopbackiface eth0 inet static (rede com fio- IP estatico)address 192.168.2.27 (endereço do meu RaspPi)netmask 255.255.255.0network 192.168.2.0broadcast 192.168.2.255gateway 192.168.2.1 (rede do meu roteador)auto wlan0iface wlan0 inet dhcp wpa-ssid minha rede wpa-psk minha senha
Para salvar o que foi editado, pressione CTRL+X, depois Yes para confirmar e depois um ENTER.
Para confirmar o que foi alterado:
raspberrypi:~# cat /etc/network/interfaces
Para ativar a rede WIFI dê o comando ( o sudo é usado se não estiver usando o usuário root).
# sudo ifup wlan0
Para visualizar o status da rede use o comando ifconfig. Eth0 é a rede com fio e wlan0 é a rede wireless.
pi@raspberrypi ~ $ sudo ifconfig
eth0 Link encap:Ethernet HWaddr b8:27:eb:10:ae:87 inet addr:192.168.2.27 Bcast:192.168.2.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:898 errors:0 dropped:5 overruns:0 frame:0 TX packets:620 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:68090 (66.4 KiB) TX bytes:81249 (79.3 KiB)lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:55 errors:0 dropped:0 overruns:0 frame:0 TX packets:55 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:9890 (9.6 KiB) TX bytes:9890 (9.6 KiB)wlan0 Link encap:Ethernet HWaddr 10:bf:48:50:a7:18 inet addr:192.168.2.178 Bcast:192.168.2.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:6 errors:0 dropped:0 overruns:0 frame:0 TX packets:17 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:1720 (1.6 KiB) TX bytes:4162 (4.0 KiB)
Para testar o acesso entre o seu PC e o Raspberry use o comando ping. Por exemplo no seu PC Windows, abra uma janela de prompt de comando, e ping endereço_raspberry. Dentro do Raspberry, dê um ping para o endereço do seu PC. Para visualizar o enderço do seu PC, dê o comando ipconfig na janela do prompt.
Para testar o acesso do Raspberry Pi para a internet use o comando:
raspberrypi:~# ping 8.8.8.8 (endereço do Google)
Se não estiver acessando a Internet, faça o seguinte.
pi@raspberrypi ~ $ cat /etc/resolv.confnameserver 192.168.2.1
Acrescente esses namesevers. Vi essa dica no link abaixo:
http://www.raspberrypi.org/phpBB3/viewtopic.php?f=27&t=8580
pi@raspberrypi ~ $ sudo nano /etc/resolv.confnameserver 192.168.2.1nameserver 8.8.8.8nameserver 8.8.4.4nameserver 208.67.220.220nameserver 208.67.222.222nameserver 10.10.10.10
Uma observação importante, é sempre bom dar um reboot se alguma coisa der errado.
E lembrando que após algumas configurações, é necessário o reboot.
pi@raspberrypi ~ $ sudo shutdown -r 1
Qualquer dúvida podem perguntar.
Abraços
Gustavo Murta
…
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x9B, 0x36 }; // Endereço Macbyte ip[] = { 192, 168, 0, 110 }; // Endereço de Ip da sua RedeEthernetServer server(8090); // Porta de serviço
int area = 2;int sala = 3;int escritorio = 5;int trava = 6;int portao = 7;String readString = String(30); // string para buscar dados de endereço
// para o optacoplador Áreaconst int analogArea = A0;int sensorArea = 0;String statusArea;
// para o optacoplador Salaconst int analogSala = A1;int sensorSala = 0;String statusSala;
// para o optacoplador Escritórioconst int analogEscritorio = A2;int sensorEscritorio = 0;String statusEscritorio;
boolean statusPortao = false; // Variável para o status do portão
void setup(){ // Inicia o Ethernet Ethernet.begin(mac, ip); // Define os pinos como saída pinMode(area, OUTPUT); pinMode(sala, OUTPUT); pinMode(escritorio, OUTPUT); pinMode(trava, OUTPUT); pinMode(portao, OUTPUT); // Inicia a comunicação Serial Serial.begin(9600); }
void loop(){ //Verifica o status do sensor da Área sensorArea = analogRead(analogArea); if (sensorArea >=300) { statusArea = ("lampada area ligada"); } else { statusArea = ("lampada area desligada"); } //Verifica o status do sensor da Sala sensorSala = analogRead(analogSala); if (sensorSala >=300) { statusSala = ("lampada sala ligada"); } else { statusSala = ("lampada sala desligada"); } //Verifica o status do sensor do Escritório sensorEscritorio = analogRead(analogEscritorio); if (sensorEscritorio >=300) { statusEscritorio = ("lampada escritorio ligada"); } else { statusEscritorio = ("lampada escritorio desligada"); } // Criar uma conexão de cliente EthernetClient client = server.available(); if (client) { while (client.connected()) { if (client.available()) { char c = client.read(); // ler caractere por caractere vindo do HTTP if (readString.length() < 30) { // armazena os caracteres para string readString += (c); } //se o pedido HTTP terminou if (c == '\n') { // vamos verificar se a lâmpada da área deve ser ligada // Se a string possui o texto L=Ligar if(readString.indexOf("LigarArea")>=0) { // A lâmpada vai ser ligada digitalWrite(area, HIGH); } // Se a string possui o texto L=Desligar if(readString.indexOf("DesligarArea")>=0) { // A lâmpada vai ser desligada digitalWrite(area, LOW); } { // vamos verificar se a lâmpada da sala deve ser ligada // Se a string possui o texto L=Ligar if(readString.indexOf("LigarSala")>=0) { // A lâmpada vai ser ligada digitalWrite(sala, HIGH); } // Se a string possui o texto L=Desligar if(readString.indexOf("DesligarSala")>=0) { // A lâmpada vai ser desligada digitalWrite(sala, LOW); } { // vamos verificar se a lâmpada do escritório deve ser ligada // Se a string possui o texto L=Ligar if(readString.indexOf("LigarEscritorio")>=0) { // A lâmpada vai ser ligada digitalWrite(escritorio, HIGH); } // Se a string possui o texto L=Desligar if(readString.indexOf("DesligarEscritorio")>=0) { // A lâmpada vai ser desligada digitalWrite(escritorio, LOW); } { // vamos verificar se o portão deve abrir // Se a string possui o texto L=Ligar if(readString.indexOf("LigarPortao")>=0) { // O portão vai ser aberto digitalWrite(portao, HIGH); delay (1000); digitalWrite(portao, LOW); statusPortao = true; } // Se a string possui o texto L=Desligar if(readString.indexOf("DesligarPortao")>=0) { // O portão vai ser fechado digitalWrite(portao, HIGH); delay (1000); digitalWrite(portao, LOW); statusPortao = false; } { // vamos verificar se a trava deve ser aberta // Se a string possui o texto L=Ligar if(readString.indexOf("LigarTrava")>=0) { // A trava vai ser aberta digitalWrite(trava, HIGH); delay (2000); digitalWrite(trava, LOW); }
// dados HTML de saída começando com cabeçalho padrão client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); client.println("<font size='20'>"); // aqui vai imprimir o conteúdo da string client.print("<h5>"); client.print(statusArea); client.print("</h5>"); // aqui vai imprimir o conteúdo da string client.print("<h5>"); client.print(statusSala); client.print("</h5>"); // aqui vai imprimir o conteúdo da string client.print("<h5>"); client.print(statusEscritorio); client.print("</h5>"); client.println("<font size='20'>"); if (statusPortao) { client.print("<h5>"); client.println("PortaoAberto"); client.print("<h5>"); } else { client.print("<h5>"); client.println("PortaoFechado"); client.print("<h5>"); } //limpa string para a próxima leitura readString=""; // parar cliente client.stop(); } } } }}}} }}
Só que eu fiz o aplicativo android no App inventor segue as fotos:
Essa é a tela, que ja mudei varias vezes
Esses são os blocos da lógica
Caso se interesse dê uma olhada nas video aulas do androi e arduino no you tube:
https://www.youtube.com/user/TecnoEduardo
O Eduardo explica tudo sobre android e arduino.
…
tes, produtos muito específicos que as grandes industrias não se interessam em fabricar.Produtos assim, para o mundo em geral, não dentro do universo maker, vc pode vender no ebay.com
Nunca vendi nada, mas já comprei coisas de todo mundo... Portugal, Canadá e especialmente Japão. Tem coisas mto interessantes de lá.Cada país tem seu "mercadolivre".Destaco:EUA e internacional: ebay.comChina e internacional: alibaba.comChina: www.taobao.com/ e www.jd.com <- Só por curiosidade. Japão: https://auctions.yahoo.co.jp/ <- Comprei um amplificador compacto 5.1 e cartuchos de MSX, mto bom e barato. Pra quem coleciona por ex relógios Casio antigos é o melhor lugar. Japoneses compram de anuncios de brasileiros nesse site coisas que não tem lá como Geodes (pedras), artesanato e comida... Tinha um conhecido japones que tinha bomboniere e anunciava lá, vendia caixas daquela paçoquinha "Amor" e "Dadinho", tudo a 5x o preço que se vende aqui. Eh questão de se adaptar a língua e aproveitar oportunidades. Sem conhecimento da lingua vc pode ser vitima de erros e preconceito.
Para envio o correios é bem tranquilo. Permite normalmente enviar coisas pessoa física/pessoa fisica. Só complica se vc quiser mandar como ou pra uma empresa. Para receber basta ter uma conta no paypal.com ou similar.
Mercadolivre pelo mundo:
Data
País
Site
Agosto de 1999
Argentina
www.mercadolibre.com.ar/
Outubro de 1999
Brasil
www.mercadolivre.com.br/
Novembro de 1999
México
www.mercadolibre.com.mx/
Dezembro de 1999
Uruguai
www.mercadolibre.com.uy/
Fevereiro de 2000
Colômbia
www.mercadolibre.com.co/
Março de 2000
Venezuela
www.mercadolibre.com.ve/
Março de 2000
Chile
www.mercadolibre.cl/
Dezembro de 2000
Equador
www.mercadolibre.com.ec/
Dezembro de 2004
Peru
www.mercadolibre.com.pe/
Novembro de 2006
Costa Rica
www.mercadolibre.co.cr/
Dezembro de 2006
República Dominicana
www.mercadolibre.com.do/
Dezembro de 2006
Panamá
www.mercadolibre.com.pa/
Enfim, crie o produto e ofereça. O mundo responderá se quer ele ou não. Qualquer venda vale. A moeda lá favorece mas nos dias de hj qualquer moeda já é lucro, não estamos em condições de escolher.
Fonte:https://pt.wikipedia.org/wiki/MercadoLivre…
D 2x16
sensor temperatura Dallas DS18B20
Modulo de 8 canais para arduino(para ligar as bombas de agua luzes comedores e fertilizante)
RTC DS3231 AT24C32 llC
pretendo ver no LCD as horas e a data
a temperatura
e ligar as luzes com o timer por exemplo as 14h00 e desligar as 24h00
dar de comer 2 vezez ao dia
fertelizar em dias alternados (exp 2ªfeira ,4ª , 6ª )
tenho só um rele ligado ao pino 13 para ir tentando
Já tentei com outros exemplos e não consigo está muito confuso
obrigado pela voss atenção.
/*DS3231_test.pdeEric Ayars4/11Test/demo of read routines for a DS3231 RTC.Turn on the serial monitor after loading this to check if things areworking as they should.*/#include <OneWire.h>#include <LiquidCrystal.h> //Inclui a biblioteca do LCD#include <DS3231.h>#include <Wire.h>#include <DallasTemperature.h>#define ONE_WIRE_BUS 10#define RELAY13 //pino do releOneWire oneWire(ONE_WIRE_BUS);unsigned long UtlTime;DallasTemperature sensors(&oneWire);DeviceAddress insideThermometer = { 0x28, 0xDF, 0x63, 0x51, 0x05, 0x00, 0x00, 0xC3 };LiquidCrystal lcd(12, 11, 5, 4, 3, 2);DS3231 Clock;bool Century=false;bool h12;bool PM;byte ADay, AHour, AMinute, ASecond, ABits;bool ADy, A12h, Apm;int pinorelay13 = 13;byte year, month, date, DoW, hour, minute, second;void setup() { pinMode(pinorelay13, OUTPUT); //Define o pino como saidasensors.begin(); sensors.setResolution(insideThermometer, 10); // Start the I2C interface Wire.begin(); Clock.setSecond(10);//Set the second Clock.setMinute(50);//Set the minute Clock.setHour(18); //Set the hour Clock.setDoW(8); //Set the day of the week Clock.setDate(7); //Set the date of the month Clock.setMonth(8); //Set the month of the year Clock.setYear(14); //Set the year (Last two digits of the year) // Start the serial interface Serial.begin(115200);lcd.begin(16, 2); lcd.clear(); // start with a blank screen}void ReadDS3231(){ int second,minute,hour,date,month,year,temperature; second=Clock.getSecond(); minute=Clock.getMinute(); hour=Clock.getHour(h12, PM); date=Clock.getDate(); month=Clock.getMonth(Century); year=Clock.getYear(); Serial.print("20"); Serial.print(year,DEC); Serial.print('-'); Serial.print(month,DEC); Serial.print('-'); Serial.print(date,DEC); Serial.print(' '); Serial.print(hour,DEC); Serial.print(':'); Serial.print(minute,DEC); Serial.print(':'); Serial.print(second,DEC); Serial.print('\n'); lcd.setCursor(0,0); lcd.print("20"); lcd.print(year,DEC); lcd.print('-'); lcd.print(month,DEC); lcd.print('-'); lcd.print(date,DEC); lcd.print(' '); lcd.setCursor(0,1); lcd.print(hour,DEC); lcd.print(':'); lcd.print(minute,DEC); lcd.print(':'); lcd.print(second,DEC); lcd.print('\n'); lcd.setCursor(11,0); lcd.print("Temp"); }void printTemperature(DeviceAddress deviceAddress){float tempC = sensors.getTempC(deviceAddress);if (tempC == -127.00) {lcd.print("Error");}else{lcd.setCursor(10,1); lcd.print(tempC);lcd.print("C");lcd.print(DallasTemperature::toFahrenheit(tempC)); }}void loop() { //Aciona o rele digitalWrite(pinorelay13, HIGH); delay(50); //Aguarda 2 Horas //Desliga o rele digitalWrite(pinorelay13, LOW); delay(50); //Aguarda 5 segundos e reinicia o processo ReadDS3231();delay(1000);sensors.requestTemperatures();printTemperature(insideThermometer);lcd.setCursor(0,1); delay(04/33/20); // //Desliga o rele delay(04/36/20); //Aguarda 5 segundos // send what's going on to the serial monitor. // Start with the year/* Serial.print("2"); if (Century) { // Won't need this for 89 years. Serial.print("1"); } else { Serial.print("0"); } Serial.print(Clock.getYear(), DEC); Serial.print('-'); // then the month Serial.print(Clock.getMonth(Century), DEC); Serial.print('-'); // then the date Serial.print(Clock.getDate(), DEC); Serial.print(' ');*/ // and the day of the week /*Serial.print(Clock.getDoW(), DEC); Serial.print(' ');*/ // Finally the hour, minute, and second /*Serial.print(Clock.getHour(h12, PM), DEC); Serial.print(':'); Serial.print(Clock.getMinute(), DEC); Serial.print(':'); Serial.print(Clock.getSecond(), DEC); // Add AM/PM indicator if (h12) { if (PM) { Serial.print(" PM "); } else { Serial.print(" AM "); } } else { Serial.print(" 24h "); } } else { Serial.print(" O-"); }*/ // Indicate whether an alarm went off /*if (Clock.checkIfAlarm(1)) { Serial.print(" A1!"); } if (Clock.checkIfAlarm(10)) { Serial.print(" 10!"); }*/ // New line on display //Serial.print('\n'); // delay(1000); // Display Alarm 1 information/* Serial.print("Alarm 1: "); Clock.getA1Time(ADay, AHour, AMinute, ASecond, ABits, ADy, A12h, Apm); Serial.print(ADay, DEC); if (ADy) { Serial.print(" DoW"); } else { Serial.print(" Date"); } Serial.print(' '); Serial.print(AHour, DEC); Serial.print(' '); Serial.print(AMinute, DEC); Serial.print(' '); Serial.print(ASecond, DEC); Serial.print(' '); if (A12h) { if (Apm) { Serial.print('pm '); } else { Serial.print('am '); } } if (Clock.checkAlarmEnabled(1)) { Serial.print("enabled"); } Serial.print('\n'); // Display Alarm 2 information Serial.print("Alarm 2: "); Clock.getA2Time(ADay, AHour, AMinute, ABits, ADy, A12h, Apm); Serial.print(ADay, DEC); if (ADy) { Serial.print(" DoW"); } else { Serial.print(" Date"); } Serial.print(' '); Serial.print(AHour, DEC); Serial.print(' '); Serial.print(AMinute, DEC); Serial.print(' '); if (A12h) { if (Apm) { Serial.print('pm'); } else { Serial.print('am'); } } if (Clock.checkAlarmEnabled(2)) { Serial.print("enabled"); }*/ /* display alarm bits Serial.print('\n'); Serial.print('Alarm bits: '); Serial.print(ABits, DEC); *//* Serial.print('\n'); Serial.print('\n'); delay(1000); // Display the time once more as a test of the getTime() function Clock.getTime(year, month, date, DoW, hour, minute, second); Serial.print(year, DEC); Serial.print("/"); Serial.print(month, DEC); Serial.print("/"); Serial.print(date, DEC); Serial.print("day of the week :"); Serial.println(DoW, DEC); Serial.print(hour, DEC); Serial.print(":"); Serial.print(minute, DEC); Serial.print(":"); Serial.println(second, DEC);*/}…
Adicionado por Antonio Gomes ao 16:12 em 7 agosto 2014
através de um módulo SD Card em intervalos regulares de tempo, juntamente com a hora em que o dado foi aquisitado, através de um módulo RTC DS1307 que também possui um sensor que irá medir a temperatura. Além disso, nessa mesma periodicidade é printado na tela do módulo LCD duas das temperaturas. O arduíno que utilizo é o Mega 2560. Mas estou com um problema pois não estou conseguindo gravar os dados no arquivo de texto que é iniciado. Na porta serial diz que tudo foi iniciado com sucesso (SD Card, RTC, arquivo aberto com sucesso) porém quando retiro o cartão de memória do módulo, o arquivo de texto está em branco. Além disso, há 20 dias eu fiz vários testes e todos ocorreram com sucesso, ou seja, os dados estavam sendo gravados corretamente. Daí fiquei sem mexer no arduíno durante esse tempo e quando coloquei novamente para funcionar hoje os dados não estavam sendo mais gravados, sendo que o código de programação era o mesmo. Alguém já passou por algo parecido ou tem alguma sugestão para que eu resolva esse problema?
Abaixo segue o código que utilizei:#include <LiquidCrystal.h> #include <Wire.h> #include <OneWire.h> #include <DallasTemperature.h> #include "RTClib.h"
#include <SD.h>#include <SPI.h>#define Entrada A0 #define Saida A1 #define THERMISTORNOMINAL 2252 #define TEMPERATURANOMINAL 25 #define NAMOSTRAS 5 #define BCOEFFICIENT 3700 #define RESISTOR 3300 int led = 13; #define DS18B20_PIN 19
int amostrasentrada[NAMOSTRAS];int amostrassaida[NAMOSTRAS]; LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
RTC_DS1307 RTC;
File myFile;
OneWire oneWire(DS18B20_PIN); DallasTemperature sensors(&oneWire);
void setup(void) {
sensors.begin();
Serial.begin(9600);
pinMode(led, OUTPUT);Serial.println("Inicializando SD card...");pinMode(53, OUTPUT);digitalWrite(53, HIGH);if (!SD.begin(53)) { Serial.println("Inicializacao do SD falhou!");digitalWrite(led, HIGH);return;}
digitalWrite(led, LOW);Serial.println("Inicializacao do SD realizada com sucesso!");
myFile = SD.open("test.txt", FILE_WRITE);
if (!myFile){Serial.println("Erro na abertura de 'test.txt'!");myFile.println("Erro na abertura de 'test.txt'!");}else {Serial.println();myFile.println();Serial.println("Abertura de 'test.txt' realizada com sucesso!");myFile.println("Abertura de 'test.txt' realizada com sucesso!");Serial.println();myFile.println();}
Wire.begin(); RTC.begin(); if (!RTC.isrunning()) { Serial.println("RTC nao esta funcionando!"); myFile.println("RTC nao esta funcionando!");RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
else { Serial.println("RTC iciciado com sucesso!"); myFile.println("RTC iniciado com sucesso!"); Serial.println();myFile.println();
}
analogReference(EXTERNAL); lcd.begin(16, 2); lcd.setCursor(0, 0); lcd.print("Entrada"); lcd.setCursor(0, 1); lcd.print("Ambiente");
Serial.println("- Iniciando a gravacao do ensaio de TESTE DE RESPOSTA TERMICA -");myFile.println("- Iniciando a gravacao do ensaio de TESTE DE RESPOSTA TERMICA -");Serial.println(" Marina de Souza Ferreira");myFile.println(" Marina de Souza Ferreira");Serial.println();myFile.println();
myFile.print("Data "); Serial.print("Data "); myFile.print("Horario "); Serial.print("Horario "); myFile.print("T.Ent(C) "); Serial.print("T.Ent(C) ");myFile.print("T.S(C) "); Serial.print("T.S(C) "); myFile.println("T.Amb(C) "); Serial.println("T.Amb(C) "); myFile.close();}
void loop(void) {sensors.requestTemperatures(); DateTime now = RTC.now();
myFile = SD.open("test.txt", FILE_WRITE);
uint8_t i;
float mediaentrada, mediasaida;
for (i=0; i< NAMOSTRAS; i++)
{ amostrasentrada[i] = analogRead(Entrada); amostrassaida[i] = analogRead(Saida); delay(5000); }
mediaentrada = 0; for (i=0; i< NAMOSTRAS; i++)
{ mediaentrada += amostrasentrada[i];
} mediaentrada /= NAMOSTRAS;
mediaentrada = 1023 / mediaentrada - 1; mediaentrada = RESISTOR / mediaentrada;
float steinhartentrada, steinhartsaida; steinhartentrada = mediaentrada / THERMISTORNOMINAL; steinhartentrada = log(steinhartentrada); steinhartentrada /= BCOEFFICIENT; steinhartentrada += 1.0 / (TEMPERATURANOMINAL + 273.15);
steinhartentrada = 1.0 / steinhartentrada; steinhartentrada -= 273.15; float temp_Entrada=steinhartentrada;
mediasaida = 0; for (i=0; i< NAMOSTRAS; i++) { mediasaida += amostrassaida[i];
} mediasaida /= NAMOSTRAS; mediasaida = 1023 / mediasaida - 1; mediasaida = RESISTOR / mediasaida;
steinhartsaida = mediasaida / THERMISTORNOMINAL; steinhartsaida = log(steinhartsaida); steinhartsaida /= BCOEFFICIENT; steinhartsaida += 1.0 / (TEMPERATURANOMINAL + 273.15);
steinhartsaida = 1.0 / steinhartsaida; steinhartsaida -= 273.15;
float temp_Saida=steinhartsaida;
lcd.setCursor(10, 0); lcd.print(temp_Entrada); lcd.print("C"); lcd.setCursor(10, 1); lcd.print(sensors.getTempCByIndex(0)); lcd.print("C");
if(temp_Entrada){
myFile.println(); // Dia myFile.print(now.day(), DEC); // DiaSerial.print(now.day(), DEC); // DiamyFile.print('/');Serial.print('/');myFile.print(now.month(), DEC); // MêsSerial.print(now.month(), DEC); // MêsmyFile.print(' ');Serial.print(' ');myFile.print(now.hour(), DEC); // HorasSerial.print(now.hour(), DEC); // HorasmyFile.print(':');Serial.print(':');myFile.print(now.minute(), DEC); // MinutosSerial.print(now.minute(), DEC); // MinutosmyFile.print(':');Serial.print(':');myFile.print(now.second(), DEC); // SegundosSerial.print(now.second(), DEC); // SegundosmyFile.print(' ');Serial.print(' ');myFile.print(temp_Entrada);Serial.print(temp_Entrada);myFile.print(' ');Serial.print(' ');
}
if(temp_Saida){myFile.print(temp_Saida);Serial.print(temp_Saida);myFile.print(' ');Serial.print(' ');
}
myFile.println(sensors.getTempCByIndex(0)); Serial.println(sensors.getTempCByIndex(0));
myFile.close();
delay(4000); }
Observação: já troquei o módulo SD por outro novo e não o erro permaneceu.
Desde já muito obrigada!…
Bm ou menos
1 -111 dBm
2...30 -110...-54 dBm
31 -52 dBm ou maior
99 não detectou sinal
Portanto, depois de enviar o comando corretamente para o sim900 você deverá ler a resposta do sim900, e em seguida tratar a string recebida, retirando o valor desejado do rssi, salvando-o em uma variavel para então enviar ao lcd...
Segue um sketch que faz a leitura do rssi do sim900 e imprime o mesmo no serial monitor do arduino, estude-o, entenda como é que funciona, pois com certeza deverá ser necessário algumas modificações principalmente na instance da porta serial... dificilmente o nome da porta serial usada no sketch do exemplo ( no caso mySerial ) coincidirá com a que que foi usada no seu sketch, para verificar isso você deverá abrir a library do sim900 e verificar qual o nome usado...
O sketch:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);
// AUX GSM Leitura de dados
String linhaAtual = "";
String db = "";
boolean lendoDB = false;
void setup()
{
mySerial.begin(19200); // inicia conexao SIM900
Serial.begin(9600); // inicia conexao PC
}
void loop()
{
delay(500); // delay de envio de dados
mySerial.println("AT+CSQ"); // envia comando ao SIM900
while(mySerial.available()>0) // se existem dados na porta serial
{
char dados = mySerial.read(); // variavel dados recebe informacoes
linhaAtual += dados; // variavel linha recebe dados
if (dados == '\n') // se tiver um ENTER em dados
{
linhaAtual = ""; // apaga dados da linha
}
if (linhaAtual.endsWith(" ")) // se a linha terminar com espaco em branco
{
lendoDB = true; // estamos lendo dados
db = ""; // limpo variavel que vai receber dados em DB
}
if (lendoDB) // se estamos lendo os dados
{
if (dados != ',') // faz leitura ate encontrar virgula
{
db += dados; // adiciona info a variavel db
}
else // se nao estamos lendo
{
lendoDB = false; // sem leitura
Serial.println(db); // enviamos os dados para o computador pela porta serial
}
}
}
}
fonte: http://microembarcado.blogspot.com.br/2013/11/sim900-labview-fazendo-leitura-de-sinal.html
Espero que isto possa lhe ajudar a conseguir ver a indicação do sinal no seu display lcd.
Abraço.…
Adicionado por Wiechert ao 4:35 em 6 setembro 2014
ce Routine" = Rotina de Serviço da Interrupção), é gerada pelo TIMER1, que é programado logo no início da execução do código, para gerar uma IRQ ("Interrupt Request" = Requisição de Interrupção) 150 vezes por segundo (ou a cada 6.67 mili-segundos). Uma observação: o TIMER1 do Processador do UNO, tem 4 fontes de Interrupção diferentes, e destas 4 fontes 3 poderiam ser utilizadas para gerar as IRQs para cadenciar a varredura do Display, mas neste Sistema estamos usando a Interrupção gerada pelo COMPA ("Compare Match A").
A programação do TIMER1 para gerar as IRQs é feita na função "config_Display_Refresh", e embora esta seja extremamente simples, também é muito específica já que programa o Hardware do TIMER1, e por isso não irei falar sobre ela aqui (o código está funcionalmente comentado e descreve as operações realizadas). Mas caso alguém tenha alguma dúvida, pergunte aqui mesmo neste tópico.
A ISR do "TIMER1 COMPA" é mostrada na figura a seguir:
(clique na figura para "zoom")
Esta ISR tem três etapas:
1) atualizar o Display, executando assim a varredura do mesmo, que é a área marcada na cor verde na figura anterior. Para isto é usada a variável local "DISPLAY_sel" (que é do tipo "static", e portanto retém seu valor mesmo depois que a rotina termina sua execução), a qual indica qual Display será "ligado" neste momento (e por 6.67ms quando a próxima IRQ ocorrer). Quando a ISR é executada pela primeira vez (e apenas na primeira vez!), "DISPLAY_sel" estará com o valor "1", indicando que o Display "1" será "ligado" e exibirá o valor correspondente ao mesmo. Então conforme cada statement "case" do "switch" é chamada a função "set_Digito_Display" passando como parâmetros a variável correspondente ao Display atualmente sendo "ligado" (ou "SENHA_IN_1", ou "SENHA_IN_2", ou "SENHA_IN_3"), e também o número correspondente ao Display (ou "1", ou "2", ou "3"). Assim esta função "set_Digito_Display" irá setar nos pinos correspondentes aos bits "A", "B", "C", e "D" do Decoder 4511, o valor binário correspondente ao valor a ser exibido (dado por "SENHA_IN_1", "SENHA_IN_2", ou "SENHA_IN_3"), mantendo ligado apenas o Display especificado ("1", "2", ou "3"), e deixando desligado os demais. Mais à frente veremos como a função "set_Digito_Display" faz isso.
2) selecionar o Display que será "ligado" na próxima execução da ISR (que ocorrerá daqui a 6.67ms), que é a área marcada na cor azul na figura anterior. Para isso, simplesmente é incrementada a variável "DISPLAY_sel". Mas como esta variável deve ir de 1 a 3, se o incremento ultrapassar "3", então a variável é reciclada para o valor "1", assim selecionando o Display "1" para a próxima IRQ.
3) executar o "HOOK" correspondente a esta ISR, que é a área marcada na cor amarela na figura anterior. Um "HOOK" nada mais é do que uma chamada a uma função "genérica", e esta função pode ser alterada a qualquer momento pelo código que controla o Sistema. No entanto, neste Sistema este "HOOK" é setado uma única vez, logo no início da execução do código, para apontar a função "atualiza_Status_Botoes", e assim mantido durante todo o funcionamento do Sistema (ou seja, o "HOOK" não é mais alterado). Portanto, na área marcada na cor amarela, simplesmente será chamada a função "atualiza_Status_Botoes", a qual fará a varredura dos Botões e atualizará os status dos mesmos. A função que seta este "HOOK" é a "config_Botoes", que já foi mostrada quando falamos sobre a configuração dos Botões. Todas estas funções são extremamente simples e estão muito organizadas, então vale a pena vc dar uma olhada nas mesmas, pois certamente o aprendizado será significativo.
Então após a execução destas 3 etapas, a ISR termina, e o Processador volta a executar o código "normal" no "foreground". A ISR será executada repetidamente, a cada 6.67ms, onde o próximo Display será ligado para exibir seu valor correspondente, e também será feita a varredura dos Botões para a atualização dos status dos mesmos.
Vamos dar uma olhada rápida na função "set_Digito_Display", a qual recebe como parâmetros o valor a ser exibido num dos Displays e o indicador de qual é este Display. Esta função pode ser vista na figura a seguir:
(clique na figura para "zoom")
O valor a ser exibido é especificado através do parâmetro "DIGITO_N", o qual deve estar entre "0" e "9", uma vez que corresponde a um Dígito da Senha. Por este motivo, o Display só será atualizado se o valor do Dígito estiver dentro da faixa correta (menor ou igual a "9"), o que pode ser constatado no statement "if" na linha 541 na figura anterior.
Mas antes disso, temos a execução da função "set_Display_OFF", cujo objetivo é desligar todos os Displays, o que é feito através dos pinos que controlam os Transistores Q1, Q2, e Q3. A função "set_Display_OFF" é extremamente simples e pode ser vista na figura a seguir:
(clique na figura para "zoom")
Então no início da função "set_Digito_Display" temos que todos os três Displays são desligados. Portanto se o valor do "DIGITO_N" estiver fora da faixa permissível, como resultado temos que todos os Displays desligam, o que de certa forma nos sinaliza que alguma coisa está errada no código. Isto pode ser entendido quase como um teste de sanidade. Em outras palavras, o teste "if" pode ser eliminado, desde que seu código mantenha os valores dos Dígitos dentro da faixa correta. Mas a boa prática de programação, aconselha que se mantenha o teste "if" da linha 541.
Na figura que mostra a função "set_Digito_Display", existem 4 áreas marcadas na cor verde. Cada uma dessas 4 áreas, testa um bit do valor "DIGITO_N", e reproduz esse bit nos pinos "A" a "D" do Decoder 4511. Dessa forma, o valor do "DIGITO_N" será traduzido pelo Decoder 4511, para seu equivalente em 7 segmentos. O teste para saber se cada bit está em "0" ou "1" é feito através da operação AND (o "&" da Linguagem C/C++) com os valores 0x01 (para teste do bit "0"), 0x02 (teste do bit "1"), 0x04 (teste do bit "2"), e finalmente 0x08 (teste do bit "3"). Então conforme o resultado destes testes, ou "HIGH" ou "LOW" será setado nos pinos "A" a "D" do 4511. Ou seja, a reprodução direta e simples de um valor binário de 4 bits.
Mas em qual dos Displays este valor aparecerá? Isto é dado pelo parâmetro "DISPLAY_select", que especifica a qual dos Displays corresponde o valor "DIGITO_N". Logo o parâmetro "DISPLAY_select" pode assumir valores de 1 a 3, indicando assim em qual Display "aparecerá" o valor decodificado pelo 4511. Dentro do statement "switch" (na linha 575), há 3 áreas marcadas na cor azul, e cada uma testa se "DISPLAY_select" é um dos três Displays. Como se vê pela lógica extremamente simples, somente o Display especificado pelo parâmetro "DISPLAY_select" será ligado. E a função termina.
E o processo de varredura continua indefinidamente, na taxa de 150 Hz.
Aqui, para não demorar mais, não irei falar sobre detalhes da leitura/processamento dos status dos Botões (embora a lógica ainda seja simples). Mas qualquer dúvida é só perguntar.
Mas há um ponto muito importante a verificar. Quanto tempo todas as operações executadas na ISR, levam para serem executadas??? A forma mais simples de verificar isso é medindo. Então o que eu fiz foi usar um pino "sobrando" no UNO para gerar um pulso digital que corresponda à praticamente o tempo de duração da ISR. No caso, usei o pino 8, embora isso não apareça no circuito nem no código, pois fiz isso em uma cópia do Projeto apenas para a medição. Simplesmente, a primeira coisa que é feita na ISR, é setar o pino 8 em "HIGH", e a última coisa feita na ISR é setar o pino em "LOW". Isto fornece excelente precisão na medição do tempo gasto na ISR. O resultado pode ser visto na figura a seguir, capturada do Osciloscópio "virtual" do Proteus:
(clique na figura para "zoom")
Como se vê na figura anterior, são gastos cerca de 80 µs na ISR, e isto inclui a varredura do Display e dos três Botões. E qual percentual este tempo corresponde em relação ao tempo que sobra para a execução do código "normal" (no "foreground")??? Simples: basta dividir 80µs por 6.67ms (o ciclo da ISR = 1 / 150Hz), e então multiplicar por 100%, e teremos o percentual desejado. Vejamos então: 80µs / 6.67ms = 0.012, e o percentual será 100% x 0.012 = 1.2%. Ou seja, arredondando temos que todo o processamento da ISR corresponde a cerca de 1% do processamento total do Sistema. A coisa então é muito eficiente (mas como eu disse no início do post, algum cuidado especial deve ser tomado se forem acrescentados ao Sistema dispositivos "OneWire" ou semelhantes a DHT11 ou DHT22").
Aproveitando, pode-se verificar o ciclo da ISR, bastando apenas ajustar a escala de tempo do Osciloscópio "virtual" do Proteus, conforme pode ser visto na figura a seguir:
(clique na figura para "zoom")
E conforme esperado, o ciclo é de 6.67ms, correspondente aos 150 Hz.
Sobre a inicialização do Sistema
Dado ao objetivo deste tópico, não há muito para falar sobre a inicialização do Sistema. Mas qualquer dúvida sobre este processo, basta perguntar. Vejamos a função "setup" do Arduino, que é obrigatória nesta Plataforma, e é mostrada na figura a seguir:
(clique na figura para "zoom")
Ali, há apenas três funções de inicialização sendo executadas.
A primeira é a "config_LEDs", que simplesmente configura como saídas, os pinos dos LEDs "OK" e "ERRO", e também garante que inicialmente estes LEDs estejam desligados.
A segunda é a "config_Botoes", já mostrada aqui no post. Ela configura como entradas, os pinos dos Botões, e inicializa os status de cada Botão. Também nesta função, como já dito, é setado o "HOOK" existente na ISR do "TIMER1 COMPA" para que seja feita a varredura dos Botões e atualização dos status dos mesmos (via função "atualiza_Status_Botoes"). Observar que, o "HOOK" só será executado após a configuração do TIMER1, o que é feito logo a seguir.
A terceira e última função no "setup", é a "init_Display_Control". Ela primeiro configura e inicializa todos os pinos relacionados com o controle dos Displays (os pinos conectados ao Decoder 4511 e os de ON/OFF dos Displays via Transistores Q1 a Q3 do circuito). Então ela configura o TIMER1 para gerar as Interrupções que cadenciam a varredura dos Displays na taxa de 150Hz (incluindo a execução do "HOOK" para tratamento dos Botões).
Sobre a entrada e verificação da Senha
A inserção (ou entrada) da Senha, é controlada através de uma Máquina de Estados, e somente 3 estados foram necessários para todo o controle.
Mas antes de falar sobre a execução desta Máquina, vamos ver duas funções muito simples, que são utilizadas para decrementar ou incrementar os valores dos dígitos da Senha quando a mesma está sendo "inserida" via Botões "1" e "2". Também veremos a função que verifica se a Senha inserida está correta. Estas funções são mostradas na figura a seguir:
(clique na figura para "zoom")
A primeira função, de nome "decrementa_Digito_Senha", irá decrementar o valor do parâmetro "valor_DIGITO". Notar que o valor é do tipo byte, sendo que o "&" logo após a palavra "byte" indica que o parâmetro é passado para a função "por referência", ou seja, a função irá alterar a variável original correspondente ao parâmetro fornecido. O funcionamento é muito simples: a função verifica se o valor é "0", e caso seja, ele é setado para "9", já que a faixa de valores deve ir de 0 a 9. Mas se o valor for outro, ele simplesmente é decrementado.
A segunda função, de nome "incrementa_Digito_Senha", tem o mesmo mecanismo, porém irá incrementar o parâmetro "valor_DIGITO", também fornecido "por referência". Mas aqui é verificado se o valor é "9", e caso seja, ele é setado em "0". Do contrário, o valor é simplesmente incrementado.
A terceira e última função, a "verifica_SENHA", verifica se está correta a Senha atualmente inserida. Como a Senha inserida é constituída pelos dígitos individuais dados pelas variáveis "SENHA_IN_1", "SENHA_IN_2", e "SENHA_IN_3", é preciso "juntar" esses três dígitos em um único valor e então proceder à verificação se a Senha está correta. Como "SENHA_IN_1" tem o peso das centenas, este dígito deve ser multiplicado por 100. E como "SENHA_IN_2" tem o peso das dezenas, este dígito deve ser multiplicado por 10. E como "SENHA_IN_3" tem o peso das unidades, já está com o valor adequado para constituir a Senha atualmente inserida (e que está sendo exibida no Display). Isto é feito na linha 957 da função, onde as três parcelas são somadas. Então basta comparar o valor resultante com a Senha do Sistema, o que é feito na linha 959 da função, sendo o resultado desta comparação ("true" ou "false") informado no retorno da função.
Como dito, uma Máquina de apenas três estados, controla todo o mecanismo de entrada da Senha e verificação da mesma. Pode parecer difícil de visualizar ou acreditar nisso, mas o processo é muito simples conforme veremos a seguir.
Primeiro, vamos ver a definição dos três estados da Máquina de Estados, o que é feito em uma lista enumerada mostrada na figura a seguir:
(clique na figura para "zoom")
Notar que cada estado definido, está marcado com uma cor diferente (verde, azul, e laranja). Isto facilitará visualizar na Máquina de Estados, justamente a execução de cada um destes estados. Notar também que junto às definições, está a descrição do que é feito em cada estado, embora o próprio nome destes já deixe isso praticamente óbvio.
A Máquina de Estados está implementada na função "loop" do Arduino. Vejamos sua estrutura, o que é mostrado na figura a seguir:
(clique na figura para "zoom")
Observar as três regiões marcadas com as mesmas três cores correspondentes aos três estados da Máquina (definidos anteriormente na lista enumerada). Cada região corresponde à execução de um único estado. Quando a função "loop" é executada (e sabemos que ela é executada de forma cíclica), somente um dos estados será executado, e quem determina isso é a variável local de nome "estado_MAQ" (definida na área marcada na cor amarela na figura anterior), que é do tipo byte e também "static" (indicando que seu valor é mantido mesmo quando a função termina sua execução). Esta variável então assumirá apenas um dos três estados definidos. Mas quando o "loop" é executado pela primeira vez (e somente na primeira vez!!!) essa variável já indica o estado "SENHA_iniciar", o que garante que a Máquina tem um estado definido quando o Sistema inicia (ver área marcada em amarelo na figura).
E o próximo estado da Máquina, dependerá do estado atual em que ela se encontra e do que acontece neste estado. Vejamos então o funcionamento desta Máquina, conforme descrito a partir do seu estado inicial, o que é descrito a seguir.
No estado "SENHA_iniciar", que começa na linha 1021, as três variáveis "SENHA_IN_1", "SENHA_IN_2", e "SENHA_IN_3", que armazenam os valores que são mostrados nos três Displays, são zeradas, o que implica que veremos "000" nos Displays. Já a variável "DISPLAY_SENHA" é setada com valor "1", o que significa que o Display "1" está atualmente selecionado para a entrada de dígito da Senha. Ainda neste estado, os dois LEDs, "OK" e "ERRO" são desligados. Então a variável "estado_MAQ" é setada na linha 1032, para que a Máquina siga para o estado "SENHA_inserir".
No estado "SENHA_inserir" (que começa na linha 1038) é onde ocorrem todas as operações relacionadas à entrada de Senha. Na linha 1039, o teste "if" verifica através da função "verifica_BOTAO_trigger_ON" se o Botão "1" foi acionado, e caso isso tenha ocorrido, o "switch" na linha 1041 testa a variável "DISPLAY_SENHA" e conforme o valor desta (1, 2, ou 3) teremos que ou a variável "SENHA_IN_1", ou a "SENHA_IN_2", ou a "SENHA_IN_3", será decrementada, já que o Botão "1" tem esta funcionalidade.
Mas se o Botão "1" não foi acionado, então o "else if" na linha 1061 verifica se o Botão "2" foi acionado, e de forma semelhante ao já descrito, uma das variáveis dos Displays será incrementada, já que o Botão "2" tem esta funcionalidade.
Mas se o Botão "2" não foi acionado, então o "else if" na linha 1083 verifica se o Botão "3" foi acionado, e caso isto tenha ocorrido, então é selecionado o próximo Display através do incremento da variável "DISPLAY_SENHA". Mas aqui há mais coisas pra fazer, pois se "DISPLAY_SENHA" foi incrementada para além de "3" (ou seja, foi para "4"), significa que foi concluída a inserção dos 3 dígitos da Senha, o que é testado na linha 1087. Neste caso, deve ser verificado se a Senha inserida está correta, o que é testado na linha 1089 via função "verifica_SENHA" (que já analisamos), e se esta função retorna "true" então significa que a senha está correta, e neste caso o LED "OK" é ligado (na linha 1091). Mas se a função retornar "false", então a Senha inserida está incorreta, e o LED "ERRO" é ligado (na linha 1095). Independente se a Senha está correta ou não, como a entrada de Senha foi concluída, o Sistema deve aguardar antes de reiniciar todo o processo de entrada de Senha, e para isto na linha 1098 a variável "estado_MAQ" é setada para seguir para o estado "SENHA_aguardar".
Uma vez no estado "SENHA_aguardar" (que começa na linha 1105), novamente é aguardado que o Botão "3" seja acionado. Porém quando isto for detectado, simplesmente a Máquina de Estados é direcionada para o estado "SENHA_iniciar", o que reinicia todo o processo de inserção de Senha.
Como se vê, o processo é simples. Uma coisa importante a notar, é que a lógica mais complexa usada no processamento dos estados, é o "if / else" (o "switch" também é uma forma "sintética" de "if /else"). Isto é uma das coisas que garante a extrema confiabilidade do funcionamento da Máquina de Estados, implicando que a mesma seja praticamente livre de bugs (que são muito fáceis de ocorrer em lógicas malucas ou complexas), e ainda mantendo uma grande simplicidade.
O código e arquivos para Simulação estão neste link: "Senha_7_seg_01.zip"
Link para ver ou fazer download do vídeo da Simulação: "video"
A simulação ajuda a testar mais rapidamente o Sistema, permitindo se ver o funcionamento do Sistema sem precisar montar o circuito. Além disso possibilita que aqueles que não tem o Hardware em mãos, possam testar o Sistema e aprender com isso, fazendo suas experiências.
Em caso de dúvidas, não deixe de perguntar.
Espero ter ajudado.
Abrçs,
Elcids…
Adicionado por Elcids Chagas ao 13:54 em 15 julho 2021