아두이노 기반 보안 시스템: 스마트 모션 감지 & 알림
부품 및 소모품
| Arduino UNO | 1개 |
| 초음파 센서 HC-SR04 (일반) | 1개 |
| 서보 모터 (Tower Pro MG996R) | 1개 |
| 부저 | 1개 |
| 브레드보드 (일반) | 1개 |
| 수/암 점퍼 와이어 | 1세트 |
| 플라스틱 박스 | 1개 |
필수 도구
앱 및 온라인 서비스
- Arduino IDE
- Processing IDE
프로젝트 소개
소개
이 프로젝트는 아두이노 우노, 서보 모터, 초음파 센서, 피에조 부저로 구성된 아두이노 기반 보안 시스템입니다.
초음파 센서가 감지 범위 내 물체를 감지하면 부저가 작동합니다. 이 센서 데이터는 Processing IDE 소프트웨어로도 전송되어 그래픽 맵(레이더 화면)을 생성합니다.
서보 모터는 초음파 센서를 회전시켜 넓은 영역을 커버합니다.
꽤 간단한 프로젝트로 1시간 내에 완성 가능합니다.
제작 절차
- 센서 Trig 핀 → 아두이노 핀 2
- 센서 Echo 핀 → 아두이노 핀 3
- 센서 Vcc → 5V, GND → GND
- 부저를 브레드보드에 장착: 양극 → 아두이노 핀 10, 음극 → GND
- 서보 모터: 검정/빨강선 → GND/5V, 노랑선(신호) → 아두이노 핀 9
- 아두이노 5V → 전원, GND → 접지
배선 완료 후 그림과 같이 전체 회로를 박스 안에 넣습니다. 이제 코딩 차례입니다.
코드
아두이노 코드 (Security System_IDE)
#include <Servo.h>
int tPin = 2;
int ePin = 3;
int buz = 10;
int d1, d2;
int i = 0;
int sdistance;
Servo myServo;
void setup() {
Serial.begin(9600);
pinMode(tPin, OUTPUT);
pinMode(ePin, INPUT);
pinMode(buz, OUTPUT);
myServo.attach(9);
}
void loop() {
// 서보를 0도에서 180도로 스윕
for (i = 0; i <= 180; i += 10) {
myServo.write(i);
delay(30);
d2 = calculateDistance();
Serial.print(i);
Serial.print(",");
Serial.print(d2);
Serial.print(".");
}
// 서보를 180도에서 0도로 역스윕
for (i = 180; i > 0; i -= 10) {
myServo.write(i);
delay(30);
d2 = calculateDistance();
Serial.print(i);
Serial.print(",");
Serial.print(d2);
Serial.print(".");
}
}
int calculateDistance() {
digitalWrite(tPin, HIGH);
delayMicroseconds(10); // 10μs 펄스 (원본의 delay(1000)은 오타로 보임)
digitalWrite(tPin, LOW);
d1 = pulseIn(ePin, HIGH);
d2 = d1 * 0.0171821306; // 거리 계산 (cm)
if (d2 < 10) {
digitalWrite(buz, HIGH); // 10cm 이내면 부저 ON
} else {
digitalWrite(buz, LOW);
}
return d2;
}
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, index2 = 0;
PFont orcFont;
void setup() {
size(1366, 768); // 화면 해상도에 맞게 수정
smooth();
myPort = new Serial(this, "COM3", 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 = 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();
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);
if (iDistance < 40) { // 40cm 이내만 표시
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("2cm", width - width * 0.3854, height - height * 0.0833);
text("4cm", width - width * 0.281, height - height * 0.0833);
text("6cm", width - width * 0.177, height - height * 0.0833);
text("10cm", width - width * 0.0729, height - height * 0.0833);
textSize(40);
text("Akshay6766", 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();
}
회로도