Sensores • Arduino • Guia Completo + Projetos
Sensor Ultrassônico HC-SR04: Como Funciona e Como Usar no Arduino na Prática
O HC-SR04 é o sensor “coringa” para medir distância sem contato em projetos de robótica e automação. Ele funciona como um “sonar”: emite ultrassom, espera o eco e transforma o tempo de ida/volta em distância. Aqui você vai aprender de forma prática, com códigos prontos, projetos reais e dicas de quem monta isso no mundo real.
5V DC 2cm → 500cm Ângulo < 15° Resolução ~0,3cm TRIG 10µs ECHO TTL
Neste artigo você vai ver:
- Como o HC-SR04 calcula distância (com ilustração e timing TRIG/ECHO)
- Ligação correta no Arduino (e o que muda em placas 3.3V)
- Leitura estável: filtros, média, mediana e “anti-ruído”
- Projetos práticos: presença, nível de caixa d’água, sensor de ré, robô anti-colisão
- Erros comuns + troubleshooting
- Comparativo: Ultrassônico vs IR vs ToF
- FAQ (Perguntas frequentes)
1) Como o HC-SR04 mede distância (sem mistério)
O módulo tem dois “olhos”: um transmite e outro recebe ultrassom. O Arduino manda um pulso no TRIG e o sensor responde no ECHO. A duração do pulso em ECHO (tempo em nível alto) representa o tempo de ida e volta do som.
Ilustração: Forma de funcionamento do sensor ultrassônico.
Leitura prática: quanto mais longe o objeto, maior a duração do pulso em ECHO. O Arduino mede esse tempo (em microssegundos) e converte para centímetros.
2) Pinagem e ligação (do jeito que dá certo)
O HC-SR04 usa 4 pinos: VCC, TRIG, ECHO e GND. No Arduino UNO (5V), pode ligar direto. Em placas 3.3V, o ECHO sai em 5V — use conversão de nível.
Ilustração: pinos do HC-SR04 e ligação típica no Arduino
Se você usar ESP32 / Pico / Raspberry (3.3V): o pino ECHO sai em 5V. Use divisor resistivo (ex.: 1k + 2k) ou conversor de nível para proteger o microcontrolador.
3) Código base “profissional”
A maioria dos exemplos na internet mede 1 vez e imprime. Em projeto real isso oscila. Aqui vai um código com timeout, validação, e filtro por mediana (excelente contra ruído).
Arduino (C/C++) • HC-SR04 • Leitura estável com mediana
// HC-SR04 + Arduino UNO
// VCC->5V | GND->GND | TRIG->D9 | ECHO->D10
const int PIN_TRIG = 9;
const int PIN_ECHO = 10;
float leituraCm() {
// Disparo TRIG (10us)
digitalWrite(PIN_TRIG, LOW);
delayMicroseconds(2);
digitalWrite(PIN_TRIG, HIGH);
delayMicroseconds(10);
digitalWrite(PIN_TRIG, LOW);
// Timeout 30ms (~5m ida e volta)
unsigned long dur = pulseIn(PIN_ECHO, HIGH, 30000UL);
if (dur == 0) return -1;
// cm = (us * 0.0343) / 2
return (dur * 0.0343f) / 2.0f;
}
float mediana5(float a, float b, float c, float d, float e) {
float v[5] = {a,b,c,d,e};
// bubble sort simples (5 itens)
for (int i=0;i<5;i++){
for (int j=0;j<4;j++){
if (v[j] > v[j+1]) { float t=v[j]; v[j]=v[j+1]; v[j+1]=t; }
}
}
return v[2];
}
float distanciaEstavelCm() {
float a = leituraCm(); delay(20);
float b = leituraCm(); delay(20);
float c = leituraCm(); delay(20);
float d = leituraCm(); delay(20);
float e = leituraCm();
// Se muitas leituras falharam, retorna -1
int ok = 0;
ok += (a>0); ok += (b>0); ok += (c>0); ok += (d>0); ok += (e>0);
if (ok < 3) return -1;
// Para valores inválidos, substitui por um valor alto (não “puxa” a mediana)
if (a < 0) a = 999;
if (b < 0) b = 999;
if (c < 0) c = 999;
if (d < 0) d = 999;
if (e < 0) e = 999;
float m = mediana5(a,b,c,d,e);
if (m >= 999) return -1;
return m;
}
void setup() {
Serial.begin(9600);
pinMode(PIN_TRIG, OUTPUT);
pinMode(PIN_ECHO, INPUT);
}
void loop() {
float cm = distanciaEstavelCm();
if (cm < 0) {
Serial.println("Sem leitura confiavel.");
} else {
Serial.print("Distancia (mediana): ");
Serial.print(cm, 1);
Serial.println(" cm");
}
delay(200);
}
Por que mediana?
Ela ignora picos “loucos” (ruído, eco duplo, objeto inclinado). Em prática, fica mais estável que média simples.
4) Projetos práticos
Agora é onde o HC-SR04 vira ferramenta de projeto. Aqui vão algumas ideias que você consegue montar de forma prática, com variações.
Projeto A — Sensor de presença (LED / relé)
Acende LED quando alguém chega a < 30cm. Troque LED por relé e você tem automação real.
Projeto B — “Sensor de ré” (buzzer)
Quanto mais perto, mais rápido o bip. Ideal para robô, carrinho, bancada e didática.
Projeto C — Medidor de nível (caixa d’água)
Mede distância até o líquido e converte em porcentagem (0–100%).
Projeto D — Robô anti-colisão
Detecta obstáculo e muda direção. Base perfeita para projetos de robótica educacional.
Projeto A — Presença com LED (com histerese + confirmação)
Em projetos reais, você quer evitar “piscar” quando a distância fica oscilando perto do limite. A solução é histerese (liga em 30cm, desliga só depois de 35cm) + confirmação por leituras seguidas.
Arduino • Presença robusta (anti-falso positivo)
const int PIN_TRIG = 9;
const int PIN_ECHO = 10;
const int PIN_LED = 13;
float leituraCm() {
digitalWrite(PIN_TRIG, LOW); delayMicroseconds(2);
digitalWrite(PIN_TRIG, HIGH); delayMicroseconds(10);
digitalWrite(PIN_TRIG, LOW);
unsigned long dur = pulseIn(PIN_ECHO, HIGH, 30000UL);
if (dur == 0) return -1;
return (dur * 0.0343f) / 2.0f;
}
float distanciaEstavelCm() {
float v[5];
int ok=0;
for(int i=0;i<5;i++){ v[i]=leituraCm(); ok += (v[i]>0); delay(20); }
if(ok < 3) return -1;
for(int i=0;i<5;i++) if(v[i] < 0) v[i] = 999;
// ordena
for(int i=0;i<5;i++) for(int j=0;j<4;j++) if(v[j]>v[j+1]){ float t=v[j]; v[j]=v[j+1]; v[j+1]=t; }
if(v[2] >= 999) return -1;
return v[2];
}
const float LIGA_CM = 30.0;
const float DESLIGA_CM= 35.0;
int contAbaixo = 0;
int contAcima = 0;
bool ligado = false;
void setup(){
Serial.begin(9600);
pinMode(PIN_TRIG, OUTPUT);
pinMode(PIN_ECHO, INPUT);
pinMode(PIN_LED, OUTPUT);
}
void loop(){
float cm = distanciaEstavelCm();
if(cm < 0){
// se perdeu leitura, não muda estado
delay(120);
return;
}
if(!ligado){
if(cm <= LIGA_CM) contAbaixo++; else contAbaixo=0;
if(contAbaixo >= 3){ ligado = true; contAbaixo=0; }
} else {
if(cm >= DESLIGA_CM) contAcima++; else contAcima=0;
if(contAcima >= 3){ ligado = false; contAcima=0; }
}
digitalWrite(PIN_LED, ligado ? HIGH : LOW);
Serial.print("cm="); Serial.print(cm,1);
Serial.print(" | estado="); Serial.println(ligado ? "PRESENCA" : "LIVRE");
delay(120);
}
Projeto B — “Sensor de Ré” com Buzzer (bip por distância)
Esse é didático e impressiona: o buzzer apita mais rápido conforme se aproxima. Você pode usar buzzer ativo (mais simples) ou passivo (tone()).
Arduino • Buzzer “bip-bip” proporcional à distância
const int PIN_TRIG = 9;
const int PIN_ECHO = 10;
const int PIN_BUZZ = 6; // buzzer passivo (tone)
float leituraCm(){
digitalWrite(PIN_TRIG, LOW); delayMicroseconds(2);
digitalWrite(PIN_TRIG, HIGH); delayMicroseconds(10);
digitalWrite(PIN_TRIG, LOW);
unsigned long dur = pulseIn(PIN_ECHO, HIGH, 30000UL);
if(dur==0) return -1;
return (dur * 0.0343f)/2.0f;
}
float clamp(float v, float a, float b){ if(v<a) return a; if(v>b) return b; return v; }
void setup(){
pinMode(PIN_TRIG, OUTPUT);
pinMode(PIN_ECHO, INPUT);
pinMode(PIN_BUZZ, OUTPUT);
}
void loop(){
float cm = leituraCm();
if(cm < 0){ noTone(PIN_BUZZ); delay(120); return; }
// Faixa útil (ajuste)
float d = clamp(cm, 5.0, 120.0);
// Quanto menor a distância, menor o intervalo (mais rápido)
int intervalo = (int) ( (d - 5.0) * (500.0 - 60.0) / (120.0 - 5.0) + 60.0 );
intervalo = (int)clamp(intervalo, 60, 500);
// Tom também pode variar (opcional)
int freq = (int) (2000 - (d * 10)); // perto = mais agudo
freq = (int)clamp(freq, 800, 2000);
tone(PIN_BUZZ, freq);
delay(30);
noTone(PIN_BUZZ);
delay(intervalo);
}
Projeto C — Medidor de nível (caixa d’água) com porcentagem
Aqui o HC-SR04 mede a distância do sensor até o nível do líquido. Você define: distância vazia (tanque vazio) e distância cheia (tanque cheio).
Dica de ouro: evite espuma/agitação. Se for caixa d’água com turbulência, use média e faça leitura em intervalos maiores.
Arduino • Nível em % (0 a 100)
const int PIN_TRIG = 9;
const int PIN_ECHO = 10;
// Ajuste para seu tanque:
const float DIST_VAZIO_CM = 60.0; // sensor até o fundo (tanque vazio)
const float DIST_CHEIO_CM = 10.0; // sensor até a lâmina d'água (tanque cheio)
float leituraCm(){
digitalWrite(PIN_TRIG, LOW); delayMicroseconds(2);
digitalWrite(PIN_TRIG, HIGH); delayMicroseconds(10);
digitalWrite(PIN_TRIG, LOW);
unsigned long dur = pulseIn(PIN_ECHO, HIGH, 30000UL);
if(dur==0) return -1;
return (dur * 0.0343f)/2.0f;
}
float clamp(float v, float a, float b){ if(v<a) return a; if(v>b) return b; return v; }
void setup(){
Serial.begin(9600);
pinMode(PIN_TRIG, OUTPUT);
pinMode(PIN_ECHO, INPUT);
}
void loop(){
float cm = leituraCm();
if(cm < 0){ Serial.println("Sem leitura."); delay(1000); return; }
// Converte distância em nível: menor distância = mais cheio
float nivel = (DIST_VAZIO_CM - cm) / (DIST_VAZIO_CM - DIST_CHEIO_CM) * 100.0;
nivel = clamp(nivel, 0.0, 100.0);
Serial.print("Distancia: "); Serial.print(cm,1); Serial.print(" cm | ");
Serial.print("Nivel: "); Serial.print(nivel,0); Serial.println("%");
delay(1000);
}
Projeto D — Robô anti-colisão (lógica de desvio)
Mesmo sem entrar no seu driver de motor específico, a lógica é sempre esta: se distância < limiar → parar / ré / virar. É a base de robôs autônomos.
Pseudo-fluxo do robô:
- Leia distância
- Se < 20cm → pare
- Dê ré por 300ms
- Vire para a direita por 250ms
- Volte a andar
5) Especificações técnicas (HC-SR04)
- Alimentação: 5V DC
- Corrente de trabalho: < 2 mA
- Ângulo efetivo: < 15°
- Distância de trabalho: 2 cm até 500 cm
- Resolução: ~0,3 cm
- Sinal TRIG: pulso TTL de 10µs
- Sinal ECHO: saída TTL (pulso proporcional ao tempo)
- Níveis: 5V (alto) / 0V (baixo)
6) Boas práticas e limitações
Superfície do alvo importa
Tecidos, espuma e objetos muito inclinados absorvem/defletem o som → leitura oscila ou some.
Temperatura afeta a velocidade do som
Em ambientes extremos, pode haver erro. Para precisão alta, corrija com temperatura.
Interferência entre sensores
Se usar mais de um, dispare alternado (um por vez). Senão um “ouve” o outro.
Erro clássico: fios longos, GND ruim e ruído de motor (PWM) deixam o ECHO “maluco”. Use GND bem firme, fios curtos e, se tiver motor, separe alimentação e aterre em estrela.
7) Ultrassônico vs Infravermelho vs ToF (qual escolher?)
HC-SR04 (Ultrassônico)
- Ótimo custo-benefício
- Bom alcance
- Pode sofrer com tecido/inclinação
IR (Infravermelho)
- Curto alcance
- Sofre com luz ambiente
- Bom para detecção simples
ToF (Laser / Time-of-Flight)
- Alta precisão
- Mais caro
- Excelente para medições finas
8) FAQ (perguntas frequentes)
Qual a distância máxima real do HC-SR04?
Embora a especificação cite até 500cm, na prática leituras mais confiáveis ficam geralmente até ~400cm, dependendo do alvo e do ambiente.
O HC-SR04 funciona em ambiente externo?
Funciona, mas vento, chuva, ruído e superfícies irregulares podem piorar a estabilidade. Use filtro e evite ângulos ruins.
Posso usar vários sensores no mesmo projeto?
Sim, mas dispare um por vez (sequencial) para evitar interferência cruzada.
Preciso de resistor no ECHO com Arduino UNO?
Não. O UNO é 5V. Em placas 3.3V, sim — use divisor/conversor.
Quer colocar isso em prática hoje?
O HC-SR04 é perfeito para aprender e para projetos reais: presença, nível, robôs e automação. Se você quer um sensor simples, confiável e fácil de integrar no Arduino, ele é uma escolha excelente.
Comprar Sensor Ultrassônico HC-SR04 →