아두이노 해바라기: 태양을 추적하는 전자 해바라기 만들기
부품 및 소모품
| 아두이노 우노 |
1개 |
| RobotGeek 조도 센서 |
1개 |
| 회전 포텐셔미터 (일반) |
1개 |
| Seeed 베이스 실드 V2 |
1개 |
앱 및 온라인 서비스
프로젝트 소개
메이커는 늘 새롭고 재미있는 것에 민감합니다. 어느 날 해바라기가 태양을 따라 움직이는 영상을 보고 번뜩였습니다. '이 생체 메커니즘을 전자 장치로 모방할 수 없을까?'
며칠 뒤 태양 추적 프로젝트를 시작했습니다. 크로우테일(Crowtail) 마이크로컨트롤러 보드를 선정하고 창고에서 부품들을 챙겨 조립했습니다. 마지막에 핸드폰 플래시로 테스트했는데 완벽하게 작동했습니다!
너무 신나서 데모 영상을 SNS에 올렸더니 많은 분이 좋아요/공유하고, 직접 만들고 싶다는 메시지도 많이 왔습니다. 그래서 프로젝트를 다시 정리해 구체적인 튜토리얼로 만들었습니다. 자, 시작합니다.
1단계: 준비물
- 골판지 2장
- 스티로폼 보드 1장
- 막대 1개
- 3핀 크로우테일 케이블 6개
- 크로우테일 선형 포텐셔미터 2개
- 크로우테일 조도 센서 4개
- 크로우테일 팬-틸트 1개
- 크라우두이노 ATMega 328 V1.1 1개
- 크로우테일 아두이노용 베이스 실드 1개
2단계: 장치 머리 만들기
골판지 두 조각을 사진처럼 잘라 십자 모양으로 조립합니다. 막대를 십자에 붙여 '머리' 역할을 하게 합니다. 항상 태양을 향하게 하고, 장치를 예쁘고 안정적으로 만들어 줍니다.
3단계: 조도 센서 4개 설치
스티로폼에 센서 설치용 구멍 4개, 막대 통과용 중앙 구멍 1개를 뚫습니다. 센서에 번호를 붙여 위치 구분.
4단계: 센서와 케이블 연결
핫글루로 막대를 폼에 고정하고 센서에 케이블 꽂기.
5단계: 막대를 팬-틸트에 고정
막대를 팬-틸트에 고정합니다. 센서 위치는 사진과 일치하게(센서 1, 2는 아래쪽). 팬-틸트는 9G 서보 내장 조립품으로 수직/수평 180도 회전 제어 가능. 마지막으로 태양광 패널을 폼에 고정(장식용, 전력 공급 기능 없음).
6단계: 코드 업로드
크라우두이노와 베이스 실드를 꺼내 스택 결합. 케이블 연결 전 크라우두이노에 프로그램 업로드(마이크로 USB 케이블 필요). 크라우두이노를 컴퓨터에 연결하고 아두이노 IDE 열기.
7단계: 센서 4개를 실드에 연결
센서 케이블을 실드에 번호 일대일 대응해 연결:
- 케이블 "1" → A0
- 케이블 "2" → A1
- 케이블 "4" → A2
- 케이블 "3" → A3
8단계: 포텐셔미터를 실드에 연결
두 포텐셔미터를 A4, A5 소켓에 연결. 둘은 동일하지만 A4 연결된 건 반응 지연 시간 제어, A5 연결된 건 서보 회전 속도 제어 역할을 합니다.
9단계: 팬-틸트를 실드에 연결
아래 서보(수평 이동) → D9, 위 서보(수직 이동) → D10.
10단계: 전원 공급
크라우두이노가 메인 컨트롤러. USB 파워뱅크나 DC 어댑터로 전원 공급(이동형/고정형 선택).
11단계: 테스트!
박스 닫기. 햇빛 쫓아갈 준비 된 것 같죠? 어두운 방에서 핸드폰 플래시 켜니 이 귀여운 녀석이 따라옵니다! 보기엔 어려워 보여도 실제론 간단하니 직접 해보세요. 더 멋지고 강력하게 개선해보세요!
코드
#include <Servo.h> // 서보 라이브러리 포함
Servo horizontal; // 수평 서보
int servoh = 90; // 수평 서보 초기값
Servo vertical; // 수직 서보
int servov = 90; // 수직 서보 초기값
// 조도 센서 핀 연결 (아날로그 핀)
int ldrrd = 0; // 오른쪽 아래
int ldrld = 1; // 왼쪽 아래
int ldrlt = 2; // 왼쪽 위
int ldrrt = 3; // 오른쪽 위
void setup() {
Serial.begin(9600);
// 서보 연결
horizontal.attach(9);
vertical.attach(10);
}
void loop() {
int lt = analogRead(ldrlt); // 왼쪽 위
int rt = analogRead(ldrrt); // 오른쪽 위
int ld = analogRead(ldrld); // 왼쪽 아래
int rd = analogRead(ldrrd); // 오른쪽 아래
int dtime = analogRead(4)/20; // 포텐셔미터 읽기 (반응 지연)
int tol = analogRead(5)/4; // 포텐셔미터 읽기 (허용 오차)
int avt = (lt + rt) / 2; // 위쪽 평균
int avd = (ld + rd) / 2; // 아래쪽 평균
int avl = (lt + ld) / 2; // 왼쪽 평균
int avr = (rt + rd) / 2; // 오른쪽 평균
int dvert = avt - avd; // 상하 차이
int dhoriz = avl - avr; // 좌우 차이
// 상하 차이가 허용 오차 밖이면 수직 서보 각도 변경
if (-1*tol > dvert || dvert > tol) {
if (avt > avd) {
servov = ++servov;
if (servov > 180) servov = 180;
} else if (avt < avd) {
servov = --servov;
if (servov < 0) servov = 0;
}
vertical.write(servov);
}
// 좌우 차이가 허용 오차 밖이면 수평 서보 각도 변경
if (-1*tol > dhoriz || dhoriz > tol) {
if (avl > avr) {
servoh = --servoh;
if (servoh < 0) servoh = 0;
} else if (avl < avr) {
servoh = ++servoh;
if (servoh > 180) servoh = 180;
} else if (avl == avr) {
// 아무것도 안 함
}
horizontal.write(servoh);
}
delay(dtime);
}
커스텀 파트 및 인클로저
프로젝트 사진 참조
회로도
회로도 이미지 참조