HC-SR04 – Aplicação com Processing

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

HC-SR04 - ESQUEMA

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;
  }
}

HC-SR04 – Aplicação com Processing - Porta Serial COM

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.

HC-SR04 – Aplicação com Processing GIF

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.

 

Onde comprar os componentes?

LOJAS

 

Conheça também!