Guias · 14 min de leitura

Projeto de radar com Arduino: guia com HC-SR04, servo SG90 e Processing

Projeto de radar com Arduino passo a passo: ligação do HC-SR04 e do servo SG90, código de ângulo e distância, tela de radar verde no Processing, minirradar em OLED e soluções comuns.

Um radar com Arduino é um projeto que monta um sensor de distância ultrassônico HC-SR04 sobre um servo motor SG90, faz o sensor varrer entre 0 e 180 graus para medir a direção e a distância dos objetos próximos e mostra o resultado no computador em uma tela de radar verde, de filme. A cada ângulo, o Arduino faz uma leitura e envia uma linha “ângulo,distância” pela porta serial; um pequeno programa em Processing rodando no computador lê esses números e desenha a linha de varredura girando e os objetos detectados como linhas vermelhas.

Neste guia você encontra cada passo explicado, da lista de peças e do esquema de ligação ao código do Arduino e à tela de radar no Processing. Também mostramos um minirradar em display OLED que não precisa de computador, versões para ESP32 e Raspberry Pi Pico, como ajustar a velocidade da varredura e a precisão das medições e como resolver os erros de porta serial mais comuns. Ele é barato, dá para terminar em uma tarde e é um dos projetos com Arduino que mais chamam a atenção nas apresentações escolares.

Arduino Uno
Arduino Uno
Sensor ultrassônico HC-SR04
Sensor ultrassônico HC-SR04
Servo SG90
Servo SG90
Protoboard
Protoboard

Como funciona um radar com Arduino?

O coração do sistema é o HC-SR04. Um dos dois cilindros do sensor (T) emite uma rajada curta de som de 40 kHz que os humanos não ouvem; quando o som bate em um objeto e volta, o outro (R) capta o eco. O Arduino mede esse tempo de ida e volta em microssegundos. O som viaja no ar a cerca de 343 m/s, então precisa de uns 29 microssegundos para percorrer um centímetro; como o caminho é feito duas vezes, ida e volta, a fórmula fica distância (cm) = tempo (µs) / 58. O servo gira o sensor passo a passo e a medição se repete a cada passo. O resultado é “algo neste ângulo, a tantos centímetros”, ou seja, uma coordenada polar. Para desenhar na tela, ângulo e distância são convertidos em uma posição de pixel com x = distância × cos(ângulo) e y = distância × sen(ângulo).

PeçaFunçãoValores principais
HC-SR04Medição de distância por ultrassom40 kHz, 2–400 cm, ângulo de medição de cerca de 15°, 5 V, 15 mA
Servo SG90Gira o sensor de 0–180°0,1 s/60° (4,8 V), torque de 1,8 kg·cm, 4,8–6 V, 9 g
Arduino UnoMede, aciona o servo, envia os dados16 MHz, nível lógico de 5 V, porta serial USB
ProcessingDesenha a tela de radar no computadorGrátis, baseado em Java, biblioteca Serial incluída
OLED SSD1306 (opcional)Minitela de radar sem computador128×64 pixels, I2C, endereço 0x3C

Lista de peças do radar com Arduino

  • Arduino Uno ou Nano e um cabo USB que transmita dados (cabos só de carga não aparecem como porta no computador).
  • Sensor de distância ultrassônico HC-SR04.
  • Microsservo SG90 e os braços plásticos que vêm no saquinho dele.
  • Uma protoboard e 8–10 jumpers macho-macho e macho-fêmea.
  • Um capacitor eletrolítico de 470 µF (de pelo menos 10 V): ele impede que a tensão de alimentação caia quando o servo se move.
  • Fita dupla face, cola quente ou um pequeno suporte impresso em 3D para prender o sensor no servo.
  • Opcional: um display OLED I2C de 0,96 polegada (para a versão sem computador) e uma fonte externa de 5 V 2 A.

Esquema de ligação do radar com Arduino

LigaçãoArduino UnoESP32Raspberry Pi Pico
VCC do HC-SR045VVIN (5 V)VBUS (pino 40)
GND do HC-SR04GNDGNDGND
Trig do HC-SR04D10GPIO 26GP14
Echo do HC-SR04D11GPIO 27 (por divisor)GP13 (por divisor)
SG90 marrom (GND)GNDGNDGND
SG90 vermelho (+5 V)5VVIN (5 V)VBUS (pino 40)
SG90 laranja (sinal)D9GPIO 13GP15

No Uno, a ligação fica mais organizada se você ligar os fios de 5 V e GND do sensor e do servo nos barramentos positivo e negativo da protoboard, e esses barramentos nos pinos 5V e GND do Arduino. Encaixe o capacitor de 470 µF nos mesmos barramentos, com a perna longa (+) no 5 V e a perna curta, marcada pela faixa no corpo, no GND. Em alguns servos os fios são preto, vermelho e branco; nesse caso, o preto é o GND e o branco é o sinal. Para conferir onde ficam os pinos da sua placa, use a ferramenta de pinagem.

Quando o HC-SR04 funciona com 5 V, o pino Echo dele também fornece 5 V. Isso não é problema para um Arduino Uno, mas os pinos do ESP32 e do Raspberry Pi Pico não toleram 5 V. Coloque um divisor de tensão de 1 kΩ e 2 kΩ na linha Echo (Echo → 1 kΩ → GPIO, GPIO → 2 kΩ → GND); a tensão no pino cai para cerca de 3,3 V. Você pode conferir os valores com a calculadora de divisor de tensão.

Montando o sensor no servo

Microsservo motor SG90
Servo SG90: marrom é o GND, vermelho é o +5 V, laranja é o sinal. O HC-SR04 é colado no braço plástico do servo.

Antes de encaixar o braço, coloque o servo em 90 graus: basta carregar um sketch de teste curto com radarServo.write(90) e deixar o servo nessa posição. Depois encaixe o braço de modo que o sensor aponte bem para a frente. Assim, 0° aponta para a direita, 90° para a frente e 180° para a esquerda, e as direções na tela do Processing batem exatamente com o mundo real. Ao colar o HC-SR04 no braço com fita dupla face ou cola quente, garanta que os dois cilindros fiquem paralelos ao chão; se o sensor ficar inclinado para baixo, ele vai confundir a superfície da mesa com um objeto. Deixe folga nos fios para que não fiquem esticados durante o giro de 180 graus e prenda o servo a uma base pesada ou a uma caixa; um corpo que balança a cada passo estraga as leituras.

Montando o radar com Arduino passo a passo

  1. Ligue as peças conforme a tabela acima, não esqueça o capacitor e monte o sensor no servo.
  2. Abra o Arduino IDE; a biblioteca Servo vem com o IDE, então não há nada extra para instalar.
  3. Carregue o código do radar abaixo. Se tiver problemas para escolher a placa ou a porta, veja Arduino não carrega o código.
  4. Abra o Monitor Serial em 9600 baud; se linhas de ângulo e distância como “30,45” estiverem passando, o lado do Arduino está pronto. Depois, não deixe de fechar o Monitor Serial.
  5. Instale o Processing 4 no computador, abra um sketch novo e cole o código da tela de radar.
  6. Aperte Run (executar); a lista de portas aparece no console embaixo e a janela do radar se abre. Quando você mover a mão na frente do sensor, devem aparecer linhas vermelhas.

Código do radar com Arduino

C++ (Arduino IDE)
1#include <Servo.h>
2
3const byte SERVO_PIN  = 9;     // SG90 turuncu kablo / SG90 orange wire
4const byte TRIG_PIN   = 10;    // HC-SR04 Trig
5const byte ECHO_PIN   = 11;    // HC-SR04 Echo
6const int  MIN_ANGLE  = 0;     // tarama başlangıcı / sweep start
7const int  MAX_ANGLE  = 180;   // tarama sonu / sweep end
8const int  STEP       = 2;     // adım başına derece / degrees per step
9const int  STEP_DELAY = 40;    // ölçümden önce bekleme (ms) / wait before measuring (ms)
10
11Servo radarServo;
12int angle = MIN_ANGLE;
13int dir = STEP;
14
15int measureCm() {
16  digitalWrite(TRIG_PIN, LOW);
17  delayMicroseconds(2);
18  digitalWrite(TRIG_PIN, HIGH);                         // 10 µs tetik darbesi / 10 µs trigger pulse
19  delayMicroseconds(10);
20  digitalWrite(TRIG_PIN, LOW);
21  unsigned long us = pulseIn(ECHO_PIN, HIGH, 30000UL);  // en çok 30 ms bekle / wait at most 30 ms
22  if (us == 0) return 0;                                // yankı yok = menzil dışı / no echo = out of range
23  return us / 58;                                       // gidiş-dönüş süresi → cm / round-trip time → cm
24}
25
26void setup() {
27  Serial.begin(9600);
28  pinMode(TRIG_PIN, OUTPUT);
29  pinMode(ECHO_PIN, INPUT);
30  radarServo.attach(SERVO_PIN);
31  radarServo.write(angle);
32  delay(500);                                           // başlangıç konumuna gitsin / reach the start position
33}
34
35void loop() {
36  radarServo.write(angle);                              // servoyu yeni açıya döndür / move the servo to the new angle
37  delay(STEP_DELAY);                                    // titreşim geçsin / let the vibration settle
38  int distance = measureCm();
39
40  Serial.print(angle);                                  // biçim: açı,mesafe / format: angle,distance
41  Serial.print(',');
42  Serial.println(distance);
43
44  if (angle + dir > MAX_ANGLE || angle + dir < MIN_ANGLE) dir = -dir;  // uçta yön değiştir / reverse at the ends
45  angle += dir;
46}

Como o código funciona

Parte do códigoO que faz
STEP e STEP_DELAYDefinem quantos graus o servo gira por passo e quanto tempo esperar antes de medir; você ajusta a velocidade da varredura com essas duas constantes.
measureCm()Envia um pulso de 10 µs ao pino Trig, usa o pulseIn para medir quanto tempo o pino Echo fica em HIGH e divide por 58 para obter centímetros.
pulseIn(..., 30000UL)Espera no máximo 30 ms e retorna 0 se nenhum eco chegar. Sem esse timeout, a função poderia travar por até 1 segundo apontando para o vazio.
radarServo.write(angle)Leva o servo ao ângulo pedido; a biblioteca transforma o valor de 0–180 em um pulso de 544–2400 µs.
Serial.print ... printlnEnvia cada leitura como uma única linha “ângulo,distância”; o fim de linha diz ao Processing “dado completo”.
dir = -dirInverte o sentido quando o ângulo chega a 180 ou 0, para o servo varrer para lá e para cá sem parar.

Há um motivo para os dados serem tão simples: uma única linha separada por vírgula é fácil de ler no Monitor Serial e pode ser interpretada com uma linha de código no Processing, no Python ou no Excel. Uma distância 0 significa “nada no alcance neste ângulo”, e o Processing não desenha esses valores. Se você abrir os mesmos dados no Plotter Serial do Arduino IDE, verá o ângulo subir e descer como dente de serra e a distância saltar sempre que o sensor passa por um objeto. Usar delay não tem problema neste projeto; se quiser ler um botão ou acender um LED enquanto o radar funciona, reescreva o loop com millis().

Se o servo zumbir e tremer exatamente em 0° ou 180°, ele está batendo no limite mecânico. Reduza a varredura para 10–170°, ou inicie o servo com radarServo.attach(SERVO_PIN, 500, 2400) e ajuste a faixa de pulso ao seu servo.

A tela de radar verde no Processing

O Processing é um programa gratuito, baseado em Java, feito para programação visual, e a interface dele é muito parecida com a do Arduino IDE: você escreve o código e aperta Run. A biblioteca Serial, necessária para a comunicação serial, vem com o Processing; você pode adicioná-la pelo menu Sketch > Import Library ou simplesmente contar com a linha import no topo do código. O código abaixo vai no Processing, não no Arduino IDE.

C++ (Arduino IDE)
1// Processing 4 çizimi: Arduino IDE'ye değil, Processing'e yapıştır / Processing 4 sketch: paste into Processing, not the Arduino IDE
2import processing.serial.*;                       // Serial kütüphanesi / Serial library
3
4Serial port;
5int angle = 0;                                    // son açı / last angle
6int distance = 0;                                 // son mesafe (cm) / last distance (cm)
7final int MAX_CM = 100;                           // ekrandaki en uzak mesafe / farthest distance on screen
8float R;                                          // radar yarıçapı (piksel) / radar radius (pixels)
9
10void setup() {
11  size(1200, 700);
12  R = width * 0.45;
13  printArray(Serial.list());                      // portları konsola yaz / print the ports to the console
14  String portName = Serial.list()[0];             // gerekirse [1] ya da "COM4" yaz / use [1] or "COM4" if needed
15  port = new Serial(this, portName, 9600);        // Arduino ile aynı baud / same baud as the Arduino
16  port.bufferUntil('\n');                         // satır sonunu bekle / wait for the end of a line
17  background(0);
18}
19
20void draw() {
21  noStroke();
22  fill(0, 12);                                    // yarı saydam siyah: solan iz / translucent black: fading trail
23  rect(0, 0, width, height);
24  translate(width / 2, height - 60);              // radar merkezi alt ortada / radar centre at the bottom middle
25  drawGrid();
26  drawSweep();
27  drawObject();
28  drawLabels();
29}
30
31void drawGrid() {
32  noFill();
33  strokeWeight(2);
34  stroke(98, 245, 31);
35  for (int i = 1; i <= 4; i++) {
36    float d = 2 * R * i / 4;
37    arc(0, 0, d, d, PI, TWO_PI);                  // 25-50-75-100 cm yayları / 25-50-75-100 cm arcs
38  }
39  for (int a = 0; a <= 180; a += 30) {
40    line(0, 0, R * cos(radians(a)), -R * sin(radians(a)));   // 30 derecelik çizgiler / 30-degree lines
41  }
42}
43
44void drawSweep() {
45  strokeWeight(5);
46  stroke(30, 250, 60);
47  line(0, 0, R * cos(radians(angle)), -R * sin(radians(angle)));   // tarama çizgisi / sweep line
48}
49
50void drawObject() {
51  if (distance <= 0 || distance > MAX_CM) return;  // menzil dışı / out of range
52  float p = R * distance / MAX_CM;                 // cm → piksel / cm → pixels
53  float c = cos(radians(angle));
54  float s = sin(radians(angle));
55  strokeWeight(7);
56  stroke(255, 10, 10);
57  line(p * c, -p * s, R * c, -R * s);              // nesneden dışa kırmızı çizgi / red line from the object outwards
58}
59
60void drawLabels() {
61  resetMatrix();
62  noStroke();
63  fill(0);
64  rect(0, height - 40, width, 40);                 // yazı şeridi / text strip
65  fill(98, 245, 31);
66  textSize(20);
67  for (int i = 1; i <= 4; i++) {
68    text(MAX_CM * i / 4 + " cm", width / 2 + R * i / 4 + 4, height - 66);   // yay etiketleri / arc labels
69  }
70  String d = (distance > 0 && distance <= MAX_CM) ? distance + " cm" : "-";
71  text("Açı / Angle: " + angle + "°", 40, height - 12);
72  text("Mesafe / Distance: " + d, width / 2, height - 12);
73}
74
75void serialEvent(Serial p) {
76  String msg = p.readStringUntil('\n');            // "açı,mesafe" satırı / "angle,distance" line
77  if (msg == null) return;
78  String[] parts = split(trim(msg), ',');
79  if (parts.length == 2) {
80    angle = int(parts[0]);
81    distance = int(parts[1]);
82  }
83}

A parte mais importante do código é a função serialEvent(). Graças ao bufferUntil('\n'), o Processing junta os dados que chegam até vir um fim de linha e então chama essa função automaticamente com uma linha completa. A linha é limpa de espaços e do caractere \r com trim(), dividida em duas na vírgula com split() e convertida em números com int(). Já o draw() roda cerca de 60 vezes por segundo: primeiro ele pinta um retângulo preto translúcido sobre a tela (fill(0, 12)), depois redesenha a grade, a linha de varredura e o objeto. Como as linhas antigas ficam um pouco mais escuras a cada quadro, o rastro que se apaga, visto nas telas de radar de verdade, aparece sozinho.

ConfiguraçãoOnde?O que faz
MAX_CM = 100ProcessingA maior distância que a tela cobre; o arco externo é de 100 cm e os arcos internos mostram 25, 50 e 75 cm.
Serial.list()[0]ProcessingEscolhe a primeira porta serial do computador; se o seu Arduino estiver mais abaixo na lista, mude o índice ou digite o nome direto, como “COM4”.
9600Nos doisBaud rate; o valor do Serial.begin do Arduino e o do Processing precisam ser iguais.
fill(0, 12)ProcessingVelocidade do apagamento; 5 dá um rastro longo, 30 uma imagem quase sem rastro.
size(1200, 700)ProcessingTamanho da janela; diminua se não couber na sua tela. O raio acompanha a largura, então mantenha a altura acima da metade da largura.

Ajustando a velocidade do servo e o tempo de varredura

Segundo o datasheet, o SG90 gira 60 graus em 0,1 segundo a 4,8 V, então termina um passo de 2 graus em poucos milissegundos. O que define de fato o tempo de varredura não é o servo, mas o tempo de espera e de medição em cada passo. Depois que o servo para, o braço e o sensor balançam por um instante; medir nesse momento faz as distâncias pularem. O fabricante do HC-SR04 também recomenda deixar cerca de 60 ms entre duas medições, porque ecos do pulso anterior rebatendo pela sala podem vazar para a próxima leitura. Na prática, um total de 50–60 ms por passo (espera + medição) é um bom equilíbrio. Uma varredura completa leva mais ou menos (180 / passo + 1) × tempo do passo.

PassoSTEP_DELAYUma varredura (0→180°)Resultado
1°20 mscerca de 7 sImagem mais suave, mas lenta; o mesmo objeto é medido muitas vezes.
2°40 mscerca de 5 sConfiguração recomendada: suave e estável.
3°50 mscerca de 4 sMais rápida; graças ao feixe de 15° do sensor, nenhum objeto escapa.
5°70 mscerca de 3,5 sA tela parece aos trancos; passos maiores causam mais balanço, então a espera precisa ser maior.

Para suavizar o movimento, mantenha o passo pequeno e a espera curta; se quiser velocidade, aumente o passo e alongue um pouco a espera. Limitar a varredura à área que interessa (por exemplo, 45–135°) também corta o tempo pela metade. Se o servo der trancos sozinho, o Arduino reiniciar de vez em quando e o Processing perder a conexão, o problema não é a velocidade, e sim a alimentação: o SG90 pode puxar cerca de 100–250 mA em movimento e até 600 mA com carga. Acrescente o capacitor e, se precisar, alimente o servo com uma fonte externa de 5 V que divida o GND com o Arduino.

Melhorando a precisão das medições

Embora o HC-SR04 prometa no papel uma resolução de 3 mm, três coisas decidem a precisão de um radar: a largura do feixe, a velocidade do som e o tipo de superfície. O feixe sonoro do sensor se abre como um cone de cerca de 15 graus. Por isso, uma caneta fina a 50 cm aparece na tela não como um ponto, mas como um arco de 15–20 graus de largura; a resolução angular do radar é definida por esse feixe, não pelo passo do servo, e a direção real do objeto é o meio do arco. A velocidade do som muda com a temperatura e é calculada com v = 331,3 + 0,606 × T (m/s, T em °C). O número 58 do código corresponde a cerca de 22 °C; em uma garagem fria, as leituras saem alguns por cento longas demais.

TemperaturaVelocidade do somIda e volta por 1 cmObjeto a 100 cm (com /58)
0 °C331,3 m/s60,4 µscerca de 104 cm
10 °C337,4 m/s59,3 µscerca de 102 cm
20 °C343,4 m/s58,2 µscerca de 100 cm
30 °C349,5 m/s57,2 µscerca de 99 cm
40 °C355,5 m/s56,3 µscerca de 97 cm

Você pode medir a temperatura do ambiente com um DHT11 ou um DS18B20 e levar a velocidade do som em conta, e pode descartar leituras ruins isoladas tirando a mediana de três. Basta acrescentar as duas funções abaixo ao código principal e trocar a chamada measureCm() no loop() por uma delas. Como o filtro de mediana faz três leituras por passo, ele deixa a varredura um pouco mais lenta.

C++ (Arduino IDE)
1// Ana radar koduna eklenecek fonksiyonlar / functions to add to the main radar sketch
2
3// Sıcaklığa göre düzeltilmiş ölçüm / temperature-compensated reading
4int measureCmTemp(float tempC) {
5  digitalWrite(TRIG_PIN, LOW);
6  delayMicroseconds(2);
7  digitalWrite(TRIG_PIN, HIGH);
8  delayMicroseconds(10);
9  digitalWrite(TRIG_PIN, LOW);
10  unsigned long us = pulseIn(ECHO_PIN, HIGH, 30000UL);
11  if (us == 0) return 0;                                // yankı yok / no echo
12  float v = 331.3 + 0.606 * tempC;                      // ses hızı (m/s) / speed of sound (m/s)
13  return (int)(us * v / 20000.0 + 0.5);                 // µs × (m/s) / 20000 = cm
14}
15
16// Üç ölçümün ortancası: tek seferlik sıçramaları atar / median of three: drops one-off spikes
17int medianCm() {
18  int a = measureCm(); delay(20);
19  int b = measureCm(); delay(20);
20  int c = measureCm();
21  return max(min(a, b), min(max(a, b), c));
22}
23
24// loop() içinde kullanım / use inside loop():
25// int distance = medianCm();
26// int distance = measureCmTemp(18.5);                  // sıcaklık DHT11'den gelebilir / temperature can come from a DHT11
  • Superfícies macias (cortinas, tecido, espuma) absorvem o som; um objeto pode não aparecer onde está.
  • Superfícies inclinadas refletem o som para outro lado; uma caixa plana virada mais de 45° em relação ao sensor pode ser lida como espaço vazio.
  • Objetos a menos de 2 cm não podem ser medidos; na prática, considere pouco confiável qualquer coisa abaixo de 3–4 cm.
  • Cantos da sala causam reflexões múltiplas e podem criar “fantasmas” distantes que não existem; teste em uma área vazia e aberta.
  • Alcance: o datasheet diz 400 cm, mas as leituras estáveis de objetos pequenos normalmente chegam a cerca de 2 metros; escolha o MAX_CM de acordo.

Minirradar em display OLED (sem computador)

Se você quer que o radar seja um aparelho portátil, alimentado por bateria e que não precise de computador, pode usar um display OLED de 0,96 polegada no lugar do Processing. O centro da parte de baixo da tela SSD1306 de 128×64 vira o centro do radar; sobre ela são desenhados um semicírculo com raio de 60 pixels, a linha de varredura e pontos mostrando o último objeto medido em cada ângulo. Para a ligação do display (SDA → A4, SCL → A5) e a instalação da biblioteca, veja o guia display OLED de 0,96 polegada (SSD1306); o HC-SR04 e o servo são ligados igual ao que está acima.

Display OLED I2C SSD1306 de 0,96 polegada
Display OLED de 0,96 polegada: no minirradar sem computador, ele vira uma tela de varredura semicircular de 128×64 pixels.
C++ (Arduino IDE)
1#include <Wire.h>
2#include <Adafruit_GFX.h>
3#include <Adafruit_SSD1306.h>
4#include <Servo.h>
5
6const byte SERVO_PIN = 9;                 // SG90 sinyal / SG90 signal
7const byte TRIG_PIN  = 10;                // HC-SR04 Trig
8const byte ECHO_PIN  = 11;                // HC-SR04 Echo
9const int  MAX_CM    = 50;                // ekrandaki en uzak mesafe / farthest distance on screen
10const int  STEP      = 3;                 // adım başına derece / degrees per step
11const int  CX = 64, CY = 63, R = 60;      // radar merkezi ve yarıçapı (piksel) / radar centre and radius (px)
12
13Adafruit_SSD1306 display(128, 64, &Wire, -1);
14Servo radarServo;
15uint8_t dist[180 / STEP + 1];             // her açının son ölçümü (cm) / last reading per angle (cm)
16int angle = 0;
17int dir = STEP;
18
19int measureCm() {
20  digitalWrite(TRIG_PIN, LOW);
21  delayMicroseconds(2);
22  digitalWrite(TRIG_PIN, HIGH);
23  delayMicroseconds(10);
24  digitalWrite(TRIG_PIN, LOW);
25  unsigned long us = pulseIn(ECHO_PIN, HIGH, 30000UL);
26  if (us == 0) return 0;                  // yankı yok / no echo
27  return us / 58;
28}
29
30void setup() {
31  pinMode(TRIG_PIN, OUTPUT);
32  pinMode(ECHO_PIN, INPUT);
33  radarServo.attach(SERVO_PIN);
34  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
35    for (;;);                             // ekran bulunamadı / display not found
36  }
37  display.setTextColor(SSD1306_WHITE);
38}
39
40void loop() {
41  radarServo.write(angle);
42  delay(20);                              // çizim de zaman aldığı için kısa / short, drawing takes time too
43  int d = measureCm();
44  dist[angle / STEP] = (d > 255) ? 255 : d;   // byte'a sığdır / fit into a byte
45
46  display.clearDisplay();
47  display.drawCircle(CX, CY, R, SSD1306_WHITE);       // dış yay, alt yarısı ekran dışında / outer arc, lower half off-screen
48  display.drawCircle(CX, CY, R / 2, SSD1306_WHITE);   // orta yay = MAX_CM / 2 / middle arc = MAX_CM / 2
49  for (int i = 0; i <= 180 / STEP; i++) {
50    if (dist[i] > 0 && dist[i] <= MAX_CM) {
51      float rad = radians(i * STEP);
52      int r = map(dist[i], 0, MAX_CM, 0, R);          // cm → piksel / cm → pixels
53      display.fillCircle(CX + r * cos(rad), CY - r * sin(rad), 1, SSD1306_WHITE);
54    }
55  }
56  float rad = radians(angle);
57  display.drawLine(CX, CY, CX + R * cos(rad), CY - R * sin(rad), SSD1306_WHITE);  // tarama çizgisi / sweep line
58  display.setCursor(0, 0);
59  display.print(angle);                   // açı / angle
60  display.setCursor(98, 0);
61  display.print(d);                       // mesafe / distance
62  display.print(F("cm"));
63  display.display();
64
65  if (angle + dir > 180 || angle + dir < 0) dir = -dir;   // uçta yön değiştir / reverse at the ends
66  angle += dir;
67}

Nesta versão, as distâncias são guardadas por ângulo no array dist, então os pontos continuam na tela depois que a linha de varredura passa e são atualizados na próxima passagem. O centro do círculo fica na borda de baixo da tela, então a metade de baixo dele cai fora do display e a biblioteca não a desenha, deixando um semicírculo certinho. Enviar um quadro para a tela leva cerca de 25 ms com I2C a 400 kHz, então a espera foi reduzida para 20 ms e o passo aumentado para 3 graus; uma varredura leva cerca de 4–5 segundos. Uma escala de 50 cm é mais fácil de ler em uma tela pequena, então o MAX_CM foi definido como 50. Metade dos 2 KB de memória do Uno vai para o buffer do display, e é por isso que importa manter o array em bytes (uint8_t).

Radar com ESP32

A biblioteca Servo do Arduino não funciona no ESP32; instale no lugar dela a biblioteca ESP32Servo pelo Gerenciador de Bibliotecas. O resto do código é quase igual. Como o ESP32 trabalha em 3,3 V, não esqueça o divisor de tensão na linha Echo do HC-SR04; já o pulso de 3,3 V na linha Trig basta para disparar a maioria dos sensores. Este código usa 115200 baud, então mude também o 9600 do código do Processing para 115200. Graças ao Wi-Fi do ESP32, mais tarde você poderia enviar os dados do radar para uma página web no celular em vez de um computador; se está começando com o ESP32, comece por O que é o ESP32.

C++ (Arduino IDE)
1#include <ESP32Servo.h>                // Kütüphane Yöneticisi: ESP32Servo / Library Manager: ESP32Servo
2
3const int SERVO_PIN  = 13;             // SG90 sinyal / SG90 signal
4const int TRIG_PIN   = 26;             // HC-SR04 Trig
5const int ECHO_PIN   = 27;             // 1k/2k bölücüden / through the 1k/2k divider
6const int STEP       = 2;              // adım başına derece / degrees per step
7const int STEP_DELAY = 40;             // ölçümden önce bekleme (ms) / wait before measuring (ms)
8
9Servo radarServo;
10int angle = 0;
11int dir = STEP;
12
13int measureCm() {
14  digitalWrite(TRIG_PIN, LOW);
15  delayMicroseconds(2);
16  digitalWrite(TRIG_PIN, HIGH);
17  delayMicroseconds(10);
18  digitalWrite(TRIG_PIN, LOW);
19  unsigned long us = pulseIn(ECHO_PIN, HIGH, 30000UL);
20  if (us == 0) return 0;               // yankı yok / no echo
21  return us / 58;
22}
23
24void setup() {
25  Serial.begin(115200);                       // Processing'de de 115200 / 115200 in Processing too
26  pinMode(TRIG_PIN, OUTPUT);
27  pinMode(ECHO_PIN, INPUT);
28  radarServo.setPeriodHertz(50);              // standart servo 50 Hz / standard servo 50 Hz
29  radarServo.attach(SERVO_PIN, 500, 2400);    // SG90 darbe aralığı (µs) / SG90 pulse range (µs)
30  radarServo.write(angle);
31  delay(500);
32}
33
34void loop() {
35  radarServo.write(angle);
36  delay(STEP_DELAY);
37  int distance = measureCm();
38  Serial.printf("%d,%d\n", angle, distance);  // açı,mesafe / angle,distance
39  if (angle + dir > 180 || angle + dir < 0) dir = -dir;   // uçta yön değiştir / reverse at the ends
40  angle += dir;
41}

Radar com Raspberry Pi Pico e MicroPython

No Pico você não precisa de uma biblioteca de servo separada: ajustar a largura do pulso de um sinal PWM de 50 Hz com duty_ns() basta. O tempo do eco é medido com machine.time_pulse_us(), que retorna um número negativo no timeout. Os pinos do Pico também são de 3,3 V, então o divisor na linha Echo é obrigatório. Salve o código no Pico como main.py com o Thonny e depois feche o Thonny; senão a porta continua ocupada e o Processing não consegue se conectar. Como o Pico abre uma porta serial virtual pela USB, o valor de baud no Processing não importa; a mesma tela de radar funciona sem nenhuma mudança.

MicroPython
1from machine import Pin, PWM, time_pulse_us
2import time
3
4servo = PWM(Pin(15))                     # SG90 sinyal / SG90 signal
5servo.freq(50)                           # standart servo 50 Hz / standard servo 50 Hz
6trig = Pin(14, Pin.OUT)
7echo = Pin(13, Pin.IN)                   # bölücüden gelir / comes through the divider
8
9def set_angle(a):
10    # 0° = 500 µs, 180° = 2400 µs darbe / pulse
11    servo.duty_ns(500000 + a * 1900000 // 180)
12
13def measure_cm():
14    trig.value(0)
15    time.sleep_us(2)
16    trig.value(1)                        # 10 µs tetik / 10 µs trigger
17    time.sleep_us(10)
18    trig.value(0)
19    t = time_pulse_us(echo, 1, 30000)    # en çok 30 ms bekle / wait at most 30 ms
20    if t < 0:
21        return 0                         # yankı yok / no echo
22    return t // 58
23
24angle, step = 0, 2
25set_angle(angle)
26time.sleep_ms(500)
27
28while True:
29    set_angle(angle)
30    time.sleep_ms(40)                    # servo otursun / let the servo settle
31    print("{},{}".format(angle, measure_cm()))   # açı,mesafe / angle,distance
32    if angle + step > 180 or angle + step < 0:
33        step = -step                     # uçta yön değiştir / reverse at the ends
34    angle += step

Erros comuns e soluções

Sintoma ou mensagem de erroCausaSolução
Error opening serial port COM3: Port busy (porta ocupada)O Monitor Serial ou o Plotter Serial do Arduino IDE, o Thonny ou uma segunda janela do Processing está segurando a porta.Feche o Monitor Serial e os outros programas e rode o sketch do Processing de novo; se precisar, desconecte e reconecte o cabo USB.
ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0 (lista de portas vazia)O Serial.list() está vazio: a placa não está conectada, o cabo é só de carga ou o driver do CH340 não está instalado.Use um cabo de dados e instale o driver; se o Arduino IDE enxerga a porta, o Processing também vai enxergar.
A janela abre, mas a linha de varredura não se moveA porta errada está selecionada (no Windows, a COM1 muitas vezes é a primeira da lista) ou os baud rates são diferentes.Encontre a posição do Arduino na lista do console, mude para Serial.list()[1] ou algo parecido e use o mesmo baud rate dos dois lados.
The package “processing.serial” does not exist. You might be missing a library. (biblioteca Serial ausente)A biblioteca Serial não é encontrada; o instalador do Processing 4.4.8 veio sem ela.Atualize o Processing para uma versão mais nova ou use a 4.4.7, e confira se a linha import está digitada corretamente.
Error opening serial port /dev/ttyACM0: Permission denied (permissão negada)No Linux, o seu usuário não tem permissão para acessar a porta serial.Adicione o seu usuário ao grupo dialout (sudo usermod -a -G dialout $USER) e depois saia e entre de novo na sessão.
O código não carrega no Arduino com o Processing abertoA porta está sendo usada pelo Processing.Pare o sketch do Processing com o botão Stop antes de carregar.
A distância é sempre 0 ou sem sentidoTrig e Echo estão trocados, o sensor está sem alimentação ou o objeto está fora do alcance.Confira a ligação com a tabela e teste primeiro com um sketch simples que só mede a distância.
O servo treme e o Arduino reinicia sozinhoA porta USB não fornece a corrente do servo e a tensão cai.Acrescente um capacitor de 470 µF ou alimente o servo com uma fonte externa de 5 V com GND compartilhado.
Esquerda e direita estão trocadas na tela do radarO servo ou o sensor está montado ao contrário.No Processing, escreva angle = 180 - int(parts[0]); ou tire o braço e encaixe-o virado ao contrário.
Siga esta ordem ao depurar: primeiro veja as linhas “ângulo,distância” no Monitor Serial, depois feche o Monitor Serial e rode o Processing. Se os dados estiverem chegando certo do lado do Arduino, o problema quase sempre é a escolha da porta ou o baud rate.

Ideias para levar o projeto de radar adiante

  • Radar de segurança com alarme: quando um objeto chegar a menos de 30 cm, toque um buzzer e acenda um LED vermelho; combine com as ideias de sistema de alarme com Arduino.
  • Robô que desvia de obstáculos: coloque o radar na frente de um robô; quando o robô para, ele varre para a esquerda e para a direita e vira para a direção mais livre. Detalhes em robô que desvia de obstáculos.
  • Mapa do cômodo: grave os dados da varredura em um módulo de cartão SD e desenhe-os como uma nuvem de pontos no computador.
  • Radar sem fio: envie as leituras de um ESP32 por Wi-Fi para uma página web no celular; com um servidor web no ESP32, dá para desenhar em tempo real.
  • Mapa mais nítido: use um sensor a laser (ToF) de feixe estreito no lugar do HC-SR04; você encontra as opções na comparação de sensores de distância.
  • Bengala inteligente: monte uma bengala que avisa pessoas com deficiência visual sobre obstáculos usando um sensor de distância e um motor de vibração: projeto de bengala inteligente.

Por reunir sensor de distância, controle de servo, comunicação serial e desenho de gráficos no computador em uma só montagem, o projeto de radar com Arduino é um ótimo próximo passo para iniciantes. Para reforçar o básico, dê uma olhada também nos guias sensor de distância HC-SR04 e servo motor. No app BlueGrays você encontra projetos passo a passo de medição de distância com HC-SR04, sensor de estacionamento, uso de servo motor e robô que desvia de obstáculos, cada um com esquemas do circuito e código comentado.

Perguntas frequentes

Um radar com Arduino é um radar de verdade?

Tecnicamente não, é um sonar. Radares de verdade emitem ondas de rádio, enquanto este projeto usa ondas sonoras de 40 kHz do HC-SR04. Ele é conhecido como “radar com Arduino” porque o princípio de funcionamento é o mesmo (emitir uma onda, medir o tempo do eco, desenhar com a direção) e a tela parece a de um radar.

A que distância um radar com Arduino consegue detectar?

O alcance do HC-SR04 segundo o datasheet é de 2–400 cm. Superfícies grandes e planas, como paredes, podem ser medidas até 3–4 metros, mas, para objetos como pés de cadeira ou pessoas, o alcance confiável costuma ser de 1,5–2 metros. Ajustar o MAX_CM do código do Processing para essa faixa dá a imagem mais clara.

Do que preciso para montar um radar com Arduino?

Bastam um Arduino Uno ou Nano, um sensor ultrassônico HC-SR04, um servo SG90, uma protoboard, alguns jumpers e um capacitor de 470 µF para o servo. O programa gratuito Processing desenha a tela do radar no computador; para uma versão sem computador, você acrescenta um display OLED de 0,96 polegada.

Dá para fazer um radar com Arduino sem o Processing?

Sim. Com um display OLED SSD1306, você pode desenhar o radar direto no Arduino e transformá-lo em um aparelho portátil alimentado por bateria. Mesmo sem display, dá para acompanhar os valores de ângulo e distância em gráfico no Plotter Serial do Arduino IDE.

Como resolvo o erro “Port busy” no Processing?

Esse erro significa que outro programa está usando a porta serial. Feche o Monitor Serial e o Plotter Serial do Arduino IDE, o Thonny ou qualquer outro sketch do Processing que tenha ficado aberto e tente de novo. Se continuar, desconecte o cabo USB e conecte de novo.

Por que o servo treme e o Arduino reinicia?

O SG90 puxa picos curtos de corrente alta quando se move, e a linha de 5 V de um Arduino alimentado pela USB cai por um instante. Um capacitor de 470 µF na alimentação do servo costuma resolver; se não resolver, alimente o servo com uma fonte externa de 5 V que divida o GND com o Arduino.

Ver todos os projetos
Medição de distância com HC-SR04 (Monitor Serial)
#27Iniciante

Medição de distância com HC-SR04 (Monitor Serial)

O sensor HC-SR04 funciona como um morcego que se orienta no escuro: emite um som que você não consegue ouvir, escuta o eco e mede a distância até o objeto à sua frente. O Arduino escreve essa distânci

4.6(46)
71
Uso de servo motor
#35Iniciante
Premium

Uso de servo motor

O braço de um pequeno servo motor gira para três posições em sequência: o início, o meio e o fim do percurso, esperando dois segundos em cada parada. O Arduino informa ao motor em qual ângulo ficar, e

4.7(48)
67
Sensor de estacionamento com HC-SR04
#28Intermediário
Premium

Sensor de estacionamento com HC-SR04

Uma versão em miniatura do sensor de estacionamento de um carro: quanto mais perto um objeto chega, mais rápidos ficam os bipes. O sensor de distância mede a distância até o objeto à sua frente; se el

4.8(64)
85
Robô que desvia de obstáculos
#81Avançado
Premium

Robô que desvia de obstáculos

Que tal construir um veículo inteligente que encontra seu próprio caminho? O robô que desvia de obstáculos monitora o ambiente constantemente com o sensor ultrassônico na parte da frente. Ao encontrar

5.0(38)
49
Medidor ultrassônico de distância HC-SR04 com ESP32
#116Intermediário

Medidor ultrassônico de distância HC-SR04 com ESP32

O sensor ultrassônico HC-SR04 calcula a distância medindo o tempo que a onda sonora emitida leva para atingir um objeto e retornar (tempo de voo). Neste projeto, enviaremos um pulso de 10 microssegundos do ESP32 ao pino TRIG do sensor e leremos a duração do eco no pino ECHO com pulseIn(). Exibiremos a distância calculada em centímetros em um LCD I2C 16x2. Como o HC-SR04 opera a 5V, é preciso usar um divisor de tensão no pino ECHO; caso contrário, o GPIO de 3,3V do ESP32 será danificado.

4.9(28)
45
Sensor de estacionamento com ESP32 (HC-SR04 + barra de 5 LEDs + buzzer + OLED)
#142Avançado
Premium

Sensor de estacionamento com ESP32 (HC-SR04 + barra de 5 LEDs + buzzer + OLED)

A versão com ESP32 do sensor de estacionamento de carro! Usamos o sensor ultrassônico HC-SR04 para medir a distância até o objeto à sua frente. Conforme a distância diminui, a barra de 5 LEDs vai se preenchendo (verde → amarelo → vermelho) e o intervalo entre os bipes do buzzer diminui. Quando o objeto chega muito perto (menos de 10 cm), o alarme soa continuamente e todos os LEDs acendem.

0.0(0)
14
Medição de distância com display LCD
#31Avançado
Premium

Medição de distância com display LCD

Uma ferramenta que mede distâncias sem régua: aproxime e afaste a mão na frente do sensor e veja o número mudar. O HC-SR04 emite uma onda sonora e escuta seu eco, e o Arduino calcula a distância em ce

4.6(45)
59