HC-SR04 é um módulo de baixo custo e muito utilizado que consiste na emissão de sinais ultrassônicos onde a medição da distância é obtida com base no tempo de emissão do sinal com o tempo de retorno desse mesmo sinal refletido pelo objeto.
Esse sensor é basicamente constituído por um transmissor ultrassônico que emite as ondas ultrassônicas as quais serão refletidas pelos obstáculos, um receptor que identifica o eco do sinal emitido pelo transmissor e um circuito de controle que controla o conjunto transmissor/receptor o qual calcula o tempo entre a emissão/recepção do sinal.
Processing é um sketchbook de software flexível e uma linguagem para aprender a codificar no contexto das artes visuais. Desde 2001, a Processing promoveu a alfabetização de software nas artes visuais e a alfabetização visual na tecnologia.
Especificações do HC-SR04
-
- Alimentação: 5V DC
- Corrente de Operação: 2mA
- Ângulo de Efeito: 15°
- Alcance: 2cm ~ 4m
- Precisão: 3mm
Projeto HC-SR04 com Processing
Este clássico projeto consiste basicamente numa exposição gráfica de obstáculos na plataforma Processing obtidos através de um sensor ultrassônico HC-SR04, simulando uma tela de apresentação RADAR.
Material
-
- Arduino
- Sensor Ultrassônico HC-SR04
- Micro Servo Motor
- Base de Sustentação Servo/Sensor
Esquema de Montagem HC-SR04 com o Servo
Código Arduino
Primeiramente, deve-se incluir a biblioteca NewPing.h na IDE Arduino e em seguida é só carregar o código.
#include <NewPing.h> #include <Servo.h> #define pinTrig 9 // Trigger #define pinEcho 10 // Echo #define distMax 200 // Máxima distância de ping(cm) #define pinServo 11 // Pino do servo int anguloInicio = 90; int anguloPasso = 1; int anguloRotacao = 0; int dir = 1; // Direção inicial, quando -1 invertida Servo myservo; NewPing sonar(pinTrig, pinEcho, distMax); unsigned long changeTime; void setup() { Serial.begin(9600); myservo.attach(pinServo); } void loop() { myservo.write(anguloRotacao + anguloInicio); enviarDistancia(anguloRotacao); if (anguloRotacao >= anguloInicio || anguloRotacao <= -anguloInicio) // Inverte a direção { dir = -dir; } anguloRotacao += (dir * anguloPasso); delay(30); } int enviarDistancia(int anguloRotacao) { int cm = sonar.ping_cm(); Serial.print(-anguloRotacao, DEC); // Esse sinal é somente para conincidir com o sentido do feixe no Processing Serial.print("#"); Serial.println(cm, DEC); }
Código Processing
Baixe o aplicativo Processing, em seguida abra o código do apresentador gráfico, faça a alteração da porta serial e finalmente execute a aplicação.
import processing.serial.*; //int compTela = 1200; int compTela = 1800; int limiteAngulo = 90; int guardar = 10; int guardarPontos = 800; int intervaloMaximo = 50; int angulo; int distancia; int angRadiano; float x, y; float AngEsquerdoRad, AngDireitoRad; float[] guardarX, guardarY; Ponto[] pontos; int centroX, centroY; String dadoPortaString; Serial minhaPorta; void setup() { //size(1200, 600, P2D); size(1800, 900, P2D); noStroke(); //rectMode(CENTER); angRadiano = (compTela / 2)+30; centroX = (width / 2)+30; centroY = height+30; angulo = 0; AngEsquerdoRad = radians(-limiteAngulo) - HALF_PI; AngDireitoRad = radians(limiteAngulo) - HALF_PI; guardarX = new float[guardar]; guardarY = new float[guardar]; pontos = new Ponto[guardarPontos]; minhaPorta = new Serial(this, "COM26", 9600); minhaPorta.bufferUntil('\n'); // Receber até a nova linha } void draw() { background(#000000); // Cor preta drawRadar(); drawPlotarObjetos(angulo, distancia); drawLinhaRadar(angulo); /* Desenhar as linhas de grade no radar a cada 30 graus e escreva seus valores */ for (int i = 0; i <= 6; i++) { strokeWeight(1); // Espessura stroke(#ffffff); // Cor branca //line(angRadiano, angRadiano, angRadiano + cos(radians(180+(30*i)))*(compTela/2), angRadiano + sin(radians(180+(30*i)))*(compTela/2)); line(angRadiano, angRadiano, angRadiano + cos(radians(180+(30*i)))*(compTela/3), angRadiano + sin(radians(180+(30*i)))*(compTela/3)); fill(#ffffff); // Cor branca noStroke(); //text(Integer.toString(0+(30*i)), angRadiano + cos(radians(180+(30*i)))*(compTela/2+30), angRadiano + sin(radians(180+(30*i)))*(compTela/2+30), 25, 50); text(Integer.toString(0+(30*i)), angRadiano + cos(radians(180+(30*i)))*(compTela/3 + 30), angRadiano + sin(radians(180+(30*i)))*(compTela/3 + 30), 25, 50); } /* Escrever informações. */ //noStroke(); //fill(0); int Angulo=0; Angulo = angulo+90; fill(#ffea00); //text("Ângulo: "+Integer.toString(Angulo), 94, 100, 100, 50); text("graus", 170, 100, 100, 50); // Use Integet.toString para converter dados numéricos em string // text("Distância: "+Integer.toString(distancia-intervaloMaximo), 80, 120, 100, 50); text("mm", 175, 120, 100, 50); // text(string, x, y, largura, altura) text("Ângulo: "+Integer.toString(Angulo), 94, 230, 100, 50); text("graus", 170, 230, 100, 50); // Use Integet.toString para converter dados numéricos em string text("Distância: "+Integer.toString(distancia-intervaloMaximo), 80, 250, 100, 50); text("mm", 175, 250, 100, 50); // text(string, x, y, largura, altura) /* text("0", 620, 600, 300, 50); text("100 mm", 613, 490, 250, 50); text("200 mm", 613, 370, 250, 50); text("300 mm", 613, 250, 250, 50); text("400 mm", 613, 130, 250, 50); text("500 mm", 613, 015, 250, 50); */ text("0", 920, 930, 300, 55); text("100 mm", 913, 790, 250, 50); text("200 mm", 913, 670, 250, 50); text("300 mm", 913, 550, 250, 50); text("400 mm", 913, 430, 250, 50); text("500 mm", 913, 315, 250, 50); } void drawLinhaRadar(int angulo) { float radiano = radians(angulo); x = angRadiano * sin(radiano); y = angRadiano * cos(radiano); float px = centroX + x; float py = centroY - y; guardarX[0] = px; guardarY[0] = py; fill(#f9f75f, 40); //arc(centroX, centroY, compTela, compTela, radians(angulo-100)+0.098, radians(angulo-90)+0.098); arc(centroX, centroY, compTela*2/3, compTela*2/3, radians(angulo-100) + 0.098, radians(angulo-90) + 0.098); shiftGuardarArray(); } void drawPlotarObjetos(int angle, int distancia) { if ((distancia > 0) && (distancia < 500)) { float radiano = radians(angle); x = distancia * sin(radiano); y = distancia * cos(radiano); int px = (int)(centroX + x); int py = (int)(centroY - y); pontos[0] = new Ponto(px, py); } else { pontos[0] = new Ponto(0, 0); } for (int i = 0; i < guardarPontos; i++) { Ponto ponto = pontos[i]; if (ponto != null) { int x = ponto.x; int y = ponto.y; if (x==0 && y==0) continue; // map(value, start1, stop1, start2, stop2) // value ---> float --> o valor recebido a ser convertido // start1 ---> float --> limite inferior // Stop1 ---> float --> limite superior // Start2 ---> float --> limite inferior do alvo // Stop2 ---> float --> limite superior do alvo int colorAlfa = (int)map(i, 0, guardarPontos, 20, 0); int size = (int)map(i, 0, guardarPontos, 40, 0); fill(#c60202, colorAlfa); noStroke(); ellipse(x, y, size, size); } } shiftPontosArray(); } void drawRadar() { stroke(#ffffff); noFill(); // Cria círculos a cada 50mm) // for (int i = 0; i <= (compTela / 120); i++) { for (int i = 0; i <= (1200 / 120); i++) { arc(centroX, centroY, 120 * i, 120 * i, AngEsquerdoRad, AngDireitoRad); } } void shiftGuardarArray() { for (int i = guardar; i > 1; i--) { guardarX[i-1] = guardarX[i-2]; guardarY[i-1] = guardarY[i-2]; } } void shiftPontosArray() { for (int i = guardarPontos; i > 1; i--) { Ponto pontoAnterior = pontos[i-2]; if (pontoAnterior != null) { Ponto ponto = new Ponto(pontoAnterior.x, pontoAnterior.y); pontos[i-1] = ponto; } } } void serialEvent(Serial minhaPorta) { dadoPortaString = minhaPorta.readStringUntil('\n'); if (dadoPortaString != null) { dadoPortaString=trim(dadoPortaString); String[] values = split(dadoPortaString, '#'); try { angulo = Integer.parseInt(values[0]); distancia = int(map(Integer.parseInt(values[1]), 1, intervaloMaximo, 1, angRadiano)); } catch (Exception e) { } } } class Ponto { int x, y; Ponto(int xPos, int yPos) { x = xPos; y = yPos; } int getX() { return x; } int getY() { return y; } }
Então, feito isso, basta posicionar os objetos de pouca largura próximos ao sensor em movimento pelo servo motor e observar a apresentação deles na tela.
Então, podemos concluir que apesar de ser um pouco sofisticado esse projeto, ele é bastante simples, muito barato e permite uma boa base para desenvolvimento de projetos na plataforma Processing.