segunda-feira, 6 de maio de 2019

Fechadura Digital com Arduino: Aproximação e Senha

Este post é a parte dois da série da fechadura digital, para entender e obter explicações do código é necessário a leitura da primeira parte: http://agrodadosbr.blogspot.com/2019/05/fechadura-digital-com-arduino-uno-e-rfid.html

A fechadura digital baseada no Arduino UNO já estava bem interessante da forma que estava, lógico que aqui estamos apenas trabalhando a parte digital, ficando a mecânica e seu desafio de abrir quando a fechadura estragar para outra situação. Grande parte já estava pronto, tínhamos uma interface de comunicação e uma automação interessante, um produto já funcional.

Ocorre que o módulo RFID utilizado RC522 não apresenta tecnologias recentes de segurança, de modo a não ser recomendado como única forma de autenticação, sendo ideal utilizar autenticação dupla, sendo essa segunda forma, por exemplo, uma senha. Então resolvi adicionar um teclado a fechadura.

Mas de verdade, nem foi esse motivo, pois a fechadura que estou desenvolvendo não vai ser exposta. Então alguém para ter acesso indevido a ela vai precisar pular o portão principal (da rua), descobrir como ela funciona, acessar ela (que estará chumbada no concreto) para depois fazer alguma coisa. Então de verdade, não vai ser aqui que vão hackear a tag RFID ou algo do tipo, não é porque a autenticação do módulo é falha que isso vai representar uma falha no tipo de uso que vou utilizar. Mas se for a sua questão existe um módulo com bem mais segurança: PN532 e olha que não é tão mais caro e vem com NFC.

A questão do teclado, já que ele não vai ser usado para dupla autenticação, é mais pela comodidade. O intuito é poder sair de casa sem nada e poder retornar sem problemas, mesmo sem o celular poder adentrar. Então o teclado serve como método alternativo de entrada. No futuro desejo ter três: RFID, Google Assistant e teclado.

O teclado utilizado é um matricial 4x4
Não é a minha opção favorita, prefiro o 1x4, até para poupar pinos, que estão escassos já. Mas se precisar de mais teclas o touch 4x4 é mais confiável e robusto.
Mas como tenho em mãos apenas o matricial, vai ele mesmo. Esse teclado por ter seu código todo feito de forma manual, sem a utilização de bibliotecas, existem inúmeros exemplos em português, e no final pretendo exemplificar porque esse opção é super interessante e vai ser extremamente útil para aplicar funcionalidades.

Mas no caso em questão em optei pelo uso de bibliotecas por alguns fatores simples. Primeiro é a facilidade de código, depois vem a organização e a simplicidade do código, uma vez que essa clareza auxilia muito em um código que está sendo trabalhado e ainda terá tantas mais linhas a serem implementadas.

Desta forma foram adicionadas duas bibliotecas. Password.h e Keypad.h. A primeira automatiza toda a parte de digitação e verificação do código, a segunda permite utilizar o teclado de forma simples, e com um número bem reduzido de linhas e configurações no código. Logo acima do setup foi acionado o bloco que chamei de "Informações a respeito do teclado". Ali existe o cadastro da senha, eu optei no momento por ter apenas uma senha mesmo. Basta substituir o entre aspas (123) pela senha que desejar, aqui vale utilizar O ABCD do teclado. Não recomendo o uso do * e #, pois mais adiantes vamos ver que estão reservados.

Logo em seguida duas constantes, informam a quantidade de linhas e colunas do teclado. Depois como as teclas estão ordenadas. A seguir você informa em quais portas conectou as linhas e colunas do teclado. No caso, visto de frente, os quatro primeiros pinos são as quatro linhas, respectivamente. Ou seja, na porta 14 está conectado o pino 2 do teclado. Observe que a seguir também é criado um objeto para o teclado, com todas aquelas informações anteriores.

Já entrando no setup foi adicionado o evento que recebe as informações digitadas. Já o loop mudou pouco, antes se a porta estava trancada ele verificava o aperto do botão interno de abertura e se havia alguma leitura no RFID. Agora além de verificar tudo isso ele verifica também se existe entrada no teclado, pela função keypad.getKey().

Lá no final do código foram adicionadas as funções expostas das biblioteca, várias funções chamadas são internas da biblioteca e não visíveis pelo código. Assim a lógica ali no final é mais ou menos essa: Verifica o teclado, se foi pressionado algo ele vai ativar o buzer rapidamento, confirmando que o valor digitado foi recebido. Assim ele verifica qual o valor digitado e segue a lógica:
  • Se for *: Ele verifica se a senha digitada confere com a senha correta
  • Se for #: Ele deleta a senha que está armazenada, limpa o que foi digitado
  • Se for outro valor ele armazena como um dígito da senha
É por isso que a senha não deve conter * e #, pois são estruturas de controle. A última função verifica a senha, se for a cadastrada roda a função acessoLiberado. Se não for roda a acessoNegado. 

Aqui é importante um detalhe: Depois que a senha for digitada certa, ao rodar a função acessoLiberado é preciso limpar a memória da senha digitado rodando a função password.reset();.
Pode se rodar também quando a senha for errada, mas essa situação não interfere muito no uso do usuário, e acho até mais seguro sem ela. Forçando sempre o uso do # antes da senha. É importante fazer o reset porque se não a senha correta vai estar sempre gravada, até o # ser pressionado. Ou seja, ao apertar apenas o * ele vai confirmar a senha, uma vez que a correta está salva. Apague essa linha, digite a senha correta e depois tente abrir a fechadura apenas apertando o asterisco, você entenderá.

Assim, resumindo o funcionamento da senha:
  • Aperta o # para limpar a senha
  • Digita a senha
  • Cada tecla pressionada tem um feedback sonoro de confirmação
  • A própria biblioteca controla que cada clique digita o valor apenas uma vez
  • Se a senha for a correta a fechadura se abre igual pelos outros métodos e a senha é limpa
  • Se a senha for incorreta existe o feedback visual padrão, e a contagem de 4 erros para o alarme se soma
  • Ou seja, dois erros pelo RFID e dois erros pelo senha já são suficientes para ativar o alarme.
  • Então 4 erros, quais quer sejam os métodos é suficiente para ativar o alarme.

sexta-feira, 3 de maio de 2019

Fechadura Digital com Arduino UNO e RFID

Para o projeto de uma casa que integra uma automação residencial completa muitos pontos são importantes. Citaria logo a questão do assistente pessoal, do hub de automação, dos módulos relés, das lâmpadas inteligentes e por aí vamos longe.

Um dos pontos que não se cita normalmente são as fechaduras, ok, temos no mercado internacional e também nacional inúmeros modelos já difundidos, de sobrepor e de embutir. Elas possuem métodos de aberturas bem distintos, cartão, senha, biometria, chave física. Todas possuem um único objetivo, facilitar a abertura da sua casa e torná-la mais segura, mais complexo de violar digamos.

Um ponto que ainda é escasso é que essas fechaduras são apenas fechaduras, em pleno meio de 2019 os modelos são sim tecnológicos e super modernos, cumprem seu papel. Mas a grande maioria, e todos os modelos nacionais, pecam em um ponto. Não são pensados em automação residencial. Não possui conectividade, não tem sequer infravermelho, RF, IR, quem dirá integração com Google Assistant, Alexa, Siri. Alguns raros modelos possuem lá seu WiFi com aplicativo próprio e tal. Mas ainda sim se encontra bem mais modelos de qualquer outra coisa automatizada que de fechaduras automáticas.

Eu já passei alguns apuros por ter uma fechadura não conectada, a minha nem é dessas inteligentes, é apenas a velha chave mesmo. Já fiquei preso na rua, já deixei meu irmão preso na rua, já precisei abrir a casa a distância para parentes que chegaram de viagem. Não vejo ainda muito sentido nos benefícios e preços das fechaduras conectadas, ao menos os modelos atuais hiper limitados. E os que são conectados não facilitam a automação.

Eu quero ir dormir e dar boa noite ao Google Home, e ele sozinho vê se a porta está trancada, tranca meu carro, ativa o alarme, fecha as janelas, ativa a definição de luzes... Eu quero abrir a minha casa a distância para quem for, desde um prestador de serviço a uma ambulância. Eu quero viajar e perguntar ao Google Assistant se minha porta está trancada. Vai dizer que não perdeu muito tempo conferindo se tudo está fechado várias vezes da sua vida?

Então o básico é o seguinte, eu preciso de uma fechadura, com integração a um hub de automação residencial (Home Assistant), na qual eu posso controlar e verificar status remotamente. Além de que ela tenha funções de automação e um interface IHM embutida, afinal, um feedback sem precisar pegar o telefone é bem vindo. Assim eu desenhei no Google Documentos mesmo como seria mais ou menos a lógica de funcionamento.

Primeiro a fechadura verifica se está fechada, essa verificação pode parecer boba, mas ela vai me retornar o status que preciso para monitorar a porta remotamente. E também não faz muito sentido a porta estar aberta e mesmo assim ela ficar lendo o cartão, enfim, eu coloquei, dá pra tirar também, sem alarde. Como ela sabe se está trancada, a lingueta tem um imã na ponta, que trabalha em conjunto com o reed switch, basta ler o estado dele por meio do digitalRead. Se for 1 a porta está trancada, se for 0 a porta está destrancada. Lembrando que saber se está aberta ou não fica pro sistema de alarme, a fechadura informa apenas trancada ou destrancada.

Se ela está aberta ela fica lendo a informação. A partir do momento que está trancada ela fica lendo o leitor de RFID para ver se foi feita alguma leitura, enquanto monitora o botão de abertura interna para ver se foi acionado.

Se o cartão foi lido, ele verifica se o cartão está cadastrado. Se estiver ele roda a função de abrir a porta. Se não estiver ele indica erro e soma em uma variável. Ao atingir 4 erros a fechadura aciona o sistema de alarme da residencia. Da mesma forma que se o botão interno for pressionado a função de abertura é executada. 

Se a porta abriu ele faz a indicação visual, dois bipes e acendo o LED de confirmação. A partir desse momento ele roda um loop "enquanto" (while). Enquanto a porta está aberta ele fica verificando se a porta está aberta ou não e pisca o LED de confirmação. Quando ele verificar que a porta fechou ele tranca ela, apaga os LEDs e dá um bipe único de confirmação.

Agora vamos analisar o código que eu escrevi e os seus problemas (que são alguns).



Copie e cole na Arduino IDE, ou melhor ainda, no Visual Studio Code e vamos analisar juntos.
Primeiro a lista de materiais é a seguinte: LED para status positivo (usei um branco alto brilho), LED para status negativo (usei um vermelho comum), Buzzer (usei um ativo mesmo), um botão (pushbutton comum), um Arduino, ESP ou o que for (Usei um Arduino Uno pq sempre testo nele, mas o final vai rodar em ESP), um motor servo (para ilustrar o mecanismo da fechadura), e o Leitor RFID-RC522.

Iniciamos o código com as três bibliotecas que vamos precisar, SPI (comunicação do RFID), MFRC522 (controle do RFID) e a Servo, para controlar o servo lúdico (posicionado como cancela).
Definimos logo em seguidas algumas informações para facilitar. Declaramos variáveis e o vetor que armazena quais TAGs RFID são as autorizadas para abrir a porta. Inicia os objetos.

Agora chegamos ao setup. Aqui são apenas declarações básicas de bibliotecas, início da serial (bom para teste) e declaração de tipo de pinos.

O loop é simples: Se grava o estado da fechadura (aberto ou fechado) na variável porta. Se esse valor é 0 (está aberta) aguarda 200ms e verifica novamente.
Se o valor for outro, no caso 1, ele verifica se o botão de abertura interna está pressionado, se estiver roda a função de abertura (acessoLiberado), se não ele efetua a função que lê o RFID (leitura). Lembrando que essa questão de verificar o botão e o cartão é extremamente rápido, mesmo em um UNO.

A função leitura é aquela responsável por ler a analisar o RFID. Primeiro ele esvazia a variável que guarda as informações do cartão lido, ou seja, sempre que se terminar de ler um cartão a função retorna e limpa a informação do último cartão lido (óbvio que se for desejado dá pra salvar bem facilmente). Então nessa função ele verifica se um cartão foi encontrado pelo leitor, se não ele aguarda 50ms e verifica novamente. Se tiver sido encontrado ele armazena o ID do cartão na variável TAG. Assim ele verifica se essa TAG se encontra na lista das permitidas. Se tiver a variável permitido tem seu valor alterado para verdadeiro, se não ela continua como falso.

Agora o programa analisa a variável Permitido. Se ela for verdadeira se roda a função que abre a fechadura (acessoLiberado), a mesma que roda quando o botão é pressionado. Se a variável Permitido é falsa, ou seja, a leitura verificou que a TAG não é permitida e não alterou a variável (lembra que essa verificação só existe após a leitura de uma TAG) é aguardado um segundo, para evitar leituras seguidas e se aciona a função acessoNegado.

Agora a função de acessoLiberado, aquela que roda quando o cartão RFID está na lista de permitidos ou quando o botão interno é acionado. A primeira coisa que é feita é abrir a fechadura, alterando o ângulo do servo. Após isso se roda a interface IHM que indica para o usuário que a fechadura se abriu. Ele acende o LED de confirmação, e dá dois bipes de 300ms no Buzzer. Aguarda 5 segundos (tempo para o usuário abrir a porta).

Depois desse intervalo ele verifica o estado da porta. Aqui uma questão, ele verifica para mesmo sensor da fechadura, então ele sempre verifica se a porta está trancada ou não, o que não funciona. Até então essa verificação era correta. Agora aqui não se pode verificar se está trancado ou não, precisa é verificar se a porta está fechada, ou seja, use outro sensor, como o do alarme. Então seguindo, ele verifica se a porta está fechada e guarda a informação na variável "porta". Enquanto a porta está aberta, valor da variável 0, ele pisca o LED de indicação e atualiza a variável, que logo em seguida vai ser verificada pelo while. Ou seja, enquanto a porta estiver aberta (0), pisca o LED, quando ela fechar (1), segue o loop.

Quando ela fechar aciona o servo para a posição de trancado, desliga o LED de indicação e aciona a sirene por um curto período. Depois altera a variável permitido para falso, assim a porta só vai abrir quando ela trocar para permitido, ou seja, um cartão cadastrado for usado. Ou a função de abertura ser chamada novamente. É importante trocar o valor da variável. E reseta o contador de erros que aciona o alarme. Ou seja, se tentar 4 vezes com um cartão não cadastrado o alarme é ativado, mas se tentar 2 vezes e depois acertar você terá 4 chances na próxima tentativa.

A próxima função é a acessoNegado, que funciona quando a TAG lida é errada. Ela apenas adiciona uma tentativa na variável "errado" que conta os erros, aciona o LED de erro e o buzzer para avisar o usuário do problema. Depois ela verifica quantos erros aconteceram, se foi mais de 3 ativa a função que ativa o alarme.

A função ativaAlarme é chamada em caso que seja necessário ativar o alarme da residencia, aqui se coloca o código necessário para tal, para exemplo coloquei o buzzer tocando por dois segundos. Depois reseta o número de erros, caso contrário ao errar 4 vezes, ativar o alarme e outro dia errar uma única vez novamente o alarme seria ativado, pois o número de erros iria apenas somando e sempre seria mais de 4.

Bom, agora é necessário integrar isso ao HUB de automação e colocar uma forma alternativa de entrada, como um teclado, que pode ter um código padrão de abertura e um de socorro. É necessário também fazer ajustes como os dos sensores utilizados. Também pode se ativar o alarme que houver algum violação de abertura, só chamar a função. A abertura remota pode ser feita por MQTT, acionando a função de abertura. Essa divisão de funções auxilia demais.

E para ativar sua fechadura basta trocar os comandos de posição do servo para as funções de abrir e fechar sua fechadura.

Mas acredito que o código como está já é de grande valia para qualquer um que queira fazer um fechadura digital, inteligente ou não, autônoma ou não, já polpa muito tempo.

Para finalizar vamos verificar se tudo que era necessário foi inicialmente cumprido.
''Então o básico é o seguinte, eu preciso de uma fechadura, com integração a um hub de automação residencial (Home Assistant), na qual eu posso controlar e verificar status remotamente. Além de que ela tenha funções de automação e um interface IHM embutida, afinal, um feedback sem precisar pegar o telefone é bem vindo. Assim eu desenhei no Google Documentos mesmo como seria mais ou menos a lógica de funcionamento.''

A integração ainda não existe, mas está pronta para ser implementada, por RF, MQTT ou o que for. Funções de automação existe, como acionar o alarme sozinha e trancar sozinha quando a porta fechar. O feedback também existe por buzzer e LED, e se for o caso um visor também pode ser facilmente incluído.

Vou continuar a trabalhar na fechadura, espero que o próximo post já tenhamos integração online (espero que por MQTT) e que ele já rode em um ESP, vamos ver se o 8266 vai dar conta sem precisar apelar para o mais caro ESP32.

quinta-feira, 20 de setembro de 2018

BME280 - Uma ótima opção de sensor de temperatura, umidade e pressão atmosférica

O BME280 é um minúsculo sensor da Bosch capaz de capturar ao mesmo tempo três variáveis ambientais, a umidade relativa do ar, temperatura e pressão atmosférica/altitude. Por ser focado em dispositivos vestíveis, ele se apresenta como uma opção excelente para nós. Ele possui diminuto tamanho, boa acurácia e baixíssimo consumo. Para capturar dados ambientais a campo, o BME280 aliado a um ESP ou microcontrolador de baixo consumo pode ser a combinação perfeita. 

Seu único inconveniente é operar apenas em 3V3, dificultando um pouco a operação com a maioria dos Arduinos, mas operando perfeitamente com a família ESP, que também tem opções de consumo ínfimo.

Quando comparado com o DHT22, sensor mais comum para captura de temperatura e umidade do ar (DHT11 não serve para captura de informações), o BME280 apresenta muitas vantagens, além de seu tamanho.

Para se ter uma simples comparação o DHT22 envia seus dados por meio de um único fio de sinal digital, enquanto o BME280 faz uso do protocolo I2C e SPI, ocupando mais portas e necessitando de maiores fiações. Ambos são capazes de medir a mesma faixa de temperatura de -40°C a 80°C, sendo que o sensor da Bosch mede até 85°C. O tempo de resposta do DHT22 é o dobro do concorrente, cerca de 2s. Mas o desempate de antes vem no consumo de energia:
  • DHT22 consome 1.0 até 1.5mA em atividade, caindo para 40 até 50μA quando em repouso
  • BME280 consome 1.8 até 3.6μA quando em leitura, a depender dos dados a serem lidos, já em repouso seu consumo chega a 0.1μA
A diferença de consumo dos dois é proporcional a diferença de tamanho, com certeza em loggers movidos a bateria essa diferença será muito importante. Agora tem outra diferença notável entre os dois, o preço: DHT22 se encontra por cerca de R$16,90, contra R$30,00 do BME280. Por incrível que pareça, na China ambos são encontrados pelo mesmo preço, na faixa de R$11.


Se você deseja aprender a utilizar o BME280 deixo o link para um ótimo tutorial que utiliza o NodeMCU8266 para exemplificar: https://robotzero.one/esp8266-and-bme280-temp-pressure-and-humidity-sensor-spi/

Acredito que deu para ver as diversas vantagens que o BME280 apresenta e pensar em diversos usos para o mesmo, principalmente no que diz respeito a dobradinha com o ESP. Mas para finalizar eu realizei um teste rápido com os dois sensores conectados a um ESP8266, colocados dentro de uma caixa fechada, lado a lado na protoboard, coletando a temperatura e umidade a cada 3 segundos. A alimentação foi fornecida pela USB do NodeMCU e a coleta de informações através do serial monitor.

Os gráficos comparativos podem ser vistos abaixo:
Os gráficos reafirmam a "superioridade" do BME, dois dois pontos de precisão "21,88°C" vs um ponto de precisão do DHT "21,8°C". Também foi possível notar a confiabilidade e linearidade dos dados. Observe que em temperatura ambos apresentaram números semelhantes, o que não aconteceu com a umidade.

Claro que estes foram testes simples, mas acredito que foi possível apresentar o BME280 como uma alternativa viável ao DHT22, ainda mais comparando preços no exterior.

quinta-feira, 30 de agosto de 2018

Um datalogger simples para monitorar meu cachorro


O intuito do meu uso com microcontroladores se dá em resolver problemas e ter dados concretos para tomar decisões lúcidas. Então me vi no primeiro problema que usar um Arduino para capturar informações me seria de imensa valia. Vou explicar o problema:

Eu não tenho um abrigo de animais, mas minha casa é espaçosa, então sempre que tenho algum dinheiro a mais dou lar temporário para um animal que tiro da rua até encontrar um lar. Esses animais dormem junto a mim no meu quarto, mas o animal do momento é o Taurus, um cachorro de porte médio que venho com traumas e doença do carrapato. Devido ao fato dele não poder tomar banho e outros fatores não posso colocá-lo para dormir como os outros. Então ele dorme na área de serviço, em uma casinha improvisada, protegida por papelão, a máquina de lavar, PVC e caminhas de pano.

O problema é que após ser curado da doença de carrapato, tratamento este bem caro, o Taurus começou a apresentar tosses, acredito que pela combinação de baixa temperatura e baixa umidade. Desta forma eu precisei coletar dados sobre a noite dele. Então determinei quais os dados seriam de grande valia para que eu possa avaliar a situação e resolver o problema.

Foi então que decidi coletar os seguintes dados:
  • A umidade do ar, esse fator é importante para o bem estar da garganta, ainda mais para cães grandes que respiram pela boca boa parte do tempo.
  • A temperatura do ambiente geral, para saber se seria necessário o uso de algum artifício para gerar calor
  • A temperatura do ambiente dele, para saber se toda a proteção improvisada estava servindo para manter o animal mais aquecido que se não tivesse a proteção (o local não pega vento)
  • A movimentação do animal, preciso saber se ele passa mais tempo exposto ou dentro do local protegido que pensei que tinha feito
A lógica do produto criado foi a seguinte, ao ligar ele verifica se o cartão SD foi iniciado corretamente. Caso verdadeiro ele ativa o buzzer por um breve tempo para informar que tudo se encontra bem. Assim ele começa a analisar repetidamente o sensor pir. Se o sensor de movimento for ativado se incia o loop:
Se lê os dados do sensores DHT22 e DS18B20, se lê o horário por meio do RTC, grava esses dados no cartão SD e mostra algumas informações na tela para controle. Quando se tem um protótipo é muito difícil monitorar seu funcionamento sem uma tela, claro que depois de tudo operando normalmente a mesma pode ser removida. Caso se passe uma hora sem que o sensor de movimento se ative o sistema inicia o loop sozinho. Tudo rodando em um arduino UNO e alimentado pela tomada, utilizando uma fonte para protoboard. Foram utilizados dois LEDs, um de alto brilho branco que se ativa quando um movimento é detectado. E um vermelho normal que se ativa quando existe algum erro com a gravação no SD.

Esse datalogger foi de valia pelos novos modos de trabalho que não haviam sido incorporados nos dataloggers que construímos anteriormente no blog. Primeiro que a gravação de dados não é mais efetuada apenas por um fator, que no caso era o tempo. Agora a leitura é efetuada se acordo com um fator externo (movimentação), e se esse fator não se manisfestar durante uma hora a leitura é realizada automaticamente. Outra questão é que não apenas podemos mais trabalhar com millis. O RTC se demonstrou necessário porque eu preciso saber a hora exata da gravação, ele não ocorre mais de 15 em 15 minutos, ela ocorre em qualquer hora, e saber essa hora é crucial. Mesmo que o millis ainda seja utilizado para controle de tempo.



Bom, vou comentar um pouco das estruturas do código ao invés de comentar ele propriamente dito, uma questão de organização pessoal. O código se inicia com algumas declarações, são apenas aquelas que seriam muito importantes por serem repetitivas, umas vez que muitas portas digitais foram usadas. Depois se procede a inclusão das bibliotecas padrões dos dispositivos. Para o oled eu usei a MicroLCD, gosto muito dela por ser leve e simples para somente escrever um texto na tela. Depois que todas as configurações das bibliotecas e as variáveis são declaradas vamos ao setup básico. Utilizei a serial para testes usando o PC, mas ela não é mais necessária, incio os LEDs e buzzer como nível baixo e imprimo uma mensagem no OLED.
A parte do SD é interessante para a verificação inicial, se tudo ok o buzzer se ativa por 300ms. Se existe um erro chama a função erro(). No momento ela apenas acende o LED, mas chamar a função é uma estratégia para o futuro, quando for necessário implementar algo mais para alertar um erro basta implementar na função, assim não precisa editar no software inteiro.

O loop também é bem tranquilo e reaproveita o raciocínio do datalogger anterior. A cada 100ms atualiza a variável que armazena o tempo do millis(), e verifica o estado do sensor de movimento. O próximo laço IF apenas acende o LED quando o sensor se ativar. O próximo laço é o da leitura e gravação. Nele temos o comando "or", ou seja, se passaram uma hora da última gravação ou se o sensor foi ativado o laço IF rodará. Ele se inicia com a leitura dos sensores e depois passa para a gravação no SD. Assim se verifica se o tamanho do arquivo onde os dados estão sendo gravados aumentou, caso verdadeiro segue o loop, se falso chama a função erro().
Por fim as informações são mostradas na tela, mostra se houve movimento, para saber se a última gravação foi ativada pelo sensor ou pelo timer, os tamanhos do arquivo para garantir que está ocorrendo gravação e os dados dos sensores. O último delay prender o loop por nove segundos, já que o sensor quando ativado envia sinal em nível alto por cerca de sete segundos, sem o delay o loop ficaria rodando por sete segundos repetidamente se fosse acionado pelo sensor.

De posse as explicações vamos verificar os resultados:
Com os resultados eu gerei os gráficos abaixo:
A primeira análise que eu gostaria de fazer é do último gráfico, o da umidade ao longo do tempo, como os intervalos de tempo não são fixos a inclinação da linha se torna um problema. Mas a informações aqui importante não é a tendência, e sim os valores brutos. Podemos verificar que como esperado a umidade se elevou durante a madrugada, mas o dado importante é a umidade mínima, que se apresentou em 53%, baixa, mas não tão alarmante. Mas a primeira conclusão é que se torna interessante tomar um providência para elevar essa umidade.

Já o segundo gráfico é muito importante, ele responde se o Taurus passa a maior parte do seu tempo no abrigo, ou fora deste, assim posso determinar onde concentrar os esforços e entender quais fatores o levam a tomar essa decisão. Verifica-se que às 23:06 ele termina de comer e se dirige a sua cama (horários anteriores foram induzidos por mim para testes), lá ele dorme por praticamente 4 horas, assim ele acorda, e possivelmente se ausenta da cama por vinte minutos, acredito que para esfriar o corpo, movimentar ou tomar água. 03:35, cerca de 20 minutos depois de voltar a cama ele sai novamente, fica 40 minutos fora e retorna, onde dorme por mais uma hora. Assim ele acorda pois é o horário que os moradores se levantam. Isso responde a várias questões, a primeira é que o Taurus teve um sono tranquilo, com poucos intervalos. A segunda é que vale investir esforços na caminha, pois é o local que ele passa a maior parte de sua noite. Claro que seria necessário coleta de dados por várias noites e uso de técnicas de data science para afirmar o padrão noturno do animal, mas apenas essa noite já serviu como um bom parâmetro.

Já o primeiro gráfico é o da temperatura, observe que a temperatura ambiente possui números decimais e a do abrigo apenas números inteiros. Isso se origina da linha "int tempCama = DS18B20.getTempCByIndex(0);", onde a variável usada não foi do tipo float. Tomei essa decisão para poupar memória do atmega328p e evitar travamentos. Mas mesmo assim podemos analisar. A temperatura mínima foi de 17,9°C, o que não apresenta risco alarmante. Mas mesmo com o dado raso de temperatura foi possível ver que a temperatura do abrigo foi inferior que a temperatura do ambiente externo. É possível ver isso às 04:18, em que o ambiente estava a 18,7°C e o abrigo a no máximo 17,9°C. Ou seja, será necessário repensar toda a estratégia de construção do abrigo, pois o mesmo não cumpre totalmente seu papel. Mesmo que ali o cão esteja mais protegido do vento, em cima de uma cama fofa e com isolamento do chão. Mas se tivesse tudo isso protegido do vento a temperatura seria a ambiente da mesma forma, então o abrigo não está sendo útil, mesmo com todo o esforço para armá-lo.

Concluímos que o datalogger operou corretamente, me fornecendo informações para que assim eu possa tomar decisões e chegar a conclusões, como de que meu esforço para o abrigo não está sendo devidamente aproveitado. Claro que melhorias podem e devem ser feitas no mesmo, como a substituição do UNO por um Pro Mini, alterações e código e pontos de medição diferentes. Mas no geral estou feliz com o resultado.

Não apenas foi adicionado conhecimento de programação, como uma mudança ambiental para ativação do loop e o uso do RTC mas também me surgem ideias se uso agronômico para esse tipo de aparelho. Que tal gravar sempre que um animal faz uma ação, como passar por uma porta? Ou então monitorar a movimentação de uma vaca, para assim detectar seu cio com maior precisão? Esse ramo de monitoramento conjunto de animais e de ambientes me parece ser muito interessante no âmbito rural e comercial, e não apenas doméstico. Sendo o custo do produto em si bem baixo.

Esse é o Taurus, a "cobaia"


terça-feira, 28 de agosto de 2018

Trabalhando com hora no Arduino: Módulo RTC

Anteriormente trabalhando em nosso datalogger precisamos controlar o tempo entre as leituras, um controle normal, mas por falta de material trabalhamos com a função millis do microcontrolador, o que traz diversos problemas e a imprecisão de qual momento o dado foi realmente lido. Eu consigo saber quanto tempo depois do arduino ser ligado meu dado foi lido, mas não posso precisar que horas foi isso. E se houver uma queda de energia no processo?

Desta forma é ideal trabalhar com um módulo RTC sempre que for coletar dados, esse módulo pode não ser muito compacto, mas é barato (R$4,49) e ainda permite adicionar um sensor de temperatura no próprio corpo do RTC.

Seu funcionamento também é muito simples, basta utilizar a biblioteca RTClib (https://github.com/adafruit/RTClib). O código baixo captura a data do computador no momento da compilação do código, coloca ela como a data atual do módulo e ainda exibe as informações de data e hora no monitor serial. A conexão de cabos é simples pois o mesmo funciona por meio de I2C. 

É possível simplificar bem o código, fazendo o mesmo de tornar bem compacto apenas coletando informações do RTC. Também pode ser possível utilizar o RTC para controlar intervalos de repetição dentro do loop, como ler sensores a cada 30 segundos
Eu utilizei o código acima para criar um simples datalogger que gravasse a leitura de uma porta analógica a cada 30 segundos, ou seja, cada vez que os segundos fossem 30 ele gravava no SD a leitura analógica. Abaixo deixo o arquivo gerado, pode verificar que foi satisfatório o resultado após cerca de uma hora.



quinta-feira, 14 de junho de 2018

Temômetro: Attiny85 e DHT11

Como disse lá no início do blog, o ATTINY85 pode ser uma escolha muito interessante para algumas medições ou monitoramentos. Sendo limitado principalmente por sua memória. 

Devido a essa limitação as bibliotecas normalmente utilizadas para os ATMEGA, do UNO, MEGA e afins não se demonstram adequadas, tendo bibliotecas mais adequadas ao pequeno, focadas em simplicidade. Diversas dessas bibliotecas acompanham a instalação da placa da Digispark no IDE.

Vamos trabalhar em um projeto simples mas útil para aprender a lidar um pouco com elas. Para tal vamos usar:
  • Digispark ATTINY85
  • Jumper macho-macho e macho-fêmea
  • DHT11
  • Tela OLED 0,96 I2C
  • Mini Protoboard
Tudo será montado na mini protoboard, com 4,5 x 3,50cm aproximados, o ideal é tudo ter essa medida. Primeiro encaixe o Tiny e o OLED. Deixe duas trilhas na extremidade livre. Depois conecte o DHT11 nas trilhas livres entre o visor e o microcontrolador. Basta utilizar jumper para ligar tudo. Lembra das duas trilhas deixadas em uma extremidade? Use elas como trilha 5V e GND alimentadas pelo Tiny85.

No programa a fiação foi a seguinte: VCC no 5V. GND no GND. DHT11 no P3. SDA no P0. SCK no P2.


Agora só ligar e programar. O programa é muito simples e ocupa 96% da memória. Nele foram utilizadas as bibliotecas TinyDHT e DigisparkOLED, além da Wire para o I2C. O código se iniciação com a definição do DHT, a porta usada e o modelo. No setup é iniciada as bibliotecas e o pino do DHT é colocado como saída. Com um delay para estabilização.

No loop um novo delay e a limpeza do oled para iniciar. Observe que a captura das informações do DHT em variáveis é bem simples, sendo necessariamente feita com números inteiros devido a memória. Depois é apenas a parte de escrita no OLED, posicionando e escrevendo.

Ao final temos o delay de controle, que somado ao primeiro delay do loop dá o intervalo de leituras, jamais inferior a 2s. O tiny possui uma demora para trabalhar com a tela, assim não é recomendado atualizações pequenas, pode ser que não se consiga renderizar a tela corretamente antes da próxima escrita de dados.

Download do programa: clique aqui

Biblioteca TinyDHT: Como visto a biblioteca permite adquirir dados dos sensores DHT com pouca memória e quase nenhuma linha. Basta incluir a biblioteca, definir a porta e tipo de sensor, iniciar o sensor e ler a informação já vinculando a uma variável. A limitação é apenas trabalhar com números inteiros.
Biblioteca DigisparkOLED: Biblioteca interessante, possui como limitação exibir apenas textos. Mas as principais funções estão presentes: Limpeza da tela, tamanho de fonte, posicionamento de cursor, escrita de textos e variáveis. Observe que a forma de escrever textos é um pouco peculiar.

O nosso termômetro está pronto para o uso, e será de grande valia. Com ele você obterá rapidamente as informações. Eu utilizo para medições pontuais, como quando vou fazer algum teste eu adiciono os dados de temperatura. Ou para medir o ambiente.

Esse inverno chegou a fazer um frio absurdo em minha cidade, logo tive a curiosidade de medir a temperatura. Tive que programar um UNO, com protoboard grande e tudo mais. Ou quando alguém pergunta se o ar está seco. Agora ele fica li pronto. Basta encaixar o visor (se estiver usando para outra coisa), e pronto, muito mais compacto.

Sugestões: Possa ser que você precise de algo mais compacto. Nesse caso diversas melhorias podem ser feitas. A primeira é usar jumper sob medida, os comerciais são muito grandes. A segunda é anexar uma bateria pequena com módulo de carregamento, pode colocar em baixo da protoboard. A última é utilizar o TINY85 sozinho, apenas o microcontrolador na cápsula com pinos. Vai ficar menor, mais barato e com um consumo energético muito menor.

DS18B20 - Resistor de 4.7K ou 10K? Faz diferença?


O DS18B20 é um sensor de temperatura muito falado aqui no blog por suas diversas vantagens. Mas uma característica deste é necessitar de um resistor fazendo ponte entre o único pino de dados e a energia de alimentação. Sempre é recomendado o uso de um resistor de 4,7K e a definição de 10bits. Mas na ausência deste se encontra recomendações para usar um resistor de 10K e 12 bits.

Mas qual será a diferença na prática? Veremos discrepâncias de medições diferentes?

Para medir eu utilizei dois DS18B20 versão encapsulada, um protoboard 400 pinos, jumpers, um Arduino UNO e uma fonte de alimentação para protoboard. Os dois sensores foram ligados na protoboard, alimentada em 5V pela fonte, o GND da fonte e do UNO foram conectados. Foi utilizado o protocolo one wire na porta 8. No sensor 1 foi usado um resistor de 10K e no sensor 2 um resistor de 4K7.

Para 10K foi setado 12bits. Para 4K7 foi setado 10bits.

Ambos os sensores foram imersos em um copo de água gelada, previamente resfriada por três dias em geladeira. Os sensores foram posicionados a não tocar a borda do copo, ficando completamente submersos, a mesma altura, sem tocar entre si.

Após 3 minutos submersos para estabilização foi iniciada a verificação de dados a cada 5000ms, regulados por meio da função delay. Os dados foram capturados pela serial e enviados ao Excel. Foram 265 capturas. Temperatura ambiente aproximada de 24°C e umidade relativa de 69% (DHT11)


Se olhar apenas após uma estabilização completa, que ocorreu após a leitura de número 50, é possível observar pela formatação condicional dos valores e pelo gráfico que não existe diferença entre ambos. O sensor em 4K7 mediu apenas valores com decimais 00, 25, 50 e 75, enquanto o de 12bits mediu valores com os decimais completos. Mesmo com alta precisão nos decimais a temperatura sempre subiu, o que era esperado. Demostrando que essa precisão a mais não interfere na qualidade dos dados. Na faixa em que o sensor de 10bits mostrava números com final 00 e 25 o final do sensor de 12bits estava neste intervalo. Esse comportamento ocorreu em todos os intervalos.

Ambos os resistores mostraram a mesma qualidade nos dados, o sensor em 10K demonstrou maior detalhamento por conta dos 12bits de resolução escolhidos por software.

Mas e no caso de utilizar 12bits de resolução tanto no resistor de 4K7 quanto no de 10K? Foi realizado o teste após o teste anterior, sem tocar nos sensores, apenas atualizando o código no UNO. Foram feitas 286 coletas.


Com ambos em 12bits a situação prevalece, ambos tiveram o mesmo comportamento, com qualidade semelhante. De início foi notada um diferença fixa de 0,6°C que foi reduzindo com o passar do tempo. Diferença essa que pode ser do próprio líquido. O sensor no resistor de 10K apresentou três inconsistências, contra apenas uma do em 4K7, essa inconsistência foi característica, onde não tinha determinado se a temperatura subiu ou permaneceu.

Concluímos que a recomendação dos sites sobre o assunto de utilizar resistor de 4K7 com 10bits e de 10K com 12bits não se mostrou conclusiva. A recomendação é de utilizar o sensor de 4K7, por ter demonstrado menor inconsistência e resolução de 12bits pela sua maior precisão de dados, sem perda de qualidade dos mesmos. Mesmo assim, o uso de resistor de 10K também é aceito sem prejuízos a qualidade dos dados.