Arduino uno ultrasonic radar


    เป็นการใช้โมดูล ultrasonic มาใช้งานเป็นเรดาร์ที่ควบคุมด้วย arduino uno โดยที่มีการแสดงผลออกหน้าจอด้วยการเขียนโค้ด Processing รูปแบบการทำงานเป็นดังวีดิโอด้านล่าง

อุปกรณ์ที่ใช้มีดังนี้
1. Arduino uno
2. Micro Servo 9g sg90
3. HC-SR04 Ultrasonic module
4. Wire สายไฟต่างๆ

รูปแบบการต่อวงจรเป็นดังนี้


ในส่วนโค้ด Arduino เป็นดังนี้

// Include the Servo library
#include <Servo.h>

// Defines Trig and Echo pins of the Ultrasonic Sersor
const int trigPin = 10;
const int echoPin = 11;
// Variables for the duration and the distance
long duration;
int distance;
bool rotate_toggle = false; // switch rotate left and right

Servo myServo; // Creates a servo object for controlling the servo motor

void setup() {
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  Serial.begin(9600);
  myServo.attach(12); // Defines on which pin is the servo motor attached
}

void loop() {
  // rotates the servo motor from 15 to 165 degrees
  for (int i=15;i<=165;i++){
    if (rotate_toggle == false){
      myServo.write(i);
      if (i==165){
        rotate_toggle = true;  
      }  
    }
    else {
      myServo.write(165 - i);
      if (i==165){
        rotate_toggle = false;  
      }  
    }
    delay(30);
    distance = calculateDistance();
    if (rotate_toggle == false){
      Serial.print(i);
    }
    else{
      Serial.print(165-i);
    }
    Serial.print(",");
    Serial.print(distance);
    Serial.print(".");  
  }
}
// Function for calculating the distance measured by the Ultrasonic sensor
int calculateDistance(){
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the tricPin on HIGH state for 10 microseconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH); // Reads the echoPin, returns the sound wave travel time in microseconds
  distance = duration*0.034/2;
  return distance;
}

    การทำงานคือจะกำหนดให้ servo มีการหมุนกวาดไปกลับโดยกำหนดให้หมุนจาก 15 องศาไปถึง 165 องศา จากนั้นให้หมุนย้อนกลับทางเดิมทำให้เรดาร์ของเราเวลาสแกนจะกวาดไปและกลับ  จากนั้นมีฟังก์ชันที่ใช้ในการคำนวณระยะทางจาก ultrasonic โดยสั่งการทำงานไปที่ขา trig ของ ultrasonic module จากนั้นอ่านค่าระยะทางที่ได้จากขา echo นำผลที่ได้มาคูณด้วย 0.034/2 ซึ่งเป็นสูตรในการคำนวณของ ultrasonic   ในที่นี้มีการแสดงผลออกทาง Serial กำหนด bandwidth ที่ 9600 ค่าที่แสดงได้แก่ องศา(degree) ของ servo ที่กำลังหมุนกับค่าระยะทาง(distance) ปิดด้วย .  ในส่วนของ processing จะนำข้อมูลในไปสร้างหน้าจอเรดาร์ต่อไป

ในส่วนโค้ด Processing เป็นดังนี้


import processing.serial.*; // imports library for serial communication
import java.awt.event.KeyEvent; // imports library for reading the data from the serial port
import java.io.IOException;

Serial myPort; // defines Object Serial
// default variables
String angle = "";
String distance = "";
String data = "";
String noObject;
float pixsDistance;
int iAngle, iDistance;
int index1 = 0;
int index2 = 0;
PFont orcFont;

void setup(){
  size(1080, 610);
  smooth();
  myPort = new Serial(this, "COM3", 9600); // starts the serial communication
  myPort.bufferUntil('.'); // read data from serial port up to the character '.'. it read angle,distance.
  orcFont = loadFont("OCRAExtended-30.vlw");
}

void draw(){
  fill(98, 245, 31);
  textFont(orcFont);
  
  noStroke();
  fill(0, 4);
  rect(0, 0, width, 580);
  
  fill(98, 245, 31); // green color
  // call functions for drawing the radar
  drawRadar();
  drawLine();
  drawObject();
  drawText();
}

void serialEvent(Serial myPort){
  data = myPort.readStringUntil('.');
  data = data.substring(0, data.length()-1);
  
  index1 = data.indexOf(",");
  angle = data.substring(0, index1);
  distance = data.substring(index1+1, data.length());
  
  iAngle = int(angle);
  iDistance = int(distance);
}

void drawRadar() {
  pushMatrix();
  int radar_x = 540;
  translate(radar_x, 580); // move starting coordinates to new location
  noFill();
  strokeWeight(2);
  stroke(98, 245, 31);
  // draw the arc lines
  arc(0, 0, 970, 970, PI, TWO_PI);
  arc(0, 0, 750, 750, PI, TWO_PI);
  arc(0, 0, 500, 500, PI, TWO_PI);
  arc(0, 0, 250, 250, PI, TWO_PI);
  // draw the angle lines
  line(-radar_x, 0, -radar_x, 0);
  line(0,0,-radar_x*cos(radians(30)),-radar_x*sin(radians(30)));
  line(0,0,-radar_x*cos(radians(60)),-radar_x*sin(radians(60)));
  line(0,0,-radar_x*cos(radians(90)),-radar_x*sin(radians(90)));
  line(0,0,-radar_x*cos(radians(120)),-radar_x*sin(radians(120)));
  line(0,0,-radar_x*cos(radians(150)),-radar_x*sin(radians(150)));
  line(-620*cos(radians(30)),0,620,0);
  popMatrix();
}

void drawLine() {
  pushMatrix();
  strokeWeight(9);
  stroke(30, 250, 60);
  translate(540, 580);
  line(0, 0, 540*cos(radians(iAngle)), -540*sin(radians(iAngle)));
  popMatrix();
}

void drawObject() {
  pushMatrix();
  translate(540, 580);
  strokeWeight(9);
  stroke(255, 10, 10); // red color
  pixsDistance = iDistance*22.5; // covers the distance from the sensor from cm to pixels
  // limiting the range to 40 cms
  if (iDistance < 40){
    // draws the object according to the angle and the distance
    line(pixsDistance*cos(radians(iAngle))/1.8, 
        -pixsDistance*sin(radians(iAngle))/1.8,
        540*cos(radians(iAngle)),
        -540*sin(radians(iAngle)));
  }
  popMatrix();
}

void drawText() {
  pushMatrix();
  if(iDistance>40) {
    noObject = "Out of Range";
  }
  else {
    noObject = "In Range";
  }
  fill(0,0,0);
  noStroke();
  rect(0, 580, width, 610);
  fill(98,245,31);
  textSize(15);
  text("10cm",625,575);
  text("20cm",750,575);
  text("30cm",875,575);
  text("40cm",980,575);
  textSize(20);
  text("Object: " + noObject, 140, 600);
  text("Angle: " + iAngle +" °", 550, 600);
  text("Distance: ", 710, 600);
  if(iDistance<40) {
    text("        " + iDistance +" cm", 730, 600);
  }
  textSize(12);
  fill(98,245,60);
  translate(530+540*cos(radians(30)),560-540*sin(radians(30)));
  rotate(-radians(-60));
  text("30°",0,0);
  resetMatrix();
  translate(530+540*cos(radians(60)),560-540*sin(radians(60)));
  rotate(-radians(-30));
  text("60°",0,0);
  resetMatrix();
  translate(530+540*cos(radians(90)),570-540*sin(radians(90)));
  rotate(radians(0));
  text("90°",0,0);
  resetMatrix();
  translate(530+540*cos(radians(120)),575-540*sin(radians(120)));
  rotate(radians(-30));
  text("120°",0,0);
  resetMatrix();
  translate(530+540*cos(radians(150)),580-540*sin(radians(150)));
  rotate(radians(-60));
  text("150°",0,0);
  popMatrix(); 
}

   การทำงานประกอบด้วยฟังก์ชันการวาดเส้นสีเขียวเพื่อบอกว่าเรดาร์กำลังกวาดไปจุดไหน ฟังก์ชันวาดเส้นสีแดงเพื่อบอกระยะของวัตถุที่เรดาร์ตรวจจับได้ ฟังก์ชันวาดสเกลของเรดาร์ ฟังกช์ชันแสดงข้อมูลตัวอักษรและฟังก์ชันอ่านค่าจาก Serial ของ Arduino ต่อไปนี้จะเป็นการอธิบายการทำงานของแต่ละฟังก์ชัน

void drawRadar ฟังก์ชันวาดสเกลของเรดาร์


void drawLine ฟังก์ชันการวาดเส้นสีเขียวเพื่อบอกว่าเรดาร์กำลังกวาดไปจุดไหน


void drawObjecct ฟังก์ชันวาดเส้นสีแดงเพื่อบอกระยะของวัตถุที่เรดาร์ตรวจจับได้ กำหนดให้จับวัตถุได้ไกลที่สุดในระยะ 40cm. เนื่องจากค่าที่อ่านได้จาก Serial ทำให้ตอนวาดเส้นออกมา  ได้ระยะที่ไม่ตรงกับสเกลที่ออกแบบไว้จึงทำให้ต้องหารค่าระยะที่ได้ด้วย 1.8 (ค่านี้หาจากการปรับตัวเลขตามความเหมาะสม)


void drawText ฟังกช์ชันแสดงข้อมูลตัวอักษร


void SerialEvent อักษรและฟังก์ชันอ่านค่าจาก Serial ของ Arduino ถ้ารูปแบบที่อ่านได้จะเป็น 100,30. นั่นหมายความว่าตอนนี้ servo หมุนไปที่ 100 องศา จับวัตถุได้ในระยะ 30cm.
ภาพตัวอย่างหน้าจอเรดาร์