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.
Fonte: eletrogate.com
Para este projeto, é necessário utilizar:
Para um entendimento mais aprofundado dos componentes utilizados, veja os seguintes artigos, aqui mesmo do blog Eletrogate:
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:
Onde, na fórmula,
Para convertemos a Temperatura da Escala Celsius para Escala Kelvin, seguimos à seguinte fórmula:
Como exemplo, em uma temperatura ambiente de 30° C:
Como exemplo, para cálculo da velocidade do som com base na temperatura, em uma temperatura de 30°C:
Para calcularmos a distância utilizando um sensor de distância Ultrassônico, como o HC-SR04, devemos utilizar a seguinte fórmula:
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].
Para exemplificar melhor, iremos demonstrar na prática.
Monte o seguinte hardware:
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.
No software, primeiro fazemos a inclusão das bibliotecas:
Em seguida, definimos os pinos utilizados dos hardwares. Também definimos o tipo do DHT utilizado sendo possível utilizar 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.
Em void setup()
, inicializamos a Serial, o sensor DHT11, e configuramos as portas digitais utilizadas pelo sensor ultrassônico.
Dentro de void loop()
, criamos algumas variáveis locais para controle de dados do sensor Ultrassônico.
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.
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.
Para complementar, iremos desenvolver um projeto de Trena Métrica Portátil utilizando um Arduino NANO.
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:
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:
No software, primeiro fazemos a inclusão das bibliotecas:
Em seguida, mapeamos (definimos) os pinos utilizados no arduino NANO.
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.
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.
Sequencialmente, é criado um outro tipo de variável que possui “sub-variáveis” para armazenamento dos dados obtidos do sensor ultrassônico.
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.
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.
Ainda dentro do setup, definimos o brilho do display como máximo.
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:
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.
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.
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.
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.
Ainda 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.
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
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.
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:
Como exemplo, para a criação do array para exibição no display da letra ‘d’, temos:
Para mais detalhes da função setSegments()
, consulte a documentação no github: TM1637Display.h L54-L66.
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.
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.
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.
Ao final do loop()
, fazemos um delay de 700 milissegundos para não realizarmos a medida de distância muito rápido.
Na função leDistanciaCompensacao()
, criamos algumas variáveis locais para controle de dados do sensor Ultrassônico.
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’.
Ao final da função, atribuímos as variáveis do tipo HCSR04 os seus respectivos dados convertidos, sendo:
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.
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’.
Para calcular a autonomia (capacidade) da bateria, iremos utilizar a seguinte fórmula:
onde,
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).
Completando a fórmula, temos:
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.
Veja no vídeo abaixo o funcionamento final do projeto:
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!
|
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!