Arduino Uno 와 HC-SR04 초음파 센서를 기반으로 레이더 데모를 제작했습니다.
ESP32-C3 모듈을 사용하려 했으나 낮은 ADC 성능 때문에 Arduino 로 변경했습니다.
- 컴퓨팅 모듈 : Arduino Uno
- 초음파 센서 : HC-SR04
- 180도 회전 : SG-90 Servo
- 수동 제어 : Potentiometer


# Arduino Uno 소스 코드
// Arduino Uno 표준 Servo 라이브러리 사용
#include <Servo.h>
// 핀 정의 (Arduino Uno 기준)
#define TRIG_PIN 8 // 초음파 센서 TRIG 핀
#define ECHO_PIN 9 // 초음파 센서 ECHO 핀
#define SERVO_PIN 10 // 서보 모터 제어 핀 (PWM 핀 사용)
#define POT_PIN A0 // 가변 저항(VR) 입력 핀 (아날로그 핀 사용)
#define CONTROL_PIN 11 // 수동/자동 모드 전환을 위한 디지털 입력 핀
#define MAX_DISTANCE 100 // 최대 측정 거리 (cm)
const int minValue = 0;
const int maxValue = 1024;
Servo servo;
long duration;
int distance;
void setup() {
Serial.begin(9600);
servo.attach(SERVO_PIN);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(POT_PIN, INPUT);
pinMode(CONTROL_PIN, INPUT_PULLUP);
}
void loop() {
// 11번 핀 상태 읽음 (LOW: 수동 모드, HIGH: 자동 스캔 모드)
if (digitalRead(CONTROL_PIN) == LOW) {
int potValue = analogRead(POT_PIN);
// ADC 값을 서보 각도(0~180)로 변환
int angle = map(potValue, minValue, maxValue, 180, 0);
servo.write(angle);
delay(20);
// 필터링된 거리 측정값 사용
distance = getDistanceRaw();
if (distance != -1) {
Serial.print(angle);
Serial.print(",");
Serial.println(distance);
}
delay(10);
} else {
// 0° → 180° 스캔
for (int angle = 0; angle <= 180 && digitalRead(CONTROL_PIN) == HIGH; ++angle) {
servo.write(angle);
delay(20);
distance = getDistanceRaw();
if (distance != -1) {
Serial.print(angle);
Serial.print(",");
Serial.println(distance);
}
}
// 180° → 0° 스캔
for (int angle = 180; angle >= 0 && digitalRead(CONTROL_PIN) == HIGH; --angle) {
servo.write(angle);
delay(20);
distance = getDistanceRaw();
if (distance != -1) {
Serial.print(angle);
Serial.print(",");
Serial.println(distance);
}
}
// 잠시 대기
delay(100);
}
}
int getDistanceRaw() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// pulseIn 함수의 timeout을 20ms로 설정 (20000 마이크로초)
duration = pulseIn(ECHO_PIN, HIGH, 20000);
// echo 실패 시(timeout 발생) 0 반환
if (duration == 0) return -1;
// 거리를 cm 단위로 변환 (음속: 340m/s = 0.034cm/μs, 즉 58μs/cm)
int dist = duration / 58;
// 최대 거리를 초과하면 -1 반환
if (dist > MAX_DISTANCE) return -1;
return dist;
}
# Processing 소스 코드
import processing.serial.*;
Serial port;
String data = "";
int angle = 0;
int distance = 0;
float scale = 5.0;
int maxDist = 100;
ArrayList<PVector> points = new ArrayList<PVector>();
void setup() {
size(1000, 1000);
port = new Serial(this, "COM9", 9600);
port.bufferUntil('\n');
background(0);
frameRate(60);
}
void draw() {
fill(0, 30);
noStroke();
rect(0, 0, width, height);
translate(width/2, height/2);
stroke(0, 150, 0);
noFill();
for (int r = 20; r <= maxDist; r += 20) {
ellipse(0, 0, r * scale * 2, r * scale * 2);
fill(255);
textAlign(CENTER, CENTER);
textSize(14);
text(r + " cm", -r * scale + 25, 10);
noFill();
}
for (int a = 0; a < 360; a += 30) {
float x = cos(radians(a - 90)) * maxDist * scale;
float y = sin(radians(a - 90)) * maxDist * scale;
line(0, 0, x, y);
}
pushMatrix();
scale(1, -1);
noFill();
stroke(0, 100, 0, 80);
arc(0, 0, maxDist * scale * 2, maxDist * scale * 2, radians(-90), radians(70));
float drawAngle = map(angle, 0, 180, 90, 270);
float scanX = distance * scale * cos(radians(drawAngle - 90));
float scanY = distance * scale * sin(radians(drawAngle - 90));
stroke(0, 255, 0);
line(0, 0, scanX, scanY);
points.add(new PVector(scanX, scanY, millis()/1000.0));
float now = millis()/1000.0;
for (int i = points.size()-1; i >= 0; i--) {
if (now - points.get(i).z > 10) {
points.remove(i);
}
}
noStroke();
for (PVector p : points) {
float age = now - p.z;
float alpha = map(age, 0, 10, 255, 0);
fill(255, 50 + int(205 * (1 - age / 10)), 0, alpha);
ellipse(p.x, p.y, 6, 6);
}
popMatrix();
fill(0, 255, 0);
textSize(16);
textAlign(LEFT);
text("Angle: " + angle + "°", -width/2 + 20, -height/2 + 30);
text("Distance: " + distance + " cm", -width/2 + 20, -height/2 + 55);
text("Scan Range: 0° ~ 180°", -width/2 + 20, -height/2 + 90);
}
void serialEvent(Serial p) {
try {
data = p.readStringUntil('\n');
if (data != null) {
data = trim(data);
String[] parts = split(data, ',');
if (parts.length == 2) {
angle = int(parts[0]);
distance = int(parts[1]);
distance = constrain(distance, 0, maxDist);
}
}
} catch (Exception e) {
println("Serial Error: " + e.getMessage());
}
}
'DIY' 카테고리의 다른 글
| ESP32-C3 + PN-532 + HW-763 + SG-90 + DFPlayer ⇒ NFC 출입관리데모 (0) | 2025.10.29 |
|---|---|
| ESP32-C3 + PCM5102(I2S) + GStreamer ⇒ Audio Streaming #1 (0) | 2025.10.19 |
| [H/W] 전동 공구 배터리 팩 전압 표시 개선 (0) | 2025.10.16 |
| ESP32-C3(Arduino) + Android App(Flutter) ⇒ Bluetooth 연동 #1 (0) | 2025.10.15 |
| [F/W, H/W] SBC 소비 전력 최적화: SBC + PIC 에너지 절감 (0) | 2025.10.04 |