Experimento 36 – Arduino com sensor de distância

Material necessário:

  • Módulo sensor de distância ultrassônico HC-SR04
  • 5 LEDs
  • 5 resistores (150 ou 220 ohms dependendo da cor do LED)
  • 1 Arduino Nano
  • 1 Alto-falante de 8 ohms

Neste experimento usaremos um sensor de distância ultrassônico para reagir à distância de objetos colocados diante do sensor. O HC-SR04 consegue detectar distância de um centímetro a alguns metros. O objetivo será fazer LEDs diferentes acenderem e soar um som diferente no alto-falante à medida em que a distância mudar. O esquema está abaixo:

Esta é uma possível montagem com o protoboard.

Antes de acionar LEDs ou alto-falantes, vamos testar o HC-SR04 imprimindo os valores lidos no monitor serial. O HC-SR04 tem 4 terminais. Dois são usados para fornecimento de energia (VCC e GND), e devem ser ligados em 5V e GND. Os outros dois são a entrada TRIGGER, usado para solicitar que o sensor faça uma medição, e a saída ECHO, que contém a resposta da medição. O sensor é controlado através do envio de pulsos, que devem ter uma duração especificada, e a resposta é recebida também como um pulso, cuja duração varia conforme a distância medida. O pulso é uma onda quadrada, com estado LOW em 0 e HIGH em 5V.

Para solicitar uma medição, o Arduino precisa enviar um pulso (HIGH) de 10 microssegundos para a entrada TRIGGER do sensor. Quando o sensor recebe esse pulso, ele devolve um pulso (também HIGH) de duração variável na saída ECHO. O programa precisa então medir a duração deste pulso, e multiplicar por um valor fixo para obter a distância em centímetros.

O gráfico abaixo ilustra graficamente o pulso que precisamos enviar para a entrada TRIGGER que irá disparar uma medição:

Este outro gráfico mostra um pulso de resposta recebido em ECHO. A duração deste pulso é o tempo em que ele permanece na posição HIGH.

A linguagem do Arduino possui uma função especial para medir a largura de um pulso. A função pulseIn() recebe dois (ou três) argumentos: o primeiro é o pino onde o pulso será recebido e o segundo é o nível do pulso  (HIGH ou LOW). Por exemplo, a instrução abaixo interrompe o código até que um pulso de valor HIGH seja recebido no pino 8. Quando ele terminar (ou seja, quando o sinal voltar para LOW), a duração será gravada na variável duracao:

long duracao = pulseIn(8, HIGH);

Se o pulso nunca chegar, o programa fica esperando para sempre. Uma maneira de evitar isto é estipular um timeout, que é o terceiro argumento. A instrução abaixo espera até 1 minuto (60 segundos) pelo pulso:

long duracao = pulseIn(8, HIGH, 60000);

Para enviar o pulso de disparo, não podemos usar delay() pois a sua resolução mínima é de apenas 1 milissegundo. Neste caso precisamos usar a função delayMicrosseconds(). O pulso de disparo dura 10 microssegundos no estado HIGH, portanto precisamos começar com o estado LOW, esperar um tempo (pode ser também uns 5 a 10 microssegundos) e depois mudar o estado para HIGH, esperar 10 microssegundos, e baixar para LOW:

 digitalWrite(TRIGGER, LOW);
 delayMicroseconds(5);
 digitalWrite(TRIGGER, HIGH);
 delayMicroseconds(10);
 digitalWrite(TRIGGER, LOW);

Por fim, precisamos converter a duração do pulso recebido em ECHO na distância em centímetros. De acordo com a especificação do HC-SR04 é preciso apenas dividir por 58.

O programa abaixo pode ser usado para testar o funcionamento do sensor, imprimindo os dados recebidos no monitor serial. Faça o upload, abra o monitor serial e aproxime uma superfície plana do sensor e veja os valores recebidos na tela.

const int TRIGGER = 3;
const int ECHO = 4;

void setup() {
   pinMode(TRIGGER, OUTPUT);
   pinMode(ECHO, INPUT);
   Serial.begin(9600);
}

void loop() {
   float distance = pulse();
   Serial.println(distance); // imprime a distancia em cm
   delay(500); // must be over 60ms
}

float pulse() {
   digitalWrite(TRIGGER, LOW);
   delayMicroseconds(10);
   digitalWrite(TRIGGER, HIGH);
   delayMicroseconds(10);
   digitalWrite(TRIGGER, LOW);

   long duration = pulseIn(ECHO, HIGH);
   return duration / 58.0;
}

Agora que testamos o sensor, podemos usar esses dados para  controlar dispositivos de saída. No circuito temos LEDs e um alto-falante. O programa abaixo utiliza o arquivo do experimento 32, que define frequências de notas musicais, e seleciona notas de frequências mais altas à medida em que a distância aumenta. O aumento também causa o acendimento de mais LEDs. Aproximar um objeto a uma distância menor que 5 centímetros deve desligar o som e os LEDs:

#include "notas.h"

const int TRIGGER = 3;
const int ECHO = 4;
const int SPEAKER = 5;
const int LED_R = 6,
          LED_Y = 7,
          LED_G = 8,
          LED_B = 9,
          LED_W = 10;

const int notas[] = {
   ZZ, C4, D4, E4, F4, G4
};

void setup() {
   pinMode(TRIGGER, OUTPUT);
   pinMode(SPEAKER, OUTPUT);
   pinMode(LED_R, OUTPUT);
   pinMode(LED_Y, OUTPUT);
   pinMode(LED_G, OUTPUT);
   pinMode(LED_B, OUTPUT);
   pinMode(LED_W, OUTPUT);
   pinMode(ECHO, INPUT);
}

void luz(boolean acender, int led) {
   if (acender) {
      digitalWrite(led, HIGH);
   } else {
      digitalWrite(led, LOW);
   }
}

void loop() {
   float distance = pulse();

   // Som: idx = indice do array notas[] (0 a 5)
   int idx = (int)(distance / 5);
   if(idx > 5) { // se idx resultar em numero > 5, faça idx = 5
      idx = 5;
   }
   // soar um tom na nota correspondente por 500ms
   tone(SPEAKER, notas[ idx ], 500);

   // Luz(condição para acender, led)
   luz( distance >= 5, LED_R);
   luz( distance >= 10, LED_Y);
   luz( distance >= 15, LED_G);
   luz( distance >= 20, LED_B);
   luz( distance >= 25, LED_W);

   delay(200);
}

float pulse() {
   // envia o pulso para TRIGGER, solicitando a medição
   digitalWrite(TRIGGER, LOW);
   delayMicroseconds(10);
   digitalWrite(TRIGGER, HIGH);
   delayMicroseconds(10);
   digitalWrite(TRIGGER, LOW);

   // espera até 50 segundos por um pulso de resposta
   long duration = pulseIn(ECHO, HIGH, 50000);
   // retorna a distância em cm (calculada)
   return duration / 58.0;
}

O sensor é muito sensível e interferências são frequentes. Neste exemplo o próprio som do alto-falante pode interferir no sinal. Há várias maneiras de contorná-las e algumas usando software. Em vez de construir você mesmo os pulsos como fizemos neste exemplo, você pode usar uma biblioteca criada especificamente para facilitar o uso do sensor. Uma boa bibliioteca como a NewPing não apenas oferece funções como também lida com diferentes sensores de outros fabricantes e busca otimizar a medição, reduzindo interferências e melhorando a precisão.