호주에서 재생에너지 업계에 종사하며 아두이노로 이것저것 만들어온 지 꽤 됐지만, 이 프로젝트에서야 비로소 둘을 결합해 나만의 소형 태양광 장치를 만들기로 결심했습니다. 한 가지 미리 말씀드리자면, 이 프로젝트는 아두이노와 서보에 전원을 공급하기 위해 5V가 필요하지만, 태양광 패널은 잘해야 3.4V를 생산합니다. 그래서 정확히 말해 '본전'은 아닙니다. 하지만 개념은 확장 가능합니다. 예를 들어 8개 패널 어레이로 12V를 생산한다면 아두이노에 전원 공급하면서 휴대폰도 충전할 수 있겠죠. 언젠가 해볼 계획이며, 그때 링크를 추가하겠습니다.
참고 자료:
The DIY Life - https://www.the-diy-life.com/arduino-solar-tracker/
Brown Dog Gadgets - https://www.instructables.com/id/Solar-Altoids-USB-Charger/
둘 다 주제에 대한 좋은 정보원이며, 여기서 개념을 얻었습니다.
시작하기
먼저 태양광 패널이 필요합니다. 두 개 사용했지만 원하는 만큼 쓸 수 있습니다. 9g 서보가 들어올릴 수 있는 무게를 생각해서 너무 무겁지 않게 하세요. 제가 쓴 패널은 1.5V, 0.75W 출력의 하위권 제품이지만 가볍고 저렴하며 개념 증명용이라 출력은 중요하지 않습니다.
두 패널을 에폭시로 가장자리에 붙여 연결했습니다. 패널을 직렬로 연결하려면 한 패널의 양극을 다른 패널의 음극에 납땜하면 양극과 음극 선이 하나씩 남습니다. 두 개의 LDR(조도 센서)을 패널 양쪽(동쪽, 서쪽)에 부착하고, 각 리드에 점퍼 와이어 한 끝을 납땜합니다. 점퍼 와이어 한쪽 끝을 자르고 피복을 약 5mm 벗겨 선을 노출시키면 납땜이 더 쉽습니다.
아두이노가 LDR을 읽으려면 각각에 전압 분배 회로가 필요합니다. 전압 분배기 참고. 이 회로에서 LDR이 R1, 10kΩ 저항이 R2이고, 두 저항이 만나는 지점에 점퍼 와이어를 아두이노에 연결합니다. 브레드보드에 제작 시 LDR 한 리드는 전압 분배기, 다른 리드는 양극 파워 레일에 연결. 아래 프리칭 다이어그램 참조.
트래커 구조물
패널을 올릴 회전 지지 구조물이 필요합니다. 제 설계는 두 개의 A자 프레임으로 지지된 스프링 강철 막대입니다. 패널 어레이 아래쪽에 작은 나무 버팀목이 있고 스프링 강철이 통과할 구멍이 있습니다. 싸고 쉽고 가볍게 발사나무로 만들었지만, 영구 설치라면 얇은 강철이나 방부 처리된 합판이 좋습니다. 회전 지지물 제작 과정은 잘 기록하지 못했지만, 아래 영상으로 서보 위치와 함께 어떻게 만드는지 확인할 수 있습니다. 패널을 아래쪽 각도로 장착해 구조물 바닥을 북쪽으로 향하게 하면, 패널이 태양을 추적하며 흔들려도 항상 약간 북쪽으로 기울어져 출력을 극대화합니다(남반구 기준).
서보 장착
서보는 A자 프레임 구조물의 지지대 중 하나에 장착되고 패널 한쪽을 들어올립니다. 펜치로 스프링 강철을 구부려 양 끝에 고리를 만들어 패널 버팀목과 서보 암에 걸었습니다. 서보 암 구멍을 넓혀야 할 수 있는데, 가장 작은 드릴 비트를 사용했습니다. 강철을 서보 암이나 패널 버팀목에 접착하지 마세요. 구멍 안에서 자유롭게 회전해야 패널이 부드럽게 올라갑니다. 제자리면 패널을 구조물에서 떼어내 서보만 남겨 캘리브레이션을 진행하세요.
아두이노에 업로드하고 서보가 어디로 가는지 보세요. 스케치의 'pos' 값을 0~180 사이로 바꿔가며 재업로드해 서보 암이 직각으로 위아래를 가리키는 위치를 찾으세요. 그게 최대/최소값입니다. 제 경우 15와 140이었습니다. 값이 180에서 0으로 넘어가면 서보 암을 떼어내고 다시 장착해 정렬하세요.
조립하기
모든 것을 연결하고 다음 스케치를 입력하세요.
// Sun Tracker Sketch
// 9g 서보용, 외부 전원 없이 아두이노에서 직접 구동 가능
// 프리칭 다이어그램은 GitHub 저장소 참조
// https://github.com/nickalanf/Arduino--Projects
// 시리얼 모니터 부분은 디버깅/흥미용, 정상 작동 후 비활성화 가능
// Sketch by FIELDING - 8/2/18
#include
Servo servo;
int eLDRPin = A0; // LDR 핀 할당
int wLDRPin = A1;
int eastLDR = 0; // LDR 읽기값 저장 변수
int westLDR = 0;
int difference = 0; // 두 LDR 비교 변수
int error = 10; // 눈에 띄는 차이 임계값
int servoSet = 130; // 서보 위치 변수 - 기기마다 다름
void setup() {
servo.attach(9);
Serial.begin(9600);
}
void loop() {
eastLDR = analogRead(eLDRPin);
westLDR = analogRead(wLDRPin);
if (eastLDR < 400 && westLDR < 400) {
// 양쪽 LDR 조도 낮으면(밤) 패널을 동쪽으로 돌려 일출 대기
while (servoSet <= 140 && servoSet >= 15) {
servoSet++;
servo.write(servoSet);
delay(100);
}
}
difference = eastLDR - westLDR;
if (difference > 10) {
// 동쪽 LDR이 더 밝으면 패널을 동쪽으로
if (servoSet <= 140) { servoSet++; servo.write(servoSet); }
} else if (difference < -10) {
// 서쪽 LDR이 더 밝으면 패널을 서쪽으로
if (servoSet >= 15) { servoSet--; servo.write(servoSet); }
}
Serial.print(eastLDR); Serial.print(" - ");
Serial.print(westLDR); Serial.print(" - ");
Serial.print(difference); Serial.print(" - ");
Serial.print(servoSet); Serial.print(" - ");
Serial.println(".");
delay(100);
}
시리얼 모니터를 열고 LDR에 빛을 비추세요. 양쪽에 고르게 비추고 시리얼 모니터에 출력되는 difference 값이 얼마인지 확인하세요. 약 25 초과 또는 -25 미만이면 오차 보정 필요. 관련 오차 값을 코드에 추가하고 해당 LDR 값에 더하거나 빼세요. difference 값이 가까우면 그대로 둬도 됩니다.
테스트 준비 완료! 어두운 방에서 손전등/램프로 가장 쉽게 테스트합니다. 빛을 한 LDR에서 다른 LDR로 천천히 이동하며 패널이 움직이는지 보세요. 한쪽 LDR을 가려도 패널이 그 반대쪽으로 돌아야 합니다.
보너스: 휴대폰 충전기
패널 출력을 실제로 활용하려면 2.5V-5V DC-DC 부스트 컨버터를 패널에서 나온 선에 직접 연결하세요. 아두이노/브레드보드 회로와는 완전히 별개입니다. 표준 휴대폰 충전은 5V지만 패널 출력이 5V라도 전류가 낮을 수 있어 배터리가 가득 차거나 햇빛이 약하면 충전 안 될 수 있습니다. 가장 쉬운 해결책은 패널을 더 추가하는 것입니다!
코드
Sun Tracker
// Sun Tracker Sketch
#include
Servo servo;
int eLDRPin = A0;
int wLDRPin = A1;
int eastLDR = 0;
int westLDR = 0;
int difference = 0;
int error = 10;
int servoSet = 130;
void setup() {
servo.attach(9);
Serial.begin(9600);
}
void loop() {
eastLDR = analogRead(eLDRPin);
westLDR = analogRead(wLDRPin);
if (eastLDR < 400 && westLDR < 400) {
while (servoSet <= 140 && servoSet >= 15) {
servoSet++;
servo.write(servoSet);
delay(100);
}
}
difference = eastLDR - westLDR;
if (difference > 10) {
if (servoSet <= 140) { servoSet++; servo.write(servoSet); }
} else if (difference < -10) {
if (servoSet >= 15) { servoSet--; servo.write(servoSet); }
}
Serial.print(eastLDR); Serial.print(" - ");
Serial.print(westLDR); Serial.print(" - ");
Serial.print(difference); Serial.print(" - ");
Serial.print(servoSet); Serial.print(" - ");
Serial.println(".");
delay(100);
}