Projetos

Trena Métrica com HC-SR04 e Compensação Térmica

Eletrogate 24 de setembro de 2021

Introdução

Neste tutorial iremos aprender a como fazer a compensação de temperatura para o sensor ultrassônico HC-SR04. Também veremos um projeto, utilizando o conceito aprendido, de uma Trena Métrica Portátil com Arduino NANO.

HCSR04

Fonte: eletrogate.com


Sensor HC-SR04 e a Temperatura

Velocidade do Som

O sensor ultrassônico utiliza ondas sonoras de frequência superior à 20000 Hz para envio de pulsos sonoros, que podem ser utilizados para realizar a medição de distância com base no tempo decorrido de ida e volta do pulso de até 4 metros.

Mas as ondas sonoras sofrem influência na sua velocidade dependendo da temperatura. Então devemos fazer a correção da velocidade do som de acordo com a temperatura ambiente atual.

A fórmula para obter a velocidade do som em m/s (metros por segundo) é a seguinte:

Explicação

Onde, na fórmula,

  • c é a velocidade do som compensada;
  • c0 é a velocidade do som(331,45 m/s) à 0° Cesius (273,15 Kelvin);
  • T é a temperatura atual para compensar a velocidade do som em Kelvin;
  • e T0 é a temperatura que simboliza o valor correspondente a 0°C em escala absoluta, ou seja, 273,15K.

Para convertemos a Temperatura da Escala Celsius para Escala Kelvin, seguimos à seguinte fórmula:

Explicação

  • TempKelvin é a temperatura convertida;
  • T0 é a temperatura na escala Celsius;
  • e 273,15 é o fator de conversão.

Como exemplo, em uma temperatura ambiente de 30° C:

Explicação

Como exemplo, para cálculo da velocidade do som com base na temperatura, em uma temperatura de 30°C:

Explicação

Cálculo da Distância

Para calcularmos a distância utilizando um sensor de distância Ultrassônico, como o HC-SR04, devemos utilizar a seguinte fórmula:

Explicação

Devemos dividir o tempoIdaEVolta (em microssegundos) por dois, pois queremos a distância (em centímetros) apenas de ida [ou de volta, mas as duas medidas são iguais].

Explicação

Para exemplificar melhor, iremos demonstrar na prática.

Monte o seguinte hardware:

Explicação

Em seguida carregue o seguinte código no arduino NANO:

/*********************************************************************
  Comparação da distância medida COM e SEM compensação de Temperatura
  Criado em 14 de Setembro de 2021 por Michel Galvão
 *********************************************************************/

//Inclusão das bibliotecas
#include <DHT.h>

// Definição de pinos
#define TRIGGER_PIN  3
#define ECHO_PIN     2
#define DHTPIN 4

// Definição do tipo do DHT utilizado
#define DHTTYPE DHT11

// Criaçã do objeto da classe DHT
DHT dht(DHTPIN, DHTTYPE);

float temperaturaAtual;
unsigned long time = 0;

void setup()
{
  /*
     Inicialização do programa, executado apenas uma vez.
  */
  Serial.begin(9600);
  dht.begin(); //Inicialização do DHT
  pinMode(TRIGGER_PIN, OUTPUT); // Define pino do TRIGGER como saída
  pinMode(ECHO_PIN, INPUT); // Define pino do ECHO como entrada
}

void loop()
{
  /*
     Programa principal, executado repedidamente.
  */
  // Criação de variáveis locais
  long  tempoDuracaoIDA; // Armazena o tempo, em microSegundos, de ida do sinal até o objeto à ser medido
  float distancia; // Armazena a distância calculada
  float velocidadeSOM = 331.45 / 10000; // Armazena a velocidade do som, em cm/uS (por isso dividido por 10000, convertido de m/s)
  float velocidadeSOM_CompensacaoTemperatura; // Armazena a velocidade do som, em cm/uS, com compensação de temperatura

  //Limpa o TRIGGER
  digitalWrite(TRIGGER_PIN, LOW);
  delayMicroseconds(2);

  // Define o TRIGGER no estado HIGH por 100 microSegundos
  digitalWrite(TRIGGER_PIN, HIGH);
  delayMicroseconds(100);
  digitalWrite(TRIGGER_PIN, LOW);

  // Lê o ECHO, retorna o tempo de viagem de ida da onda sonora em microssegundos
  tempoDuracaoIDA = pulseIn(ECHO_PIN, HIGH) / 2;
  Serial.print("Distância SEM Compensação:  ");
  distancia =  (velocidadeSOM * tempoDuracaoIDA) ; // Calcula a distância em centímetros
  Serial.println(distancia); // Exibe a distância em centímetros

  //Faz a tentativa de leitura da temperatura do DHT a cada 2 segundos (2000 ms)
  if (millis() - time >= 2000) { // Se millis menos o tempo anterior for maior ou igual que 2000 ms, ...
    /* millis() retorna o número de milissegundos passados desde que a placa Arduino começou a executar o programa atual. */
    if (!isnan(dht.readTemperature())) { // se a leitura de temperatura do DHT não for uma leitura incorreta, ...
      temperaturaAtual = dht.readTemperature(); // armazena o valor lido na variável
    }
    time = millis(); // atualiza a variável que armazena o tempo anterior
  }
  Serial.print("Distância COM Compensação:  ");
  float temperaturaKevin = temperaturaAtual + 273.15; // armazena o valor da temperatura atual convertida de Celsius para Kelvin.
  velocidadeSOM_CompensacaoTemperatura = velocidadeSOM * sqrt(temperaturaKevin / 273.15); // faz o cálculo da velocidade do Som, com a compensação de Temperatura. A função 
                                                                                          // sqrt() faz o cálculo da raiz quadrada de um valor.
  distancia = (velocidadeSOM_CompensacaoTemperatura * tempoDuracaoIDA); // calcula e armazena a distância, desta vez com a velocidade compensada com a temperatura
  Serial.println(distancia);

  Serial.println();

  delay(1000); // faz a medida a cada 1 segundo (1000 ms)
}

Ao Abrir o Monitor Serial, podemos verificar: que há uma diferença de 0,46 cm entre as medidas COM e SEM compensação de temperatura.

Explicação

No software, primeiro fazemos a inclusão das bibliotecas:

Explicação

Em seguida, definimos os pinos utilizados dos hardwares. Também definimos o tipo do DHT utilizado sendo possível utilizar o

  • DHT11 (DHT 11);
  • DHT22 (DHT 22, AM2302, AM2321);
  • DHT21 (DHT 21, AM2301).

Explicação

Logo após, criamos um objeto DHT para gerenciarmos e obtermos dados do sensor DHT. Também criamos variáveis para armazenarmos a temperatura atual e também para armazenarmos o tempo para o controle de leitura do sensor DHT11.

Explicação

Em void setup(), inicializamos a Serial, o sensor DHT11, e configuramos as portas digitais utilizadas pelo sensor ultrassônico.

Explicação

Dentro de void loop(), criamos algumas variáveis locais para controle de dados do sensor Ultrassônico.

Explicação

Dentro do loop,  desligamos o emissor de frequências ultrassônicas (TRIGGER_PIN), para não ocorrer interferência na leitura. Em seguida, ativamos o emissor de ultrassom por 100 uS (microssegundos). Logo após,  fazemos a leitura do sinal emitido-refletido pelo receptor de ondas ultrassônicas (ECHO_PIN), utilizando a função pulseIn(), que possui como parâmetros:

  • pino: o número do pino no Arduino no qual se quer capturar a duração de um pulso.
  • valor: tipo de pulso a ser lido: pode ser HIGH ou LOW.

Por exemplo, se o valor HIGH é passado para a função, a função pulseIn() espera o pino ir para do estado ‘LOW’ para HIGH, começa a temporizar, então espera o pino ir para o estado LOW e para de temporizar e então retorna o tamanho do pulso em microssegundos. Para mais detalhes da função pulseIn(), consulte a documentação.

Em seguida, fazemos o cálculo da distância SEM a compensação de temperatura e exibimos na Serial.

Explicação

Sequencialmente, iremos fazer o cálculo e exibição da distância COM compensação de temperatura. Para isso, iremos fazer a leitura de temperatura do DHT11 a cada 2 segundos (2000 milissegundos) passando o valor lido para uma variável. Para efetuar a leitura a cada 2 segundos, utilizaremos a função millis(), que retorna o número de milissegundos passados desde que a placa Arduino começou a executar o programa atual. A variável de armazenagem da temperatura só irá ser atualizada somente se a leitura de temperatura for válida.

Explicação


Projeto Trena Métrica Portátil

Para complementar, iremos desenvolver um projeto de Trena Métrica Portátil utilizando um Arduino NANO.


Hardware do Projeto

Para o desenvolvimento do hardware deste projeto, siga o esquemático abaixo:

Esquemático


Software do Projeto

Para desenvolvermos o software para o microcontrolador do Arduino NANO, devemos fazer o download da biblioteca TM1637, que permitirá controlar o módulo display 7 segmentos de 4 dígitos.

Para a instalação da biblioteca, siga os passos abaixo:

  • No gerenciador de Bibliotecas da Arduino IDE, na barra de pesquisa digite: ‘TM1637’. Clique para instalar no resultado que tenha como autor o Avishay Orpaz.

Explicação

Após instaladas as bibliotecas, faça o download do seguinte arquivo .zip, extraia-o e carregue o código para a placa Arduino NANO:

Clique nesta imagem e faça o download do código arduino

No software, primeiro fazemos a inclusão das bibliotecas:

Explicação

Em seguida, mapeamos (definimos) os pinos utilizados no arduino NANO.

Explicação

Logo após, definimos o tipo do DHT utilizado, que no caso é DHT11. Também criamos variáveis para armazenar a temperatura lida do DHT11 e para armazenar o tempo para o controle de leitura do sensor DHT11.

Explicação

Em seguida, é  criado um tipo de variável para ser utilizada no programa. Este tipo de variável irá definir qual Sistema Métrico irá ser utilizado.

Explicação

Sequencialmente, é criado um outro tipo de variável que possui “sub-variáveis” para armazenamento dos dados obtidos do sensor ultrassônico.

Explicação

Em seguida, criamos um objeto da classe DHT para fazermos a leitura de temperatura do DHT11. Também criamos um objeto da classe TM1637 para controlar o que é exibido no display de 7 segmentos. É criado, também, um objeto do tipo HCSR04 para armazenamento dos dados obtidos do sensor ultrassônico.

Declaramos uma variável do tipo FormatoDistancia com a diretiva de compilação volatile, que indica ao compilador que esta variável seja carregada da RAM e não de um registrador. Fazemos isso, porque a variável pode ter seu valor mudado por algo além do controle da seção de código na qual ela aparece, como uma interrupção. Sob certas circunstâncias, o valor de uma variável armazenada em registradores pode ser impreciso. Veja mais detalhes dobre o qualificador de variável volatile em: arduino.cc/reference/pt/language/variables/variable-scope-qualifiers/volatile

Também criamos uma variável do mesmo tipo anterior, FormatoDistancia, em que irá ser acessada pelo loop, sem nenhum acesso por interrupção.

Explicação

Dentro do void setup(), inicializamos o objeto da classe DHT. Também configuramos as portas digitais do sensor ultrassônico.

Configuramos também as portas digitais dos LED’s como saída (OUTPUT). Definimos o botão btnTrocaSistema como entrada com resistor interno de Pull-Up.

Explicação

Ainda dentro do setup, definimos o brilho do display como máximo.

Explicação

Também definimos o valor inicial da variável de armazenagem de temperatura como 25°C, pois caso ocorra algum erro na leitura do sensor de temperatura, se utilize este valor para cálculo.

Em seguida, atribuímos uma interrupção externa à porta digital ao qual o botão de troca de sistema métrico está conectado. Utilizamos a função attachInterrupt(digitalPinToInterrupt(pino), ISR, modo) para isso. Esta função possui como parâmetros:

  • digitalPinToInterrupt(pino): converte o número do pino digital para o número específico da interrupção;
  • pino: o número do pino do Arduino;
  • ISR: a ISR a ser chamada quando a interrupção ocorre; essa função deve não tomar nenhum parâmetro nem retornar nenhum tipo de dado.
  • modo: define quando a interrupção deve ser ativada. Quatro constantes estão predefinidas como valores válidos:
    • LOW aciona a interrupção quando o estado do pino for LOW,
    • CHANGE aciona a interrupção quando o sempre estado do pino mudar,
    • RISING aciona a interrupção quando o estado do pino for de LOW para HIGH apenas,
    • FALLING aciona a interrupção quando o estado do pino for de HIGH para LOW apenas.

Explicação

A função alteraSistemaMedida(), é a função ao qual a interrupção irá executar sempre que o botão for pressionado. Nesta função, invertemos o estado da variável formatoDistancia e fazemos uma exibição ao usuário do Sistema Métrico utilizado atualmente.

Explicação

No void loop(), desativamos as interrupções temporariamente e, em seguida, atribuímos o valor da variável formatoDistancia à formatoDistanciaValor, ativando, seguidamente, as interrupções.

Fazemos este processo de desativação e ativação das interrupções para atribuição de valor à variável, pois se a variável volatile formatoDistancia for maior que um byte (ex. um int de 16 bits ou long de 32 bits), o microcontrolador não é capaz de lê-la em apenas um passo, porquê é um microcontrolador 8 bits e se não fizéssemos este processo, isso significaria que enquanto a seção principal do seu código lesse o primeiro ou os primeiros bytes da variável, a interrupção poderia mudar os outros bytes. Isso iria produzir valores inesperados na variável.

Também executamos a função obtemTemperatura(), que mantém a variável temperaturaAtual atualizada com a leitura de temperatura do DHT11.

Em seguida, chamamos a função leDistanciaCompensacao() e repassamos o retorno da mesma para a variável medidasObtidas.

Logo após, limpamos todos os caracteres que estiverem sendo exibidos no display 7 segmentos.

Explicação

Ainda dentro do loop, criamos uma variável local para armazenar a distância medida convertida para String. Em seguida, testamos a variável formatoDistanciaValor em uma estrutura de Controle switch.

Explicação

Caso a variável possua o valor ‘SInternacional‘, atribuímos o valor da distância medida em centímetros para a variável stringDistancia. Em seguida, testamos dentro de um if, se o conjunto de caracteres antes do ponto decimal da variável stringDistancia convertido para o tipo Inteiro é menor do que 99 (99 cm ±= 1 metro). Caso a condição seja verdadeira, sinalizamos com os LED’s que a distância está em centímetros.

ExplicaçãoAinda dentro do if, exibimos no display os algarismos antes do ponto decimal, a partir da posição 0 (0=totalmente à esquerda, 3=totalmente à direita), com a função showNumberDecEx, que além de exibir números, permite mostrar os dois-pontos central do display (passando como terceiro parãmetro a máscara de bits 0b01000000). Pode-se ver mais sobre está função no github: TM1637Display.h L84-L107.

Explicação

Ainda dentro do if(), exibimos no display os algarismos depois do ponto decimal, a partir da posição 2, com a função showNumberDec, que permite a exibição de números no display. Veja mais no github sobre esta função: TM1637Display.h L71-L82

Explicação

Se caso a condição testada anteriormente seja falsa, atribuímos o valor da distância medida em metros para a variável stringDistancia. Em seguida, testamos dentro de um if, se o conjunto de caracteres antes do ponto decimal da variável stringDistancia convertido para o tipo Inteiro é menor do que 4 (4 metros é o limite máximo ao qual o sensor ultrassônico consegue fazer leituras de distância). Caso a condição seja verdadeira, sinalizamos com os LED’s que a distância está em metros, e também exibimos no display os algarismos antes do ponto decimal, a partir da posição 0, com a função showNumberDecEx, mostrando também os dois-pontos central do display.

Explicação

Em seguida, exibimos no display os algarismos depois do ponto decimal, a partir da posição 2, com a função showNumberDec.

Caso nenhuma das condições sejam verdadeiras, desligamos todos os LED’s e exibimos no display que a medida foi inválida pois ultrapassou o limite máximo de 4 metros. Fazemos a exibição no display através da função setSegments(segments[]). Esta função possui possui como parâmetros:

  • segments[]: array de tamanho máximo do número de dígitos do display, contendo os valores brutos do segmento.

O array utilizado é preenchido com m conjunto de ‘definições’ pré-estabelecidas:

Explicação

Fonte da imagem: eletrogate.com

Como exemplo, para a criação do array para exibição no display da letra ‘d’, temos:

Explicação Exemplo

Explicação

Para mais detalhes da função setSegments(), consulte a documentação no github: TM1637Display.h L54-L66.

Explicação

Caso a variável possua o valor ‘SIngles‘, atribuímos o valor da distância medida em polegadas para a variável stringDistancia. Em seguida, testamos dentro de um if, se o conjunto de caracteres antes do ponto decimal da variável stringDistancia convertido para o tipo Inteiro é menor do que 12 (12 in =  1 pé). Caso a condição seja verdadeira, sinalizamos com os LED’s que a distância está em polegadas. E fazemos as devidas exibições no display.

Explicação

Explicação

Se caso a condição testada anteriormente seja falsa, atribuímos o valor da distância medida em Pés para a variável stringDistancia. Em seguida, testamos dentro de um if, se o conjunto de caracteres antes do ponto decimal da variável stringDistancia convertido para o tipo Inteiro é menor do que 13.12 (13.12 ft ±= 4 metros). Caso a condição seja verdadeira, sinalizamos com os LED’s que a distância está em pés e fazemos a exibição da distância no display.

Explicação

Caso nenhuma das condições sejam verdadeiras, desligamos todos os LED’s e exibimos no display que a medida foi inválida pois ultrapassou o limite máximo de 4 metros.

Explicação

Ao final do loop(), fazemos um delay de 700 milissegundos para não realizarmos a medida de distância muito rápido.

Explicação

Na função leDistanciaCompensacao(), criamos algumas variáveis locais para controle de dados do sensor Ultrassônico.

Explicação

Ainda na mesma função, fazemos o mesmo processo de obtenção e cálculo de distância que tínhamos realizado no exemplo ‘Sensor HC-SR04 e a Temperatura’.

ExplicaçãoAo final da função, atribuímos as variáveis do tipo HCSR04 os seus respectivos dados convertidos, sendo:

  • cm para m (metro): divida o valor de comprimento por 100;
  • cm para in (polegada): divida o valor de comprimento por 2.54;
  • cm para ft (pé): divida o valor de comprimento por 30.48.

Após a atribuição dos dados, retornamos para a chamada da função o objeto ‘medidas‘ do tipo HCSR04 contendo os dados relacionados ao sensor ultrassônico.

Explicação

Na função obtemTemperatura(), fazemos o mesmo processo de obtenção e gerenciamento de temperatura que tínhamos realizado no exemplo ‘Sensor HC-SR04 e a Temperatura’.

Explicação


Autonomia da Trena

Para calcular a autonomia (capacidade) da bateria, iremos utilizar a seguinte fórmula:

Explicação

onde,

  • T » Tempo (em horas);
  • C » Capacidade (em Àmperes-Horas);
  • I » Corrente (em Àmpere);

Utilizando a Bateria Universal Portátil USB – Power Bank, temos uma capacidade de “ATÉ 1200mAh”, de acordo com a fabricante, o que resulta 1,2 Ah .(conversão realizada dividindo o valor de capacidade por 1000).

Com um multímetro, na escala de corrente, foi medido no circuito do projeto uma corrente de 75 mA, equivalente à 0,075 A (conversão realizada dividindo o valor da corrente elétrica por 1000).

Explicação

Completando a fórmula, temos:

Explicação

Então, esta trena poderá ficar ligada sem desligamento por 16 horas, o que é extremamente difícil de ocorrer, visto que a trena irá ser operada por períodos curtos.


Funcionamento Final

Veja no vídeo abaixo o funcionamento final do projeto:


Conclusão

Com este post, podemos extrair os conceitos deste projeto e aplicar em outros projetos mais complexos, além de podermos melhorar o processo de medição de distância com o sensor ultrassônico HC-SR04.

Caso tenha ficado alguma dúvida, nos contate através dos comentários.

Espero que o tenha ajudado e até a próxima.

Conheça a Metodologia Eletrogate e ofereça aulas de robótica em sua escola!


Sobre o Autor


Michel Galvão

Hobbysta em Sistemas Embarcados e IoT. Tem experiência em Automação Residencial e Agrícola.


Eletrogate

24 de setembro de 2021

A Eletrogate é uma loja virtual de componentes eletrônicos do Brasil e possui diversos produtos relacionados à Arduino, Automação, Robótica e Eletrônica em geral.

Conheça a Metodologia Eletrogate e Lecione um Curso de Robótica nas Escolas da sua Região!

Eletrogate Robô

Cadastre-se e fique por
dentro de novidades!