Configurando senha no módulo Bluetooth HC-06 com comandos AT

Configurando Senha no Módulo Bluetooth HC-06 com Comandos AT

A segurança da informação é um ponto muito importante a ser considerado em sistemas de comunicação sem fio. Nesse tutorial vamos aprender como configurar uma senha no módulo Bluetooth HC-06 com comandos AT.

Veja também nosso tutorial:  Módulo Bluetooth HC-05 e HC-06 – Acionando um módulo relé via Bluetooth.

[toc]

kit arduino robótica educacional

Comunicação via Bluetooth

Nossa necessidade cada vez maior de conectividade nos leva a estarmos interligados a tudo. Até os aparelhos conversam entre si para realizar suas tarefas, através de protocolos de comunicação como o Bluetooth.

Telefones celulares, tablets, televisores, carros, e muitos outros dispositivos, contam com pelo menos uma interface para comunicação via rede, e o Bluetooth é uma delas.

Módulos Bluetooth

O Bluetooth é um padrão de comunicação sem fio, de curto alcance, com baixo custo e baixo consumo de energia. Essas características tornam essa tecnologia de comunicação uma ferramenta bastante interessante.

É muito comum encontrar projetos de Arduino usando comunicação Bluetooth, e o módulo HC-06 é um dos mais utilizados. A conexão é via comunicação serial e é realizada recebendo o endereço e o clock do outro dispositivo. O endereço é um número de 48 bits, recebido na fabricação, único para cada módulo Bluetooth.

A configuração do HC-06 é realizada por um conjunto de comandos Hayes, também conhecidos como comandos AT (attention, atenção no inglês). Trata-se uma linguagem de comandos desenvolvida para comunicação com modems. Os comandos AT são uma série de cadeias curtas de texto que podem ser combinadas para realizar operações como ligar, desligar ou para alterar configurações.

Mantendo seu Projeto Seguro

Para tornar a comunicação segura, os módulos HC-06 podem ser configurados com senha, evitando acessos indesejados. A senha pode ser alfanumérica e deve ter no mínimo 4 caracteres.

Mãos a obra - Parte 1 - Testando o Módulo Bluetooth HC-06

Nesta parte nós vamos apenas ligar o módulo e testar seu funcionamento. Não será necessário nenhum programa nessa primeira etapa. 

Componentes Necessários

Montando o Projeto

O modulo tem quatro pinos de comunicação, que devemos conectar ao Arduino. Suas funções são:.

  • VCC - Tensão de entrada, entre 3,6 a 6 volts
  • GND - O pino de O V do módulo, que é conectado ao GND do Arduino ou fonte
  • TXD - Pino de transmissão de dados
  • RXD - Pino de recepção de dados

A intenção nessa primeira parte é verificar o funcionamento do módulo HC-06. Dessa forma, precisamos apenas alimentar o VCC, e o GND. O circuito fica como a figura abaixo:

 

Circuito Módulo Bluetooth  HC-06 com Arduino
Circuito Módulo Bluetooth HC-06 com Arduino

Colocando para Funcionar

Agora, basta ligar seu Arduino e verificar no celular se ele aparece como um dispositivo Bluetooth. Você verá que o modulo já veio configurado com nome padrão, que aprenderemos a alterar.

 

Módulo Bluetooth HC-06 sendo reconhecido pelo celular Android
Módulo Bluetooth HC-06 sendo reconhecido pelo celular Android

 

Mãos a obra - Parte 2 - Configurando o modulo bluetooh HC-06

Nesta parte vamos configurar o módulo HC-06. A comunicação é serial, e no caso do Arduino Uno os pinos padrão para comunicação serial são os pinos 0 e 1. Entretanto, esses pinos também são os utilizados internamente quando gravamos um programa na memória do Arduino. Por isso, usaremos uma biblioteca especifica para comunicação serial e vamos usar os pinos 10 e 11 para as funções RX e TX.

Componentes Necessários

Montando o Projeto

O módulo HC-06 é configurado para funcionar sempre como escravo e sempre no modo AT. Não é necessário trocar a ligação elétrica para fazer as configurações.

O pino RX do módulo deve receber 3,3 V, e essa informação vem anotada no verso do módulo, como advertência.

 

Módulo Bluetooth HC-06
Módulo Bluetooth HC-06

Entretanto, a saída digital do Arduino fornece 5 V em nível alto. Por isso, adicionamos um divisor de tensão e tomamos a tensão reduzida para o pino RX.

O circuito fica como na figura abaixo. Atenção no posicionamento dos resistores. 

 


Circuito Módulo Bluetooth  HC-06 com Arduino
Circuito Módulo Bluetooth HC-06 com Arduino

 

Programando o Arduino

O código que vai fazer comunicação do Arduino com o módulo HC-06 é este:

#include <SoftwareSerial.h>

SoftwareSerial myserial(11, 10); // RX, TX

void setup() {
  delay(500);
  Serial.begin(9600);
  Serial.println("Digite os comandos AT :");
  myserial.begin(9600);
}

void loop() {
  if (myserial.available())
    Serial.write(myserial.read());
  if (Serial.available())
    myserial.write(Serial.read());
}

Enviando Comandos para o Módulo

Após carregar o código na placa Arduino, o monitor serial será responsável por gerar uma interface com o módulo HC-06, mostrando os comandos de configuração e mostrando a resposta dos parâmetros.

É fundamental colocarmos a velocidade de comunicação do monitor serial igual à do código carregado na placa Arduino.

Serial.begin(9600);

Além disso, selecionar o meio de envio para "Ambos, NL e CR":

 

Monitor Serial
Monitor Serial

 

O módulo HC-06 não responde a todos os comandos AT. Abaixo está a lista que ele aceita.

Comando Resposta Descrição
AT+VERSION HC-06-VERSÃO Informa a versão do firmware
AT+NAMENOVONOME Oksetname Muda o nome do dispositivo para NOVONOME (sem espaço depois do comando)
AT+PINNOVOPIN   Muda a senha para NOVOPIN (sem espaço depois do comando)
AT+BAUDX   Altera a taxa de transmissão do módulo para a opção X (leia abaixo)

O nome padrão é 'HC-06', e a senha padrão é '1234'.

Uma informação muito importante: alterando a taxa de transmissão, o código de comando AT que estava em funcionamento para de funcionar. Lembre que essa é a taxa de transmissão entre o Arduino e o módulo bluetooth. Se alterar o baudrate, vai ser necessário corrigir o código com a nova taxa e gravar no Arduino novamente. Os valores e velocidades respectivas são: 1 (1200 bps), 2 (2400), 3 (4800), 4 (é o padrão - 9600), 5 (19200), 6 (38400), 7 (57600) e 8 (115200).

Entendendo a fundo

Software 

A biblioteca utilizada é responsável pela comunicação serial do Arduino com outros dispositivos.

#include <SoftwareSerial.h>

Em seguida, é criado o objeto que vai se comunicar, nos pinos 11 e 10, onde o primeiro é o RX e o segundo o TX.

SoftwareSerial myserial(11, 10); // RX, TX

Quando a comunicação estiver estabelecida, e o módulo tiver algo na porta serial para enviar, o Arduino recebe os dados e imprime no monitor serial.

if (myserial.available())
  Serial.write(myserial.read());

Quando algo for escrito no monitor serial, o comando é enviado ao módulo. Quando digitamos um comando e teclamos enter, o módulo recebe o código AT e executa. A resposta será enviada ao Arduino, através da estrutura anterior.

if (Serial.available())
  myserial.write(Serial.read())

Hardware

- Montando um Divisor de tensão

Para confecção do filtro de tensão que colocamos no pino TX do HC-06, vamos usar um aplicativo que nos fornece calculadoras e técnicas que podem ser úteis em desenvolvimento.

Usando o aplicativo EletroDoid, que esta disponível para sistemas de celular Android, selecionamos a aba divisor de tensão, como na figura:

 

Aplicativo EletroDoid
Aplicativo EletroDoid

Em seguida, configuramos o divisor alimentando com os dados do nosso projeto os campos Vin, que em nosso projeto é 5 V, e Vout, que é 3,3 V. Deixe a carga em RL desabilitada, desconsiderando a resistência do pino de entrada do módulo

.

Cálculo Circuito divisor de Tensão
Cálculo Circuito divisor de Tensão

O aplicativo cria uma associação de resistores, como a que usamos em nosso projeto. Então é só ajustar os valores dos resistores que se encontram disponíveis, na sua coleção ou para comprar. Nesse tutorial, foram utilizados resistores de 1k e 2k Ohm.

Uma funcionalidade interessante desse aplicativo é que a calculadora já considera os resistores em valores comerciais. Os resistores não são fabricados em todos os valores possíveis, mas em uma quantidade de valores normatizada, que depende da sua série: E6, E12, e E24. O número depois do "E" apresenta a quantidade de valores em que o resistor é fabricado naquela série. E24, possui 24 valores numéricos e seus múltiplos. Por exemplo: um valor comercial da série E24 é 4,7 Ohm. Então existem resistores com valores múltiplos desse: 47, 470, 4,7k, 47k, e em diante.

Considerações Finais

Vimos como personalizar seu dispositivo Bluetooth, dando um nome a ele e criando uma senha, restringindo o acesso a usuários não autorizados. Esperamos que tenha gostado e que consiga fazer bom uso!

Deixe suas dúvidas nos comentários. Sugestões e críticas também são sempre bem vindos. Até o próximo!


comunicação serial

Como usar o Serial Monitor na IDE Arduino

Comunicação Serial no Arduino via Serial Monitor

A Comunicação Serial é um recurso amplamente utilizado no estabelecimento de comunicação entre uma placa Arduino e outros dispositivos, como módulos ZigBee e Bluetooth, shields, sensores, e até mesmo com o computador. A gravação de um código no microcontrolador do Arduino, por exemplo, é realizada via Comunicação Serial. Para que possamos ler informações via comunicação serial da placa arduino no computador, usaremos o Serial Monitor, ferramenta que pode ser encontrada na IDE Arduino.

Devido a esta enorme importância da comunicação serial, neste tutorial iremos apresentar alguns conceitos sobre esse tipo de comunicação e os procedimentos necessários para utilizar o serial monitor.

[toc]

kit arduino robótica educacional

O Serial Monitor

A IDE oficial do Arduino disponibiliza uma ferramenta chamada Serial Monitor. Essa ferramenta é uma interface gráfica que apresenta a troca de informações pela porta serial entre o Arduino e o computador. A comunicação via Serial Monitor é um recurso interessante, para monitorar o envio e no recebimento de dados, permitindo inclusive realizar testes sem a necessidade de uma interface externa.

Para acessarmos esta ferramenta, basta clicarmos no ícone localizado no canto superior direito da IDE, ou simplesmente, utilizar o atalho Ctrl+Shift+M. Também é possível abrir o Serial Monitor através do menu Tools, localizado na barra de ferramentas.

 

Em um primeiro momento, precisamos definir apenas a taxa de transmissão de dados (baud rate), que deve ser a mesma que a taxa de transmissão definida no programa que está carregado no Arduno. Além da informação da taxa, o Serial Monitor possui dois campos: um é o local onde você pode enviar dados para seu Arduino e o outro é uma área de exibição de saída de dados.

 


Mãos à Obra - 4 Projetos com o Serial Monitor

Aqui são apresentados 4 projetos utilizando a comunicação via Serial Monitor. Para simplificar, todos utilizam o mesmo hardware, focando no acesso e uso da ferramenta. Os projetos desenvolvidos são:

  • Enviando uma mensagem para o monitor serial
  • Enviando uma sequência de mensagens
  • Lendo dados através do monitor serial
  • Controlando o Arduino através do monitor serial

Componente necessário


Projeto 1: Enviando uma mensagem

Neste projeto vamos enviar dados através da Comunicação Serial.

Código utilizado

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    /*** Arguardando o estabelecimento da conexão ***/
  }
  Serial.print("Vida de Silicio");
}

void loop() {}

Entendendo o software

– Definindo as configurações iniciais

O primeiro passo consiste na inicialização da interface de Comunicação Serial entre a placa Arduino que estamos utilizando e o Serial Monitor. Para isto, utilizamos a função begin(), que recebe dois parâmetros: a taxa de transmissão em bits por segundo (é bastante comum 9600 em transmissões mais lentas); o segundo parâmetro é configuração de bits por transmissão, paridade e bits de parada. Deixando o segundo parâmetro em branco, a função adota o padrão. Para consultar valores possíveis para a taxa e configuração, você pode ver esse link.

Note que, por se tratarem de funções membros de uma classe, as funções disponíveis para a Comunicação Serial devem ser acessadas através do objeto global  Serial e do operador " ." (ponto), sendo assim, para utilizar a função begin(), deve-se escrever: Serial.begin(9600).

Serial.begin(9600);

Em seguida, utilizamos a função while() com o parâmetro !Serial. Esta estrutura faz com que o programa aguarde até que a conexão serial seja estabelecida, e só então, continue a execução.

while (!Serial) {
  /*** Arguardando o estabelecimento da conexão ***/
}

– Imprimindo a informação

Por fim, utilizamos a função print() para enviar a mensagem, que será visualizada no Serial Monitor.

Serial.print("Vida de Silicio");

O resultado deve ser esse:

 


Projeto 2: Enviando uma sequência de mensagens

Neste projeto vamos enviar uma sequência de dados através da Comunicação Serial.

Código do projeto

Segue o código para ser utilizado no Arduino:

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    /*** Arguardando o estabelecimento da conexao ***/
  }
  Serial.println(16,DEC);
  Serial.println(16,BIN);
  Serial.println(16,OCT);
  Serial.println(16,HEX);
  Serial.println(16.2372523,2);
}

void loop() { }

– Definindo as configurações iniciais

Dentro da função setup(), inicializamos a Comunicação Serial a uma taxa de 9600 bits por segundo com begin():

Serial.begin(9600);

Como no projeto anterior, checamos o estabelecimento da conexão serial:

while (!Serial) {
  /***** Aguardando o estabelecimento da conexão *****/
}

– Imprimindo as informações

Após estabelecer a conexão serial utilizamos a função println() para enviar um dado através da porta serial e saltar para próxima linha. Outra informação interessante das funções println() e print() é que ambas podem ser utilizadas com dois parâmetros. O primeiro parâmetro é a mensagem e o segundo é a formatação.

Para imprimir, por exemplo, números inteiros, podemos utilizar o segundo parâmetro para determinar se deve ser enviado como um decimal, binário, octal ou hexadecimal:

Serial.println(16,DEC);
Serial.println(16,BIN);
Serial.println(16,OCT);
Serial.println(16,HEX);

No caso de números reais, do tipo float, esse segundo parâmetro determina o número de casas decimais:

Serial.println(16.2372523,2);
O código todo fica assim:
void setup() {
  Serial.begin(9600);
  while (!Serial) {
    /*** Arguardando o estabelecimento da conexão ***/
  }
  Serial.println(16,DEC);
  Serial.println(16,BIN);
  Serial.println(16,OCT);
  Serial.println(16,HEX);
  Serial.println(16.2372523,2);
}

void loop() { }

E o resultado que obtemos com esse código é esse:

Se ao invés da função println(), utilizássemos a função print(), o resultado seria esse:

Repare que sem saltar linha, cada mensagem é colocada em sequência, uma após a outra.


Projeto 3: Lendo dados através do monitor serial

Neste projeto ensinaremos a você como fazer uma leitura de dados do Serial Monitor para o Arduino.

Código do projeto

Segue o código para leitura de dados via Serial Monitor.

char dado;

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    /*** Aguardando o estabelecimento da conexão ***/
  }
}

void loop() {
  if(Serial.available()) {
    dado = Serial.read();
    Serial.print(dado);
  }
}

– Declarando a variável para armazenar a leitura

Criamos uma variável do tipo char para armazenar um caractere.

char dado;

– Definindo as configurações iniciais

Como nos projetos 1 e 2, inicializamos a comunicação serial e fazemos a checagem:

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    /***** Aguardando o estabelecimento da conexão *****/
  }
}

– Imprimindo a informação recebida

Já dentro da função loop(), temos uma função if() cujo argumento consiste em uma função chamada available(). Ela é responsável por retornar a quantidade de caracteres disponíveis para leitura na porta serial. Se não há caracteres, ela retorna zero.

Na estrutura do projeto, queremos conferir se há algum caractere para ser lido. Caso haja, o conteúdo interno da função if() será executado.

if(Serial.available() > 0) {
  /***** conteúdo da função if() *****/
}

Se houver algum caractere para ser lido, utilizamos a função read() para ler o primeiro caractere da fila na porta de entrada. Efetuamos a leitura do primeiro caractere da fila e armazenamos na variável dado.

dado = Serial.read();

Por fim, para conferir o resultado desta aplicação, utilizamos a função print() para enviar o valor recebido para o Serial Monitor.

Serial.print(dado);

A função loop() ficou assim:

void loop() {
  if(Serial.available()) {
    dado = Serial.read();
    Serial.print(dado);
  }
}

Projeto 4: Controlando o Arduino através do Serial Monitor

Neste projeto ensinaremos a você como proceder para controlar um led através do monitor serial.

Código do projeto

#define LED 13

char dado;

void setup() {
  pinMode(LED,OUTPUT);
  Serial.begin(9600);
  while (!Serial) {
    /*** Aguardando o estabelecimento da conexão ***/
  }
}

void loop() {
  if(Serial.available()) {
    dado = Serial.read();
    switch(dado) {
      case 'a':
        digitalWrite(LED,HIGH);
        break;
      case 'A':
        digitalWrite(LED, LOW);
        break;
    }
  }
}

– A diretiva #define

Iniciamos o código utilizando a diretiva #define para associar o nome LED ao número 13, de modo que, toda vez que chamamos "LED" no código, o compilador do Arduino interpreta como o inteiro 13. A vantagem desse recurso é que, caso seja necessária a alteração de um valor, ele só precisa ser alterado em um único lugar.

#define LED 13

– Declarando a variável para armazenar o caractere

Criamos uma variável do tipo char para armazenar um caractere.

char dado;

– Definindo as configurações iniciais

O pino 13 é configurado como saída digital.

pinMode(LED,OUTPUT);

Fazemos a inicialização e checagem da Comunicação Serial, como nos projetos anteriores.

Serial.begin(9600);
while (!Serial) { 
  /*** Aguardando o estabelecimento da conexão ***/    
}

A função setup() fica assim:

void setup() {
  pinMode(LED,OUTPUT);
  Serial.begin(9600);
  while (!Serial) {
    /***** Aguardando o estabelecimento da conexão *****/
  }
}

– Acionando o led a partir do dado recebido

Dentro da função loop(), fazemos a checagem da porta serial para a presença de caractere. Se houver, o caractere será armazenado na variável dado.

if(Serial.available() > 0) {
  dado = Serial.read();  
}

Após a leitura do primeiro caractere da fila da porta serial utilizamos a estrutura switch()/case para determinarmos qual ação deve ser tomada. Esta estrutura funciona da seguinte maneira: passamos como parâmetro da função switch() a variável que queremos comparar e, em seguida, criamos os cases, com os valores esperados da variável. Se a variável for identificada em alguns dos cases, os comandos daquele bloco serão executados. O elemento break sinaliza o final de cada case, saindo da estrutura switch().

No código, caso a variável dado seja a letra a (minúscula), o led deve ser aceso. Caso dado seja a letra A (maiúscula), apagamos o led.  

switch(dado) {
  case 'a':
    digitalWrite(LED,HIGH);
    break;
  case 'A':
    digitalWrite(LED,LOW);
    break;
}

Lembre-se que o conteúdo descrito anteriormente está localizado dentro da função loop(), portanto os procedimentos de leitura e comparação do caractere serão realizados repetidamente.

A função loop() fica assim:

void loop() 
{
  if(Serial.available()) {
    dado = Serial.read();
    switch(dado) { 
      case 'a':
        digitalWrite(LED,HIGH); 
        break; 
      case 'A': 
        digitalWrite(LED,LOW); 
        break; 
    }
  }
}

 


Considerações finais

Nesse conteúdo foi possível demonstrar algumas possibilidades para uso da comunicação via Serial Monitor. Esperamos que você tenha gostado, e sinta-se à vontade para deixar suas sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.


Primeiros passos com Firebase - ESP8266

Primeiros passos com Firebase - ESP8266

Neste tutorial vamos fazer um circuito que permita observar a temperatura e umidade de um sensor via internet, mostrando como podemos receber sinais de um sensor DHT22 que chegam a um ESP8266 e enviá-los pela internet para uma plataforma Firebase, fazendo uma aplicação bem simples de Internet das Coisas, a famosa IoT , do inglês Internet of Things.

 

kit robotica educacional com Arduino ESP ou Microbit

O que é o Firebase?

O Firebase, produto oferecido atualmente pela Google e utilizado por empresas em todo o mundo, que integra um conjunto de tecnologias disponíveis em diversas linguagens, entregando serviços como:

  • Banco de dados armazenados em nuvem e sincronizados em tempo real;
  • Autenticação de usuários, inclusive por meio de login em provedores como Google e Facebook;
  • Facilitação na hospedagem web;
  • Pode ser usado para testes e manutenção durante o desenvolvimento dos seus apps, assim como o monitoramento dos mesmos.

Com as muitas ferramentas e serviços disponíveis pela plataforma, o desenvolvimento de apps, se torna mais ágil e problemas comuns são resolvidos mais facilmente.

A possibilidade de criar um único SDK contendo APIs do Firebase para uso tanto em Android, como também no iOS e na web é uma das facilidades oferecidas a desenvolvedores, assim como a implementação de bate-papo na aplicação e a viabilidade de testes AB, melhorando a experiência do usuário.

Há recursos também para expansão e envolvimento do público com a sua aplicação, tal como o conhecido Google Analytics, Slack e PlayStore, por exemplo.

No campo da IoT, quando tem-se objetos e aparelhos físicos conectados e em comunicação por meio da internet, também há espaço para o Firebase. Combinados os serviços oferecidos com microcontroladores, como o Arduino, são inúmeras as possibilidades de aplicações, seja em monitoramento de sensores para telemetria, ou em vertíveis (wearables), tecnologias que podem ser vestidas, como relógios inteligentes, por exemplo.

O que é IoT?

IoT, que vem do inglês "Internet of Things", refere-se à conexão da Internet com objetos do dia a dia, permitindo que estes coletem e troquem dados entre si. Basicamente, trata-se de dispositivos que, anteriormente, não tinham capacidade de conexão com a internet, como geladeiras, lâmpadas, relógios, agora estarem conectados à web para coletar e trocar dados, otimizando e automatizando processos.

O que é SDK?

SDK, que é a sigla para "Software Development Kit", refere-se a um conjunto de ferramentas de software que permitem aos desenvolvedores criar aplicações para uma determinada plataforma ou framework específico. O SDK fornece uma série de bibliotecas, guias, documentações, código e outras ferramentas para facilitar o desenvolvimento.

O que é API?

API, que significa "Application Programming Interface", é um conjunto de regras e protocolos que permite a comunicação entre diferentes software. Pode ser entendida como uma ponte que permite que diferentes programas de software se comuniquem entre si. As APIs são essenciais para permitir a integração de sistemas, permitindo que aplicativos e plataformas trabalhem em conjunto.

O que é um banco de dados?

Um banco de dados é um sistema estruturado de armazenamento que permite a coleta, organização, armazenamento e recuperação de dados. Estes dados podem ser de diversos tipos, como textos, números, imagens, entre outros. Os bancos de dados são fundamentais para sistemas e aplicações, pois fornecem uma maneira organizada de gerenciar grandes volumes de informações.

O que são Vestíveis ou wearables?

Vestíveis, ou "wearables", são tecnologias que podem ser usadas como peças de vestuário ou acessórios, como relógios, pulseiras, óculos, entre outros. Estes dispositivos normalmente possuem sensores e estão conectados à internet, coletando e fornecendo dados em tempo real para os usuários. Exemplos populares incluem relógios inteligentes, óculos de realidade aumentada e fones de ouvido inteligentes.


Mãos à Obra - Usando o Firebase em projetos de IoT

Vamos explorar algumas funcionalidades do Firebase com um exemplo prático de um circuito teste, entendendo o código necessário para um projeto simples!

Neste tutorial vamos fazer um circuito que permita observar a temperatura e umidade de um sensor via internet. Utilizaremos um DHT22, que age como um sensor de temperatura e umidade, porém você pode aplicar a outros sensores para obter diferentes informação que você deseja obter podem ser diferentes.

Componentes necessários

Montando o projeto

A montagem deve ser feita seguindo o esquema:

Ilustração do circuito e sua montagem

Olhando o DHT de frente, para a parte onde há aberturas e é feita a leitura, usa-se o pino 1 (mais à esquerda) para alimentação e o pino 4 (mais à direita) como terra.  Eles devem ser ligados, respectivamente, ao Vin e ao Gnd do ESP. Ainda seguindo essa lógica, o pino 2 do DHT deve ser ligado a uma porta digital do ESP que, no caso, foi a porta digital 5 (pino D5 do ESP). O pino 2 também deve ser ligado à alimentação (Vin) com um resistor de 10K entre eles.

Veja como ficou no nosso projeto:

Criando um banco de dados na Firebase

Entre os serviços oferecidos pelo Firebase está o Realtime Database que, como o próprio nome já diz, é um banco de dados que armazena e sincroniza dados em tempo real. Estruturalmente, ele é um banco NoSQL hospedado em nuvem, o que nos livra da necessidade de configurar servidores. Outra grande vantagem é a facilidade de integrá-lo em aplicações, seja em aplicativos iOS, Android e até Web, como é o nosso caso.

Para criar o banco:

a) Acesse a console em https://firebase.google.com  e faça login com uma conta Google.

b) Na próxima tela, adicione um novo projeto.

c) No menu à esquerda, escolha Database, depois Realtime Database e coloque modo público. Dessa forma você terá o banco e a URL que será usada para acessá-lo.

d) O último passo é o segredo do banco, uma espécie de senha. No menu lateral, é preciso clicar na engrenagem, ao lado de ‘Project Overview’ > Configurações do Projeto > Contas de serviço > Chaves secretas do banco de dados. Clicando em mostrar, o segredo pode ser obtido.

Programando

- Configurando a Arduino IDE para NodeMCU

Acesse o caminho Arquivo > Preferências e insira a URL http://arduino.esp8266.com/stable/package_esp8266com_index.json, como descrito nas fotos abaixo.

Feito isso, clique em OK e as placas esp8266 já estarão disponíveis no gerenciador de placas pelo caminho Ferramentas > Placa > Gerenciador de Placas > Instalar ‘esp8266 by ESP8266 Community’.

- Adicionando bibliotecas na Arduino IDE:

Biblioteca do Firebase

Para instalar a biblioteca do Firebase, primeiro é preciso baixá-la do GitHub: (https://github.com/googlesamples/firebase-arduino/archive/master.zip). Depois, é só acessar a Arduino IDE, adicioná-la seguindo o caminho Sketch > Incluir Biblioteca > Adicionar Biblioteca .ZIP e escolher o arquivo que foi baixado.

Biblioteca do DHT

O DTH é uma família de sensores de temperatura e umidade. O modelo que vamos utilizar aqui é o DHT22, que permite distinguir temperaturas na amplitude de -40°C até 80°C. É preciso instalar duas bibliotecas: a ‘Common sensor library’ (https://github.com/adafruit/Adafruit_Sensor) e a ‘DHT Sensor Library’ (https://github.com/adafruit/DHT-sensor-library), e incluí-las na IDE do arduino, assim como feito anteriormente.

- Escrevendo o código

O código do ESP precisa de certas alterações:

  • FIREBASE_HOST: forneça a URL do banco criado anteriormente.
  • FIREBASE_AUTH: forneça o Segredo do seu banco no Firebase.
  • WIFI_SSID e WIFI_PASSWORD: dados da sua rede WiFi.

Uma prática comum na programação são os comentários. No código abaixo, os comentários (indicados por "//") explicitam o significado e funcionalidade de cada trecho.

// Inclusão das bibliotecas necessárias
#include <DHT.h>
#include <ESP8266WiFi.h>
#include <FirebaseArduino.h>
#include <Ticker.h>

// Parâmetros do banco
#define FIREBASE_HOST "URL_do_banco"
#define FIREBASE_AUTH "Segredo_do_banco"

//Parâmetros da rede
#define WIFI_SSID "SSID"
#define WIFI_PASSWORD "Password"
#define DHT_PIN D5
#define DHTTYPE DHT22

// Intervalos de publicação. Configurado a cada 30 segundos
#define PUBLISH_INTERVAL 1000*30
DHT dht(DHT_PIN, DHTTYPE);
Ticker ticker;
bool publishNewState = true;

void publish(){
  publishNewState = true;
}

void setupPins(){
  dht.begin(); 
}

void setupWifi(){
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("connecting");
  while (WiFi.status() != WL_CONNECTED) {
	Serial.print(".");
	delay(500);
  }

  Serial.println();
  Serial.print("connected: ");
  Serial.println(WiFi.localIP());
}

void setupFirebase(){
  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
}

void setup() {
  Serial.begin(115200);
  setupPins();
  setupWifi();	
  setupFirebase();
  // Registra o ticker para publicar de tempos em tempos
  ticker.attach_ms(PUBLISH_INTERVAL, publish);
}

void loop() {
  // Apenas publique quando passar o tempo determinado
  if(publishNewState){
	Serial.println("Publish new State");
	// Obtem os dados do sensor DHT
	float humidity = dht.readHumidity();
	float temperature = dht.readTemperature();
	if(!isnan(humidity) && !isnan(temperature)){
  	// Manda para o firebase
  	Firebase.pushFloat("temperature", temperature);
  	Firebase.pushFloat("humidity", humidity);	
  	publishNewState = false;
	}else{
  	Serial.println("Error Publishing");
	}
  }
 
  delay(200);
}

Pelo Serial Monitor da Arduino IDE será possível ver a conexão com a internet, o endereço IP associado e as publicações de valores no banco. Cada ‘Publish new state’ é uma nova instância de dado gerada e armazenada no Firebase. Esses dados são gerados de acordo com a constante PUBLISH_INTERVAL e o valor é passado em milisegundos. No nosso exemplo, para cada 30 segundos o valor é de 1000*30.

Na console do firebase podem ser vistos os valores que estão sendo lidos:

 


1, 2, 3, Testando...

Vamos criar um site simples, utilizando as tecnologias web padrão HTML5, CSS3 e Javacript e hospedando-o diretamente no Firebase Hosting, outro serviço também muito lindo oferecido pelo Firebase.

 

- Ferramentas e configurações necessárias

Para fazer deploy da aplicação no Firebaseprecisamos instalar o firebase-tools, que é uma ferramenta de linha de comando para gerenciar o banco de dados e hosting de aplicações dentro da própria plataforma. Essa ferramenta é baseada em NodeJS, então precisamos da ferramenta instalada. Baixe o NodeJS no site oficial. Junto também será instalado o gerenciador de pacotes — NPM (similar ao PIP para Python).

Feito isso, é só rodar o comando no terminal: npm install -g firebase-tools

Ao final da instalação rode o comando a seguir e coloque suas credenciais do Firebase:

firebase login

 

- Programação

Crie uma pasta para o seu projeto e utilize o seguinte comando dentro da pasta:

firebase init

Assim, você estará vinculando a pasta ao projeto criado no console do Firebase, então escolha corretamente o projeto criado anteriormente. Uma pasta public será criada, onde ficarão os arquivos que podem ser hospedados no Firebase e acessados na web e também alguns arquivos de configuração do próprio projeto.

Há ainda um servidor embutido no firebase-tools. Dessa forma, estando na pasta, você também pode rodar firebase serve, para iniciar um servidor web na pasta public, na porta 5000 por padrão.

Usando a IDE da sua preferência, utilize o código de exemplo da aplicação que pode ser encontrado nesse link (app.js e o front-end em index.html). Para adequar a aplicação ao seu projeto no Firebase, deve-se alterar o começo do arquivo app.js, com as configurações do console do projeto no Firebase, seguindo os passos:

  1. Clique em Overview no menu lateral
  2. Clique em “Adicionar o Firebase ao seu aplicativo da Web”
  3. Copie o trecho dentro da segunda tag <script> e substitua pelo código correspondente no arquivo app.js

Feito isso, é só dar deploy da aplicação no hosting do Firebase. Rode o comando firebase deploy, assim você vai enviar os arquivos da pasta public pra lá e será mostrado um link para que você acesse sua aplicação online.

A aplicação deve se parecer com isso:


Considerações finais

Sobreviveu?

Simmm, acabou! Tudo certo até aqui? Finalizado este tutorial, você tem uma aplicação web que une um sensor a serviços do Firebase, contando com dados em tempo real e guardados em nuvem, ou seja, você tem uma aplicação de IoT. Esperamos que você tenha gostado e, caso tenha usado um sensor diferente, tenha sugestões, críticas ou elogios, não deixe de comentar abaixo (:


Módulo GSM SIM800L - Aplicações com Arduino

Módulo GSM SIM800L

Neste tutorial, iremos testar as principais aplicações do módulo GSM SIM800L diretamente com os comandos AT pela UART , assim, podemos fazer o mesmo código para diversos microcontroladores como PIC, ESP8266/32, ARM, AVR, etc, mudando apenas os métodos de utilização da UART de MCU para MCU, já que os comandos AT serão sempre iguais. Para esse tutorial usaremos o Arduino Mega como controlador.

Módulo GSM SIM800L
Figura 1 - Módulo GSM SIM800L

[toc]

kit robotica educacional com Arduino ESP ou Microbit

O que vamos aprender?

As principais aplicações deste módulo são:

  • SMS (receber e enviar).
  • Obter horário da rede, similar ao NTP ou RTC.
  • Obter localização por triangulação da rede.
  • Conexões TCP/UDP (inclusive SSL/TLS).
  • Ligações com entrada e saída de áudio.

Neste tutorial, Aprenderemos os 3 primeiros itens separadamente encontrados na lista apresentada.


Mãos a obra - Testando algumas funções do SIM800L

Componentes necessários

Montando o projeto

Atenção: esse módulo pode utilizar muita corrente de sua fonte em picos de transmissão (até 2A), então não alimente-o diretamente pelo Arduino. Recomenda-se utilizar uma fonte externa de 3,4V a 4,3V de no mínimo 2A. Caso não tenha uma fonte com tanta corrente, você pode adicionar alguns capacitores de alto valor capacitivo para ajudar nos picos de transmissão. Se a fonte não for suficiente para alimentá-lo, ele irá reiniciar aleatoriamente durante as transmissões.

 

Esquematico no Frittzing Arudino Mega e Módulo GSM SIM800L
Figura 2 - Esquematico no Frittzing

Projeto 1 - Enviando e recebendo SMS

Programando o Arduino

void setup()
{
  Serial2.begin(115200);
  pinMode(13, OUTPUT);//LED
  pinMode(8, OUTPUT);//Pino de reset do GSM

  //reinicia o GSM
  digitalWrite(8, 0);
  delay(2000);
  digitalWrite(8, 1);
  delay(7000);

  if (gsmWrite("AT", "OK") == "FAIL")
  {
    return;//Se o GSM nao responder, retorna a funcao (trava o mcu)
  }

  delay(5000);//Espera o termino da inicializacao do GSM
  SMSsnd("014998202683", "Arduino ON, lendo mensagens...");//Envia a mensagem pro numero. Atencao: precisa do DDD!

  
}

void loop()
{
  SMSrd();//Verifica se há novas mensagens para serem lidas a cada 10seg
  delay(10000);
}


String gsmWrite(String snd, String rcv)//Funcao que envia dados pro GSM e espera a resposta de ate 30seg
{
  Serial2.println(snd);

  if (rcv.indexOf("+CMGS") > -1)
  {
    delay(150);
    Serial2.write(0x1A);
  }

  for (uint16_t i = 0; i < 1200; i++)
  {
    delay(25);
    if (Serial2.available())
    {
      delay(50);
      String a = Serial2.readString();


      if (a.indexOf(rcv) > -1 || rcv.length() == 0)
      {
        return a;
      }
    }
  }

  return "FAIL";
}

void SMSsnd(String nm, String msg)//Funcao que envia o SMS
{
  String snd = "AT+CMGS=\"";  snd += nm;  snd += "\"";

  gsmWrite("AT+CMGF=1", "OK");
  gsmWrite("AT+CSMP=17,255,0,0", "OK");
  gsmWrite(snd, ">");
  gsmWrite(msg, "+CMGS:");
}

void SMSrd()//Funcao que le se ha SMS nao lido
{
  String c = "";
  gsmWrite("AT+CMGF=1", "OK");
  c = gsmWrite("AT+CMGL=\"REC UNREAD\"", "");

  if (c.indexOf("+CMGL:") > -1)
  {
    if    (c.indexOf("ON") > -1)//ON
    {
      digitalWrite(13, 1);//se o SMS conter o texto ON, liga o LED
    }
    else if (c.indexOf("OFF") > -1)//OFF
    {
      digitalWrite(13, 0);//se o SMS conter o texto OFF, desliga o LED
    }

    gsmWrite("AT+CMGD=1,1", "OK");//apaga todas mensagens (SIM card ha pouca memoria)
  }
}

Colocando para funcionar

Depois de ligar nosso projeto na alimentação, vamos logo receber uma mensagem indicando que o sistema está ativo, mostrando que o envio de SMS funcionou perfeitamente. Também foi adicionada a leitura de SMS, de modo que, quando um SMS é enviado com a mensagem "ON" ou "OFF",  o LED no pino 13 seja ligado ou desligado.

Mensagem recebida do Módulo GSM SIM800L
Figura 3 - Mensagem recebida do Módulo GSM SIM800L

Projeto 2 - Obtendo horário através da rede

Programando o Arduino

void setup()
{
  Serial.begin(115200);
  Serial2.begin(115200);//Inicia a Serial do GSM
  pinMode(8, OUTPUT);//Pino de reset do GSM

  //Reinicia o GSM
  digitalWrite(8, 0);
  delay(2000);
  digitalWrite(8, 1);
  delay(7000);

  String rcv = gsmWrite("AT", "*PSUTTZ:");//Espera o GSM obter o horario da rede
  if (rcv.indexOf("FAIL") > -1)
  {
    gsmWrite("AT+CLTS=1;&W", "OK");//Se nao responder, pode ser configuracao do seu GSM, entao vamos ativar a obtencao automatica de horario pela rede
    setup();//retorna ao inicio
  }

  delay(5000);
  

  
}

void loop()
{
  Serial.println(gsmTIME());//Mostra a data e horario no Serial Monitor
  delay(5000);
}


String gsmWrite(String snd, String rcv)//Funcao que envia dados ao GSM e espera a resposta
{
  Serial2.println(snd);

  if (rcv.indexOf("+CMGS") > -1)
  {
    delay(150);
    Serial2.write(0x1A);
  }

  for (uint16_t i = 0; i < 1200; i++)
  {
    delay(25);
    if (Serial2.available())
    {
      delay(50);
      String a = Serial2.readString();


      if (a.indexOf(rcv) > -1 || rcv.length() == 0)
      {
        return a;
      }
    }
  }

  return "FAIL";
}

String gsmTIME()//Funcao que retorna a data e horario
{
  String c = gsmWrite("AT+CCLK?", "+CCLK:");

  int16_t a = c.indexOf("\"") + 1;
  int16_t b = c.indexOf("\"", a);
  return c.substring(a, b);
}

Colocando para funcionar

Abrindo o Serial Monitor, podemos observar a data e o horário retornado pelo módulo GSM, lembrando que a data está no padrão (ano/mês/dia). O ultimo valor do horário corresponde ao fuso horário*4, logo, para obter nosso fuso horário, basta dividir "-12" por 4  e chegamos em -3 (fuso horário de brasília).

Data e hora do módulo GSM SIM800L
Figura 4 - Data e hora do módulo GSM SIM800L

Projeto 3 - Obtendo localização através da rede

Programando o Arduino

void setup()
{
  Serial.begin(115200);
  Serial2.begin(115200);
  pinMode(8, OUTPUT);//Pino de reset do GSM

  //Reseta o GSM
  digitalWrite(8, 0);
  delay(2000);
  digitalWrite(8, 1);
  delay(7000);

  if (gsmWrite("AT", "OK") == "FAIL")
  {
    return;
  }

  delay(5000);
  
  if (gsmWrite("AT+SAPBR=1,1", "OK") == "FAIL")//Ativa a rede pra localizacao
  {
    return;
  }
  else
  {
    String rcv = gsmWrite("AT+CIPGSMLOC=1,1", "+CIPGSMLOC:");//Pergunta a localizacao ao GSM
    int a = rcv.indexOf(":") + 2;
    int b = rcv.indexOf(",", a);
    if (rcv.substring(a, b) == "0")
    {
      a = rcv.indexOf(",", b) + 1;
      b = rcv.indexOf(",", a) + 1;
      b = rcv.indexOf(",", b);
      Serial.println(rcv.substring(a, b));//Mostra a localizacao no Serial monitor
    }
  }
}

void loop()
{
  
}


String gsmWrite(String snd, String rcv)//Funcao que envia dados ao GSM e espera a resposta
{
  Serial2.println(snd);

  if (rcv.indexOf("+CMGS") > -1)
  {
    delay(150);
    Serial2.write(0x1A);
  }

  for (uint16_t i = 0; i < 1200; i++)
  {
    delay(25);
    if (Serial2.available())
    {
      delay(50);
      String a = Serial2.readString();


      if (a.indexOf(rcv) > -1 || rcv.length() == 0)
      {
        return a;
      }
    }
  }

  return "FAIL";
}

Colocando para funcionar

As coordenadas que o módulo GSM retorna é longitude e latitude respectivamente.

Coordenadas lidas pelo Módulo GSM SIM800L
Figura 5 - Coordenadas lidas pelo Módulo GSM SIM800L

Entendendo a fundo

Software

Para utilização do módulo GSM foram usados os comandos "AT" do Datasheet, este pode ser encontrado logo abaixo em nossa seção de referências. Existem incontáveis comandos para as mais diversas aplicações e se você pretende utilizar o módulo GSM, aconselhamos que estude o Datasheet e conheça os comandos necessários para seu projeto.

A comunicação entre o Microcontrolador e o módulo GSM é feita através da porta Serial (UART) à 115200b/s neste caso, mas pode ser alterada. A cada comando enviado, normalmente, retorna-se uma resposta, então sempre que enviamos um comando, precisamos esperar a resposta para saber se os dados enviados foram realmente enviados. Para isso, foi criada uma função básica cuja função é escrever o dado no módulo GSM e esperar o retorno da resposta em um tempo limite de 30 segundos. Tome cuidado que alguns comandos podem demorar até 85 segundos para retornar resposta e caso isso aconteça, o código irá falhar por timeout. Para arrumar isso, aumente o timeout da função de leitura.

-Função gsmWrite(String snd, String rcv)

gsmWrite("AT", "OK");

A função criada para envio de dados do módulo GSM é uma boa maneira de utilizar o mesmo em diversos tipos de códigos, entretanto, como normalmente após a escrita de algum comando nós esperamos uma resposta, isto pode deixar nosso código lento e travando, já que alguns comandos demoram até 85 segundos!

Essa função basicamente escreve o comando (primeiro argumento da função, "snd") AT na porta Serial e posteriormente espera a resposta do mesmo (segundo argumento da função, "rcv"). Caso o módulo GSM não retorne a reposta esperada em 30 segundos que definimos no loop FOR() da função, retorna-se a mensagem "FAIL".

 -Comandos AT

O módulo GSM SIM800L funciona com os comandos AT e a maioria deles retorna alguma mensagem de confirmação ou erro, vamos ver como alguns deles funcionam!

AT+CCLK

Figura 6 - AT+CCLK

Quando requisitado "AT+CCLK?" do SIM800L, retorna-se "+CCLK: <time>" e ao fim, "OK". Também pode-se retornar erros como mostrado na imagem.

AT+CMGL

Figura 7 - AT+CMGL

A leitura de SMS do nosso projeto foi dedicada apenas às mensagens não lidas, por isso utilizamos "AT+CMGL="REC UNREAD"", mas você pode trocar para qualquer uma das opções acima que se encaixar melhor ao seu projeto.


Conclusões finais

As utilidades para o módulo GSM são inúmeras e isto nos permite ter uma gama de aplicações muito grande em um mesmo projeto, já que conta com diversas features, desde SMS até conexões TCP e etc. Apesar de alguns comandos demorarem bastante por causa da latência da rede telefônica, ainda podemos usufruir bem deste incrível módulo. O SIM800L faz muito mais do que mostrado aqui, entretanto estamos mostrando apenas o básico para norteá-los.

Referencias


Blynk - Crie uma Dashboard online e controle seu projeto pela internet

Blynk - Crie uma Dashboard online e controle seu projeto pela internet

Neste tutorial iremos aprender a utilizar o Blynk, uma ferramenta muito útil para quem deseja controlar seus projetos com Arduino , Raspberry Pi, ESP8266, entre outras placas, com seu smartphone, através da internet.

Blynk
Blynk

[toc]

kit robotica educacional com Arduino ESP ou Microbit

Sistemas de monitoramento e controle

Ao criar sistemas automatizados, é quase sempre fundamental que tenhamos uma interface para o monitoramento e controle das variáveis do processo cujo qual estamos controlando. Essa interfaces são chamadas de IHM, um acrônimo para Interface Homem-Máquina.

Exemplo de IHM
Exemplo de IHM

Qualquer forma de comunicação entre uma máquina e um ser humano pode ser considerado uma IHM. Essas interfaces podem ser feitas de varias formas, como por exemplo:

  • Usando LED's
  • Display imprimindo informações
  • Teclado e botões para controle das variáveis
  • Usando softwares de supervisionamento (Supervisórios)

Os supervisórios são softwares que conversam com um sistema automático através de algum tipo de rede, criando assim, uma interface de monitoramento e controle.

Apesar de haver plataformas de supervisório que podem ser usadas em conjunto com Arduino, ESP ou Raspberry PI, tal como o SCADABR, elas podem ser muito robustas para aplicações simples. Além disso, criar painéis usuais e organizados pode ser uma tarefa difícil.

Conhecendo o Blynk

O Blynk é uma ferramenta para criação de dashboards para controle, via internet, de dispositivos como Arduino , Raspberry Pi, ESP8266 dentre outros.

Através de componentes preexistentes, o Blynk fornece uma vasta gama de possibilidades, permitindo a criação de botões, Gauges, Gráficos e muitos outros componentes.

Exemplo de Dashboard com o Blynk
Exemplo de Dashboard com o Blynk

Dessa forma, é possível criar dashboards interativos de forma bem simples, bastando apenas mover os componentes desejados para a tela do seu projeto e configurar o mesmo à sua vontade.

- Blynk Server

Para usar essa ferramenta, seu Arduino, ESP ou outra placa de desenvolvimento que esteja usando  trocará informações, recebendo e enviando dados, com o Servidor online da Blynk. A Blynk disponibiliza bibliotecas compatíveis com a maioria das placas de desenvolvimento para facilitar essa interface.

Blink Server
Blynk Server

Por sua vez, essa informações poderão ser acessadas pelo aplicativo do Blynk através de um Smartphone ou outro dispositivo portátil com Android ou IOS.

Sabendo disso, neste tutorial iremos aprender a como configurar um dashboard para monitorar a temperatura e umidade de um ambiente e controlar o nível de luminosidade de um LED.


Mãos à obra - Monitorando um projeto com NodeMcu usando Blynk 

Componentes utilizados

Montando o projeto

Para realizar a motagem do projeto, utilizaremos a ordem de ligação da imagem abaixo:

Pinagem de ligação dht22/nodeMCU
Circuito montado Fritzing

Instalando aplicativo

Para começarmos a criação do nosso dashboard iremos primeiramente baixar o aplicativo Blynk na loja de aplicativos do nosso smarphone (Apple Store para iOS e Play Store para Android). Na Play Store, ao pesquisarmos a palavra Blynk, veremos que ele é o primeiro aplicativo disponível. Sabendo disso basta fazer o download do aplicativo normalmente.

Download aplicativo Blynk na Play Store

 

Ícone do applicativo

Ao fim do download, um ícone será criado na tela inicial do seu smartphone. Para iniciar o aplicativo basta selecionar o aplicativo Blynk.


Iniciando aplicativo pela primeira vez

Ao abrir o aplicativo pela primeira vez você deve criar um cadastro. Para isso você deve selecionar a opção Create new Account, uma vez nesta tela você vai precisar basicamente definir um email válido e uma senha para acessar o seu painel de aplicações.

Tela de login e botão para criar nova conta

Criando primeiro projeto

Ao criar o seu cadastro, você será direcionado a tela para criação de projetos. Para iniciarmos a criação do nosso dashboard selecione a opção New Project.

Tela para criação de novo projeto

Ao selecionarmos a opção de criar um novo projeto, seremos direcionados a tela de configuração do nosso dispositivo. Nesta tela definimos o nome do projeto, dispositivo (microcontrolador) utilizado e o tipo de conexão. Como neste projeto iremos medir temperatura e controlar um led, daremos o nome de Monitor/Leds. O dispositivo utilizado será o NodeMCU e o tipo de conexão WiFi.

 

Configuração do projeto

Após configurarmos o projeto corretamente, basta clicar no botão create e seremos direcionados ao nosso dashboard vazio.

 

Importante: Um Token será enviado ao seu email após clicar no botão create, ele será necessário no código do microcontrolador, portanto não se esqueça de fazer uma cópia para um local seguro.

 


 

Adicionando componentes ao dashboard

Neste dashboard vazio, selecione o ícone do + como mostra a figura abaixo para abrir o painel dos componentes que iremos utilizar.

Dashboard vazio

Ao clicarmos no ícone uma janela será aberta com todos os componentes disponíveis no aplicativo. Algo que deve se levar em consideração, é o fato de que o blynk apesar de grátis, permite que apenas uma quantidade limitada de widgets possam ser adicionadas em um dashboard. Para utilizar uma quantidade maior, é necessário comprar créditos. Porém para pequenos projetos esta quantidade costuma ser o suficiente.

Tela para seleção de componentes

Para elaboração deste Dashboard de exemplo, iremos utilizar apenas três componentes, sendo eles dois gauges e um slider, fazendo com que a tela fique com o formato da figura abaixo:

Dashboard montado

 


Configurando componentes

Agora que criamos a "casca" do nosso dashboard, iremos configurar cada um dos componentes adicionados para que se comuniquem com o nosso NodeMCU. para isso clique duas vezes sobre cada um dos componentes adicionados ao dashboard. Ao clicar sobre cada um dos Gauges, uma tela de configuração será aberta. Nela iremos definir o nome, valores limites e o pino de onde iremos receber os dados. Neste exemplo utilizaremos a configuração da figura abaixo para a temperatura:

Configuração Gauge Temperatura

 

Para o Gauge da temperatura , foi definido inicialmente o seu nome, o pino de onde os dados serão recebidos ( iremos entender isso melhor no código do NodeMCU e um intervalo que vai de 0 até 100 que será mostrado ao usuário neste Gauge.

Faremos o mesmo para o segundo Gauge, onde ao invés da temperatura iremos mostrar a umidade do ambiente. Iremos definir um intervalo de 0 até 100% e associaremos este gauge ao pino V5

Configuração Gauge Umidade

Por fim, iremos configurar o nosso slider com o nome de luminosidade, associado ao pino D2 do NodeMCU, e um intervalo entre 0 e 1024.

Configuração Slider

Agora que configuramos o nosso dashboard, podemos ir para o código fonte que será executado pelo nosso NodeMCU.


Programando

Antes de adentrarmos na apresentação do código, disponibilizamos uma seção para ajudar aqueles que são iniciantes no NodeMCU. Sinta-se livre para prosseguir caso você já tem domínio da IDE do Arduino e com o NodeMCU.

- Bibliotecas

Para este projeto, iremos precisar fazer o download de três bibliotecas, sendo elas:

Adafruit Unified Sensor: Biblioteca base para utilizar todas as bibliotecas disponibilizadas pela Adafruit.

DHT: Biblioteca responsável por estabelecer comunicação com sensores dht11/dht22

Blynk: Biblioteca responsável por se comunicar com seu dashboard

 

Todas elas podem ser baixadas através do Gerenciar bibliotecas, que pode ser acessado selecionando Sketch no menu principal.

Agora que temos todas as bibliotecas instaladas e o nosso circuito de monitoramento e controle de led está montado, iremos carregar o software de monitoramento abaixo para controlar o led e obter a temperatura/umidade do ambiente.

#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#define DHTPIN            D3         
//#define DHTTYPE           DHT11     
#define DHTTYPE           DHT22     

char auth[] = "Código recebido no Email";
char ssid[] = "Nome da sua rede Wifi";
char pass[] = "Senha da sua rede WiFi";
DHT dht(DHTPIN, DHTTYPE);
BlynkTimer timer;

void enviaDados(){
  float umidade = dht.readHumidity();
  float temperatura = dht.readTemperature(); 
  if (isnan(temperatura) || isnan(umidade)) {
    Serial.println("Falha ao ler dados do sensor!");
    return;
  }
  Blynk.virtualWrite(V5, temperatura);
  Blynk.virtualWrite(V6, umidade);
}

void setup() {
  pinMode(D2,OUTPUT);
  dht.begin();
  Blynk.begin(auth, ssid, pass);
  timer.setInterval(1000L, enviaDados);
}

void loop() {
  Blynk.run();
  timer.run();
}

Colocando pra funcionar

Agora que temos o código e o nosso dashboard montado, vejamos como ficou o funcionamento das duas plataformas trocando informações entre si.

 


Entendendo a fundo

Software

- Incluindo as bibliotecas necessárias

De início, iremos utilizar quatro bibliotecas, sendo duas voltadas exclusivamente para o nosso sensor de temperatura, e as outras duas voltadas para conexão sem fio e comunicação com a plataforma Blynk. As bibliotecas Adafruit_sensor e DHT, serão responsáveis por fornecer uma interface de comunicação com o sensor dht11/dht22. A biblioteca ESP8266WiFi, será responsável por fornecer toda a interface para conexão e comunicação sem fio do nosso código. E por fim a biblioteca BlynkSimpleEsp8266 será responsável por fornecer os métodos de comunicação com a plataforma Blynk.

#include <Adafruit_Sensor.h> 
#include <DHT.h> 
#include <ESP8266WiFi.h> 
#include <BlynkSimpleEsp8266.h>

- Defines

Para facilitar a criação e a troca de sensores utilizados, dois defines foram criados. Caso o usuário queira trocar o tipo de sensor dht utilizado ou o pino de comunicação basta trocar em um único lugar no define.

#define DHTPIN            D3         
//#define DHTTYPE           DHT11     
#define DHTTYPE           DHT22

- Variáveis de acesso ( Acesso WiFi )

Como iremos utilizar a conexão WiFi para acessar o nosso dispositivo remotamente, é necessário configurar a rede a qual ele irá se conectar, sabendo disso nesta parte serão criadas duas variáveis para acesso a rede sem fio.

char ssid[] = "Nome da rede";
char pass[] = "Senha da rede";

- Variáveis de acesso ( Acesso Blynk )

Para fazer com que o NodeMCU se comunique com a aplicação, é necessário que o usuário utilize aquele Token que foi enviado pelo email no processo de criação do dashboard. Com isso iremos também criar uma variável de nome auth, responsável por armazenar o token de comunicação com o dashboard.

char auth[] = "Código recebido no email";

- Instância do objeto de comunicação com o sensor

Por fim, iremos instanciar o objeto dht, que terá como função se comunicar com o sensor utilizado neste exemplo. Note que ele deve receber como argumentos para seu construtor o pino onde o sensor está conectado e o tipo de sensor utilizado.

DHT dht(DHTPIN, DHTTYPE);

- Função setup ( inicializando pinos e sensores utilizados )

Dentro da função setup, iremos simplesmente configurar o pino onde o led foi conectado D2, como um pino de saída, e inicializar o nosso sensor de temperatura através de sua função begin().

pinMode(D2,OUTPUT);
dht.begin();

- Função setup ( inicializando comunicação com aplicação blynk e temporizador )

Agora que temos os pinos de comunicação do nosso circuito incializados, podemos partir para o próximo passo, que é inicializar a comunicação com os servidores Blynk. Para fazer isso, iremos utilizar o método begin, que recebendo como parâmetros o nome da rede, a senha da rede e o código recebido no email, inicializará todo o processo de comunicação de forma transparente ao usuário. Iremos também inicializar um temporizador no nosso código, que será responsável por executar uma função toda vez que um intervalo de tempo x for alcançado, que no nosso caso será um valor de 1 segundo.

  Blynk.begin(auth, ssid, pass);
  timer.setInterval(1000L, enviaDados);

A função setInterval, recebe como parâmetros o tempo em milissegundos e a função que deve ser executada.

- Função enviaDados

A função enviaDados, é responsável por periodicamente enviar a informação do sensor para a aplicação. O processo de envio é feito da seguinte forma:

  1. Dados de temperatura e umidade são lidos do sensor através dos métodos readTemperature e readHumidity
    1. float umidade = dht.readHumidity();
      float temperatura = dht.readTemperature();
    2. Caso os dados lidos não sejam valores números, possivelmente ocorreu um erro na leitura do sensor, sendo assim o bloco if do código é acionado e a função termina sem escrever os dados para a plataforma
      1. if (isnan(temperatura) || isnan(umidade)) {
          Serial.println("Falha ao ler dados do sensor!");
          return;
        }
    3. Caso contrário, os dados de temperatura e umidade lidos pelo sistema são enviados para a plataforma através do método virtualWrite, como associamos aos nossos gauges os pinos V4 e V5 eles vão receber o valor de temperatura lido pelo nosso sistema
      1. Blynk.virtualWrite(V5, temperatura);
        Blynk.virtualWrite(V6, umidade);

- Função loop

Por fim, na função loop iremos executar tanto o nosso objeto principal blynk, quanto nosso temportizador através do método run.

Blynk.run();
timer.run();

Vídeo tutorial

Vocês também podem ver uma explicação do código em vídeo no canal abaixo:

https://www.youtube.com/watch?v=kVq3-yH8wNs&t=68s


Desafio

Agora que você sabe um pouco sobre como adicionar e configurar componentes no Blynk. Crie novos componentes no seu dashboard. Adicione gráficos para monitorar a variação da temperatura e umidade do ambiente, você irá obter resultados interessantes :D.

Considerações Finais

Este tutorial, teve como objetivo mostrar como construir dashboards através da plataforma blynk, e estabelecer uma comunicação bi-direcional com o seu nodeMCU. Espero que tenham gostado do conteúdo apresentado, sinta-se à vontade para nos dar sugestões e de deixar suas dúvidas nos comentários abaixo.


Descobrindo o endereço I2c de dispositivos com Arduino

Descobrindo o endereço I2C de dispositivos com Arduino

Quando compramos equipamentos de lojas desconhecidas quase sempre nos deparamos com o problema de não termos disponível um datasheet ou algum tipo de documentação que auxilie na utilização dos mesmos.  Sabendo disso, neste tutorial nós iremos aprender a como identificar o endereço I2C de dispositivos com um Arduino.

[toc]

kit robotica educacional com Arduino ESP ou Microbit

Protocolo I2C

O protocolo I2C, ou Inter-Integrated Circuit é um protocolo de comunicação desenvolvido pela Philips, que teve como objetivo inicial, interconectar dispositivos de baixa velocidade e curta distância. A comunicação i2C funciona por meio de um barramento onde apenas um dispositivo, denominado mestre, é responsável por requisitar informações dos dispositivos conectados. A conexão I2C é feita através de dois fios, sendo eles:

  • sda: Transmitir dados entre receptor e transmissor via barramento.
  • scl: Temporizar e sincronizar unidades conectadas ao sistema.

É também interessante possuir um resistor pull-up nas trilhas sda e scl para estabilizar o barramento de comunicação

Protocolo I2C endereço I2c
Protocolo I2C

Como a comunicação I2C é feita via um barramento, cada dispositivo conectado ao sistema deve possuir um endereço único. Este código é composto por um valor de 7 bits, disponibilizando um total de 127 endereços onde apenas o intervalo 0x8 até 0 intervalo 0x77 está disponível para utilização.


Mãos à obra - Descobrindo o endereço I2C de dispositivos utilizando o seu Arduino

Componentes utilizados:

Montando o projeto

Como teste do nosso código de pesquisa, iremos conectar um dispositivo I2C ao nosso Arduino Nano. Para fazer isso basta conectar o pino SDA ao pino A4 do Arduino e o pino SCL ao pino A5 do Arduino, além é claro dos pinos utilizados para alimentação. A figura abaixo ilustra o processo de ligação dos fios de comunicação e alimentação.

montagem circuito com arduino nano e lcd para descobrir endereço I2c

 

Veja como ficou a montagem na prática.

Atenção, sempre monte o seu circuito com a alimentação do Arduino desligada. Para evitar possíveis curtos circuitos que possam vir a danificar o seu módulo ou até mesmo o microcontrolador.

 

Programando

Agora que temos conectado ao nosso sistema um módulo que supostamente não sabemos o seu endereço. Iremos utilizar  carregar o seguinte código em nossa placa para sua identificação.

#include <Wire.h>
#define TEMPOLEITURA 100
#define TEMPOESPERA 3000
byte endereco;
byte codigoResultado=0;
byte dispositivosEncontrados=0;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  while (!Serial); 
  scanI2c();           
}

void scanI2c(){
    for (endereco=0; endereco<128; endereco++){
    Wire.beginTransmission(endereco);
    codigoResultado = Wire.endTransmission();
    if (codigoResultado==0){
      Serial.print ("Dispositivo I2c detectado no endereço: ");
      Serial.println(endereco,HEX);
      dispositivosEncontrados++;
      delay(TEMPOESPERA);

    }
    delay(TEMPOLEITURA);
  }
  if (dispositivosEncontrados>0){
    Serial.print("Foi encontrado um total de: ");
    Serial.print(dispositivosEncontrados);
    Serial.println(" dispositivos");
  }
  else{
    Serial.println("Nenhum dispositivo foi encontrado !!!");
  }
}


void loop() {

}

 


Entendendo a fundo

Software

- Incluindo as bibliotecas necessárias

De início, para ser possível a utilização da comunicação I2C no nosso Arduino, nós iremos precisar adicionar a biblioteca wire.h que pode ser feita através da seguinte sentença:

#include <Wire.h>

- Temporizadores de pesquisa e tempo de espera

Iremos também neste código criar dois temporizadores para definir de quanto em quantos milissegundos o nosso código deverá fazer a pesquisa em um novo endereço e por quanto tempo ele deve esperar após encontrar um dispositivo conectado ao barramento I2C. Para isso, iremos criar 2 diretivas define que serão responsáveis por armazenar estes valores, fazendo com que eles sejam facilmente parametrizáveis.

#define TEMPOLEITURA 100
#define TEMPOESPERA 3000

- Função setup

Na função setup, iremos inicializar a comunicação I2C para identificação de dispositivos e também iremos inicializar a comunicação serial, para que os dados sejam mostrados no serial monitor.

void setup() {
  Serial.begin(9600);
  Wire.begin();
  while (!Serial);
  scanI2c();          
}

Na versão Leonardo do Arduino, para utilização correta da porta serial, é importar adicionar o trecho:

 while (!Serial);

Pois assim iremos garantir que a comunicação serial está de fato funcionando corretamente.

- Variáveis de controle

Para deslocarmos entre os endereços, identificarmos se o dispositivo está realmente conectado ao barramento e contar quantos dispositivos estão conectados, nós iremos utilizar três variáveis do tipo byte. A utilização destas variáveis com este tipo deve-se ao fato de que como estes valores nunca serão maiores que 255(,) não existe a possibilidade de overflow. Sendo assim iremos economizar cerca de 3 bytes de memória, se utilizássemos por exemplo o tipo int para armazenar.

byte endereco;
byte codigoResultado=0;
byte dispositivosEncontrados=0;

- Função scanI2c

Dentro da função scanI2c nós iremos realizar todo o processo de busca por dispositivos conectados, que será feito da seguinte forma:

  1.  Através do comando for, percorrer todos os endereços disponíveis no protocolo I2C, partindo do 0 até o 127.
    for (endereco=0; endereco<128; endereco++);
  2. Utilizando o método  Wire.beginTransmission, iremos tentar estabelecer uma comunicação com o dispositivo conectado, utilizando como endereço a posição atual do for.
    Wire.beginTransmission(endereco);
  3. Logo em seguida iremos encerrar a transmissão através do método Wire.endTransmission. Este método possui um retorno que consiste em:
    1. Igual a 0 - Conexão fechada com sucesso
    2. Diferente de 0 - Falha na transmissão ou não existe dispositivo conectado
  4. Sabendo disso, iremos armazenar este valor de retorno em nossa variável codigoResultado
    codigoResultado = Wire.endTransmission();
    
  5. Logo em seguida verificamos se a variável codigoResultado é igual a zero, caso seja mostramos o código do dispositivo e contabilizamos a variável que mostra o total de dispositivos encontrados e aguardamos o tempo em milissegundos definido em TEMPOESPERA
    if (codigoResultado==0){
     Serial.print ("Dispositivo I2c detectado no endereço: ");
     Serial.println(endereco,HEX);
     dispositivosEncontrados++;
     delay(TEMPOESPERA);
    }
  6. Após cada tentativa de leitura também aguardamos um intervalo de tempo definido em TEMPOLEITURA.
    delay(TEMPOLEITURA);
    
  7. Ao fim do for verificamos se o número de dispositivos encontrados é maior que zero, caso seja mostramos este valor na serial, caso contrário informamos que nenhum dispositivo foi encontrado.
    if (dispositivosEncontrados>0){
      Serial.print("Foi encontrado um total de: ");
      Serial.print(dispositivosEncontrados);
      Serial.println(" dispositivos");
    }
    else{
      Serial.println("Nenhum dispositivo foi encontrado !!!");
    }

Vídeo Tutorial

Vocês também podem ver uma explicação do código em vídeo no canal abaixo:

https://www.youtube.com/watch?v=SaZYSTw627o


Desafio

Agora que você sabe como descobrir o endereço de dispotivos I2C. Tente conectar mais de um ao barramento e veja se o código consegue detectar todos. Tente também criar uma lógica para salvar o endereço dos dispositivos identificados pelo sistema.

Considerações Finais

Este tutorial, teve como objetivo mostrar uma forma bem simples para encontrar o endereço de dispositivos conectados via I2C. Espero que tenham gostado do conteúdo apresentado, sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.

Caso queira saber mais sobre o Display LCD 16x2 com Adaptador I2C, acesse o tutorial: Display LCD 20×4 e LCD 16×2 com Adaptador I2C – Utilizando o display com Arduino

 


Módulo RF 433Mhz - Comunicação entre Arduinos

Módulo RF 433Mhz - Comunicação entre duas placas Arduino 

Na maioria das vezes em que falamos sobre comunicação sem fio, pensamos imediatamente no acesso à internet através de computadores ou celulares por meio de algum modem ou roteador que esteja disponibilizando o sinal para tal propósito, no entanto, existem muitos outros métodos de comunicação sem fio. Neste tutorial, demonstraremos como é possível estabelecer uma comunicação sem fio entre duas placas Arduino via radiofrequência, utilizando os módulos Receptor e Transmissor RF 433Mhz (Módulo RF 433Mhz).

[toc]

O que é radiofrequência?

Quando pesquisamos sobre o que vem a ser o conceito de radiofrequência, nos deparamos com várias definições, no entanto, a mais adequada é que afirma que a radiofrequência consiste em uma faixa de frequências que engloba valores de aproximadamente 3KHz (algumas referências trazem valores de 9KHz, 10KHz) até 300GHz, os quais, correspondem ao intervalo de frequências utilizadas por ondas de rádio.

O uso da radiofrequência permite o controle dos mais diversos dispositivos sem que seja necessária a utilização de qualquer tipo de fio. Podemos facilmente encontrar aplicações que utilizam a radiofrequência para atender os seus propósitos, como por exemplo, os portões eletrônicos de residências, os quais, através de um controle remoto operando dentro de uma determinada faixa de frequência, pode-se acionar o motor do portão a uma grande distância.

Controle de portão eletrônico

Os módulos Receptor e Transmissor RF433Mhz

Para realizar o projeto vamos utilizar dois módulos (apresentados na figura abaixo) para que possamos estabelecer uma comunicação sem fio entre duas placas Arduino e assim, comandar uma delas através da outra.

Módulos RF 433Mhz
Módulos RF 433Mhz

Estes módulos trabalham à uma frequência de 433MHz e tem um alcance de até 90 metros em espaços abertos. Através da utilização destes, é possível realizar transferência de dados em uma velocidade que pode variar até 9200 bits por segundo, de modo que, quanto maior for a distância entre o elemento transmissor e o elemento receptor, menor deve ser a velocidade na transmissão dos dados para diminuir a probabilidade de erros.

Na figura acima, o módulo apresentado do lado direito, é o módulo transmissor. Este contem três pinos: Um para alimentação, outro para o terra e o último para dados. Por outro lado, o módulo presente do lado esquerdo, é o módulo receptor e apesar de este conter 4 pinos, utilizamos apenas 3 deles (assim como o módulo transmissor, utilizamos um pino para alimentação, um para o terra e outro para dados.


Mãos à obra - Comunicando duas placas Arduino via radiofrequência

Nesta seção iremos demonstrar todos os passos que você deve seguir para aprender fazer com que duas placas Arduino se comuniquem via radiofrequência.

Componentes necessários

Montando o projeto

Neste tutorial temos dois hardwares que serão utilizados. O primeiro deles irá conter um Arduino Micro, que por sua vez, irá atuar em conjunto com um módulo Transmissor RF 433Mhz.

Módulo Transmissor RF 433Mhz com Arduino Micro
Módulo Transmissor RF 433Mhz com Arduino Micro

O segundo hardware irá conter um Arduino UNO, o qual, irá atuar em conjunto com um módulo Receptor RF 433Mhz.

Módulo RF 433Mhz - Módulo Receptor RF 433Mhz com Arduino UNO
Módulo Receptor RF 433Mhz com Arduino UNO

Programando

Conforme apresentado no tópico anterior, o projeto a ser desenvolvido neste tutorial utiliza duas placas Arduino, portanto, teremos a presença de dois códigos para serem gravados em ambas as placas. Primeiramente, apresentamos o código a ser gravado no Arduino Micro, que por sua vez, estará atuando no envio das informações.

#include <VirtualWire.h>
 
bool estado_led;
char data[2];
 
void setup()
{
  vw_set_tx_pin(5);
  vw_setup(2000);  
  
}
 
void loop()
{
  estado_led = !estado_led;
  itoa(estado_led, data, 2);
  vw_send((uint8_t *)data, strlen(data)); 
  vw_wait_tx(); 

  delay(2000);
  }  
 

Em seguida, apresentamos o código a ser gravado no Arduino UNO, que em nosso projeto, deverá receber as informações obtidas pelo Receptor RF433 Mhz.

#include <VirtualWire.h>
 
byte message[VW_MAX_MESSAGE_LEN];    // Armazena as mensagens recebidas
byte msgLength = VW_MAX_MESSAGE_LEN; // Armazena o tamanho das mensagens
 
 
void setup()   {

    vw_set_rx_pin(5); // Define o pino 5 do Arduino como entrada 
//de dados do receptor
    vw_setup(2000);             // Bits por segundo
    pinMode(13,OUTPUT);
    vw_rx_start();              // Inicializa o receptor

 
}
 
void loop()
{
    if (vw_get_message(message, &msgLength)) // Non-blocking
    {
        Serial.print("Recebido: ");
        Serial.write(message[0]);
        if(message[0] == '0'){
          digitalWrite(13, LOW);
        }
        else if(message[0] == '1'){
          digitalWrite(13,HIGH);
        }
    }
}

Entendendo a fundo

Software - Arduino Micro / Transmissor RF 433Mhz   

- Incluindo a biblioteca que será utilizadas

Primeiramente, para desenvolvermos uma aplicação como esta, devemos incluir a biblioteca que será utilizada no código, para que assim, o mesmo possa funcionar de maneira adequada. A biblioteca VirtualWire.h é responsável pela comunicação que será estabelecida entre o Arduino UNO e o Arduino Micro através do par Transmissor/Receptor RF 433Mhz.

#include <VirtualWire.h>

-Declarando as variáveis do projeto

Posteriormente, temos um bloco onde ocorre a declaração das variáveis que serão utilizadas no decorrer do programa. A variável estado_led (do tipo booleana) é responsável por armazenar o valor referente ao estado desejado do led (que será acionado na placa Arduino receptora) e a variável data, que por sua vez, é um vetor de caracteres, terá a função de armazenar o dado que será enviado (posteriormente explicaremos o motivo desta variável ter duas posições).

bool estado_led;
char data[2];

- Estabelecendo as configurações iniciais

Na função setup(), utilizamos duas funções de configuração do módulo transmissor. A primeira delas é a função vw_set_tx_pin(), que por sua vez, é responsável por determinar qual pino do Arduino Micro será utilizado para enviar os dados da placa para o módulo Transmissor RF 433Mhz.

A outra função existente neste bloco é a função vw_setup(), a qual, serve para inicializar a comunicação entre o Arduino Micro e o módulo Transmissor RF 433Mhz, de modo que, ao utilizarmos a mesma, devemos passar como parâmetro a velocidade de transmissão em bits por segundo.

void setup()
{
  vw_set_tx_pin(5);
  vw_setup(2000);  
}

- Enviando dados através do transmissor RF 433Mhz

Dentro da função loop() vamos estabelecer toda parte referente ao envio dos dados propriamente dito. O primeiro passo a ser realizado é a inversão do conteúdo armazenado na variável estado_led, de modo que, como esta variável é do tipo booleana, os valores irão sendo alternados entre 0 e 1 a cada passagem pelo ciclo da função loop().

estado_led = !estado_led;

Em seguida, utilizamos a função itoa() para transformar o valor contido na variável estado_led em uma string e armazenar este valor, já transformado, na variável data (como dissemos anteriormente, esta variável possui duas posições, pois, após o processo de conversão de um determinado número em string, além do mesmo, surge também como resultado, o caractere terminador de strings "\0") .

A função itoa() possui 3 parâmetros, dos quais, o primeiro refere-se à variável cujo valor queremos transformar em string. O segundo, é a variável na qual queremos guardar o resultado gerado e a terceira é o tipo de dado que estamos convertendo, logo, como estamos convertendo um valor binário, utilizamos o número 2 nesta posição.

itoa(estado_led, data, 2);

Posteriormente, utilizamos a função vw_send() para enviar os dados para o Transmissor RF433Mhz transmiti-los  (note que esta função possui 2 parâmetros, de modo que, o primeiro deles refere-se à variável que queremos enviar e o seguindo diz respeito ao tamanho da mesma. Sugerimos que utilize esta função neste formato, trocando apenas o nome da variável que você irá utilizar).

 vw_send((uint8_t *)data, strlen(data));

Por fim, utilizamos a função vw_wait_tx() para que o programa aguarde a transferência total da mensagem e a função delay() para estipular o tempo que o led levará para trocar de estado.

vw_wait_tx(); 
delay(2000);

Veja como ficou nossa função loop()

void loop()
{
  estado_led = !estado_led;
  itoa(estado_led, data, 2);
  vw_send((uint8_t *)data, strlen(data)); 
  vw_wait_tx(); 

  delay(2000);
  }

Software - Arduino UNO / Receptor RF 433Mhz   

- Incluindo a biblioteca que será utilizadas

Assim como no programa desenvolvido para o Arduino Micro, devemos incluir a biblioteca que será utilizada neste código, para que assim, o mesmo possa funcionar de maneira adequada. A biblioteca VirtualWire.h é responsável pela comunicação que será estabelecida entre o Arduino UNO e o Arduino Micro através do par Transmissor/Receptor RF 433Mhz.

#include <VirtualWire.h>

-Declarando as variáveis do projeto

Posteriormente, temos um bloco onde ocorre a declaração das variáveis que serão utilizadas no decorrer do programa. As variáveis tamanho_msg e msg, ambas do tipo byte, são responsáveis por armazenar informações referentes às mensagens que serão recebidas, para que, utilizando as mesmas, seja possível interpretá-las e tomar as ações necessárias com base no conteúdo recebido.

Apenas a título de curiosidade, o elemento VW_MAX_MESSAGE_LEN é próprio da biblioteca utilizada e armazena o valor referente ao tamanho da mensagem.

byte tamanho_msg = VW_MAX_MESSAGE_LEN; 
byte message[VW_MAX_MESSAGE_LEN];

- Estabelecendo as configurações iniciais

Na função setup(), utilizamos três funções para a configuração do módulo receptor. A primeira delas é a função vw_set_rx_pin(), que por sua vez, é responsável por determinar qual pino do Arduino UNO será utilizado para receber os dados enviados do módulo Receptor RF 433Mhz para a placa Arduino utilizada.

A segunda função existente neste bloco é a função vw_setup(), a qual, serve para inicializar a comunicação entre o Arduino UNO e o módulo Receptor RF 433Mhz, de modo que, ao utilizarmos a mesma, devemos passar como parâmetro a velocidade de transmissão em bits por segundo (note que esta informação deve ser igual à estabelecida no módulo Transmissor RF 433Mhz). Por fim, através da função vw_rx_start() inicializamos a função de recebimento de dados do Receptor RF 433Mhz. Além disso, definimos o modo de operação do pino 13 através da função pinMode().

void setup()   {
   vw_set_rx_pin(5); // Define o pino 5 do Arduino como entrada 
   vw_setup(2000);  
//Serial.begin(9600);
  //while(!Serial){}
    
//de dados do receptor
    vw_setup(2000);             // Bits por segundo
    pinMode(13,OUTPUT);
    vw_rx_start();              // Inicializa o receptor 
}

- Recebendo dados através do Receptor RF 433Mhz

Basicamente, o que fazemos na função loop() é conferir se houve o recebimento de algum dado através da função vw_get_message() e caso tenha, verificamos se este valor, em string, corresponde ao caractere 0, o qual, será responsável por fazer com que o led seja apagado. Em contrapartida, caso, o valor encontrado seja o caractere 1, o led deverá ser acionado.

void loop()
{
uint8_t message[VW_MAX_MESSAGE_LEN];    
uint8_t msgLength = VW_MAX_MESSAGE_LEN; 
 
  //display.setCursor(0, 0);  //Seta a posição do cursor
    if (vw_get_message(message, &msgLength)) // Non-blocking
    {
        Serial.print("Recebido: ");
        Serial.write(message[0]);
        if(message[0] == '0'){
          digitalWrite(13, LOW);
        }
        else{
          digitalWrite(13,HIGH);
        }
        
   
    Serial.println();
    }

Considerações finais

Neste tutorial, demonstramos como você pode utilizar o conceito de radiofrequência para fazer com que duas placas Arduino troquem informações entre si. Este foi apenas um conteúdo para que você tenha uma noção de como das os primeiros passos com esta tecnologia, portanto, esperamos que continue nos acompanhando e sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.


Shield Ethernet W5100 - Controlando saídas via servidor web

Shield Ethernet W5100 - Controlando saídas de um Arduino via navegador - Servidor Web

Neste tutorial iremos dar prosseguimento ao conteúdo relacionado à criação de Servidores Web utilizando o Arduino UNO juntamente com o Ethernet Shield W5100. Anteriormente, vimos quais eram os procedimentos básicos para criar um Servidor Web e também para efetuar a leitura de valores provenientes de elementos ligados tanto às entradas analógicas quanto às digitais. Neste tutorial você aprenderá como controlar as saídas digitais do Arduino UNO por meio do navegador acessando um Servidor Web implementado com seu Shield Ethernet W5100

É importante, para o pleno entendimento desse tutorial, que o leitor tenha lido os dois tutoriais anteriores:

[toc]


Mãos à obra - Acionando saídas digitais do Arduino UNO através de um Servidor Web

Componentes necessários

Para reproduzir este projeto, você irá precisar dos seguintes componentes:

Montando o projeto

Na figura abaixo você pode conferir o hardware pronto para ser utilizado.

Hardware para servidor web com o Ethernet Shield w5100 e leds
Hardware utilizado com o Ethernet Shield w5100 e leds

Gostaríamos de sugerir que você tenha bastante cuidado no momento em que for encaixar o Ethernet Shield W5100 no Arduino UNO, pois, além da possibilidade de entortar os pinos do shield, você também pode se machucar.

Lembre-se que o shield em questão possui uma série de pinos em sua parte inferior, tanto nas laterais como em sua parte dianteira, portanto, antes de pressionar o mesmo sobre o Arduino UNO, certifique-se de que os pinos estejam levemente posicionados em suas respectivas entradas para que então você possa ir realizando o encaixe lentamente.

Realizando as conexões

Para reproduzir este projeto, garanta que o seu Shield Ethernet W5100 esteja ligado corretamente a uma das portas LAN presentes no seu modem ou roteador.

Programando

Este programa foi elaborado a partir do código-exemplo da biblioteca Ethernet.h denominado WebServer.

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };   
IPAddress ip(192, 168, 25, 26);                       
EthernetServer server(80);                             

String requisicao_do_navegador;
String parametro_da_requisicao;

void setup()
{
    Ethernet.begin(mac, ip); 
    server.begin();                 
    pinMode(2,OUTPUT);
    pinMode(7,OUTPUT);
}

void loop()
{
    EthernetClient client = server.available();

    if (client) { 
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) { 
                char c = client.read(); 
                requisicao_do_navegador += c;  
                
                if (c == '\n' && currentLineIsBlank ) 
                {     
                        if (definindo_a_requisicao(&requisicao_do_navegador)) {
                        parametro_da_requisicao = pegar_parametro_da_requisicao(&requisicao_do_navegador);
                        Serial.println(parametro_da_requisicao);
                                                 
                        client.println("HTTP/1.1 200 OK");
                        client.println("Content-Type: text/html");
                        client.println("Connection: close");
                        client.println();
                        
                        //Conteudo da Página HTML
                        client.println("<!DOCTYPE html>");
                        client.println("<html>");
                        client.println("<head>");
                        client.println("<title>Servidor Web VDS</title>");
                        client.println("</head>");
                        client.println("<body>");
                        client.println("<h1><font color=#4279c7>Servidor Web do Vida de Sil&iacute;cio</font></h1>");
                        client.println("<hr/>");                         
                        client.println("<h1>Sa&iacute;das digitais</h1>");
                        
                        client.println("<form method=\"get\">");

                        saida(client);
                        
                        client.println("<br/>");
                        saida2(client);
                        client.println("</form>");
                                                
                        
                        client.println("</body>");
                        client.println("</html>");
                        } else {
                        client.println("HTTP/1.1 200 OK");
                    }
                   
                    requisicao_do_navegador = "";    
                    break;
                }
                
                if (c == '\n') {
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    currentLineIsBlank = false;
                }
            }
        } 
        delay(1);     
        client.stop(); 
    } 
}

void saida(EthernetClient cl)
{
        
        if (parametro_da_requisicao.indexOf("P2=1") > -1) 
        { 
           digitalWrite(2, HIGH);
           cl.println("<input type=\"checkbox\" name=\"P2\" value=\"1\" onclick=\"submit();\" checked > Pino digital 2");
        } 
        else 
        {
           digitalWrite(2, LOW);
           cl.println("<input type=\"checkbox\" name=\"P2\" value=\"1\" onclick=\"submit();\" > Pino digital 2");
        }
        
}

void saida2(EthernetClient cl)
{
        
        if (parametro_da_requisicao.indexOf("P7=1") > -1) 
        { 
           digitalWrite(7, HIGH);
           cl.println("<input type=\"checkbox\" name=\"P7\" value=\"1\" onclick=\"submit();\" checked > Pino digital 7");
        } 
        else 
        {
           digitalWrite(7, LOW);
           cl.println("<input type=\"checkbox\" name=\"P7\" value=\"1\" onclick=\"submit();\" > Pino digital 7");
        }
        
}

String pegar_parametro_da_requisicao(String *requisicao) {
int pos_inicial, pos_final;
String parametro;

  
  pos_inicial = (*requisicao).indexOf("GET") + 3;
  pos_final = (*requisicao).indexOf("HTTP/") - 1;
  parametro = (*requisicao).substring(pos_inicial,pos_final);
  parametro.trim();
 
  return parametro;
}

bool definindo_a_requisicao(String *requisicao) {
String parametro;
bool requisicao_desejada = false;

  parametro = pegar_parametro_da_requisicao(requisicao);

  if (parametro == "/") {
     requisicao_desejada = true;
  }

  if (parametro.substring(0,2) == "/?") {
     requisicao_desejada = true;
  }  

  return requisicao_desejada;
}

Colocando para funcionar

Veja como ficou nosso segundo Servidor Web.

Servidor Web com Ethernet Shield W5100
Servidor Web pronto.

Entendendo a fundo

Antes de começarmos com a explicação do código, gostaríamos de ressaltar que iremos apresentar apenas os detalhes dos tópicos não contemplados nos tutoriais anteriores, pois, desta maneira, será mais fácil focar nas partes referentes às atualizações feitas sobre o programa já existente, portanto, caso você tenha alguma dúvida sobre alguma parte do programa que não seja explicada neste momento, sugerimos que acesse o nossos materiais citados anteriormente.

Software

- Definindo os pré-requisitos para o funcionamento do código

Inicialmente, devemos incluir duas bibliotecas no código para que o mesmo pudesse funcionar corretamente. A biblioteca SPI.h, responsável pela comunicação dos módulos do shield com o Arduino UNO utilizando o protocolo SPI e a biblioteca Ethernet.h que atua possibilitando a conexão do conjunto, em um primeiro momento, com uma rede local.

Após a inclusão das bibliotecas citadas, devemos definir um endereço MAC (lembre-se que este pode ser qualquer um, desde que seja único em sua rede local) e um endereço IP (este deve ser um endereço válido  e disponível dentro da sua rede local). Além disso, devemos criar o objeto que será responsável por representar o Servidor Web no código (aqui, chamamos este de server) e relacioná-lo com a porta 80.

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };   
IPAddress ip(192, 168, 25, 16);                       
EthernetServer server(80);

- Declarando as variáveis responsáveis pela manipulação da requisição do navegador

Em seguida, declaramos duas variáveis do tipo String , as quais, conforme veremos posteriormente, serão responsáveis por armazenar informações referentes à requisição feita pelo navegador.

String requisicao_do_navegador;
String parametro_da_requisicao;

- Definindo as configurações iniciais

Dentro da função setup(), devemos determinar o modo de operação dos pinos digitais que serão utilizados (estes terão o papel de saídas digitais) . Além disso, iniciamos a conexão com a rede local através da função Ethernet.begin() (passando como parâmetro os endereços MAC e IP definidos anteriormente) e também iniciamos o Servidor Web por meio da sentença server.begin() (lembre-se que server é o objeto criado para representar o Servidor Web no código).

void setup()
{
    Ethernet.begin(mac, ip); 
    server.begin();                 
    pinMode(2,OUTPUT);
    pinMode(7,OUTPUT);
}

- Entendendo as requisições do navegador

Nos tutoriais anteriores, ressaltamos o mecanismo básico de funcionamento dos códigos voltados para a criação de Servidores Web, o qual, começa através de um procedimento padrão, que por sua vez, consiste em utilizar uma variável para obter caractere por caractere da requisição feita pelo navegador até que esta seja completamente recebida pelo Arduino UNO, de modo que, apenas a partir deste ponto inicia-se o processo de elaboração da página.

Aqui, teremos uma nova condição que deve ser cumprida para que o Servidor Web entregue uma página como resposta para o navegador. Esta é função definindo_a_requisição(), cujo papel consiste em determinar se a requisição feita pelo navegador cumpre alguns requisitos para que então o Servidor Web possa entregar a página para o navegador. Repare que o parâmetro da função citada é o texto completo de requisição feita pelo navegador (armazenado na variável requisição_do_navegador) e que a mesma se encontra como parâmetro de uma função if(), ou seja, caso a função definindo_a_requisição() retorne um valor verdadeiro, o conteúdo da função if() será executado.

if(definindo_a_requisicao(&requisicao_do_navegador))
{
      ****** Conteúdo da função if() ******
}

Veja como é a função definindo_a_requisição():

bool definindo_a_requisicao(String *requisicao) {
String parametro;
bool requisicao_desejada = false;

  parametrofinal = pegar_parametro_da_requisicao(requisicao);

  if (parametrofinal == "/") {
     requisicao_desejada = true;
  }

  if (parametrofinal.substring(0,2) == "/?") {
     requisicao_desejada = true;
  }  

  return requisicao_desejada;
}

Primeiramente, como já era previsto, esta função retorna um valor booleano, ou seja, verdadeiro ou falso. O que esta função faz é basicamente chamar outra função, denominada pegar_parametro_da_requisicao(), que por sua vez, será responsável por pegar a requisição feita pelo navegador, manipulá-la e gerar um resultado a partir da mesma, de modo que, este resultado ficará armazenado na variável parametrofinal. Vamos observar o comportamento da função pegar_parametro_da_requisicao() para depois analisarmos o que ocorre com a variável citada anteriormente.

String pegar_parametro_da_requisicao(String *requisicao) {
int pos_inicial, pos_final;
String parametro;

  
  pos_inicial = (*requisicao).indexOf("GET") + 3;
  pos_final = (*requisicao).indexOf("HTTP/") - 1;
  parametro = (*requisicao).substring(pos_inicial,pos_final);
  parametro.trim();
 
  return parametro;
}

- Exemplificando com a primeira requisição feita pelo navegador

Por hora, vamos apenas analisar as requisições que o navegador pode fazer, sem nos aprofundarmos muito, para então ver como isso reflete no código. Primeiramente, imagine que você gravou o programa que disponibilizamos aqui, no seu Arduino UNO e posteriormente foi no seu navegador e digitou o endereço IP predefinido no código (no nosso caso 192.168.25.16).

Ao realizar este procedimento, o navegador enviará a seguinte requisição para o Servidor Web:

Veja o que irá acontecer com esta informação:

  1. O programa irá receber todo conteúdo da requisição e armazenar o mesmo na variável requisicao_do_navegador. 
  2. A função definindo_a_requisicao() será executada e a requisição armazenada na variável requisicao_do_navegador será o parâmetro desta função.
  3. Dentro da função definindo_a_requisicao() haverá  a execução de uma outra função chamada pegar_parametro_da_requisicao(), que por sua vez, também terá como parâmetro a requisição armazenada na variável requisicao_do_navegador.
  4. A função  pegar_parametro_da_requisicao() é responsável por retirar e armazenar (na variável parametro) o pedaço da primeira linha da requisição, que está entre as palavras GET e HTTPneste exemplo, será " / ". Entretanto, utilizando a função trim(), removemos os espaços antes e depois dos caracteres de fato, portanto, o conteúdo guardado na variável parametro será somente "/".
  5. O conteúdo da variável parametro da função pegar_parametro_da_requisicao() será levado para a variável parametrofinal da função definindo_a_requisicao(), de modo que, quando esta for testada na primeira função if() dentro desta (a que compara a variável parametrofinal com o caractere "/"), haverá uma resposta positiva, portanto, esta resposta, true, será utilizada na função if() cujo argumento é a função definindo_a_requisicao() e o servidor poderá entregar uma página como resposta à requisição feita.

- Exemplificando com as outras requisições feitas pelo navegador

Como veremos posteriormente, quando clicamos em um checkbox para acionar umas das nossa saídas digitais, o navegador irá fazer a seguinte requisição (suponha que o clique aconteceu no checkbox referente ao pino 2):

Neste caso, a variável parametrofinal da função definindo_a_requisicao() será preenchida com "/?P2=1". Repare que no primeiro if() existente nessa função terá como resultado, falso, já que o conteúdo da variável parametrofinal é diferente de "/", no entanto, no segundo if(), temos a função substring(), que por sua vez, irá pegar somente os dois primeiros caracteres da string "/?p2=1", ou seja, "/?" e irá comparar com "/?", gerando portanto, true, que será utilizado na função if() cujo parâmetro é a função definindo_a_requisicao(), permitindo assim, que o nosso Servidor Web responda à requisição com uma página.

O próximo tipo de requisição ocorre quando desmarcamos um checkbox, observe:

Nesta requisição ocorre algo semelhante ao que aconteceu anteriormente, de modo que, a variável parametrofinal da função definindo_a_requisicao() é justamente a string "/?", validando portanto, o segundo if() desta função e também o if() cujo parâmetro é a função definindo_a_requisicao(). Portanto, perceba que neste tipo de requisição, o Servidor Web tem permissão de responder à requisição com uma página.

- Exemplo de hipótese em que o servidor não deverá responder

Como vimos anteriormente, existem 3 requisições que o Servidor Web deverá responder através da criação de uma pagina, estas são: Primeiro acesso ao endereço IP do Servidor Web, quando um checkbox é marcado e quando um checkbox é desmarcado.

À título de curiosidade, existe uma requisição, que é comumente feita pelo google chrome (navegador que estou utilizando) a um servidor, relacionada ao ícone que deve aparecer na aba do navegador ao conectar-se com o servidor em questão. Esta requisição é da seguinte forma:

Note que quando este tipo de requisição for tratado, o conteúdo da variável parametrofinal será a string "/favicon.ico", que por sua vez, não se enquadra nas condições necessárias para que o programa responda através de uma pagina criada, portanto, a condição da função if() cujo parâmetro é a função definindo_a_requisicao(), não será satisfeita. Sendo assim, o que irá ocorrer é a execução do complemento else desta função if(), o qual, simplesmente envia uma mensagem de cabeçalho sem alterar o conteúdo da página enviada anteriormente.

if(definindo_a_requisicao(&requisicao_do_navegador))
{
      ****** Conteúdo da função if() ******
}
else 
{ 
      client.println("HTTP/1.1 200 OK"); 
}

- Construção da página

Após a permissão para o Servidor Web responder com uma página, utilizamos a variável parametro_da_requisicao para conter um dos 3 tipos parâmetros permitidos anteriormente ("/", "/?","/?P2=1"). Observe que, neste momento, estamos fazendo o uso apenas das strings entre os elementos GET e HTTP, sem os espaços antes e depois.

parametro_da_requisicao = pegar_parametro_da_requisicao(&requisicao_do_navegador);

Posteriormente, enviamos o cabeçalho padrão de uma pagina da Web em HTML.

client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();

Em seguida, começamos a construir, de fato, a página. Neste momento, utilizamos apenas os conceitos já apresentados nos tutoriais anteriores.

client.println("<!DOCTYPE html>");
client.println("<html>");
client.println("<head>");
client.println("<title>Servidor Web VDS</title>");
client.println("</head>");
client.println("<body>");
client.println("<h1><font color=#4279c7>Servidor Web do Vida de Sil&iacute;cio</font></h1>");
client.println("<hr/>");                         
client.println("<h1>Sa&iacute;das digitais</h1>");

Com esta porção de código, nossa página estará assim:

Servidor web com ethernet shield W5100
Adição de títulos na página

- Criação de formulários

O próximo passo que iremos fazer é criar um formulário através do par <form></form>.

Os formulários são seções de um documento que contém controles interativos, que por sua vez, permitem ao usuário submeter informações a um determinado Servidor Web.

Dentro da tag de abertura do formulário devemos declarar qual método que será utilizado para submeter o mesmo, de modo que, o método que será utilizado por nós será o método GET. Sendo assim, declaramos nosso formulário da seguinte maneira:

client.println("<form method=\"get\">");

      ***** Conteúdo do formulário *****

client.println("</form>");

Note que, no código acima, temos uma string sendo passada como parâmetro para a função println(), portanto, entre aspas duplas, no entanto, a palavra get também deve vir entre aspas duplas , por isso, utilizamos o conjunto \" para simbolizar aspas duplas dentro da string.

- Recebendo dados do formulário

Em seguida, chamamos uma função denominada saida(), que por sua vez, será responsável por criar e controlar o checkbox referente à saída digital do pino 2.

saida(client);

O que a função saida() faz é basicamente pegar o conteúdo da variável parametro_da_requisicao e através da função indexOf(), ver se nele existe a porção de texto "P2=1".

A função indexOf() retorna um número inteiro referente à posição do primeiro caractere do conjunto de caracteres buscado em uma determinada string, portanto, caso o primeiro caractere do conjunto citado esteja no começo da string, a função retornará o número 0, logo, se compararmos o retorno desta função com -1 , estaremos apenas verificando se existe o tal conjunto de caracteres na string (isso é o que importa para nós).

- Acionando as saídas

Caso exista o conjunto de caracteres "P2=1", o led presente na saída digital 2 é acionado e o servidor incluirá na programação da página, a linha referente à criação de um objeto de entrada de dados, do tipo checkbox. O que você deve entender neste momento é o seguinte:

  1. Na declaração do checkbox, existe dois parâmetros, name e value.
  2. Quando o checkbox é marcado, o navegador irá associar estes dois parâmetros e enviar esta associação na requisição, por exemplo, quando o checkbox referente ao pino digital 2 for marcado, o navegador associará o name P2 ao value 1 e irá anexar o conjunto sob a forma /?P2=1 na requisição, conforme vimos anteriormente.
  3. Esta requisição chega ao servidor e ele analisa, se existe algum elemento que comece, por exemplo, com /?.
  4. Na presença do elemento citado anteriormente, o servidor é autorizado a responder com uma página da web, porém ele deve identificar por inteiro como é o elemento que começa com /?, de modo que, se este for /?P2=1, o servidor irá perceber que o checkbox referente ao pino de saída digital 2 que foi marcado.
  5. Quando o servidor constata que o checkbox citado que foi marcado, o led é acionado e permanecerá assim até que o checkbox em questão seja desmarcado.
void saida(EthernetClient cl)
{
        
        if (parametro_da_requisicao.indexOf("P2=1") > -1) 
        { 
           digitalWrite(2, HIGH);
           cl.println("<input type=\"checkbox\" name=\"P2\" value=\"1\" onclick=\"submit();\" checked > Pino digital 2");
        } 
        else 
        {
           digitalWrite(2, LOW);
           cl.println("<input type=\"checkbox\" name=\"P2\" value=\"1\" onclick=\"submit();\" > Pino digital 2");
        }
        
}

O mesmo procedimento é realizado para o outro pino de saída digital utilizado, no entanto, este é identificado nas requisições por /?P7 = 1.

Além disso, vamos supor que você marque o checkbox referente ao pino 2, de modo que, a requisição do navegador para o servidor traga /?P2 = 1. Em um determinado momento, você também marcou o checkbox referente ao pino 7, logo, é válido pensar que, na nova requisição haverá somente o conjunto /?P7 = 1no entanto, como o checkbox referente ao pino 2 ainda está marcado, o elemento que virá na requisição será /?P2=1&P7=1

Servidor Web com Ethernet Shield W5100
Resultado final

Considerações finais

Neste tutorial, demonstramos como você pode fazer para controlar as saídas digitais do seu Arduino UNO através de um  navegador. Para isto, utilizamos um Arduino UNO em conjunto com um Ethernet Shield W5100. Esta foi a terceira parte de uma série de artigos sobre a criação de Servidores Web, portanto, esperamos que continue nos acompanhando e sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.


Shield Ethernet W5100 - Monitorando sensores com um Servidor Web

Shield Ethernet W5100 - Monitorando Sensores com um Servidor Web

Se você gostou do nosso tutorial inicial sobre a criação de Servidores Web utilizando o Arduino UNO juntamente com o Shield Ethernet W5100, prepare-se, pois, neste tutorial vamos dar sequência ao conteúdo citado, apresentando novos conceitos para que você possa incrementar a sua aplicação. Neste tutorial você aprenderá como a monitorar as informações de seu Arduino, como por exemplo, temperatura, através de um navegador com o auxilio de um Servidor Web implementado com o Shield Ethernet W5100

É importante, para o pleno entendimento desse tutorial, que o leitor tenha lido o tutorial anterior: Shield Ethernet W5100 - Criando um Servidor Web com Arduino

[toc]


Mãos à obra - Monitorando sensores com um Servidor Web

Nesta seção iremos demonstrar todos os passos que você deve seguir para aprender a monitorar sensores com um Servidor Web. De maneira mais específica, vamos desenvolver um projeto em que o usuário consiga monitorar valores de temperatura provenientes de um sensor LM35 (não esqueça de conferir nosso tutorial sobre o sensor de temperatura LM35 clicando aqui) e também o estado de um botão, ou seja, se o mesmo está pressionado ou não.

Componentes necessários

Para reproduzir este projeto, você irá precisar dos seguintes componentes:

Montando o projeto

Na figura abaixo você pode conferir o hardware pronto para ser utilizado.

Projeto Shield Ethernet W5100 - Monitorando sensores com um Servidor Web
Projeto com Shield Ethernet W5100, Arduino Uno e LM35

Gostaríamos de sugerir que você tenha bastante cuidado no momento em que for encaixar o Shield Ethernet W5100 no Arduino UNO, pois, além da possibilidade de entortar os pinos do shield, você também pode se machucar.

Lembre-se que o shield em questão possui uma série de pinos em sua parte inferior, tanto nas laterais como em sua parte dianteira, portanto, antes de pressionar o mesmo sobre o Arduino UNO, certifique-se de que os pinos estejam levemente posicionados em suas respectivas entradas para que então você possa ir realizando o encaixe lentamente.

Realizando as conexões

Para reproduzir este projeto, garanta que o seu Shield Ethernet W5100 esteja ligado corretamente a uma das portas LAN presentes no seu modem ou roteador.

Programando

Este programa foi elaborado a partir do código-exemplo da biblioteca Ethernet.h denominado WebServer.

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 25, 16); 
EthernetServer server(80);     

void setup() 
{
    pinMode(5,INPUT);
    Ethernet.begin(mac, ip);  
    server.begin();           
} 


void loop() {

    EthernetClient client = server.available();  

    if (client) 
    {    
        boolean currentLineIsBlank = true;
        while (client.connected()) 
        {
            if (client.available()) 
            {   
                char c = client.read(); 
                
                if (c == '\n' && currentLineIsBlank) {
                  
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println("Connection: close");
                    client.println("Refresh: 2");
                    client.println();
                    
                    client.println("<!DOCTYPE html>");
                    client.println("<html>");
                    client.println("<head>");
                    client.println("<title>Servidor Web VDS</title>");
                    client.println("</head>");
                    client.println("<body>");
                    client.println("<h1><font color=#4279c7>Servidor Web do Vida de Sil&iacute;cio</font></h1>");
                    client.println("<hr/>");
                    client.println("<h1>Temperatura</h1>");
                    porta_analogica(client);   
                    client.println("<br/>");
                    client.println("<h1>Entrada digital</h1>");
                    porta_digital(client); 
                    client.println("</body>");
                    client.println("</html>");
                    break;
                }
                
                if (c == '\n') 
                {    
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') 
                {
                    currentLineIsBlank = false;
                }
            } 
        } 
        
        delay(1);      
        client.stop(); 
        
    } 
} 

void porta_analogica(EthernetClient client_aux)
{
  client_aux.print("LM35:");
  int valor = analogRead(A0);
  float temperatura = (((valor*5)/1023)-0.5)*100;
  if(temperatura >=50)
  {
      client_aux.println("<font color=#FF0000>");
      client_aux.println(temperatura);
      client_aux.println("graus");
      client_aux.println("</font>");
  }
  else
  {
      client_aux.println("<font color=#000000>");
      client_aux.println(temperatura);
      client_aux.println("graus");
      client_aux.println("</font>");
  }
}


void porta_digital(EthernetClient client_aux)
{
  client_aux.print("Pino digital 5:");
  bool valor = digitalRead(5);
  if(valor == HIGH)
  {
      client_aux.println("<font color=#FF0000> Ligado</font>");
  }
  else
  {
      client_aux.println("<font color=#000000> Desligado</font>");
  }
}

Colocando para funcionar

Veja como ficou nosso segundo Servidor Web.

Shield Ethernet W5100 - Monitorando sensores com um Servidor Web
Acessando Servidor web do Shield Ethernet W5100 através de um navegador

Entendendo a fundo

Antes de começarmos com a explicação do código, gostaríamos de ressaltar que iremos apresentar os detalhes apenas dos tópicos não contemplados no tutorial anterior, pois, desta maneira, será mais fácil focar nas partes referentes às atualizações feitas sobre o programa já existente, portanto, caso você tenha alguma dúvida sobre alguma parte do programa que não seja explicada neste momento, sugerimos que acesse o nosso material citado anteriormente.

Software

- Definindo os pré-requisitos para o funcionamento do código

Inicialmente, devemos incluir duas bibliotecas no código para que o mesmo pudesse funcionar corretamente. A biblioteca SPI.h, responsável pela comunicação dos módulos do shield com o Arduino UNO utilizando o protocolo SPI e a biblioteca Ethernet.h que atua possibilitando a conexão do conjunto, em um primeiro momento, com uma rede local.

Após a inclusão das bibliotecas citadas, devemos definir um endereço MAC (lembre-se que este pode ser qualquer um, desde que seja único em sua rede local) e um endereço IP (este deve ser um endereço válido  e disponível dentro da sua rede local). Além disso, devemos criar o objeto que será responsável por representar o Servidor Web no código (aqui, chamamos este de server) e relacioná-lo com a porta 80.

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 25, 16); 
EthernetServer server(80);

- Definindo as configurações iniciais

Dentro da função setup(), devemos determinar o modo de operação do pino digital que será utilizado (este terá o papel de uma entrada digital) . Além disso, iniciamos a conexão com a rede local através da função Ethernet.begin() (passando como parâmetro os endereços MAC e IP definidos anteriormente) e também iniciamos o Servidor Web por meio da sentença server.begin() (lembre-se que server é o objeto criado para representar o Servidor Web no código).

void setup() 
{
    pinMode(5,INPUT);
    Ethernet.begin(mac, ip);  
    server.begin();           
}

- Criando a página para responder à requisição do navegador

No artigo anterior foi possível compreender como devemos proceder para elaborar uma página bem simples, contendo apenas elementos escritos e também estáticos, ou seja, que não sofriam nenhum tipo de alteração. Neste momento, iremos incrementar o programa criado anteriormente, portanto, vamos deixar de lado a parte referente ao processo de requisição do navegador (já explicado) e iremos focar apenas na elaboração da página que cumpra o objetivo proposto neste material.

Você se lembra do cabeçalho padrão que enviamos para o navegador antes de enviarmos a página propriamente dita? Para ajudar, vamos colocá-lo aqui.

client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();

Definindo tempo de atualização da página 

A primeira modificação que faremos neste momento será a inclusão de uma linha de código que faça com que a página seja atualizada em intervalos de tempo definidos. Isto é importante para este projeto em virtude de estarmos trabalhando com aquisição de variáveis, portanto, devemos atualizar a página periodicamente para que seja possível visualizarmos sempre os valores atuais das variáveis envolvidas. Sendo assim, utilizamos a seguinte sentença para que a página seja atualizada de 2 em 2 segundos.

client.println("Refresh: 2");

Veja como ficará o nosso cabeçalho padrão

client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println("Refresh: 2");
client.println();

A estrutura da página em HTML

O próximo passo que faremos será construir, de fato, a página que será enviada ao navegador. Com uma breve recapitulação, devemos lembrar que todo conteúdo que compõe a página deve estar dentro da seguinte estrutura:

client.println("<!DOCTYPE HTML>");
client.println("<html>");
           . 
           .
***** Conteúdo da página *****
           .
           .
client.println("</html>"); 

Como ressaltado anteriormente, dentro desta estrutura temos o conteúdo da página que queremos enviar para o navegador, de modo que, nesta, devemos ter pelo menos dois blocos, um responsável pelas informações gerais do documento, limitado pelo uso do par <head></head> e o outro, por sua vez, deve conter o corpo da página e está entre as tags <body> e </body>.

client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<head>");
           .
           .
   ***** Bloco 1 *****
           .
           .
client.println("</head>");
client.println("<body>");
           .
           .
   ***** Bloco 2 *****
           .
           .
client.println("</body>");
client.println("</html>");

Definido o título para a página

Neste momento, vamos utilizar apenas uma tag dentro do bloco 1, denominada <title>, cuja função consistirá em definir um título para a página (este título aparecerá na aba do navegador). Para executarmos a ação proposta, devemos colocar o título desejado entre o par <title></title>.

client.println("<!DOCTYPE HTML>");
client.println("<html>");

client.println("<head>");
client.println("<title>Servidor Web VDS</title>"); 
client.println("</head>");

client.println("<body>");
           .
           .
   ***** Bloco 2 *****
           .
           .
client.println("</body>");
client.println("</html>");

Veja como ficou o título da nossa página:

servidor Shield Ethernet W5100 - Monitorando sensores com um Servidor Web
Título da página.

Escrevendo o corpo da página web

Quanto ao corpo da página (entre o par <body></body>), a primeira coisa que faremos será colocar um título visível na própria página. Para realizar este procedimento, utilizaremos a tag <h1>, que por sua vez, consiste em uma tag para apresentar um determinado texto em um modelo predefinido. Além disso, utilizaremos também a tag <font>, através da qual, poderemos fazer alterações no título produzido.

client.println("<h1><font color=#4279c7>Servidor Web do Vida de Sil&iacute;cio</font></h1>");

Alguns pontos no trecho de código acima devem ser ressaltados:

  1. Tudo que estiver escrito entre o par <h1></h1> estará pré formatado no estilo deste cabeçalho.
  2. A tag <font> é responsável por modificar algum atributo relativo à formatação de uma determinada porção de texto. Para isto, devemos colocar o nome do atributo que queremos modificar, após a palavra font (apenas na tag de abertura), sendo assim, quando escrevemos <font color=#4279c7>, estamos indicando que a porção de texto entre o par <font color=#4279c7></font> deverá está colorida em um certo tom de azul (dado pelo código RGB em hexadecimal #4279c7).
  3. Repare que a palavra Silício foi escrita no código como Sil&iacute;cioEsta forma de escrita é necessária sempre que temos a utilização de algum tipo de acento, pois, nem todos os dispositivos estão configurados para apresentar caracteres acentuados da mesma forma. Sendo assim, utilizamos o comando &iacute; para colocar o acento agudo na letra da palavra Silício.

Veja o resultado deste procedimento na figura abaixo:

acessando Servidor Web Shield Ethernet W5100

Posteriormente, vamos inserir uma barra horizontal para separar o título criado no passo anterior dos textos que ainda serão criados, através do comando <hr/>.

client.println("<hr/>");

Após a inserção da barra citada, nossa página ficará da seguinte maneira:

Imprimindo a tempertatura

Em seguida, escrevemos outro texto utilizando o modelo de cabeçalho h1 referente ao valor que será obtido pelo sensor de temperatura LM35.

client.println("<h1>Temperatura</h1>");

Com este passo, a página será apresentada assim:

O próximo passo consiste em apresentar o valor de temperatura obtido através da conversão do sinal proveniente do sensor de temperatura utilizado. Obviamente, existem várias formas de fazer isso, no entanto, nós criamos uma função própria para isso, chamada porta_analogica() e passamos a variável client como parâmetro da mesma.

porta_analogica(client);

A função porta_analogica() será responsável por fazer a aquisição do valor de tensão na porta analógica A0 proveniente do sensor de temperatura LM35. Repare que nesta função utilizamos um conjunto if()/else para testar se o valor de temperatura é superior a um determinado valor, de modo que, caso seja, apresentaremos este valor na cor vermelha e caso não seja, na cor preta.

void porta_analogica(EthernetClient client_aux)
{
  client_aux.print("LM35:");
  int valor = analogRead(A0);
  float temperatura = (((valor*5)/1023)-0.5)*100;
  if(temperatura >=50)
  {
      client_aux.println("<font color=#FF0000>");
      client_aux.println(temperatura);
      client_aux.println("graus");
      client_aux.println("</font>");
  }
  else
  {
      client_aux.println("<font color=#000000>");
      client_aux.println(temperatura);
      client_aux.println("graus");
      client_aux.println("</font>");
  }
}

A apresentação do valor de temperatura ficará conforme a figura abaixo:

imprimindo valores de temperatura do servidor web no navegador

Imprimindo o estado da entrada digital - Botão

Após chamar a função porta_analogica(), utilizamos o comando <Br/> para fazer com que a próxima sentença utilizada na construção da página ocorra na próxima linha da tela.

client.println("<br/>");

Neste momento escrevemos um outro texto utilizando o modelo de cabeçalho h1. Este irá definir o título da seção em que o estado do botão será apresentado.

 client.println("<h1>Entrada digital</h1>");

Confira em que estágio nossa página está:

Por fim, chamamos a função porta_digital() cuja função consiste realizar os procedimentos necessários para apresentar o estado da nossa variável digital. Repare que, assim como na função porta_analogica(), também passamos a variável cliente como parâmetro.

porta_digital(client);

No bloco de código abaixo demonstramos o funcionamento da função porta_digital(), que por sua vez, apresentará a palavra Ligado, na cor vermelha, caso o botão esteja pressionado e a palavra Desligado, na cor preta, caso o botão esteja solto

void porta_digital(EthernetClient client_aux)
{
  client_aux.print("Pino digital 5:");
  bool valor = digitalRead(5);
  if(valor == HIGH)
  {
      client_aux.println("<font color=#FF0000> Ligado</font>");
  }
  else
  {
      client_aux.println("<font color=#000000> Desligado</font>");
  }
}

Veja o nosso resultado final:

Os procedimentos citados anteriormente servem para elaborar a página que será exibida no navegador em resposta a requisição feita pelo mesmo, de modo que, caso você queira entender partes do código externas ao que foi apresentado, verifique nosso primeiro tutorial.


Considerações finais

Neste tutorial, demonstramos como você monitorar as variáveis envolvidas no seu projeto, em uma página criada para ser exibida no seu navegador, utilizando um Arduino UNO e um Shield Ethernet W5100. Esta foi a segunda parte de uma série de artigos sobre a criação de Servidores Web, portanto, esperamos que continue nos acompanhando e sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.


Protocolo I2C - Comunicação entre Arduinos

Protocolo I2C - Comunicação entre Arduinos

É indiscutível que os protocolos de comunicação são alguns dos elementos mais importantes de um sistema dotado de dispositivos que possuem a necessidade de interagir entre si para que um determinado resultado possa ser obtido, pois, estes possibilitam a troca de informações entre os mesmos através do estabelecimento de regras, padrões e modelos que visam permitir a conexão entre os dispositivos citados. Neste tutorial, você aprenderá sobre um protocolo de comunicação suportado pelas placas Arduino e também por diversos módulos para Arduino, o protocolo de comunicação I2C. Além de apresentá-lo, iremos utilizar o mesmo para estabelecer uma comunicação entre 2 placas Arduino.

[toc]

O protocolo de comunicação I2C

O modo de funcionamento do protocolo I2C é baseado na interação entre elementos seguindo a hierarquia mestre/escravo, ou seja, quando temos vários dispositivos se comunicando segundo esta premissa, pelo menos um destes deve atuar como mestre e os demais serão escravos. A função do mestre consiste em realizar a coordenação de toda a comunicação, pois, ele tem a capacidade de enviar e requisitar informações aos escravos existentes na estrutura de comunicação, os quais, devem responder às requisições citadas.

A estrutura na qual o protocolo I2C atua é uma estrutura de barramento, que por sua vez, consiste em um arranjo em que todos os elementos encontram-se conectados a um ramal principal.

 

 

Na figura acima pode-se ver um modelo simplificado da estrutura de barramento citada anteriormente. Note que, neste arranjo, o barramento de comunicação I2C pode ser dividido em dois barramentos. Um deles é denominado SDA (Serial Data), o qual, é responsável pela troca de dados entre os dispositivos do arranjo e o outro barramento, denominado SCL (Serial Clock), possui a função de sincronizar os dispositivos e garantir a confiabilidade do sistema.

Na prática, como o protocolo I2C funciona?

Segundo a literatura, podemos ter a presença de até 127 dispositivos escravos anexados no barramento citado, no entanto, algumas fontes ressaltam que este valor, embora fornecido pela literatura oficial, é apenas teórico, alegando que, na prática, é possível utilizar apenas 112 dispositivos em um barramento I2C. Isso se deve o fato de que dos 128 endereços possíveis, 16 estão reservados, os quais vão de 0x00 a 0x07 e 0x78 a 0x7F, em outras palavras, os endereços possíveis estão localizados no intervalo de 0x08 a 0x77.

Exemplo prático de barramento I2C
Exemplo prático de barramento I2C

A vantagem da utilização deste tipo de estrutura é nítida quando levamos em conta o número de pinos utilizados pelos elementos e por consequência, a quantidade de fios, além de promover uma organização maior do conjunto quando temos muitos dispositivos interagindo entre si.

Endereço

Para que o mestre converse com cada escravo ele precisa saber qual o endereço do escravo a ser contactado. É importante frisar que o endereço de cada integrante de um barramento I2C deve ser único.

Geralmente, cada módulo possui um endereço padrão que em alguns casos pode ser alterado por algumas opções.

É muito comum que haja mais de um módulo, mesmo com funcionalidades totalmente diferentes, com o mesmo endereço padrão. Quando for assim, pesquise se é possível e como mudar o endereço de pelo menos um deles.

No tutorial Display LCD 20×4 e LCD 16×2 com Adaptador I2C, mostramos que existem módulo I2C para LCD que permitem que o endereço seja alterado dentro de 8 opções. Clique aqui para entender mais sobre o endereço do módulo I2C para LCD.

Comunicação entre Arduinos

Você pode conectar ao barramento diversos Arduinos. Tal como os módulos que suportam I2C, o Arduino também precisa ter um endereço cujo o qual você definirá via software.

Nesse tutorial aprenderemos como criar uma comunicação entre dois Arduinos usando I2C. Tal aplicação pode gerá infinitas opções de projetos práticos, podendo integrar varias placas Arduino e módulos compatíveis com o protocolo I2C para montar um sistema de automação.


Mãos à obra - Utilizando um Arduino Micro para fazer um Arduino UNO acionar um led 

Nesta seção iremos demonstrar todos os passos que você deve seguir para aprender a utilizar o protocolo I2C.

Componentes necessários

Para reproduzir este projeto, você irá precisar dos seguintes componentes:

Montando o projeto

 

Hardware utilizado com 2 placas Arduino comunicando através do protocolo I2C, um mestre e outro escravo
Hardware utilizado.

 

Na montagem deste hardware devemos garantir que os pinos SDA, SCL e GND de ambos os dispositivos estejam respectivamente conectados entre si. No Arduino UNO, os pinos SDA e SCL são os pinos analógicos A4 e A5 respectivamente, ao passo que, no Arduino Micro, estes são os pinos D2 e D3.

Programando

Conforme apresentado no tópico anterior, o projeto a ser desenvolvido neste tutorial utiliza duas placas Arduino, portanto, teremos a presença de dois códigos para serem gravados em ambas as placas. Primeiramente, apresentamos o código a ser gravado no Arduino Micro, que por sua vez, será o mestre do barramento

#include <Wire.h>

bool estado_LED;

void setup() {
  Wire.begin();
}

void loop() {
  Wire.beginTransmission(0x08); 
  wire.write(estado_LED);            
  Wire.endTransmission();
  
  estado_LED = !estadoLED;   

  delay(1000);
}

Em seguida, apresentamos o código a ser gravado no Arduino UNO, que em nosso projeto, se comportará como escravo.

#include <Wire.h>

void setup() {
  Wire.begin(0x08);                
  Wire.onReceive(receiveEvent);     
  pinMode(4,OUTPUT);     
}

void loop() {
  delay(100);
}


void receiveEvent(int leitura) {
  
  bool estado = Wire.read();    // receive byte as an integer

  if (estado == 1){
    digitalWrite(4,HIGH);
  }
  else{
    digitalWrite(4,LOW);
  }
}

 


Entendendo a fundo

Software - Arduino Micro (Mestre)

Neste momento, iremos demonstrar o passo a passo como funciona o código que deve ser gravado no Arduino Micro, que por sua vez, atuará como mestre no barramento

- Incluindo a biblioteca que será utilizada

Primeiramente, devemos incluir a biblioteca que será utilizada no código, portanto, através da diretiva #include, dizemos ao Arduino Micro que iremos utilizar a biblioteca Wire.h, responsável por conter as funções necessárias para gerenciar a comunicação entre os dispositivos através do protocolo I2C.

#include <Wire.h>

- Declarando a variável do projeto

Em seguida, declaramos uma variável booleana, isto é, que pode armazenar apenas dois valores (0 ou 1) , com o intuito de que esta seja responsável por conter a informação que será enviada ao Arduino UNO através do protocolo I2C para que o LED seja acionado.

bool estado_LED;

- Inicializando a comunicação através do protocolo I2C

Dentro da função Setup() utilizamos a sentença Wire.begin() para que a comunicação através do protocolo I2C seja iniciada. Como este dispositivo será o elemento mestre, não é necessário adicionar parâmetro algum à função citada (veremos adiante como proceder quando o dispositivo se comportar como escravo).

void setup() {
  Wire.begin();
}

- Iniciando a transmissão de dados

Será dentro da função loop() que iremos proceder com a transmissão de dados entre as placas Arduino. O primeiro passo que deve ser realizado para que uma informação possa ser enviada de um dispositivo mestre para um dispositivo escravo é a inicialização da transmissão com o elemento-alvo. Para isto, utilizamos a sentença Wire.beginTransmission(), tendo como parâmetro, o endereço do escravo com o qual queremos que o mestre se comunique (na configuração do dispositivo escravo veremos como pode-se definir o endereço do mesmo).

Wire.beginTransmission(0x08);

- Enviando os dados desejados

Para enviar os dados para o escravo definido pelo endereço determinado na utilização da função anterior devemos utilizar a sentença Wire.write(). O parâmetro desta função é justamente a informação que nós queremos que o mestre envie para o escravo, neste caso, o valor armazenado na variável estado_LED.

wire.write(estado_LED);

- Finalizando a transmissão

Após o envio da informação, finalizamos a transmissão utlilizando a sentença Wire.endTransmission().

Wire.endTransmission();

- Atualização da variável estado_LED

Por fim, atualizamos a variável estado_LED fazendo com que o seu valor seja o inverso do que era anteriormente, ou seja, caso seu valor seja 0, na próxima iteração (lembrando que o conteúdo da função loop() é executado repetidamente) ele deverá ser 1. Além disso, utilizamos a função delay() para que este envio de informações aconteça a cada 1 segundo.

estado_LED = !estadoLED;
delay(1000);

Veja como ficou nossa função loop():

void loop() {
  Wire.beginTransmission(0x07); 
  wire.write(estado_LED);            
  Wire.endTransmission();
  
  estado_LED = !estadoLED;   

  delay(1000);
}

Software - Arduino UNO (Escravo)

Agora iremos demonstrar o passo a passo como funciona o código que deve ser gravado no Arduino UNO, que por sua vez, atuará como escravo no barramento

- Incluindo a biblioteca que será utilizada

Assim como no caso anterior, devemos incluir a biblioteca que será utilizada no código, portanto, através da diretiva #include, dizemos ao Arduino Micro que iremos utilizar a biblioteca Wire.h, responsável por conter as funções necessárias para gerenciar a comunicação entre os dispositivos através do protocolo I2C.

#include <Wire.h>

- Definindo as configurações iniciais

Dentro da função setup() utilizamos a sentença Wire.begin() para inicializar a comunicação do Arduino UNO através do protocolo I2C, no entanto, desta vez, utilizamos o valor 0x07 como parâmetro, em outras palavras, quando fazemos isto, estamos dizendo que a placa Arduino em questão estará presente no barramento como escravo e que o endereço do mesmo será 0x07.

 Wire.begin(0x08);

Além disso, através da sentença Wire.onRecieve() determinamos qual função deverá ser executada quando chegar alguma informação proveniente do elemento-mestre do barramento. Neste caso, quando ocorrer a situação prevista, a função chamada será a receiveEvent() (note que esta função pode ter qualquer nome, utilizamos este somente pelo fato de que na literatura oficial esta é denominada desta forma na maioria das vezes).

Wire.onReceive(receiveEvent);

Por último, determinando que o pino 4 do Arduino UNO atue como uma saída digital através da função pinMode().

 pinMode(4,OUTPUT);

Veja como ficou nossa função setup()

void setup() {
  Wire.begin(0x07);                
  Wire.onReceive(receiveEvent);   
  pinMode(4,OUTPUT);     
}

- Lendo os dados recebidos

Em um primeiro momento, devemos ressaltar que não foi necessário utilizar nenhum procedimento dentro da função loop(), pois, o tratamento dos dados recebido será demonstrado posteriormente. Sendo assim, utilizamos apenas a função delay() em virtude de este procedimento ser aconselhado nos exemplos oficiais do Arduino

void loop() {
  delay(100);
}

No final do código apresentamos a função receiveEvent(), que por sua vez, será chamada sempre que houver alguma informação proveniente do mestre, chegando. Nesta função utilizamos a sentença Wire.read() para obter o valor relativo ao estado do led (enviado pelo mestre) e armazená-lo na variável estado, de modo que, conforme o conteúdo da mesma, optamos através de uma função if() se devemos acender ou apagar o led.

void receiveEvent(int leitura) 
{  
  bool estado = Wire.read();   

  if ( estado == 1){
    digitalWrite(4,HIGH);
  }
  else{
    digitalWrite(4,LOW);
  }
}

Considerações finais

Neste tutorial, demonstramos como você pode utilizar o protocolo de comunicação I2C para fazer com que duas placas Arduino troquem informações entre si. Este foi apenas um conteúdo para que você tenha uma noção de como das os primeiros passos com o protocolo citado, portanto, esperamos que continue nos acompanhando e sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.


Módulo RFID RC522 Mifare com Arduino

Módulo RFID RC522 Mifare com Arduino

Neste tutorial entenderemos um como funciona um sistema RFID e aprenderemos como utilizar o módulo RFID RC522 Mifare através do Arduino.

[toc]

Entendendo o RFID

A tecnologia de RFID (Radio Frequency IDentification – identificação por radiofrequência) é um método de identificação através de sinais de rádio. Existem diversos métodos de identificação, mas o mais comum é armazenar um número de série que identifique uma pessoa ou um objeto, ou outra informação em um microchip.  

Tal tecnologia permite a captura automática de dados para identificação de objetos com dispositivos eletrônicos conhecidos como etiquetas eletrônicas, RF tags, cartões RF ou transponders, que emitem sinais de radiofrequência para leitores que captam estas informações. Tal tecnologia existe desde a década de 40 e veio para complementar a tecnologia de código de barras, bastante difundida no mundo.

O RFID pode ser utilizado em diferentes aplicações, inclusive na parte de segurança, onde podemos citar como exemplos de sua utilização o controle de acesso em catracas, alarmes contra furtos em lojas e até mesmo para o desbloqueio de computadores. Outra função muito comum que é atribuída a essa tecnologia são os cartões de utilização de transporte público.

Aplicação comum do RFID no controle de acesso
Aplicação comum do RFID no controle de acesso

Como funciona os sistemas RFID

Um sistema de RFID é composto, basicamente, de:

  • Um transceptor com decodificador e uma antena;
  • Um transponder (chamado também de Tag) que é eletronicamente programado com informações.

O transceptor emite, através de uma antena, sinais de rádio para ativar o Tag, que por sua vez, reponde uma mensagem ao receptor com a informações armazenadas em seu chip.

Uma tag é composta, basicamente, por um chip, que armazena informações, e uma antena.

Transponder RFID
Transponder RFID

Os transponders RFID são divididos em dois tipos : passivos e ativos.

Os transponders passivos utilizam a energia da onda de rádio frequência emitida pelo leitor para transmitir o seu sinal de resposta. Geralmente vêm com suas informações gravadas permanentemente quando são fabricadas. Contudo, em algumas é possível alterar as informações armazenadas em seu chip.

A grande vantagem dos transponders passivos é a facilidade de usa-lo em diversas aplicações, tais como: etiquetas, passaportes, chaveiros, cartões, etc.

Exemplo de aplicação de uma tag RFID passiva em uma etiqueta
Exemplo de aplicação de uma tag RFID passiva em uma etiqueta

Os transponders ativos contam com uma fonte de energia própria para transmitir seu sinal de resposta, aumentando o alcance. Esse tipo de Tag pode contar com memória RAM, capaz de armazenar até 32 KB de informação.

Exemplo de transponder RFID ativo usado para identificação de um veículo.
Exemplo de transponder RFID ativo usado para identificação de um veículo. Eles são muito usados nesse tipo de aplicação devido ao seu maior alcance.

Outra característica importante dos sistema RFID é a frequência de operação. A frequência interfere na taxa de transferência de dados entre a etiqueta e o leitor e em seu alcance.

As três frequências mais utilizadas para o sistema RFID passivo são: baixa frequência (LF), de 125kHz, alta frequência (HF), 13,56 MHz, e ultra alta frequência (UHF), operando na faixa de 860 a 960MHz.

Quanto maior a frequência, maior será o alcance máximo, mas esse não é o único fator. Também influenciam no alcance do sistema RFID: potencia e sensibilidade do transceptor e o tipo de transponder.

Módulo RFID-RC522 13,56MHz Mifare

Este módulo RFID usa o chip MFRC522 da empresa NXP, que por sua vez, pode ser usado em comunicações a uma frequência de 13,56MHz, permitindo, por exemplo, sem contato, a leitura e escrita em cartões que seguem o padrão Mifare.

Módulo RFID MFRC522 Mifare - Tansceptor

Para usar a tecnologia RFID precisamos de um receptor e de um emissor. Geralmente o módulo leitor RFID RC522 acompanha um kit com uma tag e um cartão RFID o qual usaremos nesse projeto.

Exemplo de cartão e tag RFID MFRC522 Mifare
Exemplo de cartão e tag RFID MFRC522 Mifare - Transponders

Mão à obra - Usando o Módulo Leitor RFID-RC522 13,56MHz Mifare com Arduino

Componentes necessários

Montando o projeto

 

Esquema de montagem do Módulo RFID RC522 Mifare com Arduino
Esquema de montagem do Módulo RFID RC522 Mifare com Arduino

Programando

- Biblioteca

Para desenvolver o projeto proposto com o Módulo RFID RC522 utilizou-se a biblioteca MFRC522.h. Esta biblioteca foi produzida por Miguel Balboa e está disponível neste link.

Você pode expandir o tutorial abaixo para aprender como instalá-la.

Adquirindo e instalando a biblioteca que será utilizada

Para adquirir a biblioteca em questão, basta acessar o link apresentado anteriormente, clicar no botão clone or Download e por fim, no botão Download ZIP, conforme a figura abaixo.

Como baixar a biblioteca RFID
Como baixar a biblioteca RFID

Após a realização do download dos arquivos compactados no formato ZIP, abra a IDE do Arduino, selecione o menu Sketch, o submenu Incluir Bilioteca e por fim, basta clicar na opção Adicionar biblioteca .ZIP (Add ZIP Library) e encontrar o arquivo que acabou de ser baixado.

 

 

Uma outra forma de fazer isso é extrair o conteúdo do arquivo ZIP dentro da pasta Libraries (onde foi instalada a IDE do Arduino).

- Código do projeto

Não ligar o módulo RFID-RC522 em 5V, o mesmo deve ser ligado em 3,3V.

//Vida de Silício
//Felipe Gbur

#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define RST_PIN 9
#define LED_R 2//LED Vermelho
#define LED_G 3 //LED Verde
char st[20];

MFRC522 mfrc522(SS_PIN, RST_PIN);

void setup()
{
  // Inicia a serial
  Serial.begin(9600);
  // Inicia  SPI bus 
  SPI.begin();
  // Inicia MFRC522    
  mfrc522.PCD_Init();
  Serial.println("Aproxime o seu cartao/TAG do leitor");
  Serial.println();
  pinMode(LED_R, 2);
  pinMode(LED_G, 3);
}

void loop()
{
  digitalWrite (LED_G, LOW);
  digitalWrite (LED_R, HIGH);

  // Busca novos cartões 
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  // Seleciona um catão a ser lido
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }
  //Mostra ID na serial
  Serial.print("ID da tag:");
  String conteudo = "";
  byte letra;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
    Serial.print(mfrc522.uid.uidByte[i], HEX);
    conteudo.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    conteudo.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Mensagem : ");
  conteudo.toUpperCase();

  if (conteudo.substring(1) == "D6 35 19 7E") //ID CARTÃO
  {
    Serial.println("Acesso autorizado !");
    Serial.println();
    digitalWrite (LED_G, HIGH);
    digitalWrite (LED_R, LOW);
    delay(5000);//Delay apagar LED Verde
    digitalWrite (LED_G, LOW);
    digitalWrite (LED_R, HIGH);
  }
}

Colocando para funcionar

- Descobrindo o endereço do cartão ou tag

Depois de carregar o código para seu Arduino você deve entrar no monitor serial e verificar a UID de sua tag que esta sendo detectada pelo modulo e esta sendo impressa no monitor serial,  posteriormente você deve substituir a UID que já esta no código para a UID de sua tag. É possível ver na imagem a baixo Duas tag diferentes sendo utilizadas, sendo que uma delas não esta cadastrada.

Descobrindo a ID do cartão.

- Projeto com Cartão cadastrado

Resultado final.


Entendendo a fundo

Software

– Incluindo as bibliotecas a serem utilizadas no projeto

Inicialmente, observe que foi necessário incluir duas bibliotecas no código para que o mesmo pudesse funcionar corretamente. A biblioteca SPI.h é a responsável pela comunicação utilizando o protocolo SPI enquanto a biblioteca MFRC522.h atua sobre a biblioteca SPI.h simplificando o processo de comunicação através do protocolo citado, para que assim, o usuário possa utilizar o Módulo Leitor RFID-RC522 de maneira mais fácil.

#include <SPI.h> 
#include <MFRC522.h>

– Nomeando os pinos de entrada e saída através da diretiva #define

Em seguida, utilizamos a diretiva #define para associar os pinos digitais 10 e 9 para serem usado na comunicação SPI. Também nomeamos o pinos digitais que serão usados para acionar os LED's.

#define SS_PIN 10 
#define RST_PIN 9 
#define LED_R 2   //LED Vermelho 
#define LED_G 3   //LED Verde

Vale ressaltar que isso é apenas um recurso para facilitar a didática da programação, portanto, não obrigatório.

– Declarando o objeto mfrc522

Em seguida, cria-se o objeto chamado  que irá representar o módulo RFID

Lembre-se:mfrc522 é apenas um nome que escolhemos, sendo assim, é importante ressaltar que, o objeto identificado por mfrc522 poderia ser chamado de qualquer outro nome, como por exemplo, moduloRFID.

MFRC522 mfrc522(SS_PIN, RST_PIN);

– Definindo as configurações iniciais

Primeiramente, na função setup(), utiliza-se a função Serial.begin() para inicializar a comunicação serial do Arduino UNO com o computador  (onde será possível ver o resultado do projeto)

Serial.begin(9600);

Em seguida, utiliza-se a função SPI.begin() para inicializar a comunicação.

// Inicia SPI bus 
SPI.begin();

Posteriormente, recorre-se à função mfrc522.PCD_Init() para inicializar o RFID-MFRC522.

// Inicia MFRC522 
mfrc522.PCD_Init();

A função mfrc522.PICC_IsNewCardPresent() inserida dentro de um laço de repetição, faz com que o modulo fique buscando por um novo cartão a ser lido.

// Busca novos cartões 
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }

Suscetivamente a função mfrc522.PICC_ReadCardSerial() tem como objetivo ler a TAG ler o cartão que foi encontrado anteriormente.

// Seleciona um catão a ser lido
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }

Esta parte do código tem como finalidade imprimir no monitor serial a UID da TAG que foi lido.

 //Mostra ID na serial
  Serial.print("ID da tag:");
  String conteudo = "";
  byte letra;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
    Serial.print(mfrc522.uid.uidByte[i], HEX);
    conteudo.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    conteudo.concat(String(mfrc522.uid.uidByte[i], HEX));
  }

Aqui é onde você define a UID do seu cartão/tag if (conteudo.substring(1) == "Sua tag"), onde no código é usada como exemplo a seguinte TAG: 75 25 17 CB.

Nesta parte também é onde esta definida a função do projeto, em nosso caso, quando o tag for lido o LED verde deve se acender para sinalizar que o acesso foi autorizado.

É importante ressaltar que caso queira registrar mais de uma tag você deve copiar o código a partir do if e posteriormente registrar a UID da nova tag.

Serial.print("Mensagem : ");
  conteudo.toUpperCase();

  if (conteudo.substring(1) == "75 25 17 CB") //UID CARTÃO
  {
    Serial.println("Acesso autorizado !");
    Serial.println();
    digitalWrite (LED_G, HIGH);
    digitalWrite (LED_R, LOW);
    delay(5000);//Delay apagar LED Verde
    digitalWrite (LED_G, LOW);
    digitalWrite (LED_R, HIGH);
  }

Desafio

  1. Implemente um projeto que imprima em um Display LCD 16x2, ou no monitor serial caso não tenha o LCD, o nome do portador do Cartão;
  2. Faça um controle de ponto identificando o horário de saída e de entrada de uma pessoa usando o RTC DS3231.

Tutoriais vão de ajudar nesses desafios:

Considerações finais

Hoje aprendemos um pouco sobre a tecnologia RFID, e como utilizamos o módulo RFID-RC522 13,56MHz. Comente o que achou da postagem, e compartilhe conosco  como pretende utilizar desta tecnologia em seu projeto.


Shield Ethernet W5100 - Criando um Servidor Web com Arduino

Shield Ethernet W5100 - Primeiros passos na criação de um Servidor Web com Arduino

Em uma das nossas publicações anteriores ensinamos como você deve proceder para criar um Servidor Web com o NodeMCU. Neste tutorial, iremos utilizar um Shield Ethernet W5100 para criar um Servidor Web que terá como função fornecer uma página web contendo informações enviadas pelo Arduino UNO.

Respostar do servidor web - Página feita através do Arduino Uno em conjunto com o Ethernet Shield W5100
Resultado deste projeto.

[toc]

O que é um Servidor Web?

Ao navegarmos pelo gigante universo de possibilidades da internet, podemos não nos dar conta do que existe por trás disso tudo.

A internet é uma união de redes de computadores em nível mundial conversando entre si através de um conjunto próprio de protocolos de comunicação, como por exemplo, o TCP/IP, que por sua vez, consiste em um protocolo para transmissão de informações orientado à conexão, ou seja, cuja função consiste em permitir que as maquinas se comuniquem e gerenciem o estado atual da transmissão.

- Os Servidores

Um dos protagonistas desse universo são os servidores. A grosso modo, esses servidores são computadores responsáveis por fornecer e receber dados dos diversos clientes, atuando como centralizadores de informação.

servidor cliente
Conexão cliente/servidor

Indo um pouco a fundo, um servidor consiste em um software dentro um computador centralizador. Através de uma rede particular ou da internet,  esse servidor pode receber dados de clientes bem como fornecê-los.

O estabelecimento das relações entre o conjunto Servidor/Cliente é baseado em um sistema de recebimento, processamento e resposta, no qual, o servidor recebe, processa e responde a requisições feitas por um Cliente através de algum protocolo de comunicação.

- O HTTP - Protocolo de Transferência de Hipertexto

Um dos principais exemplos da relação Servidor/Cliente é a relação entre os computadores que atuam como servidores hospedando sites e os navegadores que utilizamos em nossos computadores ou celulares, os clientes. Neste tipo de relação, utiliza-se para estabelecer a comunicação, o procotolo o HTTP (Hypertext Transfer Protocol), o qual, é responsável pelo tratamento dos pedidos e respostas entre cliente e servidor na World Wide Web ou em uma rede localNesse contexto, chamamos os servidores de Servidores Web.

Comunicação requisição http servidor web
Utilização do protocolo HTTP.


- HTML - Linguagem de Marcação de Hipertexto

As informações que o Servidor Web envia para seu navegador a partir de uma requisição HTTP feita pelo mesmo, pode ocorrer em alguns determinados formatos que precisarão ser interpretados. Um desses formatos é o HTML (HyperText Markup Language), que por sua vez, é uma linguagem utilizada na construção de páginas na Web.

Por trás de uma Página web
Linguagem HTML.

O Shield Ethernet W5100

Como sabemos, os shields compatíveis com o Arduino UNO são placas de circuito que podem ser conectadas sobre o mesmo, encaixando-se perfeitamente, com o intuito de expandir suas capacidades em determinada vertente.

Neste tutorial, apresentamos o Shield Ethernet W5100, que por sua vez, consiste em um shield dotado de dois módulos, um módulo Ethernet que irá permitir a conexão do Arduino UNO, em um primeiro momento, com uma rede local e um módulo para cartão SD.

Sendo assim, perceba que é perfeitamente possível utilizar este módulo somente para ler/escrever dados em um cartão de memória ou apenas para conectar o Arduino UNO a uma rede local.

Shield Ethernet W5100 servidor web arduino
Shield Ethernet W5100.

Neste tutorial iremos utilizar apenas o módulo Ethernet do shield em questão, pois, iremos elaborar uma pagina simples para ser apresentada ao usuário através do navegador, no entanto, o módulo de cartão SD é muito útil para conter arquivos necessários para a construção de uma página mais rica em informações, como por exemplo, imagens.


Mãos à obra - Criando um Servidor Web com o Arduino UNO e o Shield Ethernet W5100

Nesta seção iremos demonstrar todos os passos que você deve seguir para aprender a criar um Servidor Web.

Componentes necessários

Para reproduzir este projeto, você irá precisar dos seguintes componentes:

Montando o projeto

Shield Ethernet W5100 no Arduino uno
Hardware utilizado.

Gostaríamos de sugerir que você tenha bastante cuidado no momento em que for encaixar o Shield Ethernet W5100 no Arduino UNO, pois, além da possibilidade de entortar os pinos do shield, você também pode se machucar.

Lembre-se que o shield ethernet W5100 possui uma série de pinos em sua parte inferior, tanto nas laterais como em sua parte dianteira, portanto, antes de pressionar o mesmo sobre o Arduino UNO, certifique-se de que os pinos estejam levemente posicionados em suas respectivas entradas para que então você possa ir realizando o encaixe lentamente.

Realizando as conexões

Para reproduzir este projeto, garanta que o seu Shield Ethernet W5100 esteja ligado corretamente a uma das portas LAN presentes no seu modem ou roteador.

Programando

Este programa foi elaborado a partir do código-exemplo da biblioteca Ethernet.h denominado WebServer.

Antes de utilizar este código, leia a seção Entendendo a fundo para adaptar os trechos necessários para o funcionamento da sua aplicação.

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 25, 16); 
EthernetServer server(80);     

void setup() 
{
    Ethernet.begin(mac, ip);  
    server.begin();           
} 

void loop() 
{
    EthernetClient client = server.available();  

    if (client) 
    { 
      
        boolean currentLineIsBlank = true;
        while (client.connected()) 
        {
            if (client.available())
            {   
                char c = client.read(); 
                
                if (c == '\n' && currentLineIsBlank) 
                {
                  
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println("Connection: close");
                    client.println();
                    client.println("<!DOCTYPE html>");
                    client.println("<html>");
                    client.println("<head>");
                    client.println("<title>Servidor Web VDS</title>");
                    client.println("</head>");
                    client.println("<body>");
                    client.println("<h1>Meu primeiro Servidor Web</h1>");
                    client.println("<p>Esperamos que voce tenha gostado deste tutorial</p>");
                    client.println("</body>");
                    client.println("</html>");
                    break;
                }
                
                if (c == '\n') 
                {
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') 
                {
                    currentLineIsBlank = false;
                }
            } 
        }
        
        delay(1);      
        client.stop(); 
        
    } 
}

Colocando para funcionar

Veja como ficou nosso primeiro Servidor Web.

Respostar do servidor web - Página feita através do Arduino Uno em conjunto com o Shield Ethernet W5100
Página da web criada.

Entendendo a fundo

Software

- Incluindo as bibliotecas a serem utilizadas no projeto

Inicialmente, observe que foi necessário incluir duas bibliotecas no código para que o mesmo pudesse funcionar corretamente. A biblioteca SPI.h é a responsável pela comunicação dos módulos do Shield Ethernet W5100 com o Arduino UNO utilizando o protocolo SPI e a biblioteca Ethernet.h atua possibilitando a conexão do conjunto, em um primeiro momento, com uma rede local.

#include <SPI.h>
#include <Ethernet.h>

- Definindo o endereço MAC do Arduino UNO

O próximo passo consiste em definir o endereço MAC que será atribuído ao Arduino UNO.

Na prática, o endereço MAC pode ser qualquer um, desde que seja único na rede. Como sugestão, copie a sentença abaixo.

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};

- Definindo o endereço IP do Arduino UNO

Além do endereço MAC definido anteriormente, torna-se necessário definir um endereço IP para o nosso Arduino UNO. Isso é imprescindível para que seja possível estabelecer a conexão entre o mesmo e a rede.

Este endereço deve estar disponível na sua rede local para que possa ser utilizado

Existem várias maneiras de encontrar um endereço válido na sua rede local, de modo que, demonstraremos uma forma bastante simples de realizar este procedimento, confira abaixo:

  1. Acesse um computador que esteja conectado na sua rede local
  2. Abra o Prompt de Comando do Windows (supondo que o sistema operacional seja Windows)
  3. Digite ipconfig

Neste momento, um conjunto de informações será disponibilizado, no entanto, o dado que requer sua atenção é justamente o endereço IP da máquina que você está utilizando (ele estará apresentado pelo nome IPV4).

Verificando o ip a ser usado pelo ethernet shield w5100

Primeiramente, repare que o endereço IP destacado possui quatro partes separadas por pontos. Para encontrarmos um possível endereço disponível em nossa rede local, basta modificarmos a última parte do endereço encontrado, como por exemplo, o endereço 192.168.25.16 . Geralmente, este procedimento é suficiente para encontrar possíveis endereços disponíveis em redes locais pequenas, como as das nossas casas.

IPAddress ip(192, 168, 25, 16);

- Criando o objeto server

Neste momento, cria-se um objeto chamado server, que por sua vez, será responsável por representar o Servidor Web no código do Arduino UNO.

Note que ao criarmos o objeto, passamos o número 80 como parâmetro, pois estamos determinando a porta que o Servidor Web utilizará para enviar as páginas web que serão criadas posteriormente.

A título de curiosidade, quando digitamos o endereço de algum site no navegador, ele automaticamente procura a porta 80 do servidor no qual está se conectando, de modo que, se o serviço responsável por disponibilizar as páginas da web para o cliente estiver em outra porta, devemos especificar esta no endereço do site citado, por exemplo: www.exemplo.com.br:1234

EthernetServer server(80);

- Iniciando a comunicação com a rede local e o Servidor Web

Na função setup() iniciamos a conexão com a rede local através da função Ethernet.begin() (passando como parâmetro os endereços MAC e IP definidos anteriormente) e também iniciamos o Servidor Web por meio da sentença server.begin() (lembre-se que server é o objeto criado para representar o Servidor Web no código).

Ethernet.begin(mac, ip);
server.begin();  

Veja como ficou nossa função setup():

void setup() 
{
   Ethernet.begin(mac, ip);
   server.begin();
}

- Respondendo as requisições de um navegador

Verificando se existe requisição de conexão

Primeiramente, na função loop(), temos a sentença server.available() que verifica se existe tem algum cliente tentando fazer uma conexão. Como dito anteriormente, vamos chamar de cliente, o navegador que está tentando fazer a conexão com o Servidor Web através do endereço IP do mesmo. Repare que foi criada uma variável para conter o valor retornado pela função server.available().

EthernetClient client = server.available();

Em seguida, temos uma função if() cujo conteúdo será executado apenas no caso de termos um cliente tentando se conectar ao Servidor Web criado e iniciado anteriormente.

if (client)
{
   ***** Conteúdo da função if() *****
}

Supondo que temos um cliente tentando se conectar com o nosso Servidor Web, primeira sentença do conteúdo da função if() apresentada anteriormente consiste na declaração de uma variável de controle booleana que será utilizada na leitura da requisição feita pelo navegador.

boolean currentLineIsBlank = true;

Posteriormente, temos uma função while(), que por sua vez, fará com que a execução do programa fique restrita ao seu conteúdo enquanto o parâmetro passado para mesma for verdadeiro. O parâmetro citado corresponde à sentença client.connected(), responsável por retornar verdadeiro ou falso, caso o cliente esteja conectado ou não com o Servidor Web, respectivamente.

Portanto, enquanto o cliente estiver conectado com o nosso servidor, o programa ficará preso na função while().

while (client.connected())
{
       ***** Conteúdo da função while()
}

Imagine que a conexão do cliente (navegador) com o nosso Servidor Web tenha sido estabelecida. Neste momento o programa irá se preparar para receber a requisição feita pelo cliente, que por sua vez, é dada em forma de um grande texto, logo, utilizamos a função if() juntamente com a sentença client.available() para verificar se ainda existe alguma informação proveniente do navegador para ser lida. Caso exista, o conteúdo desta função será executado.

if (client.available())
{
      ***** Conteúdo da função if() *****
}

Lendo a requisição do cliente

Caso exista alguma informação para ser lida, utilizamos a sentença client.read() para ler caractere por caractere do grande texto de requisição citado anteriormente, de modo que, a cada passagem por esta sentença (lembre-se que isso é feito de maneira cíclica), um novo caractere será armazenado na variável do tipo char c.

 char c = client.read();

Após preenchermos a variável c com um determinado caractere da requisição, fazemos uma série de comparações deste com alguns parâmetros específicos para saber se o Arduino UNO recebeu o pacote de informações inteiro ou não.

O objetivo aqui não é entender tudo que esta vindo do cliente mas simplesmente entender que existe uma solicitação acontecendo e que após o término da mesma, vamos devolver como resposta uma pagina da web, sendo assim, devemos esperar que venha o texto completo de solicitação, até a ultima linha.

Caso a condição desta primeira função de tratamento da variável c seja verdadeira, quer dizer que recebemos o pacote completo e que o conteúdo desta função if() será executado.

if (c == '\n' && currentLineIsBlank)
{
      ***** Conteúdo da função if() *****
}

Enviando informações para o navegador

Neste momento, nós iremos criar as funções necessárias para que o nosso Arduino UNO envie uma página da web como resposta à solicitação do navegador. As instruções que utilizaremos para enviar informações ao navegador serão baseadas na sentença client.println().

Primeiramente, enviamos um cabeçalho padrão informando ao navegador que estamos mandando uma página da web utilizando o protocolo HTTP, feita utilizando a linguagem HTML.

                     client.println("HTTP/1.1 200 OK");
                     client.println("Content-Type: text/html");
                     client.println("Connection: close");  
                     client.println();

- Usando HTML para montar a página web

HTML é uma linguagem, porém, não exatamente uma linguagem de programação mas sim uma linguagem de marcação, ou seja, através desta nós enviamos comandos para um navegador, que por sua vez, irão orientar o mesmo na montagem da pagina.

Uso de tags em HTML

Em um primeiro momento, nós devemos saber que a linguagem HTML é composta por elementos que iremos chamar de tags. Estes consistem em comandos que são enviados para o navegador para informarmos alguma coisa ao mesmo, para pedirmos que ele mostre algo, para definirmos o formato de fonte que queremos, se é negrito, qual cor, entre outros.

Todos as tags em HTML são declaradas entre os sinais de maior e menor <nome_da_tag>. Torna-se importante ressaltar que muitas tags possuem uma abertura e um fechamento (este possui o mesmo nome da tag, porém, com uma "/" antes do respectivo nome, por exemplo, </nome_da_tag>), de modo que, tudo o que está entre a abertura e o fechamento de uma determinada tag será afetado pelo comando gerado pela função da mesma.

A estrutura da página em HTML

Vamos começar a entender a estrutura de uma pagina em HTML. Primeiramente, qualquer pagina em HTML precisa possuir a tag <html> cuja função é indicar para o navegador que estamos começando um bloco de programação utilizando a linguagem HTML (opcionalmente podemos utilizar também a tag <!DOCTYPE HTML> para informar o tipo documento, de modo que, se não colocarmos isto, o navegador entenderá da mesma forma) e o fechamento da mesma </html>, que por sua vez, indica o fim do bloco citado.

client.println("<!DOCTYPE HTML>");
client.println("<html>");
           . 
           .
***** Conteúdo da página *****
           .
           .
client.println("</html>"); 
 

Dentro do bloco citado anteriormente, temos o conteúdo da página que queremos enviar para o navegador, de modo que, neste, devemos ter pelo menos dois blocos, um responsável pelas informações gerais do documento, limitado pelo uso do par <head></head> e o outro, por sua vez, deve conter o corpo da página e está entre as tags <body> e </body>.

client.println("<!DOCTYPE HTML>");
client.println("<html>");
client.println("<head>");
           .
           .
   ***** Bloco 1 *****
           .
           .
client.println("</head>");
client.println("<body>");
           .
           .
   ***** Bloco 2 *****
           .
           .
client.println("</body>");
client.println("</html>"); 

Definido o título para a página

Neste momento, vamos utilizar apenas uma tag dentro do bloco 1, denominada <title>, cuja função consistirá em definir um título para a página (este título aparecerá na aba do navegador). Para executarmos a ação proposta, devemos colocar o título desejado entre o par <title></title>.

client.println("<!DOCTYPE HTML>");
client.println("<html>");

client.println("<head>");
client.println("<title>Servidor Web VDS</title>"); 
client.println("</head>");

client.println("<body>");
           .
           .
   ***** Bloco 2 *****
           .
           .
client.println("</body>");
client.println("</html>"); 

Veja como ficou o título da nossa página:

endereço IP do servidor web
Título da página.

Escrevendo o corpo da página web

Quanto ao corpo da página, a primeira coisa que faremos será colocar um título visível na própria página. Para realizar este procedimento, utilizaremos a tag <h1>, que por sua vez, consiste em uma tag de cabeçalho, cuja função consiste em apresentar um determinado texto em um modelo predefinido. Lembre-se que os textos que tiverem fora do par <h1></h1> serão apresentados fora do padrão citado.

client.println("<!DOCTYPE HTML>");
client.println("<html>");

client.println("<head>");
client.println("<title>Servidor Web VDS</title>"); 
client.println("</head>");

client.println("<body>");
client.println("<h1>Meu primeiro Servidor Web</h1>");  
client.println("</body>");

client.println("</html>");

Veja como está nossa página até agora

Shield Ethernet W5100 - tela acessada via navegardor
Primeiro texto da página.

Opções de cabeçalhos

Devemos ressaltar que não há nenhum problema em utilizar vários cabeçalhos iguais, portanto, você pode tranquilamente criar vários textos utilizando o cabeçalho h1, pois, ele apenas indica uma certa formatação. Além do cabeçalho que já utilizamos, temos também os cabeçalhos h2,h3,h4,h5,h6, os quais, nesta ordem, possuem fontes cada vez menores.

Escrevendo um texto simples

Por fim, utilizaremos uma tag voltada para a escrita de textos simples. Esta pode ser referenciada no código pelo par <p></p>.

client.println("<!DOCTYPE HTML>");
client.println("<html>");

client.println("<head>");
client.println("<title>Servidor Web VDS</title>"); 
client.println("</head>");

client.println("<body>");
client.println("<h1>Meu primeiro Servidor Web</h1>");  
client.println("<p>Esperamos que voce tenha gostado deste tutorial</p>");
client.println("</body>");

client.println("</html>"); 

Veja nosso resultado final:

Página da web criada.

- Verificando se a requisição foi finalizada

Após o desenvolvimento da nossa página, saímos da função if() utilizada para saber se a requisição foi finalizada e encontramos outras duas funções if() que cumprem o teste das condições não contempladas pela primeira, ou seja, atuam no tratamento da variável enquanto a requisição não foi finalizada.

if (c == '\n') 
{
    currentLineIsBlank = true; 
} 
else if (c != '\r')
{
    currentLineIsBlank = false;
}

Por fim utilizamos a função delay() para garantir que o navegador receba esta informação que estamos mandando e também a sentença client.stop() para parar a conexão.

delay(1);     
client.stop();

Considerações finais

Neste tutorial, demonstramos como você pode dar os primeiros passos na criação de um Servidor Web utilizando um Arduino UNO e um Shield Ethernet W5100. Esta foi apenas a primeira parte de uma série de artigos sobre a criação de Servidores Web, portanto, esperamos que continue nos acompanhando e sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.


Módulo Bluetooth HC-06 e HC-05 – Arduino

Módulo Bluetooth HC-05 e HC-06 – Acionando um módulo relé via Bluetooth

Dentre os mais diversos protocolos de comunicação atuais, o Bluetooth certamente é um dos mais populares. Sendo assim, neste tutorial, iremos aprender como montar um projeto com uma placa Arduino, usando um smartphone para ligar e desligar uma pequena bomba submersa com o auxílio de um módulo relé e do módulo Bluetooth HC-06 / HC-05 . Para estabelecer a comunicação entre nosso smartphone e o Arduino, iremos utilizar o aplicativo Bluetooth Controller. O aplicativo possui uma interface simples, onde com uma configuração básica seremos capazes de controlar o nosso módulo relé.

[toc]

A importância de um sistema de comunicação sem fio

Sistemas automáticos precisam de meios para interagir com o usuário ou com outros sistemas, de modo que, isso faz da comunicação um assunto muito importante quando estamos tratando de automação.

Ter uma forma de comunicação sólida em um projeto é muito importante, pois será através dela que iremos estabelecer a interface que permitirá a comunicação entre o usuário e o sistema.

Infelizmente, grande parte dos microcontroladores não possuem uma interface sem fio já embutida e como consequência temos a criação de uma grande dificuldade em projetos onde existe a necessidade de um canal de comunicação sem fio. Com isso, uma solução interessante é o uso do padrão Bluetooth, que é voltado para aplicações de baixo consumo. Um módulo capaz de suprir esta demanda, é o módulo HC-06, que veremos a seguir.

Simbolo do padrão Bluetooth
Simbolo do padrão Bluetooth

Seguindo a linha de raciocínio anterior, o padrão Bluetooth, tem como principais vantagens:

  • Baixo consumo energético
  • Velocidade de transmissão considerável
  • Integração com smartphones
  • Padrões retrocompatíveis

Com todas estas características, podemos considerar que o padrão Bluetooth é de fato um ótimo meio para se transmitir dados de forma fácil e com um baixo custo energético para o sistema. Porém, o padrão tem suas limitações, como:

  • Curto alcance
  • Conexão ponto a ponto ( apenas dois pares podem se comunicar por vez )

Protocolo Bluetooth e o uso com Arduino

Em suas versões mais simples, as placas Arduino não contam com uma conexão Bluetooth nativa. Porém, é possível a aquisição de módulos capazes de estabelecer a conexão e a troca de mensagens entre a sua placa Arduino e um outro dispositivo com interface Bluetooth.

Um módulo com este propósito é o HC-06, este circuito é capaz de abstrair toda a parte da comunicação sem fio necessária para a comunicação bluetooth, fornecendo uma interface serial para que o microcontrolador possa enviar ou receber dados.

Com o uso do Bluetooth, você pode desenvolver uma vasta gama de projetos, como por exemplo:

  • Controlar robôs:
Controlando um robô com módulo Bluetooth HC-05
Controlando um robô usando Bluetooth
  • Automatizar praticamente qualquer coisa que esteja conectada ao seu Arduino
Acendendo um LED usando o módulo Bluetooth HC-05 / HC-06
Acendendo um LED usando o módulo Bluetooth HC-05 / HC-06

Módulo Bluetooth HC-05 e HC-06

Estes módulos utilizam a versão 2 do padrão Bluetooth, que por sua vez, apesar de já estar ultrapassado, ainda é viável em projetos como o que será desenvolvido neste tutorial. Com eles você abstrai toda a parte da comunicação sem fio, bastando enviar os dados via comunicação serial para eles.

Esses módulos são muito semelhantes e para nosso projeto você poderá optar por qualquer um dos dois. A diferença entre eles, além da versão do firmware, é o número de pinos. Geralmente os módulos HC-06 possuem apenas 4 pinos, enquanto que geralmente os módulos HC-05 contam com 6 pinos.

É importante ressaltar que o módulo Bluetooth HC-06 não possui o modo de funcionamento master dessa forma se optar pelo seu uso, o módulo ficará restrito a sempre precisar solicitar uma conexão com o dispositivo para a requisição ou transmissão de dados. Caso tenha a necessidade de um módulo capaz de funcionar tanto no modo master quanto slave, você pode utilizar o módulo Bluetooth HC-05, que é capaz de operar nos dois modos.

- Módulo HC-05

O módulo Bluetooth HC-05, dispõe de 6 pinos de entrada e saída de dados, sendo dois deles para alimentação do sistema, dois para transmissão e recepção de dados via serial e dois para programa-lo em modo master. Logo abaixo temos a especificação do dispositivo:

Módulo Bluetooth HC-05
Módulo Bluetooth HC-05
  • Especificações
    • Bluetooth: 2.0V
    • Tensão de funcionamento: 3.3v~5v
    • Taxa de transmissão: 2Mbps
    • Frequência: 2,4 Ghz
    • Nível lógico: 3.3v
    • Pinos: VCC , GND , TXD , RXD;
    • Perfis suportados: Escravo (slave) e Mestre (master)

- Módulo HC-06

O módulo Bluetooth HC-06, dispõe de apenas 4 pinos de entrada e saída de dados, sendo dois deles para alimentação do sistema, e os outros dois para transmissão e recepção de dados via serial. Logo abaixo temos a especificação do dispositivo:

Módulo Bluetooth HC06
Módulo Bluetooth HC-06
  • Especificações
    • Bluetooth: 2.0V
    • Tensão de funcionamento: 3.3v~5v
    • Taxa de transmissão: 2Mbps
    • Frequência: 2,4 Ghz
    • Nível lógico: 3.3v
    • Pinos: VCC , GND , TXD , RXD;
    • Perfis suportados: Escravo (slave) e Mestre (master)

Módulo Relé

É comum, em projetos de automação, termos que acionar ou desligar dispositivos mediante algum parâmetro tal como a temperatura do ambiente, pressão, ou até mesmo a simples solicitação do usuário. Para que isso seja possível, podemos utilizar um circuito comumente conhecido como relé, que por sua vez, nada mais é do que uma simples chave eletromecânica acionada através de uma bobina em seu interior, permitindo ligar e desligar equipamentos elétricos, através da abertura ou fechamento de seu contato em virtude do fornecimento de energia a esta bobina.

Neste projeto, iremos também utilizar um módulo relé para realizar o acionamento da nossa bomba quando requisitado pelo usuário. Este módulo utiliza apenas três pinos, sendo dois para alimentação (5 Volts) e outro para acionamento.

Módulo Relé 1 canal

Mãos à obra - Acionando um módulo relé utilizando o módulo Bluetooth HC-06 ou HC-05 - Arduino

Como esse projeto irá usar o módulo Bluetooth no modo Slave, poremos usar tanto o HC-05 quanto o HC-06. Para nosso projeto usaremos o HC-06, mas você pode adotar os mesmos procedimentos para o HC-05.

Componentes utilizados

Montando o projeto

A montagem deste projeto, pode ser feita seguindo a seguinte ordem para os fios:

Esquema de montagem no Arduino Uno com HC-05
Esquema de montagem no Arduino Uno com HC-05

A montagem do sistema deve ficar semelhante a imagem abaixo

ATENÇÃO: Tanto o módulo HC-06, quanto o HC-05 utilizam o nível lógico de 3.3 volts, logo para utilizar o pino de transmissão TX, você deve adicionar ao projeto um divisor de tensão, já que o nível lógico do Arduino Uno ( 5 Volts ) pode danificar o seu módulo. Porém como neste tutorial não iremos transmitir informações do arduino para o telefone, não iremos precisar do divisor de tensão.

Esquema de montagem do projeto como módulo Bluetooth HC-06 e módulo relé no Arduino Uno na prática
Projeto montado na prática com Módulo Bluetooth HC-06 e Arduino Uno

Sempre monte seu projeto com a alimentação desligada para evitar possíveis curtos circuitos que podem danificar o seu dispositivo.

Programando

Agora que temos o nosso circuito montado, iremos partir para o código responsável por receber os dados através do Bluetooth e determinar se o relé deve ser acionado ou não. Neste exemplo em especial, não será necessária nenhuma biblioteca de terceiros, ou seja todas as bibliotecas que iremos utilizar já se encontram disponíveis na IDE do Arduino. O código abaixo ilustra todo o processo de funcionamento do nosso sistema:

#include <SoftwareSerial.h>
#define RX 8
#define TX 9
#define RELE 7
SoftwareSerial bluetooth(RX, TX); // RX, TX

void setup() {
  Serial.begin(9600); // Inicializa a serial nativa do Arduino
  pinMode(RELE,OUTPUT); // Inicializamos o pino 7 do relé como output
  digitalWrite(RELE,HIGH); // Inicializa a chave como desligada
  bluetooth.begin(9600); // Inicializa a serial via software (Onde está conectado o nosso módulo bluetooth)
}

void verificaBluetooth(){ // Verifica se existe algum dado a ser lido da serial
  if (bluetooth.available()){ // verifica se existem bytes a serem lidos da porta serial virtual
     char dados = bluetooth.read(); // Lê 1 byte da porta serial
     Serial.print(dados); // Mostra esse dado lido na porta serial
     if (dados=='0'){ // Se o byte lido for igual a 0
       digitalWrite(RELE,HIGH); // Desliga a chave
     }
     else{
        if (dados=='1'){ // Se o byte lido for igual a 1
          digitalWrite(RELE,LOW); // Liga a chave e aciona a bomba
        }
     }
  }
}

void loop (){
  verificaBluetooth();
}

Conectando o celular ao Arduino

Agora que temos o código que irá rodar no Arduino, devemos agora instalar o aplicativo que iremos utilizar no controle da bomba. Para instalar o aplicativo basta seguir os seguintes passos:

  • Na play store pesquisar por Bluetooth Controller, e instalar o aplicativo que está marcado

Bluetooth Controller intalando

instalando o Bluetooth Controller

  • Com o aplicativo instalado, iremos agora criar dois botões que serão utilizados para ligar e desligar a nossa mini bomba submersa, para isso devemos clicar no botão SET KEYS:

Configurando o Bluetooth Controller

  • Ao clicar em SET KEYS, seremos direcionados para a tela onde configuramos os botões q serem utilizados. Neste primeiro caso, iremos configurar apenas dois botões, sendo eles responsáveis por ligar e desligar o relé, o tipo de dado enviado também deverá corresponder ao que o nosso código espera, logo enviaremos 1 quando quisermos que a bomba seja ligada, e 0 quando quisermos que a bomba seja desligada.

configurando as saídas do Bluetooth Controller

  • Agora com todos os botões configurados, iremos buscar o dispositivo que queremos nos conectar, para isso selecionamos a opção SCAN   

Bluetooth Controller

  • Ao clicar no botão SCAN, seremos novamente redirecionados para outra tela, sendo esta no caso para selecionar o dispositivo com o qual desejamos nos conectar. No meu caso o dispositivo se chama Controle rele, porém pode ser que o seu se chame HC-05 ou HC-06 dependendo do qual esteja usando.

Na primeira conexão, você deverá fornecer uma senha para que o pareamento seja feito com sucesso, por padrão esta senha é 1234.

Bluetooth Controller procurando por dispositivos

  • Com a conexão estabelecida, agora podemos ligar e desligar a nossa bomba sem a necessidade de contato direto com ela.

Bluetooth Controller pareado com o Arduino e HC06

Colocando para funcionar


Entendendo a fundo

Software

- Incluindo as bibliotecas necessárias

Neste código, em especial, iremos apenas incluir uma única biblioteca, chamada SoftwareSerial. Neste exemplo iremos simular uma porta serial, através dos pinos 8 e 9 do Arduino, desta forma, mantemos a serial em hardware livre para ser utilizada no debug e gravação do código a ser executado. Essa biblioteca é nativa da IDE Arduino.

#include <SoftwareSerial.h>

- Parâmetros de configuração

Para facilitar o uso dos pinos selecionados para este sistema, iremos definir as seguintes constantes como mostra o código logo abaixo:

#define RX 8 
#define TX 9 
#define RELE 7

- Objeto bluetooth

Como dito anteriormente, iremos utilizar uma biblioteca que simula uma comunicação serial, desta forma evitamos a utilização da serial nativa, que pode ser utilizada posteriormente para depuração do código. O trecho de código abaixo, cria o objeto bluetooth, que será responsável por enviar os dados a serem transmitidos através pelo módulo HC-06. Algo que é importante ressaltar é que o módulo HC-06 abstrai toda a parte de comunicação do usuário, bastando apenas com que ele envie os dados que deseja transmitir utilizando a comunicação serial.

SoftwareSerial bluetooth(RX, TX); // RX, TX

-  Inicializando portas de comunicação e configurando relé para desativado

Na função setup, iremos inicializar as duas portas de comunicação (nativa e a que conectamos o nosso módulo bluetooth), através dos comandos Serial.begin(9600) e bluetooth.begin(9600). Também inicializamos o pino onde o módulo relé está conectado como OUTPUT, e inicializamos o módulo relé no estado HIGH. Algo que também deve ser levado em consideração, é o fato de que este módulo relé, diferente dos outros é ativo no nível lógico LOW, por isso inicializamos ele como HIGH.

void setup() { 
Serial.begin(9600); // Inicializa a serial nativa do arduino 
pinMode(RELE,OUTPUT); // Inicializamos o pino 7 do módulo relé como output 
digitalWrite(RELE,HIGH); // Inicializa a chave como desligada 
bluetooth.begin(9600); // Inicializa a serial via software (Onde está conectado o nosso módulo bluetooth) 
}

- Função Verifica loop

Já na função verificaBluetooth, iremos seguir a seguinte lógica:

  1. Verificamos se existe algum dado a ser lido em nossa serial virtual
    1. Se existir nós iremos ler apenas o primeiro byte desta mensagem através do comando bluetooth.read()
    2. Mostramos este dado lido na tela afim de ver se ele é realmente o que enviamos
    3. Logo em seguida verificamos se este valor é 0
      1. Se o valor for igual a 0 iremos abrir a chave do módulo relé ( desligar a bomba )
      2. Caso seja 1 iremos fechar a chave do módulo relé ( ligar a bomba )
      3. Caso não seja nenhum dos dois casos, iremos manter o sistema como está
void verificaBluetooth(){ // Verifica se existe algum dado a ser lido da serial
  if (bluetooth.available()){ // verifica se existem bytes a serem lidos da porta serial virtual
     char dados = bluetooth.read(); // Lê 1 byte da porta serial
     Serial.print(dados); // Mostra esse dado lido na porta serial
     if (dados=='0'){ // Se o byte lido for igual a 0
       digitalWrite(RELE,HIGH); // Desliga a chave
     }
     else{
        if (dados=='1'){ // Se o byte lido for igual a 1
          digitalWrite(RELE,LOW); // Liga a chave e aciona a bomba
        }
     }
  }
}

Considerações Finais

Este tutorial, teve como objetivo mostrar a utilização do módulo Bluetooth HC-06 e HC-05 no modo slave, em um contexto onde a utilização do Arduino é muito aplicada, que é a automação de equipamentos. Com este código apresentado como base, podem ser criados diversos projetos, como automatização residencial e controle de robôs, utilizando um smartphone. Espero que tenham gostado do conteúdo apresentado, sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.

Caso esteja começando com Arduino recomendamos que conheça a Apostila Arduino Básico.


Lendo dados do Google planilhas com ESP - Banco de dados

Lendo dados do Google planilhas com ESP - Banco de dados

No tutorial Banco de dados com Google planilhas com ESP, aprendemos a enviar dados para o Google Planilhas. Entretanto, para fazer justo ao nome "banco de dados", também precisamos recuperar dados da planilha para manipula-los ou até criar comandos de controle pela planilha, que permitirá, por exemplo, ativar atuadores ou ler dados que colocamos na planilha. Dessa forma, neste tutorial iremos aprender como ler os dados do Google Planilhas através de um ESP.

[toc]

Configurações iniciais - Requisitando dados do Google planilhas

O processo necessário para adquirir dados da planilha é quase o mesmo em relação ao método de envio (GET), entretanto para fazer isso, precisamos obter uma chave secreta. Esta chave faz o papel de "senha", para que ninguém consiga ler seus dados sem ela.

Atenção: Há maneiras mais seguras, como restringir o acesso da chave ou usar autenticador. Será mostrado o método mais simples.

Passo 1-) Entre na plataforma de gerenciamento de API's da Google: https://console.developers.google.com/apis , crie um novo projeto e de um nome qualquer.

Este projeto será apenas para "guardar" sua chave com a respectiva API, neste caso, Google planilhas.

Figura 1 - Criando um projeto de API.

 

Passo 2-) Vá em "Credenciais" e crie uma "Chave de API"

Figura 2 - Criando a Chave de API.

 

Figura 3 - Chave de API.

 

Feche a janela e a partir de agora, já temos nossa chave necessária para requisição de dados (e futuramente, altera-los).

 

Passo 3-) Volte para a página inicial do Google APIs, clique em "Biblioteca", selecione "Google Sheets API" e "Ativar"

Figura 4 - Ativando a API.

 

 

 

Terminamos de criar nossa chave e ativa-la, agora podemos manipular qualquer planilha que tenhamos salvo no Google Drive!


Mãos a obra - Lendo o Google planilhas

Componentes necessários

Código do projeto

Atenção: é necessário que você use os dados da sua planilha e faça uma alteração na mesma, explicaremos logo abaixo.

#include <ESP8266WiFi.h>

WiFiClientSecure cl;//Cria um cliente seguro (para ter acesso ao HTTPS)
String textFix = "GET /v4/spreadsheets/12IYuWdV0aJa8mQPhsR5C6AVEwZufyC05wufTrTJsSg/values/";
String key = "?key=IzaSyDmot3XwHfsNhqeuKdINMYxpyFK4cY";//Chave de API
//Essas Strings serao auxiliares, para nao precisar ficar re-escrevendo toda hora


void setup()
{
    Serial.begin(115200);//Inicia a comunicacao serial
    WiFi.mode(WIFI_STA);//Habilita o modo estaçao
    WiFi.begin("SUA REDE", "SUA SENHA");//Conecta na sua rede
    delay(3000);//Espera um tempo para se conectar no WiFi

}

void loop()
{

    if (cl.connect("sheets.googleapis.com", 443) == true)//Tenta se conectar ao servidor do Google APIs na porta 443 (HTTPS)
    {
        String toSend = textFix;//Atribuimos a String auxiliar na nova String que sera enviada
        
        toSend += "C2:C4";//Os valores que queremos ler da planilha. Para uma única célula, use algo como "A2"; para ler varios, use algo como "A1:C4".
        toSend += key;//Adicionamos a chave na String
        toSend += " HTTP/1.1";//Completamos o metodo GET para nosso formulario.

        cl.println(toSend);//Enviamos o GET ao servidor-
        cl.println("Host: sheets.googleapis.com");//-
        cl.println();//-
			

        Serial.println("Dado recebido:\n");//Mostra no Serial Monitor todo o pacote recebido.-
        Serial.print(cl.readString());//-
        cl.stop();//Encerramos a conexao com o servidor.
    }
    else
    {
        Serial.println("Erro ao se conectar");
    }
	

    delay(5000);

}

Ajustando o código para sua planilha

Antes de testar, precisamos alterar os dados do código para os seus dados e também compartilhar o link da sua planilha. Sem isso não irá funcionar!

Lembrando: altere apenas os dados destacados, o restante é necessário para funcionamento correto.

Passo 1-) Vá no começo do código e altere a chave (destacada) por sua chave.

Figura 5 - Alterando a Chave de API.

 

Passo 2-) Ainda nesta parte, altere o ID com o da planilha que você deseja obter os dados. Para isso vá em seu Google Drive, entre na planilha e pegue o ID:

Neste caso, vamos pegar a própria planilha criada na primeira parte do material.

configurando o google planilhas - banco de dados

Figura 6 - Alterando o ID da planilha.

 

Se você testar o código, verá que não temos permissão para acessar o banco de dados no Google planilhas. Isso acontece pois nossa "Chave de API" precisa estar com o link público (Qualquer pessoa com o link pode visualizar). Você pode contornar isso usando os Autenticadores ou adicionando Emails confiáveis ao sistema. Usaremos o mais simples para didática e fácil entendimento. Veja a saída do Serial monitor:

Figura 7 - Serial Monitor: Erro de permissão ao acessar o banco de dados no Google Planilhas

 

Passo 3-) Para deixar o link público, vá na sua planilha e siga os passos:

  • 1-) Clique em "Compartilhar" no canto superior direito.
  • 2-) Clique em "Avançado".

 

  • 3-) Clique em "Alterar...".

 

  • 4-) Clique em "Ativado: qualquer pessoa com link" e salve.

Colocando para funcionar

Agora podemos testar e já estará funcionando!

lendo as células do google planilhas - banco de dados com ESP
Figura 8 - Serial Monitor: Resposta de um grupo de células do nosso banco de dados no Google Planilhas

 

Veja que o pedido foi de um grupo de células, neste caso, C2:C4. Isso significa que iremos receber os dados das células C2,C3 e C4 em ordem da respectiva chamada.


Entendendo a fundo

Software

- String auxiliar (textFix)

String textFix = "GET /v4/spreadsheets/12IYuWdV0aJa8mQPhsR5C6AVEwZufyC05wufTrTJsSg/values/";

Basicamente é onde colocamos o ID da nossa planilha, você deve alterar para o ID de sua planilha!

- String auxiliar (key)

String key = "?key=IzaSyDmot3XwHfsNhqeuKdINMYxpyFK4cY";//Chave de API

Esta outra String, é onde atribuímos nossa Chave de API, você deve alterar para sua Chave de API.

- Obtenção dos dados

toSend += "C2:C4";

Aqui fica a grande jogada, onde conseguimos pegar células individuais, ou grupos de células. Vamos a um breve resumo.

Nossa planilha:

Banco de dados no Google Planilhas
Nosso banco de dados no Google Planilhas

 

Célula individual: Imagine que você precisa do valor da célula C2("Vida").

toSend += "C2";

 

Grupo de células: Imagine que você precisa do valor de um grupo de células, neste caso C2, C3 e C4 ("Vida", "De", "Silicio").

toSend += "C2:C4";

 

Podemos ver a resposta do Google ao pedido C2:C4 no Serial Monitor:

Lendo o banco de dados no Google planilhas
Lendo o banco de dados no Google planilhas

 

Você pode estar se perguntando: "Como vou usar essa String cheia de 'lixo' ?"

Este será o desafio de vocês! Futuramente criaremos um tutorial sobre manipulação de Strings. Mas aqui vai uma dica, procure sobre estes comandos em programação:

Com elas, você é capaz de pegar partes e caracteres específicos da String e ainda criar protocolos de mensagens para uma comunicação efetiva.


Desafio

Tente pegar apenas o valor que você queria da planilha. Você irá usar os dois comandos citados acima para "limpar" a String recebida pelo Google e assim tornando-a útil para o uso no microcontrolador.

Fechamento

Agora que você consegue obter valores da planilha, pode usar dados da planilha para algum processamento interno ou criar comandos de controle através da planilha! As possibilidades são muitas e depende de você. Boa sorte.

Referências

  • https://developers.google.com/sheets/guides/concepts
  • https://developers.google.com/sheets/guides/values

Banco de dados com Google planilhas com ESP32 / ESP8266

Banco de dados com Google planilhas - ESP

O Google planilhas é um "Excel online", que te permite criar tabelas e coisas do tipo, online, sem a necessidade de instalar no seu computador. Podemos compartilhar essa tabela para outras pessoas visualizarem ou edita-las. Nesse tutorial aprenderemos como usar o Google Planilhas para criar um banco de dados online, gratuito e simples, visto que não precisamos ter um servidor dedicado à hospedar o serviço. Esta primeira parte será ensinado apenas a enviar os dados usando um ESP.

[toc]

Banco de dados

Banco de dados é um conjunto de dados, normalmente relacionados entre si, como por exemplo: dados de clientes, LOG de temperaturas e coisas similares. Normalmente são dados organizados por colunas e linhas (matriz/tabela) para fácil entendimento por nós.

Poderíamos usar MySQL ou Firebase, que nos permite criar banco de dados de forma eficiente e confiável, entretanto,  é preciso ter um servidor apenas para hospedar seu banco de dados sempre disponível.

Você pode ler mais sobre Banco de dados e o uso do MySQL no tutorial: Arduino e MySQL – Registrando temperatura em um banco de dados usando o Shield Ethernet W5100

O Google planilhas oferece uma solução simples e gratuita para o armazenamento dos dados coletados. Podemos criar essas tabelas em conjunto do Google Forms, para enviar os dados dos nossos sensores, clientes e etc., sem a necessidade de um computador ou servidor pago hospedando o banco de dados, já que a Google se encarrega totalmente do serviço.

Obtendo os recursos necessários

Para usar esse incrível recurso precisaremos de uma conta no Google, e com ela criaremos dois arquivos, um de Planilha e outro Form.

Iremos através do formulário, enviar dados para a planilha (os dados do formulário irão para a planilha).

Passo 1-) Vá ao seu Google Drive e crie uma Planilha.

Passo 2-) Altere o nome da sua planilha para ser de fácil identificação nos próximos passos.

Figura 3 - Alterando o nome da planilha.
Figura 3 - Alterando o nome da planilha.

Passo 3-) Volte no Drive e crie um formulário.

Passo 4-) Altere o titulo do seu formulário para o desejado, e configure as perguntas.

Na planilha, os títulos das perguntas serão as colunas, e as respostas serão as linhas. Usaremos a opção "Resposta curta", que permite adicionar números e textos pequenos.

Passo 5-) Vá em "Respostas", vamos atribuir o formulário à planilha criada anteriormente. Clique nas "três bolinhas", e "Selecionar destino da resposta".

Passo 6-) Selecione a planilha desejada e estará pronto para receber nossos dados.

Agora, nosso formulário esta pronto para receber os dados e automaticamente transmitir para a planilha.

Para testar o formulário, clique no "Olho" ao canto superior direito, para abrir o link do formulário.

Figura 7 - Abrindo o link do formulário.
Figura 7 - Abrindo o link do formulário.

Após digitar o numero e clicar em "Enviar", será mostrado o aviso que a resposta foi registrada.

Figura 8 - Resposta enviada.
Figura 8 - Resposta enviada.

Agora, volte à sua Planilha, e veja que os resultados já estão aparecendo!

A coluna "Carimbo de data/hora" é preenchida automaticamente pelo sistema do Google, poupando imenso trabalho e requisitos do nosso sistema, dispensando até mesmo RTCs. A outra coluna "Numero" é o titulo da nossa pergunta, e a linha é a resposta que inseri.

Figura 9 - Resposta do formulário na planilha.
Figura 9 - Resposta do formulário na planilha.

Agora que aprendemos a utilizar o formulário em conjunto com a planilha, precisamos apenas integrar no Microcontrolador.


Mãos à obra

Componentes necessários

Conheça um pouco mais sobre ESP:

Código do projeto

Atenção: Não copie e cole o código inteiro, precisamos fazer algumas alterações no link utilizado. Será explicado logo abaixo em "Entendendo a fundo".

Caso esteja usando o ESP32, altere as bibliotecas removendo a ESP8266WiFi.h e incluindo as bibliotecas WiFi.h e WiFiClientSecure.h

Alguns usuário relatam erro com as versões mais novas do core esp8266 (quando você instala pelo menu (ferramentas > placa > gerenciar placas). A solução é instalar e usar a versão 2.4.0

// Código Banco de dados com Google planilhas com ESP - Vida de Silício

#include <ESP8266WiFi.h> 
// Alterar a linha anterior por #include <WiFi.h> se estiver usando ESP32
// #include <WiFiClientSecure.h> // Incluir esta biblioteca se estiver usando ESP32

WiFiClientSecure client;//Cria um cliente seguro (para ter acesso ao HTTPS)
String textFix = "GET /forms/d/e/1FAIpQLSdm6M_0mTVx_LKHLB1J3u_hjaag_hBtMfDHQlTIKe0EoatfsQ/formResponse?ifq&entry.717212213=";
//Essa String sera uma auxiliar contendo o link utilizado pelo GET, para nao precisar ficar re-escrevendo toda hora


void setup()
{
    Serial.begin(115200);//Inicia a comunicacao serial
    WiFi.mode(WIFI_STA);//Habilita o modo estaçao
    WiFi.begin("SUA REDE", "SUA SENHA");//Conecta na rede
    
    delay(2000);//Espera um tempo para se conectar no WiFi

}


void loop()
{
    if (client.connect("docs.google.com", 443) == 1)//Tenta se conectar ao servidor do Google docs na porta 443 (HTTPS)
    {
        String toSend = textFix;//Atribuimos a String auxiliar na nova String que sera enviada
        toSend += random(0, 501);//Adicionamos um valor aleatorio
        toSend += "&submit=Submit HTTP/1.1";//Completamos o metodo GET para nosso formulario.

        client.println(toSend);//Enviamos o GET ao servidor-
        client.println("Host: docs.google.com");//-
        client.println();//-
        client.stop();//Encerramos a conexao com o servidor
        Serial.println("Dados enviados.");//Mostra no monitor que foi enviado
    }
    else
    {
        Serial.println("Erro ao se conectar");//Se nao for possivel conectar no servidor, ira avisar no monitor.
    }

    delay(5000);
}

Colocando para funcionar

Após a editar o código com as suas informações, tudo irá funcionar corretamente. Veja como ficou o nosso, enviando valores aleatórios para nossa planilha a cada ~5 Segundos.


Entendendo a fundo

Precisamos fazer algumas alterações para o funcionamento do sistema com sua planilha. Sem isso, você irá enviar dados para nossa planilha de teste! (hehe)

Passo 1-)  Abra seu formulário (Figura 7).

Passo 2-) Copie todo o link entre "docs.google.com" e "/viewform". Salve isso em algum lugar, já iremos utilizar.

O nosso ficou "/forms/d/e/1FAIpQLSdm6M_0mTVx_LKHLB1J3u_hjaag_hBtMfDHQlTIKe0EoatfsQ".

Passo 3-)  Clique com o direito no "Input Text Box" e "inspecionar elemento".

Passo 4-) Agora, iremos pegar o nome desse Input Text Box.

O nosso é "entry.717212213".

Agora, devemos alterar esses dois valores no código, pois são os valores da sua planilha, e no código demonstrado de exemplo, foi utilizado nossos dados.

Obs: Altere apenas as partes destacadas, o restante é necessário para o correto funcionamento.

Atualização por contribuição do leitor Anselmo:

Caso tenha dificuldade em encontrar os entry, bastar seguir os seguintes passos:

    1. Clique no formulário com o botão direito do mouse e selecione "Exibir código fonte da pagina" (Ctrl+U);
    2. Agora pesquise pelo nome do campo inserido no formulário usando a ferramenta de pesquisa do navegador (Ctrl+F);
    3. No final do código vai encontra algo parecido com:  FB_PUBLIC_LOAD_DATA_ = [null,[null,[[490158642,"nome do campo",null,0,[[12345678,null,0,null,[[1,9,[""];
    4. O entry vai ser o numero após o colchete “12345678”,
    5. Inclua "entry." antes do número, fincando “entry.12345678”;
    6. Se você tiver outros campos, os outros entry do formulário vão estar na sequencia.

Exemplo: Campo do formulário: Teste var 1

    • Procure por “Teste var” (Ctrl+F);
    • No final do código vai encontra algo parecido com: "teste var 1",null,0,[[278629525,null,0,null,[[1,9,[""]
    • Copie o número após o colchete “278629525”
    • basta agora incluir "entry." antes do número , ficando “entry.278629525”

 

Passo 5-) Vá no começo do código e altere esta parte destacada, pelo que você copiou no item 2.

Esta parte é o "ID/KEY" do seu formulário, cada formulário tem o seu.

Passo 6-) Nessa mesma parte do código, altere essa outra parte destacada, pelo valor copiado no item 4.

Se você tiver mais de uma entrada para dados, a String ficaria por exemplo:

"GET /forms/d/e/1FAIpQLSdm6M_0mTVx_LKHLB1J3u_hjaag_hBtMfDHQlTIKe0EoatfsQ/formResponse?ifq&entry.717212213=123&entry.312212717=1234"

Os dados em negrito são os dados que você adicionaria, sendo de sensores, temperatura e etc.

Se você quiser testar com nossa planilha, sinta-se livre. Entretanto, é permitido apenas a visualização. Link da nossa planilha.

Software

- String auxiliar

String textFix = "GET /forms/d/e/1FAIpQLSdm6M_0mTVx_LKHLB1J3u_hjaag_hBtMfDHQlTIKe0EoatfsQ/formResponse?ifq&entry.717212213=";

Essa String textFix é uma auxiliar para nao precisar ficar reescrevendo toda hora, desde que essa parte é FIXA. O único valor que iremos alterar é após o  igual "=", que será o valor enviado à planilha.

- Função WiFiClient::connect()

if (client.connect("docs.google.com", 443) == 1)

Precisamos antes de enviar o método GET, se conectar no servidor. Essa função se conecta à URL (IP), na porta desejada.

- Corpo restante do GET

String toSend = textFix;//Atribuimos a String auxiliar na nova String que sera enviada
toSend += random(0, 501);//Adicionamos um valor aleatorio
toSend += "&submit=Submit HTTP/1.1";//Completamos o metodo GET para nosso formulario.

client.println(toSend);//Enviamos o GET ao servidor-
client.println("Host: docs.google.com");//-
client.println();//-
client.stop();//Encerramos a conexao com o servidor
Serial.println("Dados enviados.");//Mostra no monitor que foi enviado

Após a conexão com o servidor, adicionamos um valor aleatório na String final à ser enviada, e também terminamos o restante do necessário a ser enviado.


Desafio

Foi demonstrado apenas o envio de uma variável para a planilha, entretanto em qualquer projeto pode ser necessário o envio de diversas. Faça as alterações necessárias, adicionando os novos "Input Text Box" e tente enviar varias variáveis para sua planilha!

Fechamento

Em diversos projetos precisamos enviar dados ou guarda-los para analise, e um banco de dados como SQL pode ser desnecessário, uma vez que precisamos de um servidor para hospedar o banco de dados; com este método é possível facilmente criar seu banco de dados online, compartilhar com amigos e etc.

Na parte 1 foi mostrado apenas o procedimento para envio dos dados, entretanto, podemos precisar pegar valores da tabela para uso. Já a parte 2, você aprenderá como ler os valores da planilha para manipulação de dados ou até criar comandos de controle para o MCU: Lendo dados do Google planilhas com ESP – Banco de dados

Referências

  • https://developers.google.com/sheets/api/guides/values

Banco de dados MySQL com Arduino e Shield Ethernet W5100

Banco de dados MySQL com Arduino e Shield Ethernet W5100 – Registrando temperatura em um banco de dados

Sabemos que a utilização de placas Arduino é bastante difundida nos dias atuais, de modo que, o seu uso está presente em uma grande diversidade de aplicações, que vão desde trabalhos acadêmicos até projetos comerciais e industriais, no entanto, um grande problema surge em todas estas vertentes quando nos deparamos com a necessidade de armazenar informações inerentes a um determinado processo. Sendo assim, neste tutorial iremos aprender como fazer o registro de informações, mais especificamente, de temperatura em um banco de dados MySQL com o auxilio do shield ethernet W5100.

[toc]

O que são bancos de dados?

De uma maneira bem simples, pode-se entender um banco de dados como sendo um local onde podemos armazenar uma série de informações de maneira estruturada, organizada, que por sua vez, estejam à disposição para serem utilizadas tanto por softwares quanto por usuários diferentes. Podemos, por exemplo, armazenar os valores de temperatura coletados ao longo de um dia por uma placa Arduino e armazenar os mesmos numa tabela juntamente com a hora da medição.

Pense em uma industria com centenas de sensores que fazem medições de dados do processo a todo instante. É necessário que os dados estejam organizados de forma adequada e que os mesmos estejam acessíveis sempre que necessário, pois, caso contrario, estes seriam uma gama de informações sem utilidade prática.

Sendo assim, podemos perceber que os bancos de dados são recursos muito importantes e essenciais para o funcionamento dos mais variados tipos de estabelecimentos, desde os menores até as grandes indústrias, hospitais e etc, pois, através dos dados presentes nos mesmos, realiza-se o controle, por exemplo, de funcionários, de material, de custos e além disso, é possível até mesmo auxiliar nas tomadas de decisão em virtude de uma análise estatística feita sobre os mesmos.

Para realizarmos este tutorial deve-se ter em mente que os bancos de dados ficam armazenados em um servidor, portanto, antes de acessarmos um banco de dados, devemos acessar primeiramente o servidor onde estes estão inseridos. Em contrapartida, as estruturas intrínsecas a um banco de dados são as tabelas (estas são, de fato, tabelas, dotadas de linhas e colunas).

Estrutura de um banco de dados MySQL

O MySQL, nosso Banco de dados

Quando realizamos algumas pesquisas sobre o que é o MySQL encontramos algumas fontes dizendo que o mesmo se trata de um banco de dados, enquanto outras, classificam o mesmo como um sistema gerenciador de banco de dados (SGBD) que utiliza a linguagem SQL como interface para realizar manipulação dos dados armazenados. Neste tutorial, como não estamos focados em toda parte teórica por trás deste assunto, basta encararmos o MySQL como um banco de dados, que não teremos maiores problemas.

 

Para utilizamos o MySQL, é necessário instalarmos um servidor, responsável por entre outras coisas, armazenar os dados e responder às requisições feitas por um cliente conectado com mesmo (conforme falando anteriormente, tanto softwares quanto usuários podem interagir com um servidor). O MySQL possui uma versão gratuita para a comunidade, que por sua vez, inclui diversos elementos, entre eles, o servidor e uma interface gráfica para ser utilizada como cliente.

A nossa sugestão é que você realize o download do instalador completo e instale o mesmo no seu computador.


Mãos à obra – Registrando informações no banco de dados

Neste momento, iremos demonstrar todos os passos para que você consiga realizar o objetivo que estamos propondo neste tutorial.

Componentes utilizados:

Montando o projeto

Esquema de montagem do Arduino Uno com Shield W5100 e Sensor de temperatura LM35
Esquema de montagem do Arduino Uno com Shield W5100 e Sensor de temperatura LM35

Programando

Antes de adentrarmos na apresentação do código, disponibilizamos uma seção para ajudar aqueles que são iniciantes no assunto. Sinta-se livre para prosseguir caso você já tem domínio da IDE do Arduino.

Conectando o Arduino ao computador

Primeiramente, conecte seu Arduino ao computador e abra a IDE Arduino. Em seguida, é necessário selecionar a porta COM na qual o Arduino está conectado (este procedimento pode ser feito clicando no menu Ferramentas (tools) e em seguida escolhendo-se a porta correspondente no submenu Porta (port). Neste caso, a porta na qual está o Arduino é apresentada da seguinte maneira: COM3 (Arduino UNO).

IDE Arduino configurando porta de comunicação

Por fim, garanta também que o tipo de placa apropriado esteja selecionado (isso pode ser feito acessando o menu Ferramentas (tools) e o submenu Placa (board)).

Configurando a placa Arduino UNO na IDE Arduino

- Biblioteca

Para desenvolver o projeto proposto  utilizou-se uma biblioteca capaz de atuar sobre um servidor MySQL fazendo com que o Arduino possa manipular dados existentes nas tabelas dos bancos de dados MySQL. Esta biblioteca pode ser encontrada aqui.

Adquirindo e instalando a biblioteca que será utilizada

Para adquirir a biblioteca em questão, basta acessar o link apresentado anteriormente, clicar no botão clone or Download e por fim, no botão Download ZIP, conforme a figura abaixo.

Baixando a biblioteca responsável pela comunicação com o banco de dados MySQL
Baixando a biblioteca responsável pela comunicação com o banco de dados MySQL

Após a realização do download dos arquivos compactados no formato ZIP, abra a IDE do Arduino, selecione o menu Sketch, o submenu Incluir Bilioteca e por fim, basta clicar na opção Adicionar biblioteca .ZIP (Add ZIP Library) e encontrar o arquivo que acabou de ser baixado.

Uma outra forma de fazer isso é extrair o conteúdo do arquivo ZIP dentro da pasta Libraries (onde foi instalada a IDE do Arduino).

– Preparação (VOCÊ DEVE LER ESTA PARTE)

Antes de partir para o código desta aplicação, devemos entender uma coisa: A placa Arduino utilizada não é capaz de criar bancos de dados e tabelas, conforme será visto adiante, portanto, para que seja possível registrarmos valores de temperatura em um banco de dados MySQL, devemos criar manualmente o banco de dados no servidor MySQL e também a tabela na qual serão efetuados os registros.

Além disso, devemos também realizar a criação de um usuário para ser utilizado neste nosso projeto.

O primeiro passo para que seja possível realizar a integração do Arduino com um banco de dados MySQL consiste em criar um usuário para acessar o servidor, bem como, a sua senha de acesso.

Quando nós instalamos um servidor MySQL em um computador, um usuário padrão chamado root (juntamente com uma senha definida pelo usuário) é criado no momento da instalação, porém, recomenda-se que criemos um novo usuário para entrar no servidor através do mesmo. Este procedimento deve ser realizado por dois motivos, onde o primeiro é que o próprio desenvolvedor da biblioteca recomenda que isto seja feito e segundo por que existem vários relatos de que o Arduino não consegue se conectar ao servidor através do usuário root.

Para realizar este procedimento, basta entrar no terminal do servidor MySQL. Isto pode ser feito, primeiramente, acessando o Prompt de comando e percorrendo o caminho até a pasta onde o servidor foi instalado e em seguida, utilizando o comando apresentado na figura a seguir:

Após a realização do passo anterior, você deverá digitar a senha do usuário root (definida na instalação do servidor) e então será possível acessar diretamente o terminal.

Na figura anterior, criamos um usuário chamado arduino, o qual, está atrelado a uma senha também nomeada arduino. O símbolo determina que qualquer IP pode entrar no servidor MySQL através deste usuário. Obviamente, em termos de segurança, este não é o procedimento mais adequado, no entanto, para nossa demonstração, é suficiente.

Agora que já criamos o usuário, devemos criar um banco de dados dentro do servidor, chamado banco_arduino. Este procedimento é bastante simples e pode ser realizado da seguinte maneira:

Por fim, devemos criar uma tabela (que será preenchida pelo Arduino UNO), que por sua vez, será o local onde serão inseridas as informações referentes aos valores de temperatura provenientes do sensor de temperatura LM35. Queremos uma tabela com o seguinte formato:

Exemplo de medições no banco de dados MySQL
Exemplo de medições no banco de dados MySQL

Para isto, devemos proceder conforme a figura abaixo:

Veja como ficou a tabela criada

Neste momento, temos todos os pré-requisitos necessários para começarmos a realizar a aplicação proposta neste tutorial.

– Código do projeto

Segue o código a ser utilizado no Arduino para registrar valores de temperatura em um banco de dados MySQL

#include <Ethernet.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>
#include <SPI.h>

#define LM35 A0

int leitura;
float leituraconvertida
char sentenca[128];
char valortemp[10];

byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

IPAddress server_addr(192,168,25,5);  
char user[] = "arduino";              
char password[] = "arduino";        

char INSERIR_TEMP[] = "INSERT INTO registrotemp (temperatura) VALUES (%s)";
char BANCODEDADOS[] = "USE banco_arduino";

EthernetClient client;
MySQL_Connection conn((Client *)&client);

void setup() 
{ 
   Serial.begin(115200);
   while (!Serial); 
   Ethernet.begin(mac_addr);
   Serial.println("Conectando...");
   if (conn.connect(server_addr, 3306, user, password)) 
   {
      delay(1000);
      
      MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
      cur_mem->execute(BANCODEDADOS);
      delete cur_mem;
   }
   else
   {
      Serial.println("A conexão falhou");
      conn.close();
   }
}


void loop() 
{
   Serial.println("Executando sentença");

   leitura = analogRead(LM35);
   leituraconvertida = (float(analogRead(LM35))*5/(1023))/0.01;

   dtostrf(leituraconvertida, 4, 1, valortemp);
   sprintf(sentenca, INSERIR_TEMP, valortemp);
   
   MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
   cur_mem->execute(sentenca);
   delete cur_mem;

   delay(2000);
}

Entendendo a fundo

Software

Neste momento, iremos explicar o funcionamento do código apresentado, porém, de maneira bastante detalhada.

- Incluindo as bibliotecas a serem utilizadas no projeto

Primeiramente, para desenvolvermos uma aplicação como esta, devemos incluir todas as bibliotecas que serão utilizadas no código, para que assim, o mesmo possa funcionar de maneira adequada. A biblioteca Ethernet.h é responsável pela comunicação que será estabelecida entre o Arduino UNO e a rede através do Shield ethernet wiznet w5100. Já a biblioteca SPI.h  tem como função coordenar a integração do shield citado com o Arduino UNO por meio do protocolo de comunicação SPI.

As bibliotecas MySQL_Connection MySQL_Cursor têm como função promover a conexão Arduino UNO/servidor MySQL e executar as sentenças de manipulação de informações em um banco de dados.

#include <Ethernet.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>
#include <SPI.h>

- Nomeando o pino de entrada analógica através da diretiva #define

Em seguida, utilizamos a diretiva #define para associar o pino de entrada analógica A0 ao nome LM35 (vale ressaltar que isso é apenas um recurso para facilitar a didática da programação, portanto, não obrigatório).

#define LM35 A0

- Declarando as variáveis a serem utilizadas no projeto

Posteriormente, temos um bloco onde ocorre a declaração das variáveis que serão utilizadas no decorrer do programa. As variáveis leitura (tipo inteiro) e leituraconvertida (tipo float) são responsáveis por armazenar o valor obtido da porta de entrada analógica A0 (através da função analogRead(), portanto, contido no intervalo de 0 a 1023) e o valor já convertido em temperatura, respectivamente.

int leitura;
float leituraconvertida;

Observe que também foram criados dois vetores do tipo char, estes são: sentenca e valortemp. Os elementos citados servirão para conter as frases (lembre-se que um vetor de elementos do tipo char é um vetor de caracteres) necessárias para a construção das sentenças que serão utilizadas para manipular os dados no servidor MySQL.

O tamanho dos vetores deve ser tal que os mesmos consigam armazenar as mensagens que serão utilizadas, sendo assim, não existe um valor certo para os mesmos, mas sim, um valor que atenda as necessidades conforme será visto mais adiante. Note que também é possível não declarar um valor para o tamanho, deixando que o programa calcule automaticamente a dimensão do mesmo.

char sentenca[128];
char valortemp[10];

- Definindo o endereço MAC do Arduino UNO

O próximo passo consiste em definir o endereço MAC que será atribuído ao Arduino UNO para que a conexão entre o mesmo e a rede possa ser estabelecida. No desenvolvimento deste projeto, conectamos o Shield Ethernet em nosso modem.

Na prática, este endereço pode ser qualquer um, desde que seja único na rede.

byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

- Definindo os parâmetros para a conexão com o servidor MySQL

Após a realização dos procedimentos listados anteriormente, deve-se definir os parâmetros necessários para que o Arduino UNO consiga ser conectado ao servidor MySQL existente. A primeira informação essencial é IP do servidor MySQL (caso o servidor esteja rodando, por exemplo, no seu laptop, o IP a ser inserido neste campo será justamente o IP do seu computador na rede local e para consulta-lo basta abrir o prompt de comando, digitar ipconfig e copiar o Endereço IPV4 (se estiver em inglês, IPV4 Address)).

IPAddress server_addr(192.168.25.5);

Veja como esta informação pode ser obtida:

Em seguida, escolhe-se um dos usuários cadastrados e a senha do mesmo, para que o Arduino UNO entre no servidor MySQL através destas informações. Neste caso, utilizamos o usuário chamado arduino cuja senha atribuída ao mesmo é arduino.

char user[] = "arduino";             
char password[] = "arduino";

- Criando as sentenças para manipulação de dados

Agora, devemos criar as sentenças que serão utilizadas pelo Arduino UNO para registrar as informações no banco de dados existente no servidor MySQL. 

A primeira sentença informa ao Arduino UNO qual dos bancos de dados existentes no servidor MySQL será manipulado, neste caso, o banco chamado banco_arduino.

Quando estamos interagindo diretamente com um servidor MySQL através do seu terminal, utilizamos a sentença "USE <nome do banco de dados>;" para selecionar um determinado banco de dados existente no servidor em questão. Sendo assim, declaramos um vetor de variáveis do tipo char, sem tamanho definido, para que este armazene a sentença citada anteriormente, de modo que, quando necessário, o Arduino UNO seja capaz de utilizá-la.

char BANCODEDADOS[] = "USE banco_arduino";

A segunda sentença é responsável por preencher uma linha de uma determinada tabela existente dentro de um banco de dados, neste caso, a tabela chamada registro.

Quando manipulamos uma tabela de um banco de dados através do terminal de um servidor MySQL, utilizamos a sentença "INSERT INTO <nome da tabela> <coluna a ser preenchida da tabela> VALUES <valor a ser colocado na interseção da coluna definida anteriormente com próxima linha vazia não preenchida>;" para preencher uma determinada linha da mesma. Desta maneira, assim como no item anterior, declaramos um vetor de variáveis do tipo char para que seja possível armazenar a sentença adequada para o propósito citado.

char INSERIR_TEMP[] = "INSERT INTO registrotemp (temperatura) VALUES (%s)";

- Declarando os objetos client e conn

Neste momento, cria-se dois objetos que serão utilizados posteriormente, de modo que, um destes é do tipo EthernetClient, chamado client (que representará o elemento responsável pela comunicação via ethernet no código) e outro do tipo MySQL_Connection, chamado conn (que será responsável pela conexão com o servidor MySQL).

Lembre-se: client e conn são apenas nomes, sendo assim, é importante ressaltar que, os objetos identificados por client e conn poderiam ser chamados de quaisquer outros nomes, como por exemplo, conexaoethernet e conexaomysql, respectivamente.

EthernetClient client;
MySQL_Connection conn((Client *)&client);

- Estabelecendo a conexão com o servidor MySQL

Primeiramente, utilizamos a função Serial.begin() para inicializar a comunicação serial. Neste caso, determinamos como parâmetro da função uma taxa de 115200 baud/s em virtude deste valor ter sido utilizado pelo desenvolvedor da biblioteca presente neste tutorial. Em seguida, recorremos à função while() com o argumento !Serial, para que o programa só continue sendo executado após a comunicação serial ter sido estabelecida.

Não só estes procedimentos, como todos os outros que envolvem a manipulação da porta serial, servem apenas para testes, isto é, para que você possa verificar se o programa está com algum tipo de erro ou se está funcionando perfeitamente, portanto, as linhas referentes aos mesmos podem ser comentadas caso o programa esteja funcionando da maneira desejada.

 Serial.begin(115200);
 while (!Serial); // wait for serial port to connect

Em seguida, utilizamos a função Ethernet.begin() para iniciar a comunicação com a rede via Ethernet. Observe que o parâmetro desta função é o endereço MAC definido anteriormente.

Ethernet.begin(mac_addr);

Para facilitar na visualização da execução do programa, imprimimos na porta serial a seguinte informação: "Conectando..."

Serial.println("Conectando...");

A próxima linha de código conta com uma função if(), cujo argumento é uma outra função, responsável pela conexão do Arduino com o servidor MySQL, de modo que, nesta função são passados como parâmetros o endereço IP da máquina onde está o servidor, a porta para o acesso do mesmo (geralmente, na instalação do servidor, a porta que vem definida como padrão é a 3306), o usuário e a senha do mesmo. Caso esta função consiga ser executada com exito, isto é, caso a conexão com o servidor ocorra sem problemas, o argumento testado na função if() será verdadeiro e o seu conteúdo será executado.

if (conn.connect(server_addr, 3306, user, password)) 
{
    ****** Conteúdo da função if() ******
}

O conteúdo da função if() começa com a utilização de uma função delay() para estabelecer um atraso na execução do programa e garantir o estabelecimento da conexão com o servidor MySQL.

delay(1000);

Em seguida, criamos um objeto do tipo MySQL_Cursor, chamado cur_mem. Este cursor será responsável por executar as sentenças que serão utilizadas para manipular as informações do banco de dados.

MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);

Posteriormente, utilizamos a função execute(), de modo que, o parâmetro da mesma é justamente a variável do tipo char BANCODEDADOS. Lembre-se que o conteúdo desta variável é a frase "USE banco_arduino", que por sua vez, é o comando responsável por selecionar o banco de dados banco_arduino, entre os outros eventuais bancos existentes no servidor.

cur_mem->execute(BANCODEDADOS);

Por recomendação do desenvolvedor da biblioteca, após a execução da sentença desejada, apagamos o cursor criado anteriormente, em virtude do uso de memória.

delete cur_mem;

Confira o conteúdo completo da função if()

if (conn.connect(server_addr, 3306, user, password)) 
{ 
    delay(1000);
  
    MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
    cur_mem->execute(BANCODEDADOS);
    delete cur_mem;
}

Caso a condição da função if() não seja satisfeita, isto é, se a conexão com o servidor não tiver ocorrido com sucesso, executa-se o conteúdo da função else, que por sua vez, consiste nas funções Serial.println() para imprimir uma mensagem de falha na conexão e a função close(), responsável por encerrar a tentativa de conexão.

{
     Serial.println("A conexão falhou");
     conn.close();
}

Observe como está a nossa função setup():

void setup() {
 
  Serial.begin(115200);
  while (!Serial); 
  Ethernet.begin(mac_addr);
  Serial.println("Conectando...");
  if (conn.connect(server_addr, 3306, user, password)) 
  {
     delay(1000);
   
     MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
     cur_mem->execute(BANCODEDADOS);
     delete cur_mem;
  }
  else
  {
     Serial.println("A conexão falhou");
     conn.close();
  }
}

- Registrando a temperatura em banco de dados MySQL

O primeiro procedimento a ser executado na função loop() é o envio de uma mensagem através da porta serial avisando ao usuário que algum tipo de manipulação no banco de dados está sendo executada.

Serial.println("Executando sentença");

Em seguida, realiza-se a leitura da porta de entrada analógica (através da função analogRead()) na qual está conectado o sensor e armazena-se o resultado na variável leitura.

leitura = analogRead(LM35);

Posteriormente, realizamos a conversão do valor inteiro adquirido para valores de temperatura. O cálculo apresentado e toda explicação sobre o sensor de temperatura LM35 estão presentes no nosso tutorial LM35 - Medindo a temperatura com Arduino.

leituraconvertida = (float(analogRead(LM35))*5/(1023))/0.01;

O próximo passo consiste na conversão do valor de temperatura de float para string. Isso deve ser feito para que este valor possa ser inserido em uma sentença (lembre que elas são montadas sobre um vetor de char) e assim, possa ser utilizado para manipular as informações do banco de dados.

A função utilizada para cumprir este propósito é a dtostrf(). Nesta função, existem quatro parâmetros, onde estes são: a variável do tipo float que queremos converter, o número de algarismos que o resultado da conversão deve ter (incluindo a vírgula), o número de casas após a vírgula e o vetor de char em que será armazenada a informação retornada por esta função.

dtostrf(leituraconvertida, 4, 1, valortemp);

Veja com mais detalhes o funcionamento desta função:

Após a conversão do valor citado, utilizamos a função sprintf() construir a sentença contendo a instrução que será utilizada na manipulação do banco de dados. O primeiro parâmetro desta função consiste na variável do tipo char na qual será armazenada a sentença após ser construída, o segundo, deve conter a variável que armazenou a parte textual da frase e o local onde será inserida a variável (%s) e o terceiro parâmetro é justamente a variável que será inserida no local especificado no segundo parâmetro.

sprintf(sentenca, INSERIR_TEMP, valortemp);

Veja um esquema detalhado do funcionamento da função:

Em seguida, realizamos o mesmo procedimento apresentado anteriormente para manipular o banco de dados, onde, primeiramente criamos o cursor, executamos uma sentença (deste vez é a sentença para incluir uma linha na tabela) e por fim, deletamos o cursor criado.

MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
cur_mem->execute(sentenca)
delete cur_mem;

Por fim, utilizamos a função delay() para fazer com que o banco de dados seja preenchido apenas a cada 2 segundos

delay(2000);

Veja como ficou a nossa função loop()

void loop() {
 
  Serial.println("Recording data.");

  leitura = analogRead(LM35);
  conversao = (float(analogRead(LM35))*5/(1023))/0.01;

  dtostrf(conversao, 1, 1, temperatura);
  sprintf(sentenca, INSERIR _TEMP, temperatura);
  
  // Initiate the query class instance
  MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
  // Execute the query
  cur_mem->execute(query);
  // Note: since there are no results, we do not need to read any data
  // Deleting the cursor also frees up memory used
  delete cur_mem;
delay(2000);
}

Considerações finais

Neste tutorial demonstramos um conteúdo novo e muito interessante para aqueles que gostam de desenvolver aplicações com uma placa Arduino mas não sabem como, por exemplo, registrar informações para uso posterior. Aqui, apresentamos os procedimentos necessários para fazer com que seja possível elaborar um projeto integrando o processo de aquisição de dados com o Arduino UNO e o armazenamento dos mesmos em um banco de dados de um servidor MySQL. Esperamos que você tenha gostado deste conteúdo e sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.


Display LCD 20x4 e 16x2 com Adaptador I2C

Display LCD 20x4 e LCD 16x2 com Adaptador I2C – Utilizando o display com Arduino

No tutorial sobre a utilização de um display lcd 16x2 com Arduino aprendemos a importância dos displays e como usar um LCD de caracteres, em especial o 16x2. Apesar de esse LCD ser prático e simples, ele possui um problema, uma grande demanda por ligações. Para resolver isso, podemos usar um módulo adaptador I2C que facilita ainda mais o uso desse tipo de recurso. Nesse tutorial iremos aprender a usar o Display LCD 20x4 com Adaptador I2C junto a um Arduino.

O uso tanto do display LCD 16x2 tanto do display LCD 20x4 é muito semelhante, a diferença entre eles é o numero de caracteres que dispõem na tela. Como falamos sobre o modelo 16x2 no último tutorial, iremos aproveitar a oportunidade para mostrar um pouco mais sobre o modelo 20x4. Caso você tenha em suas mão o 16x2, você poderá facilmente adaptar o programa usado nesse tutorial para você.

[toc]

Porque usar comunicação I2C para controlar seu LCD?

Display LCD 20x4 Azul
Display LCD 20x4 Azul

Na figura acima, percebemos a existência de uma grande quantidade de contatos para realização do seu acionamento. Para facilitar o seu uso, iremos trabalhar com o adaptador I2C para display LCD.

Para usar esse LCD diretamente no Arduino, você irá precisa, além das ligações de alimentação,  de 6 pinos: RS, EN, D7, D6, D5, e D4 para que seu LCD converse com seu Arduino. Se você estiver trabalhando com um projeto mais complexo, talvez você não terá tantos pinos disponíveis no seu Arduino para seu LCD da forma usual.

Com o módulo de interface I2C, você precisará de apenas 2 pinos (I2C) para imprimir as informações que deseja em seu LCD. Se você já tiver usando outros componentes I2C em seu projeto, esse pino não precisará usar mais nenhuma porta, visto que ele poderá usar os mesmo pinos já usado para o outro dispositivo I2C.

Adaptador I2C para Display LCD 20x4 e 16x2

Adaptador I2C para display LCD
Adaptador I2C para display LCD

Para que seja possível a comunicação entre o Arduino e o LCD, precisaremos de um adaptador I2C. Esse adaptador nada mais é  que um conversor cuja função consiste em manipular os contatos do LCD, de modo que, após este processo, teremos apenas 2 contatos para realizar a comunicação com uma placa Arduino através do protocolo I2C.

Ele conta com o chip PCF8574T ou PCF8574AT que é responsável por essa interface . Você pode encontrar vários modelos de módulos ligeiramente diferentes.

Em geral eles possuem o seguinte formato:

detalhamento Adaptador I2C LCD
detalhamento Adaptador I2C para display LCD

Como você pode ver na imagem, a maioria dos módulos de interface I2C para LCD possuem:

  • Pinos para conexão com o Display (16 pinos);
  • Pinos de Alimentação do Módulo (GND e VCC);
  • Pinos de comunicação I2C (SDA e SCL);
  • Trimpot para ajuste de contraste da tela;
  • Jumper para ligar e desligar a luz de fundo (Backlight);
  • Led indicador de módulo ligado.
  • Chip de Interface (PCF8574T ou PCF8574AT )

Endereço do módulo I2C

Para alguns modelos ainda é possível configurar o endereço do módulo I2C através de A0, A1 e A2. Abaixo você pode conferir a tabela de endereços possíveis para cada um dos chips (PCF8574T ou PCF8574AT ):

Endereços configuráveis para os chips PCF8574T e PCF8574AT.( L para 0V e H para 5V)

A0, A1 e A2 são portas do nosso Chip:

Portas do chip PCF8574T e PCF8574AT
Portas do chip PCF8574T e PCF8574AT

Que em geral vem ligados a alimentação do módulo (VCC):

Esquema de ligação dos pinos de endereço
Esquema de ligação dos pinos de endereço

Quando conectamos o ponto 1 com 1, 2 com 2 ou 3 com 3, estamos colocando um nivel lógico baixo em A0, A1 ou A2 respectivamente. Na figura anterior, os pinos A0, A1 e A2 estão conectados ao chip do módulo. Veja que segundo esse esquemático, estamos com 5V em cada um dos 3 pinos. Ou seja, nosso endereço será 0x27 caso o chip seja o PCF8574T ou 0x3F caso o chip seja o PCF8574AT.

tabela do lcd i2c

Para alterar o endereço podemos colocar um ponto de solda para conectar os pinos A0, A1 ou A2 ao GND para as placas que tenha essa opção:

Opção para alteração de endereço

Para conectar os pinos A0, A1 ou A2 ao GND, você precisa pode usar solda de estanho para ligar o ponto de baixo com o de cima, tal como na figura a seguir:

Adaptador com chip PCF8574T com A0, A1 e A2 conectados ao GND. logo o endereço será 0x20.

Display LCD 20x4 com adaptador I2C

Para o nosso tutorial, iremos usar um LCD que já possui o adaptador soldado ao módulo display. Para o display que usaremos não temos a opção de mudança de endereço:

Display LCD 20x4 com adaptador
Display LCD 20x4 com adaptador

Veja em detalhes o módulo I2C usado:

Repare que ele não tem a opção de mudança de endereço. O chip dele é o PCF8574T, ou seja, iremos usar o endereço 0x27.

Display LCD 16x2 com adaptador I2C

Você também pode usar a versão do Display LCD 16x2 com adaptador I2C. A maior diferença é a quantidade de caracteres. Explicaremos mais a frente como adaptar o programa que usamos nesse tutorial para o display LCD 16x2.

O endereçamento funcionará da mesma forma que o explicado anteriormente. Verifique o modelo do seu adaptador para descobrir o endereço do mesmo.

Display LCD 16x2 Azul + Adaptador I2C
Display LCD 16x2 Azul + Adaptador I2C

Mãos à obra – Imprimindo informações no display LCD 20x4 I2C

Componentes utilizados

Caso tenha um LCD 16x2 ou 20x4 e queira adapta-lo, basta adquirir o Módulo i2C separado.  Módulo I2C para Display LCD compativel com 16x02 e 20x4

Montando o projeto

Na figura abaixo, o leitor poderá conferir como foi realizada a montagem do projeto apresentado neste tutorial.  Lembre-se de montar o projeto com o seu Arduino desligado.

Esquema de montagem do Display LCD 20x4 Azul + Adaptador I2C com Arduino Micro
Esquema de montagem do Display LCD 20x4 Azul + Adaptador I2C com Arduino Micro

Esquema de montagem do Display LCD 20x4 Azul + Adaptador I2C com Arduino UNO
Esquema de montagem do Display LCD 20×4 Azul + Adaptador I2C com Arduino UNO

Veja como ficou o nosso:

Projeto montado com Display LCD 20x4 Azul + Adaptador I2C com Arduino Micro

Programando

Antes de adentrarmos na apresentação do código, disponibilizamos uma seção para ajudar aqueles que são iniciantes no assunto. Sinta-se livre para prosseguir caso você já tem domínio da IDE do Arduino.

Conectando o Arduino ao computador

Primeiramente, conecte seu Arduino ao computador e abra a IDE Arduino. Em seguida, é necessário selecionar a porta COM na qual o Arduino está conectado (este procedimento pode ser feito clicando no menu Ferramentas (tools) e em seguida escolhendo-se a porta correspondente no submenu Porta (port). Neste caso, a porta na qual está o Arduino é apresentada da seguinte maneira: COM3 (Arduino Micro).

Por fim, garanta também que o tipo de placa apropriado esteja selecionado (isso pode ser feito acessando o menu Ferramentas (tools) e o submenu Placa (board)).

- Biblioteca

Para desenvolver o projeto proposto com o Display LCD I2C 20X4 utilizou-se uma biblioteca capaz de atuar sobre o protocolo I2C para facilitar os processos de endereçamento e troca de dados que fazem parte do funcionamento do protocolo citado. Esta biblioteca pode ser encontrada aqui.

Adquirindo e instalando a biblioteca que será utilizada

Após a realização do download dos arquivos compactados no formato ZIP, abra a IDE do Arduino, selecione o menu Sketch, o submenu Incluir Bilioteca e por fim, basta clicar na opção Adicionar biblioteca .ZIP (Add ZIP Library) e encontrar o arquivo que acabou de ser baixado.

Uma outra forma de fazer isso é extrair o conteúdo do arquivo ZIP dentro da pasta Libraries (onde foi instalada a IDE do Arduino).

– Código do projeto

Segue o código a ser utilizado no Arduino para imprimir informações no Display LCD I2C 20x4.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Inicializa o display no endereco 0x27
LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3, POSITIVE);
 
void setup()
{
 lcd.begin (20,4);
}
 
void loop()
{
  lcd.setCursor(0,0);
  lcd.print("********************");
  lcd.setCursor(9,1);
  lcd.print("VIDA");
  lcd.setCursor(5,2);
  lcd.print("DE SILICIO");
  lcd.setCursor(0,3);
 lcd.print("********************");
}

Entendendo a fundo

Software

- Incluindo as bibliotecas

Inicialmente, observe que foi necessário incluir duas bibliotecas no código para que o mesmo pudesse funcionar corretamente. A biblioteca wire.h é a responsável pela comunicação utilizando o protocolo I2C enquanto a biblioteca LiquidCrystal_I2C.h atua sobre a biblioteca wire.h simplificando o processo de comunicação através do protocolo citado, para que assim, o usuário possa utilizar o Display LCD I2C 20x4 de maneira mais fácil.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

- Criando o objeto lcd 

Em seguida, cria-se um objeto que será utilizado posteriormente para representar o Display LCD I2C 20x4 no código.

Lembre-se: lcd é apenas um nome, sendo assim, é importante ressaltar que este objeto poderia ser chamado por qualquer outro nome, como por exemplo, display.

LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3, POSITIVE);

Essa função é padrão tanto para o LCD 20x4 como para o 16x2. Nela definimos o endereço do adaptador, que para o nosso equivale sempre 0x27.

Além do endereço, definimos, nesse comando, os  pinos no chip I2C usados para conexões no LCD. Como esse pinos sempre são os mesmos, temos esse comando sendo usado para definir apenas o endereço, que para alguns módulos pode ser alterado. As demais configurações são padrões.

// Define os pinos do chip I2C usados para as conexões do LCD:
//               (Endereço,en,rw,rs,d4,d5,d6,d7,bl, blpol)
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

- Definindo as configurações iniciais

Dentro da função setup() utilizamos a função lcd.begin() (repare que o nome lcd corresponde ao objeto criado anteriormente) para inicializar o Display LCD I2C 20x4, de modo que, os parâmetros utilizados são o número de colunas e o número de linhas do display, nesta ordem.

void setup()
{
 lcd.begin (20,4);
}

Veja que, caso esteja usando um display LCD 16x2, aqui você definirá o tamanho do LCD com 16 colunas e 2 linhas:

void setup()
{
 lcd.begin (16,2); //configuração para display 16x2
}

- Imprimindo informações no Display

O primeiro passo na manipulação do display consiste em localizar o cursor no local adequado. Este cursor nada mais é do que o elemento que apontará para o espaço que será preenchido com um caractere, sendo assim, utilizamos a função setCursor() para determinar qual será o ponto de partida da escrita de uma sequência de caracteres.

Perceba que a as posições dos espaços para escrita são dadas da seguinte forma:

Desta maneira, ao utilizarmos "0" e "0" como parâmetros, estaremos definindo a coordenada (0,0) como ponto de partida para o começo da escrita.

lcd.setCursor(0,0);

Em seguida, utilizamos a função print() para poder escrever algo a partir da posição que definimos como ponto de partida. Neste caso, simplesmente preencheremos com '*'.

lcd.print("********************");

Posteriormente, utilizamos novamente a função setCursor() para posicionar o cursor na segunda linha.

lcd.setCursor(9,1);

Com o cursor posicionado, escrevemos a palavra 'VIDA'.

 lcd.print("VIDA");

Para continuar, posicionamos o cursor na próxima linha.

lcd.setCursor(4,2);

E escrevemos as palavras "DE SILICIO".

lcd.print("DE SILICIO");

Para finalizar, posicionamos o cursor no início da última linha.

lcd.setCursor(0,3);

Neste momento, iremos proceder da mesma maneira que fizemos na primeira linha, preenchendo a mesma com '*'.

lcd.print("********************");

Veja como ficou nossa função loop():

void loop()
{
  lcd.setCursor(0,0);
  lcd.print("********************");
  lcd.setCursor(0,1);
  lcd.print("aaaaaaaaaaaaaa");
  lcd.setCursor(0,2);
  lcd.print("ssssssssssssssss");
  lcd.setCursor(0,3);
  lcd.print("ddddddddddddddd");
}

Adaptando o programa para o display LCD 16x2

Para adaptar esse programa para o LCD 16x2 você precisa ter em mente que a tela é menor. Tendo 16 colunas e 2 linhas.

- Definindo as configurações iniciais

Dentro da função setup() utilizamos a função lcd.begin()  para inicializar o Display LCD I2C 16x2, de modo que, os parâmetros utilizados são o número de colunas e o número de linhas do display, nesta ordem.

void setup()
{
 lcd.begin (16,2); //configuração para display 16x2
}

- Imprimindo informações no Display

Na manipulação do display precisamos localizar o cursor no local adequado usando o comando setCursor() . Perceba que a as posições dos espaços para escrita são dadas da seguinte forma:

Em seguida basta usar o comando lcd.print().


Considerações finais

Neste tutorial buscamos elaborar um conteúdo semelhante ao que já temos sobre a utilização de displays LCD, no entanto, neste caso, utilizamos um display que ao invés de utilizar vários pinos numa placa Arduino, este necessita apenas de 4 pinos em virtude de a comunicação ser feita através do protocolo de comunicação I2C. Esperamos que você tenha gostado deste conteúdo, sinta-se à vontade para nos dar sugestões, críticas ou elogios. Lembre-se de deixar suas dúvidas nos comentários abaixo.


Comunicação Wireless TCP com ESP (Parte 2)

Comunicação Wireless TCP com ESP

Daremos inicio a segunda parte do nosso material sobre comunicações Wireless. No tutorial anterior, foi abordado sobre o protocolo UDP, que não é orientado à conexão. Desta vez, vamos aprender sobre o protocolo TCP, este por sua vez, é orientado à conexão, que nos garante a entrega de mensagens, ordenação do recebimento/envio, etc. O código aqui apresentado irá funcionar tanto para ESP8266 quanto para o ESP32, já que a diferença é mínima e funciona da mesma forma.

 

[toc]

Protocolo TCP

TCP (Transmission Control Protocol) é um protocolo para transmissão de dados voltado à conexão, ou seja, permite que as maquinas se comuniquem e gerenciem o estado atual da conexão com seus clientes e servidores. Uma característica importante do TCP é seu gerenciamento do status da rede e os dados, com isto, podemos saber se o dado enviado foi realmente entregue ao destinatário, também garante a entrega ordenada das informações sem que haja colisões e perdas inperceptíveis. Muitas aplicações usam o TCP para efetuar suas comunicações, sendo amplamente usado em todo tipo de situação, ao contrario do UDP que por não ser orientado à conexão, pode gerar erros em nossos sistemas.


Mãos à obra

Componentes necessários

Obs: Você pode usar qualquer aplicativo ou programa para transmitir os pacotes TCP. Nós usaremos o primeiro encontrado na Play Store para ser fácil de vocês encontrarem caso queiram usar também. Link do TCP Client na Play Store

Código do projeto

#ifdef ESP8266//Se estiver usando ESP8266, automáticamente irá adicionar as bibliotecas do ESP8266.
#include <ESP8266WiFi.h>
#include <WiFiServer.h>
#elif defined ESP32//Se estiver usando ESP32, fara a mesma operaçao.
#include <WiFi.h>
#endif

WiFiServer sv(555);//Cria o objeto servidor na porta 555
WiFiClient cl;//Cria o objeto cliente.


void setup()
{
    Serial.begin(115200);//Habilita a comm serial.

    WiFi.mode(WIFI_AP);//Define o WiFi como Acess_Point.
    WiFi.softAP("NodeMCU", "");//Cria a rede de Acess_Point.

    sv.begin();//Inicia o servidor TCP na porta declarada no começo.
}

void loop()
{
    tcp();//Funçao que gerencia os pacotes e clientes TCP.
}

void tcp()
{
    if (cl.connected())//Detecta se há clientes conectados no servidor.
    {
        if (cl.available() > 0)//Verifica se o cliente conectado tem dados para serem lidos.
        {
            String req = "";
            while (cl.available() > 0)//Armazena cada Byte (letra/char) na String para formar a mensagem recebida.
            {
                char z = cl.read();
                req += z;
            }

            //Mostra a mensagem recebida do cliente no Serial Monitor.
            Serial.print("\nUm cliente enviou uma mensagem");
            Serial.print("\n...IP do cliente: ");
            Serial.print(cl.remoteIP());
            Serial.print("\n...IP do servidor: ");
            Serial.print(WiFi.softAPIP());
            Serial.print("\n...Mensagem do cliente: " + req + "\n");

	    //Envia uma resposta para o cliente
            cl.print("\nO servidor recebeu sua mensagem");
            cl.print("\n...Seu IP: ");
            cl.print(cl.remoteIP());
            cl.print("\n...IP do Servidor: ");
            cl.print(WiFi.softAPIP());
            cl.print("\n...Sua mensagem: " + req + "\n");
			
        }
    }
    else//Se nao houver cliente conectado,
    {
        cl = sv.available();//Disponabiliza o servidor para o cliente se conectar.
        delay(1);
    }
}

Colando para funcionar

Devo lembrar que o IP padrão do ESP em modo Acess_Point é 192.168.4.1

1-) Precisamos nos conectar na rede WiFi criada pelo micro controlador.

2-) Logo, iremos adicionar o servidor com seu IP e PORTA no aplicativo. Lembre-se que você pode usar qualquer aplicativo ou programa de computador para isso.

 

3-) Após incluir os dados do servidor no aplicativo, podemos conectar-se e enviar os dados.

 

 

Obs: Também há dados disponíveis no Serial monitor, que o micro controlador escreveu, olhe como ficou.


Entendendo a fundo

Software

-Função WiFiClient::connected()

if (cl.connected())//Detecta se há clientes conectados no servidor.
{

}

Esta função retorna se há cliente conectado em nosso servidor. Também irá retornar que há clientes até que todos dados sejam lidos do buffer, se não, continuará aparecendo clientes conectados até que todos dados sejam lidos.

-Função WiFiClient::available()

if (cl.available() > 0)//Verifica se o cliente conectado tem dados para serem lidos.
{

}

Esta função, retorna a quantidade de bytes disponiveis para a leitura no buffer do cliente. Pode ser usada para detectar se há dados, e também para efetuar a leitura byte a byte do buffer, afim de montar a String final.

-Função WiFiClient::print()

cl.print();

Usada para enviar a String para o cliente. Há várias maneiras de mandar uma informação para o cliente, desde write(), printf() até print() e println().

-Função WiFiServer::available()

cl = sv.available();//Disponabiliza o servidor para o cliente se conectar.

Esta função, obtem um cliente que esta conectado ao servidor e tem dados disponiveis para a leitura. Pode ser entendida a grosso modo que diz ao cliente que há um servidor disponivel para enviar dados.


Desafio

O desafio desta vez, é tentar conectar multiplos clientes ao mesmo tempo em seu servidor. Este código não permite isto, então faça alterações e estude sobre as bibliotecas usadas para permitir multiplas conexões!

Fechamento

Neste tutorial, você aprendeu a efetuar uma troca simples de mensagens entre o Cliente (nosso celular) e o Servidor (ESP), pode ser usada de mesma forma para comunicação entre dois micro controladores. Na parte 3 deste material, aplicaremos as aulas passadas em um aplicativo em Android ou PC para se comunicar com nosso ESP8266/32. Não se esqueça de comentar sobre duvidas, elogios e criticas! Também aceitamos sugestões sobre a terceira parte deste material.

 


Comunicação Wireless UDP com ESP (Parte 1)

Comunicação Wireless UDP com ESP

Neste material, iremos aprender a fazer uma comunicação Wireless UDP entre dois ESP8266 para transmissão de informações. O grande diferencial do ESP é sua comunicação Wireless com suporte a WiFi, então nada mais justo que aprender a usar isto. Lembrando que este código também funciona para o ESP32.

 

[toc]

Protocolo UDP

O protocolo UDP, da camada de transporte, nos permite de forma rápida e descomplicada, o envio de informações através da rede. A simplicidade de usar o UDP é compensada ao fato de não ser uma comunicação orientada à conexão, como por exemplo o TCP, logo, não há garantia que os pacotes sejam recebidos de forma ordenada ou se quer sejam recebidos. Usa-lo para aplicações simples é recomendado, já que não são dados críticos; a perda de pacotes (improvável, porém possa acontecer) não é tão prejudicial ao sistema. Iremos transmitir de um Cliente para um Host.

Esta comunicação simples pode ser feita para transmitir dados até um banco de dados em um computador ou informações para outros Micro controladores. As aplicações são as mais diversas e variadas possíveis, novamente, o limite é sua imaginação.

Lembre-se, serão dois ESP8266, um cliente e outro host. Os dois códigos estarão logo abaixo!

Veja como é rápido o processo de envio e recebimento dos dados. O cliente pisca quando envia o pacote e o host  pisca após receber o pacote, é tão rápido que os dois parecem piscar juntos:

 


Mãos à obra

Componentes necessários

 

Hardware

Acenderemos o LED_BUILTIN do NodeMCU para indicar a transmissão de dados. Este LED OnBoard, está conectado ao pino D4 do NodeMCU.

Código do projeto

Cliente

#include <ESP8266WiFi.h>//Biblioteca do WiFi.
#include <WiFiUdp.h>//Biblioteca do UDP.

WiFiUDP udp;//Cria um objeto da classe UDP.
long x;//Variavel para ser enviada.

void setup()
{
   pinMode(D4, OUTPUT);//Habilita o LED onboard como saida.
   digitalWrite(D4, 1);//Desliga o LED.

   WiFi.mode(WIFI_STA);//Define o ESP8266 como Station.
}

void loop()
{
   connect();//Sub-rotina para conectar-se ao host.

   send();//Sub-rotina para enviar os dados ao host.

   delay(500);//Aguarda meio segundo.
}

void connect()//Sub-rotina para verificar a conexao com o host.
{
   if (WiFi.status() != WL_CONNECTED)//Caso nao esteja conectado ao host, ira se conectar.
   {
      WiFi.begin("NodeMCU", "");//Conecta à rede do host.
      delay(2000);//Espera ate que a conexao seja feita.
   }
}

void send()//Sub-rotina para enviar dados ao host.
{
   if (WiFi.status() == WL_CONNECTED)//Só ira enviar dados se estiver conectado.
   {
      x = random(0, 1000);//Gera um numero aleatorio entre 0 e 1000.
      udp.beginPacket("192.168.4.1", 555);//Inicializa o pacote de transmissao ao IP e PORTA.
      udp.println(x);//Adiciona-se o valor ao pacote.
      udp.endPacket();//Finaliza o pacote e envia.

      digitalWrite(D4, 0);//-
      delay(5);//-
      digitalWrite(D4, 1);//Pisca o led rapidamente apos enviar.
   }
   else//Caso nao esteja com uma conexao estabelicida ao host, piscara lentamente.
   {
      digitalWrite(D4, 0);
      delay(250);
      digitalWrite(D4, 1);
   }
}

 

Host

#include <ESP8266WiFi.h>//Biblioteca do WiFi.
#include <WiFiUdp.h>//Biblioteca do UDP.

WiFiUDP udp;//Cria um objeto da classe UDP.

String req;//String que armazena os dados recebidos pela rede.

void setup()
{
   pinMode(D4, OUTPUT);//Habilita o LED onboard como saida.
   digitalWrite(D4, 1);//Desliga o LED.

   Serial.begin(115200);//Habilita a comunicaçao serial para a string recebida ser lida no Serial monitor.

   WiFi.mode(WIFI_AP);//Define o ESP8266 como Acess Point.
   WiFi.softAP("NodeMCU", "");//Cria um WiFi de nome "NodeMCU" e sem senha.
   delay(2000);//Aguarda 2 segundos para completar a criaçao do wifi.

   udp.begin(555);//Inicializa a recepçao de dados UDP na porta 555
}

void loop()
{
   listen();//Sub-rotina para verificar a existencia de pacotes UDP.
}

void listen()//Sub-rotina que verifica se há pacotes UDP's para serem lidos.
{
   if (udp.parsePacket() > 0)//Se houver pacotes para serem lidos
   {
       req = "";//Reseta a string para receber uma nova informaçao
       while (udp.available() > 0)//Enquanto houver dados para serem lidos
       {
           char z = udp.read();//Adiciona o byte lido em uma char
           req += z;//Adiciona o char à string
       }

       //Após todos os dados serem lidos, a String estara pronta.

       Serial.println(req);//Printa a string recebida no Serial monitor.

       digitalWrite(D4, 0);//-
       delay(5);//-
       digitalWrite(D4, 1);//Pisca o LED rapidamente apos receber a string.
    }
}

 

Entendendo a fundo

Software

Recomendamos que vocês a leiam esta referência sobre WiFi, praticamente todos comandos disponíveis estão explicados AQUI.

Cliente

 

-Enviando dados para o destino

udp.beginPacket("192.168.4.1", 555);//Inicializa o pacote de transmissao ao IP e PORTA.
udp.println(x);//Adiciona-se o valor ao pacote.
udp.endPacket();//Finaliza o pacote e envia.

Nesta parte, usamos 3 funções do UDP, entre elas estão:

-Função WiFiUDP::beginPacket()

udp.beginPacket("192.168.4.1", 555);

Estamos enviando o pacote para o IP "192.168.4.1" que é o IP padrão do host no ESP8266, na porta 555.

 

-Função WiFiUDP::println()

udp.println(x);

Adicionamos o valor da variável X ao pacote.

 

-Função WiFiUDP::endPacket()

udp.endPacket();

Por ultimo, fechamos o pacote para finalmente ser enviado ao destino.

 

Para melhor entendimento, veja esta figura:

 

  • Vermelho = beginPacket();
  • Verde = print();
  • Azul = endPacket();

 


Host

 

-Função WiFiUDP::parsePacket()

udp.parsePacket();

Esta função faz a verificação de novos dados no buffer. Se houver dados novos para serem lidos, a função irá retornar um numero maior que zero.


Desafio

O desafio agora é você fazer uma mensagem de retorno para quem enviou uma mensagem ao host, por exemplo, quando o cliente 1 enviar dados ao host, o host responda "OK". Também faça um Print do IP de quem foi recebido o dado. Na referencia do WiFi (citado acima), há os comandos necessários!

 

Finalizando

Com a possibilidade de comunicação entre dispositivos pelo WiFi ou Wireless Ponto-a-Ponto, podemos fazer projetos muito legais e redes de dispositivos para se comunicarem. Não se esqueça de ver a parte 2 do material, sobre TCP! Dúvidas? Sugestões? Críticas? Comente abaixo!


Servidor WEB com ESP - NodeMCU

Servidor WEB com NodeMcu - ESP

Vamos aprender à criar um Servidor WEB usando HTML e TCP/IP em nosso pequeno ESP8266 ou ESP32. Para essa experiência usaremos o NodeMcu, mas daremos as instruções para você fazer o mesmo projeto com o ESP32. Um servidor web é, como o nome sugere, um servidor de informações que serão fornecidas pelo MCU através da internet ou até LAN. Podemos acessar estes dados em computadores, celulares ou outros MCU's, e também enviar informações e instruções para o MCU.

Http servidor web

Aplicação prática

Acionar LEDs, motores, luzes, ventiladores, etc. Você terá uma interface HMI (Interface Homem-Máquina) e com isso, conseguirá manipular seu sistema das mais diversas formas. Ver status de funcionamento de sensores ou atuadores, as possibilidades são muitas, depende de você. Mostraremos apenas o básico, o controle de um LED por botão, porém, após você entender o funcionamento deste sistema, conseguira fazer muitas coisas!

Para este projeto, você verá o básico necessário para implementar com sucesso um acionamento (transmissão de dados SITE->MCU).

TCP

O protocolo TCP/IP (Transmission Control Protocol) é um protocolo para transmissão orientado à conexão, ou seja, permite que as maquinas se comuniquem e gerenciem o estado atual da transmissão.

Uma característica muito importante sobre o TCP é seu gerenciamento do status da rede e os dados, com isto, podemos saber se o dado enviado foi realmente entregue ao destinatário, também garante a entrega ordenada das informações sem que haja colisões e perdas imperceptíveis.

De um jeito mais fácil, TCP será nosso “Caminhão”, que irá levar as informações até o navegador de quem acessar nosso IP.


HTML

HTML é uma linguagem de marcação utilizada em sites da WEB e são interpretadas pelos navegadores (http request). Quando o usuário se conectar ao IP do ESP pelo navegador, o mesmo irá enviar os dados no formato do HTML via TCP e com isso, após o navegador receber os dados, irá mostrar a página web!

Clique aqui para ver mais Informações sobre HTML


Mãos à obra

Componentes necessários

Hardware

Vamos acender o LED_BUILTIN do NodeMCU, este LED OnBoard, está conectado ao pino D4 do NodeMCU.

NodeMcu trabalhando como servidor web

Código do projeto

Não se esqueça de colocar suas credenciais do WiFi na linha 14 para o funcionamento do código!

#include <ESP8266WiFi.h>//Biblioteca que gerencia o WiFi.
#include <WiFiServer.h>//Biblioteca que gerencia o uso do TCP.

WiFiServer servidor(80);//Cria um objeto "servidor" na porta 80 (http).
WiFiClient cliente;//Cria um objeto "cliente".

String html;//String que armazena o corpo do site.

void setup()
{
   Serial.begin(9600);//Inicia comunicaçao Serial.

   WiFi.mode(WIFI_STA);//Habilita o modo STATION.
   WiFi.begin("SUA REDE", "SUA SENHA");//Conecta no WiFi (COLOQUE O NOME E SENHA DA SUA REDE!).

   Serial.println(WiFi.localIP());//Printa o IP que foi consebido ao ESP8266 (este ip que voce ira acessar).
   servidor.begin();//Inicia o Servidor.

   pinMode(D4, OUTPUT);//Define o LED_BUILTIN como Saida.
}

void loop()
{
   http();//Sub rotina para verificaçao de clientes conectados.
}

void http()//Sub rotina que verifica novos clientes e se sim, envia o HTML.
{
   cliente = servidor.available();//Diz ao cliente que há um servidor disponivel.

   if (cliente == true)//Se houver clientes conectados, ira enviar o HTML.
   {
      String req = cliente.readStringUntil('\r');//Faz a leitura do Cliente.
      Serial.println(req);//Printa o pedido no Serial monitor.

      if (req.indexOf("/LED") > -1)//Caso o pedido houver led, inverter o seu estado.
      {
         digitalWrite(D4, !digitalRead(D4));//Inverte o estado do led.
      }

      html = "";//Reseta a string.
      html += "HTTP/1.1 Content-Type: text/html\n\n";//Identificaçao do HTML.
      html += "<!DOCTYPE html><html><head><title>ESP8266 WEB</title>";//Identificaçao e Titulo.
      html += "<meta name='viewport' content='user-scalable=no'>";//Desabilita o Zoom.
      html += "<style>h1{font-size:2vw;color:black;}</style></head>";//Cria uma nova fonte de tamanho e cor X.
      html += "<body bgcolor='ffffff'><center><h1>";//Cor do Background

      //Estas linhas acima sao parte essencial do codigo, só altere se souber o que esta fazendo!

      html += "<form action='/LED' method='get'>";//Cria um botao GET para o link /LED
      html += "<input type='submit' value='LED' id='frm1_submit'/></form>";

      html += "</h1></center></body></html>";//Termino e fechamento de TAG`s do HTML. Nao altere nada sem saber!
      cliente.print(html);//Finalmente, enviamos o HTML para o cliente.
      cliente.stop();//Encerra a conexao.
   }
}

Entendendo a fundo

Software

-Função WiFiServer::available()

cliente = servidor.available();

Aqui, estamos dizendo ao cliente que há um servidor disponível para conexão.

-Detectando clientes conectados

if (cliente == true){}

Com esta condicional, é verificado a existência de clientes conectados no ESP, e se sim, enviará o HTML para o cliente.

-Enviando a estrutura do HTML

cliente.print(html);

Após a criação da estrutura do HTML, precisamos enviar para o cliente. É feito com um simples print().

-Fechando conexão

cliente.stop();

Após o envio do HTML, encerramos a conexão pois não é necessário se manter conectado.


Foi usado um botão do tipo SUBMIT para fazer uma requisição GET ao Host, para entender melhor como funcionam os botoes no HTML, veja ESTE tutorial.

Fechamento

Com a possibilidade de receber e enviar dados pela internet, nossos horizontes ficam bem amplos. Podemos tanto controlar o MCU para por exemplo acionar o portão da garagem, ou descobrir se esta chovendo com sensores e etc. Dúvidas? Sugestões? Críticas? Comente abaixo!