이중축 태양광 추적기: 자동/수동 모드 전환 가능한 고효율 선트래킹 시스템
부품 및 소모품
| 부품 | 수량 | 비고 |
| 아두이노 우노 | 1 | 메인 컨트롤러 |
| MG996R 서보 모터 | 2 | 수평/수직 축 구동 (고토크 메탈 기어 권장) |
| 포토레지스터 (CdS) | 4 | 좌상, 우상, 좌하, 우하 4방향 조도 감지 |
| 로터리 포텐셔미터 | 2 | 수동 모드 시 수평/수직 각도 직접 제어용 |
| 택트 스위치 12mm | 1 | 자동/수동 모드 전환 버튼 |
| LED (적색, 청색) | 각 1 | 수동/자동 모드 표시용 |
| 10kΩ 저항 | 5 | 포토레지스터 분압용 4개 + 버튼 풀업 1개 |
| 221Ω 저항 | 2 | LED 전류 제한용 |
필요 도구
소프트웨어
- Arduino IDE
- Autodesk Tinkercad (회로 시뮬레이션 및 코드 개발용)
프로젝트 개요
초등학생 메이커 클럽(Young Hackers, 2017-2018) 프로젝트로, 5V 소형 태양광 패널을 이축(수평/수직)으로 회전시켜 최대 일사량을 추적하는 시스템입니다. OpenSourceClassroom의 설계를 기반으로 하되, 자동 모드(4개 조도 센서 기반)와 수동 모드(포텐셔미터 2개 직접 제어)를 버튼 하나로 전환하도록 확장했습니다. 학생들이 분업(납땜, 절연, 나사 조립 등)해 제작 라인 방식으로 완성했습니다.
동작 원리
모드 전환
- 버튼(핀 7) 눌림 감지 → 모드 토글 (디바운스 50ms)
- 수동 모드: 적색 LED ON → 포텐셔미터 2개(A0: 좌우, A1: 상하) 값 0~1023 → 0~180° 매핑해 서보 직접 제어
- 자동 모드: 청색 LED ON → 4개 포토레지스터(A2~A5) 읽기 → 각 센서별 보정 매핑(최소/최대값 다름) 후 0~100 스케일 정규화
자동 추적 알고리즘
- 좌/우 평균 조도 계산: `LeftLight = (TL + BL)/2`, `RightLight = (TR + BR)/2`
- 상/하 평균 조도 계산: `TopLight = (TL + TR)/2`, `BottomLight = (BL + BR)/2`
- 편차 임계값 4% 이상일 때만 서보 1°씩 이동 (진동 방지)
- 좌측이 밝으면 좌측으로(서보 각도 증가), 우측이 밝으면 우측으로(각도 감소)
- 상단이 밝으면 상단으로(서보 각도 감소), 하단이 밝으면 하단으로(각도 증가)
- 서보 한계(0°/180°) 체크 후 이동
코드 (완전판)
#include <Servo.h>
int mode = 0; // 0: 수동, 1: 자동
int buttonState = 0;
int prevButtonState = 0;
// 조도 센서 원시값
int topLeftLight, topRightLight, bottomLeftLight, bottomRightLight;
// 정규화된 조도 (0~100)
int LeftLight, RightLight, TopLight, BottomLight;
Servo servo_9; // 수평 (핀 9)
Servo servo_10; // 수직 (핀 10)
void setup() {
pinMode(7, INPUT); // 모드 버튼
pinMode(12, OUTPUT); // 적색 LED (수동)
pinMode(11, OUTPUT); // 청색 LED (자동)
pinMode(A0, INPUT); // 포텐셔미터 좌우
pinMode(A1, INPUT); // 포텐셔미터 상하
pinMode(A2, INPUT); // 포토레지스터 좌상
pinMode(A3, INPUT); // 포토레지스터 우상
pinMode(A4, INPUT); // 포토레지스터 좌하
pinMode(A5, INPUT); // 포토레지스터 우하
servo_9.attach(9);
servo_10.attach(10);
}
void loop() {
// 모드 버튼 디바운스 & 토글
buttonState = digitalRead(7);
if (buttonState != prevButtonState) {
if (buttonState == HIGH) {
if (mode == 1) {
mode = 0;
digitalWrite(12, HIGH); // 적색 ON
digitalWrite(11, LOW); // 청색 OFF
} else {
mode = 1;
digitalWrite(11, HIGH); // 청색 ON
digitalWrite(12, LOW); // 적색 OFF
}
}
}
prevButtonState = buttonState;
delay(50);
if (mode == 0) {
// 수동 모드: 포텐셔미터 직접 매핑
servo_9.write(map(analogRead(A0), 0, 1023, 0, 180));
servo_10.write(map(analogRead(A1), 0, 1023, 0, 180));
} else {
// 자동 모드: 센서별 개별 보정 후 정규화
topLeftLight = map(analogRead(A2), 50, 980, 0, 100);
topRightLight = map(analogRead(A3), 200, 990, 0, 100);
bottomLeftLight = map(analogRead(A4), 170, 970, 0, 100);
bottomRightLight = map(analogRead(A5), 250, 1000, 0, 100);
// 평균 조도 계산
TopLight = (topRightLight + topLeftLight) / 2;
BottomLight = (bottomRightLight + bottomLeftLight) / 2;
LeftLight = (topLeftLight + bottomLeftLight) / 2;
RightLight = (topRightLight + bottomRightLight) / 2;
// 수평 축 제어
if (abs(RightLight - LeftLight) > 4) {
if (RightLight < LeftLight) { // 좌측이 밝음
if (servo_9.read() < 180) servo_9.write(servo_9.read() + 1);
} else { // 우측이 밝음
if (servo_9.read() > 0) servo_9.write(servo_9.read() - 1);
}
}
// 수직 축 제어
if (abs(TopLight - BottomLight) > 4) {
if (TopLight < BottomLight) { // 하단이 밝음
if (servo_10.read() < 180) servo_10.write(servo_10.read() - 1);
} else { // 상단이 밝음
if (servo_10.read() > 0) servo_10.write(servo_10.read() + 1);
}
}
}
}
회로도
제공된 배선도 이미지 참조. 주요 포인트: 포토레지스터 4개는 각각 10kΩ 풀다운 저항과 분압 구성, 서보 전원은 아두이노 5V에서 공급(소형 패널용), 대형 패널 시 외부 전원 필수.
제작 포인트 & 교육적 가치
- 센서 보정 필수: 각 포토레지스터 특성 차이 커서 `map()` 최소/최대값 개별 측정 후 하드코딩 필요
- 임계값(4%) 튜닝: 환경 조도 변화폭에 따라 조정 (너무 작으면 진동, 너무 크면 추적 지연)
- 기계적 구조: 서보 혼-패널 연결부 백래시 최소화, 풍하중 고려 고정
- 교육 효과: 피드백 제어, 센서 융합, 상태 머신(모드 전환), 분업 협업 경험
확장 아이디어
- RTC 모듈 추가로 일출/일몰 시각 기반 수면 모드 구현
- 전압/전류 센서로 실제 발전량 로깅 및 MPPT 알고리즘 비교
- LoRa/Wi-Fi 모듈로 원격 모니터링 및 펌웨어 OTA 업데이트
- 대형 패널용: 서보 → 스테퍼 모터/리니어 액추에이터, PID 제어 도입