Montando um contador de voltas

O contador de voltas - Giro motor

Se você deseja avaliar o movimento de um objeto, como por exemplo quanto tempo um corpo demora para percorrer uma determinada distância ou quantas vezes o objeto passa por um determinado ponto, é interessante utilizar um equipamento que consiga detectar movimentos e que exiba em um display as informações que você deseja obter do movimento avaliado. Neste tutorial, iremos aprender a construir um contador de voltas que se baseia em dados obtidos pelo sensor ultrassônico HC-SR04 e que exiba em um display LCD 16x2 informações como o número de voltas dada pelo objeto, o tempo da volta, o tempo total do percurso e a diferença entre o tempo da volta e o tempo ideal.

Esse tipo de equipamento pode ser usado, por exemplo, para se obter a velocidade de um veículo a cada vez que este passa pelo contador durante uma volta em uma pista, ou em aplicações esportivas, como no atletismo, onde é necessário medir o tempo de prova do atleta.

Arduino Uno

O dispositivo básico para o desenvolvimento do projeto é a plataforma a ser utilizada na programação das funcionalidades e na integração dos componentes, que neste caso poderá ser um Arduino Uno, com o qual grande parte dos leitores já estão familiarizados.

Arduino Uno

kit robotica educacional com Arduino ESP ou Microbit

Para os leitores que estão entrando agora no mundo da eletrônica e não conhecem esta plataforma, o link abaixo explica com clareza o que é e como funciona o Arduino Uno e outros:

https://portal.vidadesilicio.com.br/o-que-e-arduino-e-como-funciona/

O sensor ultrassônico HC-SR04

O sensor ultrassônico HC-SR04 é composto de um circuito pronto com um emissor e um receptor de ondas sonoras. O sinal emitido, ao colidir com qualquer obstáculo, é refletido de volta na direção do sensor. Durante todo o processo, o aparelho está com uma espécie de “cronômetro” de alta precisão funcionando. Assim, é possível saber quanto tempo o sinal levou desde a sua emissão até o seu retorno. Como a velocidade do som no ar é conhecida, é possível, de posse do tempo que o sinal levou para ir até o obstáculo e voltar, calcular a distância entre o sensor e o obstáculo.

Sensor Ultrassônico HC-SR04

O sensor possui 4 pinos:

  • VCC: alimentação em 5V
  • GND
  • Trigger: pino digital; responsável por emitir 8 pulsos ultrassônicos na frequência de 40khz em intervalos de tempo contínuos que, ao encontrarem um objeto, são parcialmente refletidos ao sensor
  • Echo: um PWM, que recebe a informação coletada pelo sensor e traduz como dados ao arduino - no código, esses dados são tratados e transformados nas informações exibidas à quem utiliza o sistema.

O sensor é capaz de medir distâncias de 2 cm a 4 m com precisão de 3mm, e consegue detectar objetos cuja área mínima é de 0,05 m².

O display LCD 16x2

O display LCD 16x2 é muito usado em projetos com arduino onde é necessário que haja uma apresentação visual de informações. No link abaixo você poderá ter maiores informações sobre o funcionamento do display LCD e seu uso com o Arduino Uno e outros:

https://portal.vidadesilicio.com.br/display-lcd-16x2-com-arduino/

O display LCD utilizado neste tutorial é formado por 16 colunas e 2 linhas, com backlight (luz de fundo) azul e letras na cor branca. O dispositivo LCD apresenta 16 pinos de contatos, os quais:

  • Pino 1 (VSS): GND
  • Pino 2 (VCC): alimentação em 5V
  • Pino 3 (V0): tensão para ajuste de contraste
  • Pino 4 (RS): seleção do sinal (1 para passar um dado, 0 para passar uma instrução)
  • Pino 5 (RW): habilitação de escrita e leitura (1 para ler, 0 para escrever)
  • Pino 6 (E): enable (1 para habilitar, 0 para desabilitar)
  • Pinos 7 a 14 (B0 a B7): barramento de dados (conectados aos pinos digitais do arduino)
  • Pinos 15 e 16 (A e K): responsáveis por fornecer energia aos LEDs que ficam ao fundo do display
Display LCD 16x2

Você poderá optar por utilizar um módulo I2C para ligar o arduino ao display, o que lhe poupará pinos e permitirá que você insira novos componentes e funcionalidades ao seu projeto. Com o módulo I2C, as 16 ligações do display ao arduino são reduzidas a 4. O link abaixo mostra como utilizar o LCD dessa maneira:

https://portal.vidadesilicio.com.br/display-lcd-20x4-16x2-adaptador-i2c/

Mãos a obra - Imprimindo informações no display a partir de dados obtidos pelo sensor

Componentes necessários

Montando o projeto

Esquemático do projeto
  • Conecte os pinos de VCC (ou VDD) do display, do sensor, dos leds e do potenciômetro ao 5V do arduino.
  • Conecte os pinos de GND do display, do sensor, dos LEDs e do potenciômetro ao GND do arduino.
  • Conecte o pino V0 do display ao terminal do meio do potenciômetro.
  • Conecte o pino RS do display ao pino digital 13 do arduino e o pino de enable do display ao pino 12 do arduino.
  • Aterre os pinos B0 a B3 que não serão utilizados, além do pino RW.
  • Interligue os pinos D4 a D7 ao pinos 11 a 8 do arduino, respectivamente.
  • Aterre o pino K do display e interligue o pino A ao 5V do arduino.
  • Conecte o pino de Trigger do sensor ao pino 7 do arduino, e o pino de Echo ao pino digital 6.
  • Faça a conexão do LED vermelho ao pino 4 do arduino e o LED verde ao pino 3, lembrando de colocar os resistores de 330 Ω entre os LEDs e os pinos digitais.
  • O pushbutton deve ser interligado ao 5V e ao GND do arduino, sendo que a ligação do GND deve ser feita através de um resistor de 1k Ω. Conecte o pino 5 do arduino ao pushbutton, sendo que a ligação deve ser entre o pino digital e o meio entre o pushbutton e o resistor de 1k Ω (divisor de tensão do potenciômetro).

Tendo em vista que o potenciômetro é um resistor de resistência variável, ele foi utilizado no projeto para variar o contraste do display. Além disso, o pino A do display foi interligado ao 5V para fornecer brilho máximo a tela, facilitando visualizar as informações que serão exibidas.

Para este projeto, considerou-se a situação de um veículo dando voltas em uma pista e, portanto, as informações exibidas no display são tempo da volta, tempo total, número de voltas e diferença entre o tempo da volta e o tempo ideal. Você pode alterar o código do projeto para exibir informações diferentes dependendo do seu interesse.

Considerando que o sensor ultrassônico é capaz de calcular distâncias, a detecção da passagem do veículo pelo sensor, contabilizando uma volta, foi feita a partir de uma faixa de distâncias detectadas pelo sensor que indicaria a passagem do veículo. Dessa forma, o sensor estaria continuamente medindo uma distância fixa e, se caso a distância medida fosse reduzida para um valor dentre uma faixa de valores estipulados, haveria a indicação de que o veículo passou pelo sensor e completou uma volta.

Um pushbutton foi utilizado para indicar o início da contagem pelo contador de voltas. Também utilizou-se um led vermelho para alertar se caso o tempo da volta fosse maior do que o tempo ideal e um led verde para se caso o tempo da volta fosse menor do que o tempo ideal estipulado.

Verifique como ficou nossa montagem na prática:

Montagem do projeto na prática

Bibliotecas

Para estabelecer a comunicação com o display e imprimir informações no LCD, foi utilizada a biblioteca “LiquidCrystal.h”. Esta biblioteca geralmente já acompanha a IDE do arduino e pode ser encontrada na aba “Incluir Biblioteca” dentro de “Sketch”.

Como encontrar a biblioteca “LiquidCrystal.h”

Ademais, para obter os dados gerados pelo sensor ultrassônico HC-SR04, foi utilizada a biblioteca “Ultrasonic.h”. Você pode baixar-lá no site:  https://github.com/filipeflop/Ultrasonic.

Instale a biblioteca no diretório padrão de suas bibliotecas. Geralmente, este diretório se encontra dentro da pasta “Arduino”, localizada em “Documentos”.

Adicionando a biblioteca ao diretório

Código do projeto

Segue o código a ser usado no projeto:

#include <LiquidCrystal.h>
#include <Ultrasonic.h>

//Define os pinos do Arduino ligados ao Trigger e Echo
#define PINO_TRG  7
#define PINO_ECHO 6

//Pino para push button de ação
#define pino_pushbutton 5

//Pinos conectados aos Leds
#define LEDVM 4
#define LEDVD 3

//Tempo ideal por volta em segundos
#define IDEAL 20

//Número total de voltas
#define NVOLTAS 11

//Variavel para armazenar o valor obtido pelo sensor
long microsec;

//Variavel para guardar o valor da distância obtida pelo sensor em cm
float cmMsec;

//Faixa de distancia para a identificacao da placa
float distancia_minima = 100;
float distancia_maxima = 200;

//Variaveis para armazenar o tempo
unsigned long tempoTotal = 0;
unsigned long tempoAnt = 0;
unsigned long tempoAtual = 0;
unsigned long tempoSeg = 0;
unsigned long tempoMin = 0;
unsigned long tempoInicial;
int diferenca = 0;

//Numero de voltas completadas
int voltas = 0;

//Inicializa o sensor ultrasonico e LCD nos pinos especificados
Ultrasonic ultrasonic(PINO_TRG, PINO_ECHO);
LiquidCrystal lcd(13, 12, 11, 10, 9, 8);

void IniciaLCD() {
  lcd.begin(16, 2);
  lcd.clear();
  lcd.home();
  lcd.print("TV=");
  lcd.setCursor(4, 0);
  lcd.print(":");
  lcd.setCursor(8, 0);
  lcd.print("TT=");
  lcd.setCursor(13, 0);
  lcd.print(":");
  lcd.setCursor(0, 1);
  lcd.print("NV=");
  lcd.setCursor(6, 1);
  lcd.print("Dif=");
  lcd.setCursor(14, 1);
  lcd.print("s");
}

void AtualizaLCD() {
  // Escreve tempo de volta
  lcd.setCursor(3, 0);
  lcd.print((int)tempoMin);
  lcd.setCursor(5, 0);
  if (((int)tempoSeg % 60) < 10) {
    lcd.print('0');
    lcd.print((int)tempoSeg % 60);
  }
  else lcd.print((int)tempoSeg % 60);

  // Escreve tempo total
  unsigned long TT = 0.001 * (tempoTotal - tempoInicial);
  lcd.setCursor(11, 0);
  if (((int)TT / 60) < 10) {
    lcd.print('0');
    lcd.print((int)TT / 60);
  }
  else lcd.print((int)TT / 60);
  lcd.setCursor(14, 0);
  if (((int)TT % 60) < 10) {
    lcd.print('0');
    lcd.print((int)TT % 60);
  }
  else lcd.print((int)TT % 60);

  // Escreve número de voltas
  lcd.setCursor(0, 1);
  lcd.print("NV=");
  lcd.setCursor(3, 1);
  lcd.print(voltas);

  // Escreve diferença de tempo
  int dif = abs((int)diferenca);
  lcd.setCursor(10, 1);
  if (diferenca >= 0.0)
    lcd.print('+');
  else lcd.print('-');
  if (dif < 10) {
    lcd.print('0');
    lcd.print('0');
    lcd.print(dif);
  }
  else if (dif < 100) {
    lcd.print('0');
    lcd.print(dif);
  }
  else lcd.print(dif);
}

void setup() {
  //Inicializa a serial
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.home();
  lcd.setCursor(4, 0);
  lcd.print("Contador");
  lcd.setCursor(1, 1);
  lcd.print("tempo de volta");
  pinMode(pino_pushbutton, INPUT);
  pinMode(LEDVM, OUTPUT);
  pinMode(LEDVD, OUTPUT);
}

void loop() {
  // Inicia Leds de alerta desligados
  digitalWrite(LEDVM, LOW);
  digitalWrite(LEDVD, LOW);

  while (digitalRead(pino_pushbutton) == 0); // Aguarda botão ser pressionado
  IniciaLCD();
  tempoTotal = millis();
  tempoAnt = tempoTotal;
  tempoInicial = tempoTotal;
  int aux; // Variável auxiliar

  while (voltas < NVOLTAS) {

    tempoTotal = millis();//Guarda o tempo total contado pelo arduino em milissegundos

    //Le os valores do sensor ultrasonico
    microsec = ultrasonic.timing();

    //Converte o tempo retornado pelo sensor na distância identificada em cm
    cmMsec = ultrasonic.convert(microsec, Ultrasonic::CM);

    if (cmMsec > distancia_minima && cmMsec < distancia_maxima) {

      //Para se obter o tempo da ultima volta em minutos
      tempoAtual = tempoTotal - tempoAnt;

      tempoAnt = tempoTotal;

      tempoSeg = (0.001) * tempoAtual;//conversao do tempo atual para segundos

      tempoMin = (tempoSeg / 60.0); //conversao do tempo atual para minutos

      //Numero de voltas
      voltas++;

      //Diferenca de tempo entre a volta executada e ideal
      diferenca = tempoSeg - IDEAL;

      //Verificar se o tempo está com desvio de +-10% do ideal
      if (tempoSeg > IDEAL * 1.1) {
        // Acende led alerta velocidade baixa
        digitalWrite(LEDVD, LOW);
        digitalWrite(LEDVM, HIGH);
      }
      else digitalWrite(LEDVM, LOW);
      if (tempoSeg < IDEAL * 0.9) {
        // Acende led alerta velocidade alta
        digitalWrite(LEDVD, HIGH);
        digitalWrite(LEDVM, LOW);
      }
      else digitalWrite(LEDVD, LOW);

      // Espera 5 seg após passagem pela chegada enquanto atualiza display
      if (voltas < NVOLTAS) {
        for (aux = 0; aux < 10; aux++) {
          delay(500);
          tempoTotal = millis();
          AtualizaLCD();
        }
      }
    }
    AtualizaLCD();
  }
  while (!digitalRead(pino_pushbutton));
  voltas = 0;
  tempoSeg = 0;
  tempoMin = 0;
  diferenca = 0;
  lcd.clear();
  lcd.print("Aperte o botao");
  lcd.setCursor(0, 1);
  lcd.print("p/ nova contagem");
  delay(800);
}

Colocando para funcionar

Veja como ficou o resultado final:

Testando o código

 

Testando o código

Entendendo a fundo

Software

- Função LiquidCrystal()

LiquidCrystal lcd(13, 12, 11, 10, 9, 8);

Esta função cria um objeto do tipo LiquidCrystal. Para o projeto em questão, os parâmetros da função são os pinos do arduino para: RS, Enable, B4, B5, B6, B7. Você pode verificar as outras três maneiras de declarar esta função no site:

https://www.arduino.cc/en/Reference/LiquidCrystalConstructor

- Função lcd.begin()

lcd.begin(16, 2);

Função responsável por inicializar a interface com o LCD e deve ser chamada antes de qualquer outro comando da biblioteca. Os parâmetros são o número de colunas e linhas do display.

- Função lcd.print()

lcd.print("TV=");

Esta função escreve o conteúdo na tela do LCD, na posição atual do cursor.

- Função lcd.setCursor()

lcd.setCursor(4, 0);

Função que posiciona o cursor do LCD na posição desejada na tela, onde o texto será escrito. Os parâmetros são as coordenadas referentes a coluna e a linha desejadas.

- Função Ultrasonic()

Ultrasonic ultrasonic(PINO_TRG, PINO_ECHO);

Esta função cria um objeto do tipo Ultrasonic. Os parâmetros da função são, em sequência, os pinos do arduino conectados ao Trigger e ao Echo do sensor.

- Função ultrasonic.timing()

microsec = ultrasonic.timing();

Esta função retorna o tempo de retorno do pulso emitido pelo sensor.

- Função ultrasonic.convert()

cmMsec = ultrasonic.convert(microsec, Ultrasonic::CM);

Função que converte o tempo retornado pelo sensor na distância identificada em cm.

- Função millis()

tempoTotal = millis();

Esta função retorna o tempo em milissegundos desde quando o arduino começou a executar o programa.

Fechamento

Com este tutorial aprendemos a desenvolver um dispositivo muito útil na avaliação do movimento de objetos, com diversas aplicações práticas. Espero que tenham gostado do conteúdo e não se esqueçam de deixar suas dúvidas, sugestões, críticas ou elogios nos comentários abaixo.


Montando um medidor de batimento cardíaco com Arduino

O que é um fotopletismógrafo?

Fotopletismógrafo é um aparelho com o qual podemos medir a frequência cardíaca através da variação do fluxo de sangue em determinada parte do corpo.

A medida que o coração bate, a densidade de sangue em determinado membro do corpo varia mantendo um comportamento bem definido que acompanha a frequência cardíaca. Desta forma, podemos medir a frequência cardíaca citada através do uso de um emissor e de um sensor de luz, pois a intensidade de luz que atinge o sensor varia juntamente com a densidade de sangue. Este tipo de processo é também chamado de hemodinâmico, devido ao seu princípio de funcionamento.

[toc]

kit arduino robótica educacional


Mãos à obra - Montando um fotopletismógrafo

Componentes necessários

Para a montagem do projeto necessitamos dos seguintes itens:

Observação: Para montar este dispositivo, você precisará de um led de alto brilho branco e de um sensor de luz. Neste caso usaremos o BPW34, que nada mais é que um foto receptor cuja sensibilidade é mais direcionada (a luz ambiente pouco interfere no resultado, já que o sensor é sensível a luz incidente em uma área bem determinada). Além disso, construiremos filtros e amplificadores de sinais usando capacitores, resistores e amplificadores operacionais.

Montando o projeto

– Montagem do sensor

Primeiramente faremos a montagem do nosso sensor. Para isso, cortamos um pedaço de velcro, de modo que possa cobrir o dedo indicador e através de furos inserimos o fotoemissor em uma parte e o fotorreceptor em outra. Para firmá-los colocamos cola quente nas laterais e na parte de trás. Nas imagens abaixo temos o fotoemissor e o fotorreceptor respectivamente:

 

 

– Bloco amplificador

Nas montagens de protoboard a seguir as duas linhas de alimentação mais externas serão destinadas ao Ground ou referência do circuito.

Feito isso, agora vamos ao primeiro bloco do nosso circuito para tratar o sinal. O fotorreceptor gera um sinal de corrente que é proporcional a luz que incide sobre ele. Com isso, precisamos de um bloco que transforma esse sinal de corrente em um sinal de tensão amplificado. Para isso, usamos um Amplificador de Transresistência, que está representado abaixo:

 

– Bloco do filtro passa-alta

Assim, partimos para a segunda parte do nosso projeto, que é um filtro passa altas de primeira ordem com frequência de corte em 1Hz e ganho unitário:

 

– Bloco filtro passa-baixa

A terceira parte é um filtro passa baixas de segunda ordem, com frequência de corte em 40Hz e ganho de 20dB:

 

Com isso, a montagem completa do circuito é mostrada abaixo:

Na montagem podemos ver um resistor circulado em vermelho que serve para limitar corrente no LED de alto brilho, já que ele é ligado com a mesma tensão de alimentação positiva dos amplificadores operacionais. Seu valor é 680 ohms.

O fotorreceptor deve ter um de seus terminais ligados na entrada inversora do amplificador de transresistência e o outro ligado ao GND.

Com isso, já podemos visualizar a onda correspondente aos batimentos cardíacos de uma pessoa no osciloscópio. Na figura abaixo é mostrada a onda de frequência cardíaca de uma pessoa usando a montagem deste tutorial.

Caso você não tenha acesso a um osciloscópio, poderá plotar esse mesmo sinal com o Serial Ploter do arduino. Para isso, será preciso dar um Offset no sinal para que não haja parte negativa, já que a entrada analógica do arduino aceita tensões de 0V a 5V. Assim sendo, podemos acrescentar uma outra parte no nosso circuito, que é um amplificador somador.

– Adicionando um offset ao sinal

Além de amplificar o sinal, este bloco do circuito soma uma tensão DC ao sinal que é uma fração da tensão de alimentação, de modo que o sinal permanece no intervalo apropriado ao arduino.

Repare que o amplificador usado no final será um Amplificador somador inversor, de modo que a forma de onda estará de “cabeça para baixo”. Com isso, você precisará inverter seu sinal no arduino (usando uma lógica simples com valores altos para tensões perto de 0V e valores baixos para tensões perto de 5V), antes de plotá-lo no Serial Plotter, ou você poderá optar por usar um amplificador somador não-inversor. Ou ainda, acrescentar mais um circuito amplificador inversor antes do amplificador de Offset, o que não será muito eficiente, mas funcionará bem.

Hardware montado

Com isso, nossa montagem final para representar o sinal no arduino será a seguinte:

Programando

Caso você não tenha o osciloscópio e deseje ver a forma de onda no seu computador, basta utilizar o seu arduíno com o código descrito abaixo. A saída da montagem precisa estar conectada na entrada A0 analógica do arduíno. O código abaixo possui a função de ler o sinal e monta o gráfico em função do tempo do sinal de entrada.

int analogPin = A0;
int sinal = 0;

void setup()
{
  Serial.begin(9600);
void loop()
{
  sinal = analogRead(analogPin);   
  Serial.println(sinal);     
}

Feito isto, basta apertar Ctrl+Shift+L.


Entendendo a fundo

Os batimentos do coração bombeiam sangue para as diversas partes do corpo de modo que a densidade sanguínea varia na mesma frequência que o coração bate. Com isso o sensor de luz na ponta do dedo indicador capta essa variação de densidade e transforma isso em um sinal de corrente que é amplificado e transformado em um sinal de tensão pelo amplificador de transresistência. O BPW34 é um fotorreceptor que funciona como uma fonte de corrente, com valores na faixa de µA, portanto, dependentes da luminosidade que incide nele.

Depois do amplificador de transresistência, temos um filtro passa-altas com frequência de corte de 1Hz, cuja função é atenuar toda e qualquer tensão com frequência menor que 1Hz. Deste modo, eliminamos qualquer tensão DC da iluminação natural sobre o sensor.

Com o filtro passa baixas de 40Hz, conseguimos atenuar tensões de frequência maiores que 40Hz, que na maioria das vezes são ruídos e não compõem os harmônicos do sinal de interesse.Esse filtro atenua as frequência maiores que 40hz de forma mais abrupta, pois ele é de segunda ordem. Além disso ele dá um ganho de 20dB (10 vezes) no sinal de entrada que está na banda de passagem (menor que 40Hz).

Todos os capacitores cerâmicos e os dois capacitores eletrolíticos (que ficam entre o +vcc e o terra e o outro entre o terra e o -vcc) servem para manter a tensão de alimentação dos amplificadores operacionais constantes e assim, eliminar ruídos e interferências.

No fim, o amplificador somador, além de amplificar o sinal, soma-o com uma tensão DC que neste caso é 0.22% da tensão de alimentação.

Se você ainda tiver problemas com ruído, talvez seja devido ao efeito capacitivo do diodo fotorreceptor. Para resolver isto, basta acrescentar um capacitor em paralelo com o resistor de 4.7MΩ. O valor deste capacitor deve o mesmo do efeito capacitivo do diodo, algo na faixa de pF, basta verificar no datasheet do componente (no caso do BPW34 é algo na faixa de 20 a 100 pF).


Considerações finais

Assim concluímos o nosso tutorial. Espero que todos consigam montar este, que é um dos dispositivos mais usados na área médica. Lembrem-se de verificar os valores de todos os componentes e testar cada bloco do projeto para que erros sejam facilmente detectados. Em caso de dúvidas, deixem nos comentários.


Lendo sensores analógicos em Deep Sleep com ULP - ESP32

Leitura de sensores analógicos pelo ADC com ULP

Neste tutorial, aprenderemos a ler um sensor analógico através do ADC no ESP32 em Deep Sleep, utilizando o ULP. Esse método de leitura, permite uma economia de bateria gigantesca, já que não precisamos acordar o microcontrolador para efetuar a leitura, situação na qual o gasto é bem maior do que quando mesmo procedimento é feito pelo ULP.

Figura 1 - ULP.

[toc]

kit robotica educacional com Arduino ESP ou Microbit

Por que utilizar?

Imagine que em seu projeto portátil, é preciso ler o sensor de temperatura a cada 30 segundos e para isso, logicamente, precisamos acordar o microcontrolador para efetuar essa tarefa, entretanto, o consumo do ESP32 nesse caso seria de 40mA apenas para ler o sensor. Com o ULP, podemos fazer essa leitura em Deep Sleep e o consumo enquanto o ULP está funcionando não passaria de 150uA, com uma média de consumo dependendo do duty cycle do ULP. Com isso, economizaríamos nesse caso de 150uA (100% duty cycle), aproximadamente 270x mais bateria do que se acordássemos o microcontrolador para essa mesma tarefa.

É fácil perceber o aumento incrível na duração da bateria que poderia ser obtido apenas ao usar o ULP para ler o sensor, as aplicações desse guerreiro são muito grandes, mas o foco é para Sleep.

Se você ainda não conhece o ULP, clique aqui para ver a introdução sobre este incrível coprocessador de baixo consumo presente no ESP32.


Mãos a obra - Lendo um sensor de temperatura em Deep Sleep

Componentes necessários

Códigos do projeto

- Main code (C ou C++), responsável pela programação do ESP32 em si.

#include <C:/msys32/ESP32/ESP32/components/arduino/cores/esp32/Arduino.h>
#include <C:/msys32/ESP32/esp-idf/components/driver/include/driver/rtc_io.h>
#include <C:/msys32/ESP32/esp-idf/components/driver/include/driver/adc.h>
#include <C:/msys32/ESP32/esp-idf/components/ulp/ulp.c>
#include <C:/msys32/ESP32/ESP32/build/main/ulp_main.h>
extern "C"
{
#include <C:/msys32/ESP32/esp-idf/components/esp32/include/esp_clk.h>
}
//Pode ser preciso arrumar os diretorios das bibliotecas
//Pode ser preciso remover o "extern 'C'{}" e definir a biblioteca fora dele, alguns usuarios relatam erro sem o uso do extern

extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start");
extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end");
void ulp();


extern "C" void app_main()
{
	initArduino();//inicia configuracoes do arduino, caso nao use o Arduino component, remova essa linha
	pinMode(2, OUTPUT);

	if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_ULP)//se o wakeup for por causa do ULP, tomara alguma atitude
	{
		digitalWrite(2, 1);
		delay(500);
		digitalWrite(2, 0);
	}
	else//se nao, iniciara o ULP
	{
		ulp();//configura e inicializa o ulp
	}
	

	esp_sleep_enable_ulp_wakeup();//habilita o wakeup pelo ULP
	esp_deep_sleep_start();//entra em deep sleep eterno
}




void ulp()
{
	adc1_config_channel_atten(ADC1_CHANNEL_4, ADC_ATTEN_11db);
	adc1_config_width(ADC_WIDTH_12Bit);
	adc1_ulp_enable();
	//configura o ADC1 #4 (GPIO32) para 3.3V 12bit e atribui o uso ao ULP
	
	ulp_set_wakeup_period(0, 10000000);//ativa o timer de wakeup do ULP apos cada HALT para 10seg

	ulp_load_binary(0, ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t));//carrega os arquivos
	ulp_run((&ulp_main - RTC_SLOW_MEM) / sizeof(uint32_t));//inicia o ULP
}

- ULP code (Assembly .S), responsável pela programação do ULP em si.

#include "soc/soc_ulp.h"
#include "soc/rtc_io_reg.h"
#include "soc/sens_reg.h"
#include "soc/rtc_cntl_reg.h"


.bss//secao das variaveis


.text//secao do codigo


	.global main
	main:

		move r0, 0//r0 = 0
		move r1, 0//r1 = 0
		stage_rst//stage_cnt = 0

		leitura:
			stage_inc 1//stage_cnt++
			adc r1, 0, 4+1//r1 = leitura ADC GPIO32
			add r0, r0, r1//r0 = r0+r1
			jumps leitura, 4, lt//loop responsavel pelas leituras, equivale a um FOR()

		rsh r0, r0, 2//calcula a media das 4 leituras r0 = r0/4
		jumpr wakeup, 496, ge//se a media da leitura que esta em r0 for maior ou igual que 496 (40 graus celsius), acorda o mcu
		halt//coloca o ULP em sleep e ativa o timer de wakeup (definido com 10 segundos no main code)

	wakeup:
		wake//acorda o mcu
		halt

Entendendo a fundo

Software

leitura:
			stage_inc 1
			adc r1, 0, 4+1
			add r0, r0, r1
			jumps leitura, 4, lt

		rsh r0, r0, 2
		jumpr wakeup, 496, ge
		halt

A parte interessante e diferente do código é justamente a leitura do canal ADC, nós poderíamos fazer mais simples sem utilizar uma estrutura de repetição FOR(), entretanto, é sempre interessante fazer uma média de leituras (inclusive com delay's) para evitar ruídos e coisas do tipo. Já ensinamos a fazer o laço FOR() no tutorial introdutório do ULP.

  1. É feito a leitura do canal ADC no GPIO32 4x e a cada leitura, o valor é somado no registrador R0.
  2. Após as 4 leituras precisamos tirar a média entre eles, entretanto, não há mnemônicos simples para divisão como "DIV". Usaremos os operadores de BitWise (RSH - Right Shift Bit) para dividir o valor por 4. Por causa da divisão facilitada com o RSH na base 2 (2, 4, 8, 16...), também faremos uma quantidade de leituras na base 2.

Não se esqueça de conferir o Set de Instruções do ULP nas referências em caso de dúvidas.

-Mnemônico ADC

adc r1, 0, 4+1

Efetua a leitura do ADC no GPIO32 e atribui o valor ao registrador R1.

O segundo e terceiro operador (parâmetro) deste mnemônico se refere a tabela abaixo, onde:

Segundo operador: Controlador ADC (ADC1 = 0 ou ADC2 = 1). Usamos "0" pois o GPIO32 faz parte do ADC1.

Terceiro operador: MUX+1. O GPIO32 esta descrito como "...CH4", logo foi usado seu canal+1 (4+1).

Figura 2 - Pinagem MUX do ADC.

-Mnemônico RSH

rsh r0, r0, 2

O Right Shift Bit foi usado para calcular a média das 4 leituras. Lembre-se que os valores decimais (após a vírgula) são excluídos, restando apenas os inteiros.

-Mnemônico JUMPR

jumpr wakeup, 496, ge

Esse é o nosso "IF a moda antiga", que pula para a label "wakeup" se o valor do ADC for maior ou igual que 496. Ocasionando no Wake up do ESP32 pelo ULP.

Pelo fato de operações aritméticas não serem tão simples neste Assembly do ULP, em vez da condicional (jumpr) que faz o wake up do ESP32 usar valores como 32°C, onde é preciso efetuar varias contas, usaremos o valor direto do ADC que economiza processamento e tempo. O valor 496 no ADC com o LM35 equivale a 40°C .

Mais informações sobre o LM35 podem ser vistas clicando aqui.


Considerações finais

Mesmo que as aplicações do ULP estejam voltadas a Sleep, podemos usa-lo até com o ESP32 ligado, para por exemplo ler o canal ADC enquanto o ESP32 faz outra tarefa em que não se possa "perder tempo" lendo os lentos canais de ADC. Também é possível criar funções ISR para criar interrupções entre ULP e Main Core, deixando a brincadeira em um nível muito mais sério e interessante.


Desafios

O desafio desta vez é criar a rotina de interrupção citada acima (ISR) para uma comunicação extremamente rápida e eficiente entre ULP e Main Core. Você pode procurar no datasheet sobre o registrador (bit) que o comando WAKE do ULP ativa quando o ESP32 não esta em Sleep e criar a ISR.

Referências

http://esp-idf.readthedocs.io/en/latest/api-guides/ulp_instruction_set.html

https://portal.vidadesilicio.com.br/ultra-low-power-coprocessor-ulp-esp32/


Sensor de Gás MQ-135 e a Família de sensores MQ

Sensor de Gás MQ-135 e a família MQ de detectores de Gás 

O sensor gás MQ-135 é capaz de detectar a concentração de vários gases tóxicos em um ambiente tais como: amônia, dióxido de carbono, benzeno, óxido nítrico e também fumaça ou álcool. Neste tutorial vamos aprender como usa o módulo sensor de gás MQ-135 junto a um Arduino.  Esse tutorial também pode ser aplicado para outros sensores de gás, com alguns ajustes, tais como: MQ-2, MQ-3, MQ-4, MQ-5, MQ-6, MQ-7, MQ-8,MQ-9, etc.

Detector de gás / sensor de gás MQ-135
Detector de gás / sensor de gás MQ-135

[toc]

A importância dos sistemas de proteção

Os processos industriais envolvem o uso e fabricação de substâncias altamente perigosas, especialmente produtos inflamáveis, tóxicos e oxidantes. Os gases fazem parte desses ambientes como participantes de reações, catalisadores ou produtos finais. Outras vezes são resíduos ou subprodutos indesejáveis. Escapes ocasionais de gás ocorrem e criam um perigo potencial para a planta industrial, seus funcionários e pessoas que vivem nas proximidades. Incidentes e acidentes em todo o mundo, envolvendo asfixia, intoxicação, explosões e perdas de vidas é um lembrete constante desse problema.

Por isso, sistemas automáticos de detecção de gases são fundamentais para a proteção das pessoas envolvidas nesses processos. É necessário que tenhamos sensores adequados e que sejam posicionados em lugares estratégicos, de preferência com redundância.

É claro que esse tipo de proteção não se limita a industria. Podemos ver facilmente a aplicação de sensores de gás e fumaça em uma cozinha residencial ou em ambientes públicos. Enfim, podemos usar a automação a favor da vida, evitando assim acidentes.

Sensor de gás MQ

Existe uma grande gama de sensores de gás, estre eles, temos os MQ's. Esses sensores de detecção modernos e de baixo custo para gás combustível, são do tipo eletro-catalítico. Eles são feitos de uma bobina de fio de platina aquecido eletricamente, coberto primeiro com uma base de cerâmica, tais como alumina e, em seguida, com um revestimento final exterior do catalisador de paládio ou ródio disperso em um substrato de tório.

- Por dentro do sensor MQ

Na figura a seguir podemos entender um pouco melhor como é por dentro de um sensor de gás MQ.

Dentro de um sensor de gás MQ

Na vertical temos um resistência elétrica que aquece o ar. Essa resistência é ligada através da alimentação dos pinos H's, um vai no 5V e o outro no GND (0V).

De A para B temos nosso sensor de gás. Em uma atmosfera onde possa haver gás poluidor, a resistência do sensor de gás diminui conforme a concentração do gás poluente aumenta. Ou seja, quanto mais gás poluente, menor será a resistência entre A e B. Podemos conferir as variação da resistência conforme a concentração de gases no gráfico à seguir retirado da folha de dados do MQ-135:

Comportamento da resistência entre A e B conforme a concentração de alguns gases. para o sensor de gás MQ135
Comportamento da resistência entre A e B conforme a concentração de alguns gases.

Sendo assim, podemos montar um circuito onde temos uma tensão que será proporcional à quantidade de gases  poluentes.

Esquema interno de um sensor de gás MQ 135
Esquema interno de um sensor de gás MQ

Conforme a resistência entre A e B diminuir (mais gases poluentes), maior será a tensão em cima do resistor RL. Falamos um pouco sobre esse tipo de circuito, o divisor de tensão, no tutorial sobre o sensor de luz LDR.

- Encapsulamento dos sensores MQ

Em geral, os sensores da família MQ possuem o formato como o da figura a seguir:

Encapsulamento de um MQ-135
Encapsulamento de um sensor de gás MQ-135

Como você pode ver, na parte de baixo temos alguns pinos. Ao todo são seis. Esse seis pinos dão acesso ao circuito interno já explicado.

Dentro do encapsulamento do MQ-135
Dentro do encapsulamento do sensor de gás MQ-135

Para facilitar o uso, podemos adquirir esse sensores junto a uma placa que já conta com o circuito necessário para seu pronto funcionamento alem de contar com um circuito comparador.

Família de sensores de gás MQ
Família de sensores de gás MQ

Lista de sensores de Gás

Aqui está a lista de alguns dos sensores de gás que você pode encontrar. Você pode escolher o mais adequado para o seu projeto.

Nome do Sensor  Sensível para
MQ-2 Detecção de gases inflamáveis: GLP, Metano, Propano, Butano, Hidrogênio, Álcool, Gás Natural, outros inflamáveis e fumaça.
MQ-3 Detecção de Álcool , Etanol e fumaça.
MQ-4 Detecção de Metano, Propano e Butano.
MQ-5 Detecção de GLP e gás natural
MQ-6 Detecção de gás GLP (Gás de Cozinha), Propano, Isobutano e Gás Natural Liquefeito
MQ-7 Detecção do gás Monóxido de Carbono
MQ-8 Detecção do gás hidrogênio
MQ-9 Detecção de Monóxido de Carbono e gases inflamáveis
MQ-131 Detecção de ozônio
MQ-135 Detecção de Gás Amônia, Óxido Nítrico, Álcool, Benzeno, Dióxido de Carbono e Fumaça
MQ-136 Detecção de Gás Sulfídrico H2S
MQ-137 Detecção de Gás Amônia
MQ-138 Detecção de n-hexano, benzeno, NH3, álcool, fumaça, CO, etc.

Módulo sensor de Gás MQ-135 - Gases tóxicos e Fumaça

O modulo utilizado, MQ-135 funciona bem detecção de fumaça e outros gases tóxicos, especialmente amônia, vapor de sulfeto e benzeno. Sua capacidade de detectar vários gases nocivos e menor custo faz do MQ-135 uma escolha ideal de diferentes aplicações de detecção de gás.

Ele pode detectar concentrações na faixa de 10 a 1.000ppm (partículas por milhão), possuindo um range de tensão de 0 - 5V. Os módulos do MQ135 são capazes de operar na faixa de temperatura de -10 a 70ºC, consumindo uma corrente aproximada de 150mA.

mq-135
Módulo sensor de amônia MQ-135

O módulo também conta com um potenciômetro para regular a sensibilidade do  sensor, girando ele para um dos lados o sensor ficara mais sensível aos gases.

Atrás dp Sensor de Gás MQ-135 - Gases tóxicos e Fumaça
Por trás do módulo Sensor de Gás MQ-135

Mãos a Obra - Desenvolvimento do Projeto

Componentes necessários

Montando o projeto

A montagem do circuito é bem simples e direta. Basta seguir o esquemático abaixo.

Esquema de montagem do Arduino com o Sensor de Gás MQ-135 - Gases tóxicos e Fumaça

O modulo MQ 135 possui 4 pinos: dois pinos para alimentação (Vcc e GND) e dois pinos para emissão dos sinais elétricos, sendo um sinal digital (D0) e o outro um sinal analógico (A0). Para realizar a montagem, iremos conectar os pinos na seguinte ordem:

Pinos do Sensor de Gás MQ-135 - Gases tóxicos e Fumaça

Em nossa experiência conectamos os pinos do sensor direto na placa Uno, sem o auxilio do protoboard, tal como indicado na tabela anterior. Veja como ficou o nosso montado:

Projeto montado na prática com um Arduino Uno e Sensor de Gás MQ-135 - Gases tóxicos e Fumaça

Programando

Segue o código que utilizamos nesse projeto para fazer a detecção de gás no ambiente.

#define MQ_analog A2
#define MQ_dig 7

int valor_analog;
int valor_dig;

void setup() {
   Serial.begin(9600);
   pinMode(MQ_analog, INPUT);
   pinMode(MQ_dig, INPUT);
}

void loop() {
   valor_analog = analogRead(MQ_analog); 
   valor_dig = digitalRead(MQ_dig);

   Serial.print(valor_analog);
   Serial.print(" || ");
   if(valor_dig == 0)
     Serial.println("GAS DETECTADO !!!");
   else 
     Serial.println("GAS AUSENTE !!!");
   delay(500);

}

Colocando para funcionar

Primeiramente precisamos deixar que a resistência interna do sensor de gás esquente o suficiente para que as medições se estabilizem. Espere por 3 minutos. Chamamos essa espera de tempo de queima. Explicaremos isso mais a frente.

Após deixar o sensor de gás esquentar, vamos testa-lo forçando o ambiente com um fosforo/isqueiro para gerar CO2 (fumaça). O monitor serial irá indicar o valor analógico lido pelo sensor e também indicara se o gás foi detectado ou não, isso é uma resposta ao sinal digital emitido pelo módulo, e esse será calibrado conforme nos quisermos ao girar o potenciômetro. Para calibrar a detecção digital vamos estimular o sensor com o gás do isqueiro e quando acharmos que a estimulação seja suficiente, giramos o potenciômetro até que ele altere o estado entre NÃO DETECTADO <-> DETECTADO, assim esse passa a ser o novo ponto de referencia digital.

Testando o Sensor de Gás MQ-135 - Gases tóxicos e Fumaça para calibrar
Sensor de gás sendo exposto à fumaça da queima do fósforo

As imagens a seguir mostram a sequência que o sensor digital teve alternando o estado de LOW <->HIGH quando o valor analógico estava próximo de 82, neste exemplo eu mantive o fosforo acesso por alguns segundos próximo ao sensor apenas. Veja que na sequência de valores analógicos chega até 380, então de acordo com a duração e proximidade do fosforo ao sensor podemos ir calibrando o sensor digital dele.

Detectando a fumaça
Durante a detecção da fumaça
Deixando de detectar a fumaça

Entendo a fundo

Software

– Nomeando os pinos utilizados através da diretiva #define

O primeiro passo do programa consiste fazer o uso das diretivas #define para nomear os pinos que serão utilizados no projeto, ou seja, o pinos que estarão conectados ao sensor apresentado anteriormente. Sendo assim, neste caso temos que o pino de entrada analógica do Arduino UNO A2 passa a ser identificado no código através do nome MQ_analog, enquanto, o pino de entrada digital 7 do mesmo será referenciado no código pelo nome MQ_dig.

#define MQ_analog A2
#define MQ_dig 7

– Declarando a variável responsável por armazenar o estado do sensor

Em seguida, declaramos duas variáveis para armazenar os valores que forem lidos pelas portas do Arduino UNO, sendo uma delas do tipo inteiro, para a parte analógica e a outra, booleana, para a parte digital.

int valor_analog;
bool valor_dig;

– Configurando o sistema

Dentro da função void setup() vamos configurar as portas do Arduino e a comunicação serial. Vamos iniciar a comunicação serial numa taxa de 9600 bits por segundo e as portas utilizadas devem ser setadas como ENTRADAS (INPUT), afinal eles irão receber sinais elétricos para o Arduino.

void setup() {
   Serial.begin(9600);
   pinMode(MQ_analog, INPUT);
   pinMode(MQ_dig, INPUT);
}

– Rodando o programa principal

Dentro do void loop() teremos o programa rodando em loop infinito, sendo assim iremos faremos a leitura das portas do Arduino e imprimiremos na serial os valores para que possamos ter parâmetros mensuráveis. Com a função analogRead() fazemos a leitura analógica da porta A2. Utilizaremos esse valor apenas como parâmetro para calibrar a sensibilidade digital do sensor.

valor_analog = analogRead(MQ_analog);

Utilizando a função digitalRead() temos a leitura booleana do sensor, quando a resposta for 1 o gás esta sendo detectado, e quando for 0 o gás está ausente. Veremos mais adiante que a sensibilidade do sensor precisa ser ajustada com o potenciômetro do modulo.

valor_dig = digitalRead(MQ_dig);

Por fim fazemos a impressão dos valores lidos na serial, para que assim, possamos ver o resultado das leituras.

if(valor_dig == 0)
 Serial.println("GAS DETECTADO !!!");
 else 
 Serial.println("GAS AUSENTE !!!");
Detectando o gás
Detectando o gás

Hardware

– Calibrando o módulo digital

Como dito antes é necessário calibrar o sensor digital do módulo MQ 135. Para isso rode o programa anterior e abra o monitor serial e, com auxilio de uma pequena chave Philips, gire o potenciômetro na parte de trás do módulo até que o você encontre um ponto que altere de 0 pra 1. O valor analógico irá servir como base para mediar a sensibilidade do sensor.

Atrás do sensor de gás e fumaça MQ 135 - Resistência de calibração
Atrás do módulo MQ 135 - Resistência de calibração

- Tempo de queima - Burn-in time

Para que o sensor esteja pronto para fazer as medições é necessário aguardar um tempo denominado como Burn -in time (Tempo de queima) ou preheat (pré aquecimento). Esse tempo varia de modelo para modelo, mas para testes mais simples, como para familiarizar com o sensor, podemos aguardar cerca de 3 minutos. Esse é o tempo necessário para que a resistência do sensor aqueça até a temperatura ideal de funcionamento do sensor. Durante esse período as medições podem oscilar muito.

Para aplicações oficiais, tal como implementação de um detector de incêndio, onde precisamos de uma precisão de medição maior e mais confiável,  é recomendado pelos fabricantes que o tempo de queima seja de pelo menos 24 horas. Esse é o tempo necessário para que o sensor alcance a plena estabilização das medições entre os terminais internos A e B.


Considerações finais

Este projeto apresenta uma utilização básica do sensor MQ 135. 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.

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


Touch capacitivo - ESP32

Touch capacitivo com ESP32

Nesse tutorial aprenderemos a usar sensores de touch capacitivo em nossos projetos com o ESP32, que tem suporte nativo a este recurso incrível. Em vários projetos, precisamos adicionar botões ou algum tipo de sensor para toque (pressão); o mais usado por ser barato e fácil, é o Push Button, porem, alem de dar um aspecto "velho" ao projeto, pode gerar problemas mais frequentes como por exemplo Bounce. Para contornar estes problemas, usaremos o Touch capacitivo, que é o mesmo do seu celular moderno (Smartphone), ao mínimo toque, é detectado e executado tal tarefa.


Mãos à obra - Implementando um touch capacitivo no ESP32

Componentes necessários

Montando o projeto

A montagem é simples, apenas sendo necessário ligar o jumper ao GPIO4, ficara parecido com o nosso:

Touch capacitivo esp32

Programando

long lastms;//Váriavel para guardar o ultimo toque.

void setup()
{
    Serial.begin(9600);//Inicia a comunicação Serial para visualização dos valores do Touch.
    pinMode(LED_BUILTIN, OUTPUT);//Define o LED OnBoard como saída
    touchAttachInterrupt(4, led, 20);//Atribui uma função (led) quando for detectado um valor menor de (20) ao pino (4).
    lastms = 0;//Inicializa a váriavel em 0.

    //Para chegar a este valor usado (20), é necessário apenas ver os valores que aparece no Serial monitor,
    //toque o fio e veja qual sera o novo valor. Ao tocar, a tendencia do valor é aproximar-se de 0.
}


void loop()
{
    Serial.println(touchRead(4));//Mostra o valor do touch no monitor.
    delay(100);
}

void led()//função que foi atribuida para o evento do touch.
{
    if (millis() - lastms > 150)//Verifica se o ultimo toque faz mais de 150mS
    {
        digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));//Inverte o estado do led.
        lastms = millis();//Salva o ultimo tempo em que foi tocado.
    }
}

Colocando para funcionar

Após o upload, podemos tocar na ponta do fio que perceberemos o LED invertendo seu estado. Se você manter tocado, verá que o LED ficará piscando, no intervalo de 150mS. Veja como ficou o nosso neste video:


Entendendo a fundo

Software

- Função de Interrupção touch -  touchAttachInterrupt()

touchAttachInterrupt(4, led, 20);

Esta função, atribui uma rotina de interrupção para quando for detectado um valor abaixo do definido para o pino. Neste caso, quando o ESP32 detectar um valor abaixo de 20 no pino 4, irá chamar a função led(). A nossa função led() apenas inverte o estado do led com um intervalo de tempo para que não pisque muito rápido.

Lembre-se que a função interrupção é como uma chamada telefônica. O controlador para tudo que está fazendo para atende-la.

- Função led()

A função led() é chamada através da interrupção no pino 4.

void led()//função que foi atribuida para o evento do touch.
{
    if (millis() - lastms > 150)//Verifica se o ultimo toque faz mais de 150mS
    {
        digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));//Inverte o estado do led.
        lastms = millis();//Salva o ultimo tempo em que foi tocado.
    }
}

Sabemos que o processamento de um microcontrolador é muito mais rápido do que podemos interagir. Quando acionamos o touch, o ESP chamará milhares de vezes a interrupção que foi atribuída a função led(). Por isso é importante implementarmos uma maneira de fazer com que a iteração do LED ocorra apenas após um determinado tempo

Uma forma de fazer isso é usar um contador de tempo com o auxilio da função millis(), uma variável auxiliar e um IF.

  1.  A função millis() conta o tempo em milissegundos desde que o ESP32 foi ligado.
  2.  A variável auxiliar armazena o valor do millis() da ultima vez que houve alteração do estado do LED
  3. A condicional IF compara o tempo atual do millis() com o tempo armazenado na variável auxiliar, se for maior que o tempo escolhido, ele entra na rotina do IF, altera o estado do LED e novamente armazena o novo tempo de millis().

Ou seja: Essa rotina subtrai o tempo atual com o anterior, e se for maior que 150mS, irá inverter o LED e salvar o novo tempo. Dessa forma, só invertemos o estado do LED depois que passou 150ms da ultima mudança de estado.

Veja que se você ficar com o dedo pressionado o tempo todo, teremos o LED ligando e desligando de 150ms em 150ms.

Você poderia usar delay() também, mas o problema é que o delay mantem o microcontrolador parado contando o tempo enquanto esse tipo de rotina implementada permite que o controlador continue com a execução das outras tarefas.

Por isso essa função condicional é bastante usada para atribuir intervalos entre as ações, uma alternativa saudável para o delay().

- Função de leitura do touch

touchRead(4)

Esta função, retorna o valor do pino (Threshold). Este valor pode váriar de acordo do lugar de ESP32. Em nossos testes, ao plugar o ESP32 na Protoboard, o valor foi de 84 para 60. Os valores quando não estamos tocando ficaram em média de 60, e ao tocar, aproximou-se de 0.

Por isso definimos 20 na função anterior, pois ao tocar, o valor aproxima-se de 0, então colocando 20, teremos certeza que foi um toque e chamamos a função para inverter o LED.

- Uma outra forma de implementar o touch

Veja que você poderia implementar a leitura no seu programa sem usar a interrupção. Usando um IF na função loop por exemplo.

void loop()
{
    Serial.println(touchRead(4));//Mostra o valor do touch no monitor.
    delay(100);

    if(touchRead(4) < 20) //verifica se o valor lido é menor que 20
    {
      if (millis() - lastms > 150)//Verifica se o ultimo toque faz mais de 150mS
        {
          digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));//Inverte o estado do led.
          lastms = millis();//Salva o ultimo tempo em que foi tocado.
        }
    }
}

O programa todo ficaria assim:

long lastms;//Váriavel para guardar o ultimo toque.

void setup()
{
    Serial.begin(9600);//Inicia a comunicação Serial para visualização dos valores do Touch.
    pinMode(LED_BUILTIN, OUTPUT);//Define o LED OnBoard como saída
    lastms = 0;
}

void loop()
{
    Serial.println(touchRead(4));//Mostra o valor do touch no monitor.
    delay(100);

    if(touchRead(4) < 20) //verifica se o valor lido é menor que 20
    {
      if (millis() - lastms > 150)//Verifica se o ultimo toque faz mais de 150mS
        {
          digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));//Inverte o estado do led.
          lastms = millis();//Salva o ultimo tempo em que foi tocado.
        }
    }
}

Hardware

Antes do touch capacitivo entrar em uso continuo em celulares, o touch era resistivo, sendo necessário tocar a tela com certa pressão para que fosse detectado o toque. Já o touch capacitivo, é mais sensível e permitindo um manuseio mais fácil da tela. Veja a imagem representando o touch capacitivo:

Touch capacitivo esp32 1

Quando você toca no fio ou tela, há uma troca de elétrons entre as partes, e com isso, permite o nosso sistema detecta-lo.


Desafio

O desafio desta vez, é que você monte um teclado matricial com o touch do ESP32 para digitar uma senha por exemplo.

teclado matricial


Fechamento

Hoje você aprendeu a usar esta íncrivel função que ESP32 nos dá. Com ela, é possível deixar nosso projetos extremamente modernos e bonitos. Alem disto, você também pode usa-lo em conjunto com o ULP para acordar o ESP32 de Deep-Sleep, viabilizando projetos portáteis e vestíveis. Se houver alguma sugestão, dúvida ou crítica, comente abaixo que iremos te responder.


HC-SR04 - Sensor Ultrassônico com Arduino

HC-SR04 - Sensor Ultrassônico de distância com Arduino

O sensor ultrassônico HC SR04 é amplamente utilizado em aplicações onde se deseja medir distância ou evitar colisões, como na robótica móvel e de reabilitação. Neste tutorial aprenderemos como utilizar o Módulo Sensor HC-SR04 com Arduino.

Sensor Distância Ultrassônico HCSR04, HC-SR04 ou HC SR04
Sensor Distância Ultrassônico HC SR04

Sensor Ultrassônico HC-SR04

Tudo começa pela emissão de um pequeno pulso sonoro de alta frequência que se propagará na velocidade do som no meio em questão. Quando este pulso atingir um objeto, um sinal de eco será refletido para o sensor. A distância entre o sensor e o objeto pode então ser calculada caso saibamos o tempo entre a emissão e a recepção do sinal, além da velocidade do som no meio em questão. Afigura a seguir exemplifica o processo.

sensor ultrassônico HC-SR04 funcionamento
Sensor ultrassônico HC-SR04

Para uma melhor medição da distância, a área do objeto na qual a onda será refletida deve ser de pelo menos 0,5 m2.


Mãos à obra - Medindo distância com o HC-SR04

Componentes necessários:

Montando o projeto

Agora vamos conectar os componentes do projeto. Para isso, desligue o cabo USB de seu Arduino e monte seu circuito conforme a figura a seguir.

esquema de montagem do Arduino uno com Sensor ultrassonico HC-SR04, HCSR04

O HC SR04 possui 4 pinos sendo eles:

  • Vcc – Deve ser conectado a um pino 5V do Arduino.
  • Trig – Deve ser conectado a um pino digital configurado como saída. Utilizaremos o pino 8.
  • Echo – Deve ser conectado a um pino digital configurado como entrada. Utilizaremos o pino 7.
  • Gnd – Deve ser conectado a um pino GND do Arduino.

Programando

Crie um no programa (sketch) e salve com o nome de “programa_ultrassom_hcsr04”.

Nesse exemplo utilizaremos a biblioteca Ultrasonic.h. A utilização dessa biblioteca é bastante simples.

Clique aqui para baixa a biblioteca Ultrasonic.h
Clique aqui para baixar a biblioteca Ultrasonic.h

- Instalar a biblioteca pelo IDE do Arduino

Esse é o método mais fácil. Primeiramente, faça o download dos arquivos da biblioteca compactados no formato zip. Geralmente as bibliotecas já são distribuídas compactadas, porém às vezes é necessário fazer o download dos arquivos separadamente e compactá-los à parte. Em seguida, basta abrir o IDE e ir em “Sketch -> Incluir Biblioteca -> Adicionar biblioteca .ZIP” E selecionar o aquivo baixado:

Imagem explicando como adicionar uma biblioteca IDE Arduino

Com isso, a nova biblioteca foi instalada. Para utilizá-la, basta ir em “Sketch -> Incluir Biblioteca” e selecionar a biblioteca desejada.

Você pode ver mais detalhes sobre como adicionar uma biblioteca no tutorial Sensores DHT11 e DHT22 e o Uso de Bibliotecas.

- Código exemplo

Com o seu programa salvo, escreva nele o código abaixo:

//Leitura de distância com o sensor HC-SR04
#include <Ultrasonic.h>
 Ultrasonic ultrassom(8,7); // define o nome do sensor(ultrassom)
//e onde esta ligado o trig(8) e o echo(7) respectivamente

long distancia;

// Esta função "setup" roda uma vez quando a placa e ligada ou resetada
 void setup() {
 Serial.begin(9600); //Habilita Comunicação Serial a uma taxa de 9600 bauds.
 
 }

// Função que se repete infinitamente quando a placa é ligada
 void loop()
 {
   distancia = ultrassom.Ranging(CM);// ultrassom.Ranging(CM) retorna a distancia em
                                     // centímetros(CM) ou polegadas(INC)
   Serial.print(distancia); //imprime o valor da variável distancia
   Serial.println("cm");
   delay(100);
 }

Após escrever o código, salve e depois clique em Carregar (Upload) para que o programa seja transferido para seu Arduino.

Colocando para funcionar

Abra o Serial Monitor e coloque um obstáculo na frente do sensor ultrassônico. Se tudo deu certo, conforme você variar a distância do obstáculo em relação ao sensor, a distância medida aparecerá no serial monitor, tal como a figura a seguir.

monitor serial sensor ultrassônico HC-SR04 distância


Entendendo a fundo

Entendendo o Software

- Biblioteca Ultrasonic.h

Na elaboração do software utilizaremos a biblioteca Ultrasonic.h. Essa biblioteca implementa as funcionalidades do sensor ultrassom HC-SR04, tornando sua utilização extremamente simples.

- Declarando um Ultrassom

Para o uso dessa biblioteca devemos definir o nome do sensor e em quais pinos estão conectados os pinos trig e echo.

Ultrasonic nomesensor(trig,echo);

No exemplo a seguir, o nome do sensor é ultrassom, o pino do trig está conectado na porta 8 e o pino do echo na porta 7.

Ultrasonic ultrassom(8,7);

- Medindo a distância

Para ler a distância, basta chamar a função Ranging(CM). Para valor em centímetros, deve-se usar CM e para valor em polegadas, deve-se usar INC. Essa função retorna um valor de variável long.

long distancia = ultrassom.Ranging(CM); // distancia recebe o valormedido em cm

Observe que usamos o nome do sensor escolhido, no nosso caso ultrassom, seguido de ponto e o nome da função que queremos usar. Para o Arduino estamos falando que queremos usar determinada função do objeto mencionado, no nosso caso o ultrassom.

- Imprimindo na porta serial

Para imprimir o valor de distância lido usamos a função Serial.print().

Serial.print(distancia); //imprime o valor da variável distancia
Serial.println("cm");

Repare que na primeira linha imprimimos o valor da variável distância e na segunda linha imprimimos a palavra cm, que está entre aspas duplas. Sempre que quisermos imprimir um texto devemos colocá-lo dentro de aspas duplas, caso contrário o programa irá entender que o texto é o nome de uma variável.

Repare também que na segunda linha usamos o sufixo -ln depois de print. Esse sufixo informa que depois de escrito o texto, o programa deve pular uma linha.

Entendendo o Hardware

Como dito anteriormente, o sensor ultrassom mede a distância através da medição do tempo que uma onda leva para sair do emissor, colidir com um obstáculo e ser refletido, para, finalmente, ser detectado pelo receptor. Desta forma, podemos notar que nosso sensor ultrassom possui dois cilindros metálicos que se assemelham a olhos em sua placa. São, na realidade, dois altos falantes: um trabalha como o emissor do sinal ultrassom e o outro como receptor.

sensor ultrassônico HC-SR04
Sensor ultrassônico HC-SR04

- Fazendo a leitura do tempo

Para iniciarmos uma medição, o pino Trig, que funciona como gatilho do nosso sensor ultrassom, deve receber um pulso de 5V por pelo menos 10 microssegundos. Isso fará com que o sensor HC-SR04 emita 8 pulsos ultrassônicos em 40kHz (T piezzo) e o pino ECHO, que funcionará como nosso cronômetro, vai para 5V, iniciando assim a espera pelas ondas refletidas.

Assim que uma onda refletida for detectada, o pino Echo, que estava em 5V, será alterado para 0V. Desta forma, o período que o pino Echo fica em 5V é igual ao tempo que a onda emitida leva para ir até o obstáculo e voltar.

Veja a imagem abaixo para entender o que acontece no sensor HC-SR04.

gráfico de pulsos no sensor HCSR04, HC-SR04 ou HC SR04

Por fim, para sabermos quão longe nosso obstáculo está, basta contarmos quanto tempo (T) a tensão no pino Echo ficou em 5V. Em posse desse tempo, sabendo que ele é o dobro do tempo de ida e volta da onda do sensor ultrassônico até o obstáculo, e, considerando a velocidade do som igual a 340,29 m/s, temos:

formula som

Desta forma, temos que a distância até o obstáculo é igual a ΔS.

A função Ultrasonic.h faz exatamente o procedimento descrito, retornando apenas o valor da distância.

Outra opção de código

Poderíamos seguir o procedimento explicado usando o seguinte código:

// Leitura HC-SR04
const uint8_t trig_pin = 10;
const uint8_t echo_pin = 9;

uint32_t print_timer;

void setup() {
Serial.begin(9600); // Habilita Comunicação Serial a uma taxa de 9600 bauds.

// Configuração do estado inicial dos pinos Trig e Echo.
pinMode(trig_pin, OUTPUT);
pinMode(echo_pin, INPUT);
digitalWrite(trig_pin, LOW);
}

void loop() {
// Espera 0,5s (500ms) entre medições.
if (millis() - print_timer > 500) {
print_timer = millis();

// Pulso de 5V por pelo menos 10us para iniciar medição.
digitalWrite(trig_pin, HIGH);
delayMicroseconds(11);
digitalWrite(trig_pin, LOW);

/* Mede quanto tempo o pino de echo ficou no estado alto, ou seja,
o tempo de propagação da onda. */
uint32_t pulse_time = pulseIn(echo_pin, HIGH);

/* A distância entre o sensor ultrassom e o objeto será proporcional a velocidade
do som no meio e a metade do tempo de propagação. Para o ar na
temperatura ambiente Vsom = 0,0343 cm/us. */
double distance = 0.01715 * pulse_time;

// Imprimimos o valor na porta serial;
Serial.print(distance);
Serial.println(" cm");
}
}

Desafio

Sabendo como funciona um sensor ultrassônico, faça o programa que meça a distância sem o auxílio da biblioteca.

Fechamento

Esperamos que tenham gostado, deixe seu comentário com duvidas, sugestões ou com a foto ou vídeo de seu projeto!! Compartilhe à vontade.

 

Apostila Arduino Básico

 


DHT11 e DHT22 | Sensor de umidade e Temperatura com Arduino

DHT11 e DHT22,  Sensor de umidade e Temperatura com Arduino

Umidade e temperatura são duas grandezas que estão muito relacionadas quando o assunto é climatização. Nesse tutorial você aprenderá a medir essas duas grandezas através do sensor de umidade e temperatura DHT11 ou o DHT22 em conjunto com um Arduino.

[toc]

Sensores de umidade e temperatura DHT11 e DHT22

O sensor DHT11 e o sensor DHT22 são sensores básicos e de baixo custo que utilizam um termistor e um sensor capacitivo para medir a temperatura e a umidade do ar ambiente.

Esses sensores são bastante simples de usar, mas requer cuidado com o tempo entre duas leituras consecutivas, uma vez que é necessário um intervalo de, no mínimo, 1 segundo entre uma leitura e outra.

SensorDHT11 (azul) e DHT22 (branco)
Sensor DHT11 (azul) e DHT22 (branco)

Existem diferentes versões do DHT, similares na aparência e na pinagem, porém com características diferentes. As características do DHT11 e DHT22, dois modelos populares desse sensor, são:

Sensor DHT11

  • Muito baixo custo
  • Tensão de alimentação de 3V a 5V
  • 2.5mA de corrente máxima durante a conversão
  • Bom para medir umidade entre 20% e 80%, com 5% de precisão
  • Bom para medir temperaturas entre 0 e 50°C, com ±2°C de precisão
  • Taxa de amostragem de até 1Hz (1 leitura por segundo)
  • Dimensões: 15.5mm x 12mm x 5.5mm
  • 4 pinos com 0.1" de espaçamento entre eles

Sensor DHT22

  • Baixo custo
  • Tensão de alimentação de 3V a 5V
  • 2.5mA de corrente máxima durante a conversão
  • Bom para medir umidade entre 0% e 100%, com 2% a 5% de precisão
  • Bom para medir temperaturas entre -40 e 125°C, com ±0,5°C de precisão
  • Taxa de amostragem de até 0,5Hz (2 leituras por segundo)
  • Dimensões: 15.1mm x 25mm x 7.7mm
  • 4 pinos com 0.1" de espaçamento entre eles

Como pode ser observado, o DHT22 é um pouco mais preciso e trabalha em uma faixa um pouco maior de temperatura e umidade. Porém, ambos utilizam apenas um pino digital e são relativamente lentos, visto que é necessário um intervalo de tempo relativamente grande entre cada leitura.


Incluindo Bibliotecas

Uma grande vantagem das placas Arduino é a grande diversidade de bibliotecas disponíveis que podem ser usadas em seu programa. Isso faz com o trabalho pesado em programação seja abstraído e resumido em simples comandos.

Com isso, o desenvolvedor não precisa de conhecimento muito aprofundado em programação, podendo gastar menos tempo nisso, resultando em mais tempo para trabalhar com empenho na estratégia de controle.

A seguir, iremos aprender como adicionar uma biblioteca em sua IDE. Esse mesmo procedimento será usado para outros sensores ou módulos.

Incluindo a biblioteca DHT

Para trabalhar de forma fácil com o DHT, podemos baixar uma biblioteca para ele no GitHub do Rob Tillaart (https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTlib).

Baixar biblioteca DHTlib - Atualizada em 24/08/2017
Baixar biblioteca DHTlib - Atualizada em 24/08/2017

Há mais de uma forma de incluir bibliotecas no seu programa, a principal é:

Instalar a biblioteca pelo IDE do Arduino

Esse é o método mais fácil. Primeiramente, faça o download dos arquivos da biblioteca compactados no formato zip. Geralmente as bibliotecas já são distribuídas compactadas, porém às vezes é necessário fazer o download dos arquivos separadamente e compactá-los à parte. Em seguida, basta abrir o IDE e ir em "Sketch -> Incluir Biblioteca -> Adicionar biblioteca .ZIP":

Imagem explicando como adicionar uma biblioteca

Na janela que abrir, selecione a biblioteca a ser adicionada:

inserindo biblioteca dht.h

Com isso, a nova biblioteca foi instalada. Para utilizá-la, basta ir em "Sketch -> Incluir Biblioteca" e selecionar a biblioteca desejada:

biblioteca dht.h na ide arduino

Observe que o IDE adicionou no início do seu código a linha incluindo a biblioteca no seu programa.:

#include <dht.h>

Outras opções:

Instalar manualmente a biblioteca

Para instalar manualmente uma biblioteca, feche o IDE do Arduino e em seguida descompacte os arquivos da biblioteca. Se os arquivos .cpp e .h não estiverem dentro de uma pasta, crie uma e mova os arquivos para lá. Em seguida, basta mover a pasta para o local:

Windows: "Meus documentos\Arduino\libraries"

Mac: "Documents/Arduino/libraries"

Depois desse processo, a biblioteca estará disponível em "Sketch -> Incluir Biblioteca" na próxima vez que o IDE for aberto.

Incluir a biblioteca sem instalá-la

É possível também utilizar a biblioteca sem instalá-la no IDE do Arduino. Para isso, basta descompactar a biblioteca e colocar os arquivos .h e .cpp no mesmo diretório do programa, incluindo no início do mesmo a linha:

#include "nome_da_biblioteca.h"

Mãos à obra – Usando o Sensor de umidade e temperatura DHT11 com Arduino

Componentes necessários

Montando o projeto

Agora vamos conectar os componentes do projeto. Para isso, desligue o cabo USB de seu Arduino e monte seu circuito conforme a figura a seguir.

Esquemático do circuito DHT11 com Arduino uno

Conectando o Arduino ao computador

Conecte seu Arduino ao computador e abra a IDE Arduino.

Antes de carregar um programa, você precisa selecionar qual porta você deseja usar para fazer carregar o programa no Arduino (upload). Dentro do Arduino IDE, clique no menu Ferramentas (tools) e abra o submenu Porta(Port). Clique na porta que seu Arduino está conectado, tal como COM3 ou COM4. Geralmente aparece o nome da placa Arduino : “COM3 (Arduino/Genuino Uno)”.

Você também precisa garantir que o tipo de placa apropriado está selecionado em Ferramentas(Tools) no submenu Placa (Board).

Programando

Crie um programa (sketch) e salve com o nome de “programa_dht11”.

Com o seu programa salvo, escreva nele o código conforme escrito abaixo.

#include <dht.h> // Inclui a biblioteca no seu código
 
dht DHT; // Cria um objeto da classe dht
uint32_t timer = 0;
 
void setup()
{
  Serial.begin(9600); // Inicializa serial com taxa de transmissão de 9600 bauds
}
 
void loop()
{
  // Executa 1 vez a cada 2 segundos
  if(millis() - timer>= 2000)
  {
 
    DHT.read11(A1); // chama método de leitura da classe dht,
                    // com o pino de transmissão de dados ligado no pino A1
 
    // Exibe na serial o valor de umidade
    Serial.print(DHT.humidity);
    Serial.println(" %");
 
    // Exibe na serial o valor da temperatura
    Serial.print(DHT.temperature);
    Serial.println(" Celsius");
 
    timer = millis(); // Atualiza a referência
  }
}

Após escrever o código, clique em Carregar (Upload) para que o programa seja transferido para seu Arduino.

Colocando para funcionar

Caso tenha ocorrido tudo conforme esperado, poderemos fazer a leitura da temperatura através do monitor serial. Abra o monitor serial para verificar o que está sendo lido na entrada A0.


Entendendo a fundo

Entendendo o Software

millis()

Retorna o número de milissegundos desde a placa Arduino começou a funcionar com programa atual. Este número irá saturar (voltar para zero), após, aproximadamente, 50 dias.

 timer = millis();         //Atualiza a referência

Veja que usamos o millis como nossa referência de tempo. Toda vez que a diferença entre o millis e o timer for de 2000 milissegundos, entraremos no if e o timer irá assumir o valor atual de millis.

Desta forma, o programa irá executar o que está dentro do if de 2000 em 2000 milissegundos, ou seja, 2 em 2 segundos.

Esse tipo de estrutura é muito comum e será usada em outras experiências.

Biblioteca dht.h

Na elaboração do software utilizamos a biblioteca dht.h. Esta biblioteca implementa as funcionalidades do sensor DHT11 e DHT22 tornando sua utilização extremamente simples.

Declarando um DHT

Ao usar essa biblioteca trataremos cada sensor DHT como um objeto, dessa forma precisamos declará-lo no início do código.

dht DHT; // Cria um objeto da classe dht

Depois de declarado, sempre que quisermos mexer em alguma função desse DHT, devemos usar o nome da função precedida do nome do DHT e ponto.

DHT.exemplo(); // chama função exemplo() para o objeto DHT

Lendo o sensor

Para ler o sensor basta chamar o método de leitura (read11 se estiver utilizando o DHT11, ou read22 se estiver utilizando o DHT22) e em seguida ler os valores nos atributos temperature e humidity.

Importante: O sensor demora no mínimo 1 segundo de intervalo entre uma leitura e outra.

DHT.read11(A1); // chama método de leitura da classe dht,
                    // com o pino de transmissão de dados ligado no pino A1

Temos o valor de umidade em porcentagem armazenado em:

float umidade = DHT.humidity

Temos o valor de temperatura em graus Celsius armazenado em:

float temperatura = DHT.temperature

Exemplo de aplicação:

    // Exibe na serial o valor de umidade
    Serial.print(DHT.humidity);
    Serial.println(" %");
 
    // Exibe na serial o valor da temperatura
    Serial.print(DHT.temperature);
    Serial.println(" Celsius");

Fechamento

Esperamos que tenham gostado, deixe seu comentário com duvidas, sugestões ou com a foto ou vídeo de seu projeto!! Compartilhe à vontade.

Tutorial feito em parceria com Ronan Largura

Apostila Arduino Básico