Automação Residencial

Assistente de Estacionamento com Arduino e HC-SR04

Eletrogate 1 de agosto de 2023

Introdução

Para quem dirige, estacionar um carro em uma vaga de garagem é uma tarefa corriqueira, mas que pode apresentar um desafio e prejuízos. Quem nunca “estacionou de ouvido”, colidindo com a parede no fundo, podendo causar danos a esta e ao veículo? Pensando nisso, as montadoras instalaram sensores de estacionamento na traseira dos carros para auxiliar durante o estacionamento. Porém, nem todos os carros possuem este dispositivo. Além disso, dependendo da geometria da sua garagem (ex.: canos), mesmo os carros com estes sensores podem não ser eficazes para evitar a colisão.

Neste artigo, mostraremos uma solução que funciona a partir de um sensor ultrassônico colocado na garagem, ao invés de no veículo. LEDs nas cores verde, amarelo e vermelho e um buzzer indicam ao motorista a situação.


Funcionamento do Assistente

Nosso assistente funcionará da seguinte forma: suponha uma garagem genérica, onde definimos distâncias conforme a figura abaixo:

Nosso assistente se ativa ao detectar movimento. Quando for identificado um veículo dentro da garagem, ele acenderá o LED da cor apropriada com base na cor da zona da figura acima. Caso o veículo entre na zona roxa, além de acender o LED vermelho, será acionado, também, um alarme sonoro (buzzer).

A detecção de distância se faz através de um sensor ultrassônico. A ausência de variação de distância em um intervalo de tempo (ex: 5 seg) é tida como indicativo de veículo parado, desativando a sinalização.


O circuito

O circuito deste artigo é didático, usando uma protoboard e uma Arduino Uno R3. Mais à frente, abordaremos opções para uma montagem prática definitiva.

O diagrama do circuito pode ser visto na figura abaixo, assim como sua montagem na protoboard.

Basicamente, nosso circuito contém uma Arduino tendo uma entrada com o sensor ultrassônico HC-SR04 e 3 saídas com LEDs de cores diferentes (verde, amarelo e vermelho) em série com resistores de 330 Ohms e um buzzer em série com um resistor de 100 ohms.

O sensor ultrassônico HC-SR04 funciona através da emissão de um pulso ultrassônico de 10 us (pino Trig), permitindo medir o tempo de retorno do eco deste pulso em algum obstáculo à frente (pino Echo). Ele permite medir distâncias entre 2 cm a 4 m.

Abaixo, vídeo demonstrando o funcionamento em miniatura:


Programação

O circuito é idêntico ao vídeo de referência. Porém, a programação foi refeita para efeitos de clareza, didática e experimentação.

O primeiro ponto a entendermos é o funcionamento do sensor de distância. Para medirmos a distância, precisamos enviar um pulso de 10 us e, depois, verificar o tempo de retorno do eco para indicar a distância. Este tempo é obtido a partir do comando pulseIn(), que mede o tempo do pulso no pino Echo do HC-SR04. 

Nosso programa utiliza a função MedeDistancia(). O que ela faz é chamar a função DisparaPulsoUltrassonico(), que envia o pulso, obtém o tempo do pulso do HC-SR04 e usa a função CalculaDistancia() para obter a distância em metros, retornando a distância em centímetros (x100). O cálculo é feito com base no trajeto (ida e volta) e a velocidade do som no ar. Para efeitos práticos, desconsideramos o fato do emissor e receptor estarem a uma certa distância, o que geraria um caminho triangular do pulso sonoro.

// Mede a distância do sensor ultrassônico
float MedeDistancia() {
  float TempoEcho = 0;                       // variável tempo do eco
  DisparaPulsoUltrassonico();                // dispara pulso ultrassonico
  TempoEcho = pulseIn(PinEcho, HIGH);        // mede duração do pulso HIGH de eco em micro seg
  return CalculaDistancia(TempoEcho) * 100;  // retorna distância em cm
}
// Envia um pulso de 10 us
void DisparaPulsoUltrassonico() {
  digitalWrite(PinTrigger, HIGH);  // pulso alto de Trigger
  delayMicroseconds(10);           // atraso de 10 microsegundos
  digitalWrite(PinTrigger, LOW);   // pulso baixo de Trigger
}
// Calcula a distância com base no tempo do pulso
float CalculaDistancia(float tempo_us) {
  return ((tempo_us * velocidadeSom_mpus) / 2);  // calcula distancia em metros
}

O Loop principal inicialmente mede a distância. Com base nela, o programa verifica se o veículo está parado. Caso não esteja, ele verifica as faixas de distância, começando da mais perto para a mais longe, chamando as funções Sinaliza(faixa) ou desligaSinais(), caso esteja fora da garagem. Estas duas últimas ligam ou desligam os LEDs e buzzer como desejado.

Como exemplo, para ligar o LED verde usamos um comando digitalWrite(PinLEDverde, HIGH); 

Para acionar o buzzer usamos o comando tone(PinBuzzer, 500);

Para efeito de debug, usamos o comando Serial.print()/Serial.println() para enviar ao PC dados sobre a distância medida.

Para efeito didático e de experimentação, foram criadas algumas constantes e variáveis. Elas foram úteis para ajustar o funcionamento do circuito com uma miniatura. 

As constantes de limite (ex.: limite verde) contêm os valores, em centímetros, entre o sensor e o limite da faixa em questão. No programa, estes valores estão ajustados para uma miniatura. Porém, podem ser alterados para indicar da forma que for desejado na sua aplicação, em especial.

A constante atraso tem a ver com o delay() no loop principal. Em debug, usando os comandos seriais para o PC, este tempo pode ser de 200–500 ms. Na versão final, os comandos seriais podem ser removidos e o atraso reduzido. A constante Maxcontador funciona em conjunto para definir um tempo de 5s para detectar a parada do veículo. 

A constante tolerância pode ser utilizada para calibrar a detecção de parada de veículo. Como as leituras do HC-SR04 podem indicar pequenas variações, aumentar a tolerância reduz o impacto de “ruídos” na leitura da distância (ver função estaParado).

O programa completo pode ser visto abaixo. 

/* Programa de assistente de garagem com Sensor de Distância Ultrassônico   
   Blog Eletrogate - https://blog.eletrogate.com/
   Arduino Uno - LCD 16/2 azul - IDE 2.1.0
   Mauro Vianna   27/junho/2023
   
*/

// Pinos do arduino utilizados
int PinTrigger = 5;     // pino usado para disparar os pulsos do sensor
int PinEcho = 6;        // pino usado para ler a saida do sensor
int PinLEDvermelho = 2; // pino usado pelo LED vermelho
int PinLEDamarelo = 3;  // pino usado pelo LED amarelo
int PinLEDverde = 4;    // pino usado pelo LED verde
int PinBuzzer = A0;     // pino usado pelo buzzer

// Variaveis e constantes para controle de distancia
const int atraso = 200;       // tempo de espera do loop 
const int MaxContador = 5000/atraso;   // número de iterações para considerar parado (5s)
const float tolerancia = 1.0;   // tolerancia para detecção de movimento    
const float velocidadeSom_mps = 340;        // em metros por segundo
const float velocidadeSom_mpus = 0.000340;  // em metros por microsegundo
float Distancia = 0;          // Distancia medida
float DistanciaAnterior = 0;  // Distancia anterior medida (detecção de movimento)
int contador = 0;             // contador de tempo para detecçaõ de movimento

// Valores limites das faixas de sinalização
const int LimiteVerde = 29;
const int LimiteAmarelo = 17;
const int LimiteVermelho = 10;
const int LimiteBuzzer = 8;

// Comandos de sinalização
const int Verde = 1;
const int Amarelo = 2;
const int Vermelho = 3;
const int Buzzer = 4;

// Inicialização
void setup() {
  pinMode(PinTrigger, OUTPUT);      // configura pino Trigger como saída
  digitalWrite(PinTrigger, LOW);    // pino trigger - nível baixo
  pinMode(PinEcho, INPUT);          // configura pino ECHO como entrada
  pinMode(PinLEDvermelho, OUTPUT);  // configura pino LED vermelho como saída
  pinMode(PinLEDamarelo, OUTPUT);   // configura pino LED amarelo como saída
  pinMode(PinLEDverde, OUTPUT);     // configura pino LED verde como saída
  pinMode(PinBuzzer, OUTPUT);       // configura pino Buzzer como saída
  Serial.begin(9600);               // inicializa monitor serial 9600 Bps (debug)
  delay(100);                       // atraso de 100 milisegundos
  Distancia = MedeDistancia();
  DistanciaAnterior = Distancia;
  desligaSinais();
}

// Loop principal
void loop() {

  Distancia = MedeDistancia();

  if (estaParado()) { desligaSinais(); }
  else if (Distancia <= LimiteBuzzer) { Sinaliza(Buzzer);  } 
  else if (Distancia <= LimiteVermelho) { Sinaliza(Vermelho); } 
  else if (Distancia <= LimiteAmarelo) { Sinaliza(Amarelo); } 
  else if (Distancia <= LimiteVerde) {Sinaliza(Verde); } 
  else { desligaSinais();}
  
  Serial.print("Distancia em centimentros: ");  // mostra no monitor serial
  Serial.print(Distancia);                      // mostra o calculo de distancia em metros
  Serial.println();
  delay(atraso);                                // tempo de atraso 
}

// Envia um pulso de 10 us
void DisparaPulsoUltrassonico() {
  digitalWrite(PinTrigger, HIGH);  // pulso alto de Trigger
  delayMicroseconds(10);           // atraso de 10 microsegundos
  digitalWrite(PinTrigger, LOW);   // pulso baixo de Trigger
}

// Calcula a distância com base no tempo do pulso
float CalculaDistancia(float tempo_us) {
  return ((tempo_us * velocidadeSom_mpus) / 2);  // calcula distancia em metros
}

// Mede a distância do sensor ultrassônico
float MedeDistancia() {
  float TempoEcho = 0;                       // variável tempo do eco
  DisparaPulsoUltrassonico();                // dispara pulso ultrassonico
  TempoEcho = pulseIn(PinEcho, HIGH);        // mede duração do pulso HIGH de eco em micro seg
  return CalculaDistancia(TempoEcho) * 100;  // retorna distância em cm
}

// Sinaliza a faixa apropriada
void Sinaliza(int faixa) {
  desligaSinais();
  if (faixa == Verde) {
    digitalWrite(PinLEDverde, HIGH);
  } else if (faixa == Amarelo) {
    digitalWrite(PinLEDamarelo, HIGH);
  } else if (faixa == Vermelho) {
    digitalWrite(PinLEDvermelho, HIGH);
  } else if (faixa == Buzzer) {
    digitalWrite(PinLEDvermelho, HIGH);
    tone(PinBuzzer, 500);
  }
}

// Desliga a sinalização
void desligaSinais() {
  digitalWrite(PinLEDverde, LOW);
  digitalWrite(PinLEDamarelo, LOW);
  digitalWrite(PinLEDvermelho, LOW);
  noTone(PinBuzzer);
}

// verifica se está parado
byte estaParado() {
  byte parado;
  if (sq(Distancia - DistanciaAnterior) <= tolerancia) {
    if (contador >= MaxContador) {
      Serial.println("Sem movimento. Desligando sinais...");
      parado = 1;
    } else {
      contador++;
      parado = 0;
    }
  } else {
    contador = 0;
    parado = 0;
  }
  DistanciaAnterior = Distancia;
  return parado;
}

Discutindo o Caso Real

Nosso circuito atende bem ao teste de bancada em protoboard. Mas, e se quisermos realmente montá-lo na garagem? Na referência, temos a página do site instructables do Youtuber detalhando como montar o circuito final para a garagem. Cabe aqui algumas observações para entender as diferenças. 

A primeira diferença foi a separação do circuito em 2 partes: A primeira contém os LEDS indicadores, conectados por um cabo de 4 vias (GND, 3x LEDs) a primeira parte, com o arduino e Buzzer. O módulo com os LEDS deve ser posicionado em altura visível (nível do para-brisa e retrovisor) e o módulo com o sensor deve ser posicionado na altura do porta-malas.

A segunda diferença foi o uso de uma Arduino Nano, mais adequada para soldagem em placa. Esta é alimentado por uma fonte de 5 V com o plug USB apropriado.

A Nano tem as mesmas funcionalidades da Uno R3, inclusive uma entrada USB para alimentação e comunicação com o PC. Porém, não tem o segundo conector para fonte externa com plug P4.


Possibilidades

Algumas possibilidades de melhoria ou alteração do projeto, a critério do leitor:

  • Uso de um único LED multicor;
  • Instalação do buzzer no mesmo módulo com os LEDs, se necessário para ser ouvido melhor;
  • Substituição dos LEDS para outros LEDS mais claros, se o ambiente demandar (muito claro);
  • Substituição do buzzer para sinal sonoro mais potente (ambiente ruidoso).

Conclusão

Vimos, neste artigo, um circuito simples, mas com uma boa aplicação prática. É um exemplo de como problemas cotidianos podem ser resolvidos de forma descomplicada, facilitando nossa vida e evitando danos. Além disso, aprendemos um pouco mais sobre eletrônica e programação, no processo.


Sobre o Autor


Mauro Roberto

Formado em engenharia elétrica com ênfase em eletrônica e sistemas pela PUC-RJ. Pós graduado em Teoria de Controle e Estatística. Atuou vários anos em desenvolvimento de sistemas software. Hobbysta em impressão 3D, arduino e robótica.


Eletrogate

1 de agosto de 2023

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!