組員:
411114235 林俊良
411114236 鄭丞哲
411114238 黃宥霖
一、介紹:
超音波距離感測器是一種利用超音波來測量物體與感測器之間距離的設備。它廣泛應用於工業、自動化、機器人技術等領域。工作原理感測器內部的發射器會發射出一個超音波脈衝,並接收脈衝,通過公式算出距離使用超音波距離感測器,配合伺服馬達完成較大角度的偵測,並以圖示表現。
二、Arduino程式碼:
// 引入 Servo 函式庫
#include <Servo.h>
// 定義超音波感測器的 Trig 和 Echo 腳位
const int trigPin = 10;
const int echoPin = 11;
// 用於計算持續時間和距離的變數
long duration;
int distance;
Servo myServo; // 建立一個 Servo 物件來控制伺服馬達
void setup() {
pinMode(trigPin, OUTPUT); // 將 trigPin 設為輸出
pinMode(echoPin, INPUT); // 將 echoPin 設為輸入
Serial.begin(9600); // 設置串口通信速率為 9600
myServo.attach(12); // 定義伺服馬達連接的腳位
}
void loop() {
// 使伺服馬達從 15 度旋轉到 165 度
for(int i = 15; i <= 165; i++) {
myServo.write(i); // 設置伺服馬達的角度
delay(30); // 等待 30 毫秒
distance = calculateDistance(); // 呼叫函式計算每個角度下超音波感測器測得的距離
Serial.print(i); // 將當前角度傳送到串口
Serial.print(","); // 傳送一個逗號,方便在 Processing IDE 中進行索引
Serial.print(distance); // 將距離值傳送到串口
Serial.print("."); // 傳送一個點號,方便在 Processing IDE 中進行索引
}
// 重複之前的步驟,從 165 度旋轉回 15 度
for(int i = 165; i > 15; i--) {
myServo.write(i); // 設置伺服馬達的角度
delay(30); // 等待 30 毫秒
distance = calculateDistance(); // 呼叫函式計算每個角度下超音波感測器測得的距離
Serial.print(i); // 將當前角度傳送到串口
Serial.print(","); // 傳送一個逗號,方便在 Processing IDE 中進行索引
Serial.print(distance); // 將距離值傳送到串口
Serial.print("."); // 傳送一個點號,方便在 Processing IDE 中進行索引
}
}
// 用於計算超音波感測器測得距離的函式
int calculateDistance() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2); // 等待 2 微秒
digitalWrite(trigPin, HIGH); // 設置 trigPin 為高電位持續 10 微秒
delayMicroseconds(10); // 等待 10 微秒
digitalWrite(trigPin, LOW); // 設置 trigPin 為低電位
duration = pulseIn(echoPin, HIGH); // 讀取 echoPin,返回聲波往返時間(微秒)
distance = duration * 0.034 / 2; // 計算距離(公分)
return distance; // 返回計算得出的距離
}
三、Processing程式碼:
import processing.serial.*; // 導入串口通信函式庫
import java.awt.event.KeyEvent; // 導入讀取串口數據的函式庫
import java.io.IOException;
Serial myPort; // 定義串口對象
// 定義變數
String angle = "";
String distance = "";
String data = "";
String noObject;
float pixsDistance;
int iAngle, iDistance;
int index1 = 0;
int index2 = 0;
PFont orcFont;
void setup() {
size(1200, 700); // ***更改為您的螢幕解析度***
smooth();
myPort = new Serial(this, "COM5", 9600); // 開始串口通信
myPort.bufferUntil('.'); // 讀取串口數據直到遇到字符 '.'
}
void draw() {
fill(98, 245, 31);
// 模擬運動模糊和慢速淡化效果
noStroke();
fill(0, 4);
rect(0, 0, width, height - height * 0.065);
fill(98, 245, 31); // 綠色
// 呼叫函式繪製雷達
drawRadar();
drawLine();
drawObject();
drawText();
}
void serialEvent(Serial myPort) { // 開始從串口讀取數據
// 讀取串口數據直到遇到字符 '.',並將其存入字符串變數 "data"
data = myPort.readStringUntil('.');
data = data.substring(0, data.length() - 1);
index1 = data.indexOf(","); // 找到字符 ',' 並將其位置存入變數 "index1"
angle = data.substring(0, index1); // 讀取從位置 "0" 到 "index1" 的數據,即角度值
distance = data.substring(index1 + 1, data.length()); // 讀取從位置 "index1" 到數據末尾的數據,即距離值
// 將字符串變數轉換為整數
iAngle = int(angle);
iDistance = int(distance);
}
void drawRadar() {
pushMatrix();
translate(width / 2, height - height * 0.074); // 移動起始坐標到新位置
noFill();
strokeWeight(2);
stroke(98, 245, 31);
// 繪製弧線
arc(0, 0, (width - width * 0.0625), (width - width * 0.0625), PI, TWO_PI);
arc(0, 0, (width - width * 0.27), (width - width * 0.27), PI, TWO_PI);
arc(0, 0, (width - width * 0.479), (width - width * 0.479), PI, TWO_PI);
arc(0, 0, (width - width * 0.687), (width - width * 0.687), PI, TWO_PI);
// 繪製角度線
line(-width / 2, 0, width / 2, 0);
line(0, 0, (-width / 2) * cos(radians(30)), (-width / 2) * sin(radians(30)));
line(0, 0, (-width / 2) * cos(radians(60)), (-width / 2) * sin(radians(60)));
line(0, 0, (-width / 2) * cos(radians(90)), (-width / 2) * sin(radians(90)));
line(0, 0, (-width / 2) * cos(radians(120)), (-width / 2) * sin(radians(120)));
line(0, 0, (-width / 2) * cos(radians(150)), (-width / 2) * sin(radians(150)));
line((-width / 2) * cos(radians(30)), 0, width / 2, 0);
popMatrix();
}
void drawObject() {
pushMatrix();
translate(width / 2, height - height * 0.074); // 移動起始坐標到新位置
strokeWeight(9);
stroke(255, 10, 10); // 紅色
pixsDistance = iDistance * ((height - height * 0.1666) * 0.025); // 將距離從厘米轉換為像素
// 限制範圍到 40 厘米
if (iDistance < 40) {
// 根據角度和距離繪製物體
line(pixsDistance * cos(radians(iAngle)), -pixsDistance * sin(radians(iAngle)), (width - width * 0.505) * cos(radians(iAngle)), -(width - width * 0.505) * sin(radians(iAngle)));
}
popMatrix();
}
void drawLine() {
pushMatrix();
strokeWeight(9);
stroke(30, 250, 60);
translate(width / 2, height - height * 0.074); // 移動起始坐標到新位置
line(0, 0, (height - height * 0.12) * cos(radians(iAngle)), -(height - height * 0.12) * 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, height - height * 0.0648, width, height);
fill(98, 245, 31);
textSize(25);
text("10cm", width - width * 0.3854, height - height * 0.0833);
text("20cm", width - width * 0.281, height - height * 0.0833);
text("30cm", width - width * 0.177, height - height * 0.0833);
text("40cm", width - width * 0.0729, height - height * 0.0833);
textSize(40);
text("SciCraft ", width - width * 0.875, height - height * 0.0277);
text("Angle: " + iAngle + " °", width - width * 0.48, height - height * 0.0277);
text("Distance: ", width - width * 0.26, height - height * 0.0277);
if (iDistance < 40) {
text(" " + iDistance + " cm", width - width * 0.225, height - height * 0.0277);
}
textSize(25);
fill(98, 245, 60);
translate((width - width * 0.4994) + width / 2 * cos(radians(30)), (height - height * 0.0907) - width / 2 * sin(radians(30)));
rotate(-radians(-60));
text("30°", 0, 0);
resetMatrix();
translate((width - width * 0.503) + width / 2 * cos(radians(60)), (height - height * 0.0888) - width / 2 * sin(radians(60)));
rotate(-radians(-30));
text("60°", 0, 0);
resetMatrix();
translate((width - width * 0.507) + width / 2 * cos(radians(90)), (height - height * 0.0833) - width / 2 * sin(radians(90)));
rotate(radians(0));
text("90°", 0, 0);
resetMatrix();
translate(width - width * 0.513 + width / 2 * cos(radians(120)), (height - height * 0.07129) - width / 2 * sin(radians(120)));
rotate(radians(-30));
text("120°", 0, 0);
resetMatrix();
translate((width - width * 0.5104) + width / 2 * cos(radians(150)), (height - height * 0.0574) - width / 2 * sin(radians(150)));
rotate(radians(-60));
text("150°", 0, 0);
popMatrix();
}
四、成品照片:
圖一 : arduino 接線組
五、組員心得:
411114235 林俊良:
這次做期末的作品時,遇到了很多問題,主題也一直改來改去,直到最後主題才又改回超音波距離感測在這之前主要遇到困難的地方是無法像我們所想的只用Arduino就能完成,在嘗試之後還是沒有辦法完成
我學到了如何使用超音波感測器來精確地測量物體與感測器之間的距離。使用伺服馬達配合超音波感測器,可以在不同角度進行測量,在Processing IDE中進行進一步的分析和處理。這個過程讓我更熟悉了Arduino的基本操作和程式設計。
411114236 鄭丞哲:
起初做期末成品的想法是利用 Arduino 和相關零件配合接著依據收集到的數據做出相對應的指令,自動化控制電腦程式,但是想法與實際執行有點落差且程式設計方面難度遽增,在多次嘗試之後還是沒有辦法完成,既然如此,我們就想到如何在現有的感測器上去改良或具有更好的應用性質。雖然沒有成功得做出想要的功能,但我覺得有朝一日自我的程式設計能力變得更好還能繼續嘗試相關的 Arduino 於生活中的應用。
411114238 黃宥霖:
我們在第一次實驗中遇到了瓶頸當我們想讓Arduino執行跳回桌面時(Win+D)Arduino無法控制鍵盤嘗試無果後我們更改了呈現方式,改成聲波感測雷達的方式,超音波感測雷達是一種利用超聲波進行距離測量和物體檢測的技術,其工作原理是發射超音波信號,並根據反射回來的回波計算目標物體的位置和距離。我們在改主題後面臨的困難也不小因為要開不同的程式去跑雷達,是一個很困難的挑戰。而透過這次學習我們收穫很多希望下次能做一些更難的操作,挑戰自我。