Sketch para Interruptores – Avanços

Depois de 2 meses, estou de volta.

Férias e outros assuntos acabaram fazendo com que eu deixasse o blog um pouco de lado, mas contra a vontade.

O bom é que chegou uma infinidade de sensores e módulos que eu havia comprado, e agora certamente assunto não vai faltar. Entre os itens que chegaram e pretendo falar a respeito estão:

  • Raspberry
  • Led WS2801
  • Células solares

Alem dos itens que comprei, a reforma da casa andou um pouco. O serviço de gesso esta pronto nos quartos, e logo vamos por em prova o ambiente de testes.

Por falar nele, este post é uma continuação dos posts anteriores, portanto, caso ainda não tenha lido, sugiro que leiam os dois posts abaixo, pois este aqui continua exatamente onde o anterior parou:

  1. Automação Residencial – Ambiente de Teste
  2. Sketch funcional para uso com interruptores pulsadores

Agora que leram, vamos dar uma utilidade maior ao nosso código, inserindo alguma “inteligência” nos pulsadores. Novamente vamos nos ater somente ao pulsador 1, pois senão o texto fica enorme e analisar um pulsador é o suficiente para compreendermos. Claro que se surgirem dúvidas, por favor perguntem, bem como receberei com o maior agrado qualquer sugestão.

Insiram no começo do código (antes do setup) as seguintes variáveis:

// Variavel para acionar todas as lampadas
boolean todas = false;
//Teste toques multiplos
int contagem=0;
long tempoA=0;

Substituam o código no início do loop, referente ao pulsador 1, pelo seguinte código:

  int tempoPulsa1 = pulsador1Tempo();

 if (tempoPulsa1 > 2000){
 if(!todas){
 int i = 0;
 for (i=0;i<4;i++){
 tone(13, 800, 50); // play the tone
 delay(100);
 }
 }
 todas=true;
 }
 else if (tempoPulsa1 > debounceTime){
 pulsa1_estado = true;
 }
 else {
 if (todas){
 aciona_todas();
 pulsa1_estado = false;
 todas = false;
 }
 else if (pulsa1_estado == true ) {
 //comutaRele(spot1, spot1_estado);
 pulsa1_estado = false;
 contagem++;
 tempoA=millis();
 }
 if (contagem > 0){
 if(millis() - tempoA > 300){
 if(contagem==1)
 comutaRele(spot1,spot1_estado);
 else if (contagem == 2){
 comutaRele(spot1,spot1_estado);
 tone(13, 800, 50);
 }
 contagem=0;
 }
 }
 // if (contagem ==1){
 // if(millis() - tempoA > 2000){
 // comutaRele(spot1,spot1_estado);
 // contagem=0;
 // }
 // }

 }

Agora, insiram ao final do sketch a seguinte função:

void aciona_todas(){
 if (!spot1_estado){
 spot1_estado = !spot1_estado;
 digitalWrite(spot1, spot1_estado);
 }
 if (!spot2_estado){
 spot2_estado = !spot2_estado;
 digitalWrite(spot2, spot2_estado);
 }
 if (!led_estado){
 led_estado = !led_estado;
 digitalWrite(led, led_estado);
 }
}

Quem não entendeu as mudanças a serem feitas no código apresentado no post anterior, baixe no link abaixo o sketch funcional(arquivo zipado):

lampada_v4

Legal, vamos entender agora as modificações e o que elas fazem. Preste atenção e não hesite em perguntar, por que é muito importante entendermos o que estamos fazendo. Lembrem-se que estamos apenas no início do projeto.

Se lembrem que, pela explicação do post anterior, toda a lógica do sketch faz apenas com que uma lampada seja acessa ou apagada, conforme dermos UM toque no pulsador. Se ficarmos pressionando o pulsador indefinidamente, a lampada vai ficar acendendo e apagando. Com as modificações introduzidas neste post, vamos detectar e tratar as seguintes situações:

  • Toque longo no interruptor
  • Duplo toque rápido

Toque longo no pulsador

Para interpretarmos o toque rápido, criamos a variável todas e atribuímos a ela o valor false. A ideia desta variável é controlar o acendimento de todas as lampadas de um comodo, por exemplo, quando um determinado interruptor for pressionado por determinado tempo. Essa ideia pode ser expandida, e qualquer pulsador da casa pode ser “programado” para acender um conjunto de lampadas, que pode ser todas. As possibilidades são muitas, e depende apenas da necessidade e criatividade.

Voltando para a analise do código, se lembrem que enquanto estamos pressionando o pulsador, uma variável correspondente é incrementada pelo tempo que o interruptor se mantem pressionado. Após alguns testes, defini que 2 segundos é um bom tempo para considerar um “toque longo” no interruptor, e podem ver no código que é justamente um tempo maior que 2000 (ou 2 segundos) que uso para alterar a variável todas da forma desejada. O que interessa mesmo após a verificação de que o tempo pressionado foi maior que dois segundos é a linha todas = true; Basicamente invertemos o valor da variável todas de false para true, sinalizando futuramente para o sketch o tratamento que queremos.

Após a variável todas ter seu valor alterado para true, a verificação if (todas) retornará true, e o bloco do if será executado. Dentro deste bloco temos uma chamada a função aciona_todas(), recém criada. Esta função simplesmente verifica se as lampadas estão acesas, acendendo-as caso não estejam. Então desativamos as variáveis pulsa1_estado e todas, já que o objetivo foi alcançado, que era acender todas as lampadas com um toque longo.

Pronto, mais nada relativo ao pulsador 1 será executado, até que o interruptor seja novamente pressionado. Mas, e aquele código logo após a verificação do valor da variável que armazena o tempo de pressionamento?? Bem ai…

Ajuda inesperada

Tenho dois filhos, um de 6 anos, Pedro, e o outro de 9 anos, João. O Pedrinho é um terror, e esta sempre me “ajudando” em todas estas trapalhadas que invento. Então o Sr Pedro pegou um buzzer(aquele alto-falanto pequeninho), e queria que eu colocasse ele no ambiente de testes, mais precisamente ele queria que o buzzer ficasse “apitando” se eu segurasse o interruptor. Então dai veio a ideia de incorporá-lo realmente ao projeto, mesmo por que seria muito interessante uma forma de saber QUANDO o interruptor foi pressionado o suficiente para um toque longo, alem de servir para outros avisos sonoros.

Então, explicando o código, a primeira vez que o tempo de pressionamento for maior que 2000 (ou 2 segundos), ele verifica o valor da variável todas, e se for true (notem a exclamação invertendo o valor da variável), ele aciona o buzzer dando 4 “apitinhos” para avisar que o tempo foi atingido. Se você continuar pressionando o pulsador, não haverá mais “apitinhos”, pois logo após atribuímos true á variável, e as verificações posteriores resultam em false.

Espero que tenham compreendido como foi implementado o “toque longo”, sei que muito provavelmente há formas melhores, e contribuições serão bem vindas. Thanks ao Pedrinho, e lá vamos nós “matar” mais um pino do Arduino por comodo.

Duplo toque rápido

Detectar dois toques rápidos me deu muita dor de cabeça. Não sou expert em programação, e, após muito pensar, cheguei a uma solução até melhor do que eu queria. Vamos analisar o código e ver como cheguei a esta solução.

As novas variáveis contagem e tempoA controlam respectivamente o número de “toques rápidos” e o tempo a ser considerado para um “toque rápido”. Após o tempo de pressionamento do pulsador(tempoPulsa1) ser maior que debounceTime, a variável tempo1_estado recebe true, sinalizando que o pulsador foi pressionado. Quando soltamos o pulsador, considerando que não atingimos o tempo de 2 segundos, a verificação da variável todas “falha”, e a verificação da variável pulsa1_estado “passa”.

No bloco do if, “desativamos” a variável pulsa1_estado atribuindo false a ela, incrementamos a variável contagem de 0 para 1, e armazenamos o tempo atual atribuindo a tempoA o valor retornado pela função millis().

Continuando, se o valor de contagem for maior que 0, indicando que o pulsador foi pressionado, verificamos se o tempo desde o ultimo pressionamento foi maior que 0,3 segundos (ou 300 milésimos de segundo). Caso o tempo seja maior, verificamos se o valor de contagem é igual a 1, caso seja, significa que o pulsador foi acionado uma vez, e então acionamos a lampada. Se contagem for 2, também acionamos a lampada, mas desta vez emitimos um apito, apenas para indicar que a lampada foi acesa com um um toque duplo rápido. Por fim, “resetamos” a variável contagem, atribuindo 0 novamente a ela.

Notem que esse ultimo bloco de código é a alma do negócio. A variável contagem somente será maior que 0 se o pulsador for pressionado por pelo menos uma vez, e por um tempo menor que 2 segundos. Notem também que enquanto não passar o tempo de 300 milisegundos, nada acontecerá, inclusive a variável contagem não voltará a 0. Com isso, temos 300 milisegundos para acionar novamente o pulsador, sempre por um tempo menor que 2 segundos, pois do contrário estaremos ativando a variável todas e “by-passando” todo o código do “toque rápido”. Ao acionarmos novamente o pulsador, incrementaremos a variável contagem, e então poderemos detectar o toque duplo. Ainda, observem que tempoA é sempre “resetado” ao acionarmos o pulsador.

Eu disse anteriormente que a solução ficou melhor do que eu esperava, pois percebam que ficou fácil detectar tanto 1 ou 2 toques rápidos, quanto 3 ou mais toques rápidos. Os 300 milisegundos foram definidos por tentativas, e considero um tempo que não incomoda, é desconsiderável o delay entre acionar o pulsador e a lampada acender. Pelo que vi, dá para diminuir esse tempo até próximo dos 150 milisegundos, sem prejudicar a detecção de um toque duplo. Poder detectar n toques rápidos faz brotar um monte de idéias na cabeça, como por exemplo algum código baseado em determinado número de pressionamento de determinados pulsadores, enfim, a criatividade rola solta.

Para encerrar, mais um pouquinho de história. Repararam o código que esta comentado? Pois bem…

Beta-testers aprovados

Assim que fiz o sketch, chamei o Pedro e o João para verem. O Pedrinho chegou e pressionou rapidamente o pulsador umas 200 vezes seguidas. Claro que parou o pulsador em questão né? Eu verificava apenas se contagem valia exatamente 1, como ele pressionou várias vezes, contagem foi lá para as alturas, e o if nunca retornava true, nem mesmo contagem voltava mais a 0. Fiquei com cara de tacho na frente dos dois, e lá vamos nós descobrir o que eu tinha feita errado. Antes de chama-los para ver, eu testei apertando diligentemente o pulsador exatamente 2 vezes, e não 200 como o Sr Pedro fez.

Finalizando.

Bem, embora eu esteja satisfeito com o que tenho até agora, tenho plena consciência de que pode ser muito melhorado, ou mesmo feito de outra forma, muito melhor. Fiquem a vontade para fazer perguntas, dar sugestões, críticas, etc, etc.

Tem surgido alguns comentários bem interessantes, e espero que cada vez aumente mais, pois sem dúvida que a troca de idéias favorece e leva todos a ganharem um pouco.

Abs.

2 thoughts on “Sketch para Interruptores – Avanços

  1. Patrick Costa

    Ola! Excelente post!!! Sou um entusiasta da área de TI e eletrônica e estou interessado em automação residencial. Suas ideias são ótimas, fácil de entender e me impressionou a forma que detalha seu pensamento criativo.

    Tenho algumas duvidas, quantos reles individuais o arduino consegue trabalhar ? Se eu utilizarmos uma placa com 16 reles (http://goo.gl/j0DSzQ), como será a ligação? É necessário uma placa de reles especifica para o arduino?

    Parabéns e continue com os trabalho.

    Abraços

    Reply
    1. Valdinei Rodrigues dos Reis Post author

      Boa noite Patrick.
      Muito obrigado pela visita e pela gentileza nos elogios.

      Essa placa não sai da minha cabeça. Como pode ver pelo meu projeto, os reles são individuais e estarão localizados junto às lampadas. Eu preferi assim porque considerei que seria melhor levar os fios de acionamento do rele (Cabo UTP) da central até as lampadas do que levar os fios das lampadas(muito maiores). Porem, se é melhor ter tudo centralizado é uma dúvida constante para mim…

      Respondendo a sua pergunta, essa placa que citou é alimentada por 12V, precisa ver com qual voltagem vai alimentar o Arduino, e se for diferente de 12v vai precisar de fontes separadas, não se esquecendo que o GND tem que ser o mesmo. Os pinos (que efetivamente acionam os reles) precisam de 5v, portanto pode usar diretamente o Arduino para isso. Como o Arduino tem 14 pinos digitas, e destes dois são usados para a serial, você pode usar pinos analógicos para isso sem problema. Ah, se estiver usando o Arduino Mega, número de pinos não vai ser problema.
      Se ainda estiver em dúvidas, por favor avise.

      Abs.

      Reply

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

14 − treze =