2016년 9월 29일 목요일

스마트 태양 에너지 추적 및 발전기

이 작품은 제가 어떤 대회에 제출하려고 만든 거예요. 대회에 제출하려면 여러가지 규정에 맞게 글도 써야 하고, 디자인도 해야 해요. 기존에 만든 제품과도 달라야 해요. 코드를 오픈하였으니 누구나 만들수 있을 겁니다. 하지만, 대회에 나갈때는 똑같이 만들면 안되요!^^ 어떻게 하였는 지 아래 글을 참고하세요^^

발명 동기
화석 에너지로 인해, 지구의 환경은 오염되고 있습니다. 우리가 살아가는 데 필요한 전기를 사용하기 위해서, 석유나 석탄을 이용해, 전기를 만들고 있습니다. 

화석 에너지에 비해, 태양 에너지는 환경 오염도 없고, 무한대입니다. 태양 에너지를 잘 이용하면 화석 에너지가 필요 없겠죠. 자연도 보호하고요.


하지만, 태양 에너지를 얻기 위해 사용하는 태양 전지는 그 효율이 그리 좋지 않다고 합니다. 기술자들의 말로는 14~22% 정도라네요(연합뉴스)...

현재 많은 태양 에너지 발전기가 나와 있지만, 태양이 태양 전지를 수직으로 비추고 있지 않을 때는 태양 전지 효율은 더 떨어진다고 합니다. 

스마트 태양 추적기를 만들어, 이런 문제를 해결하고, 더불어, 무선으로 태양 추적기의 상태를 휴대폰으로 확인해서, 문제가 있을 경우 바로 수리할 수 있게 하고 싶습니다. 

디자인
디자인은 태양을 따라 추적기가 회전할 수 있도록 큰 원판과 앞뒤로 움직이는 패널을 서로 연결하도록 하였습니다. 원판과 패널은 서보모터로 움직입니다.
태양과 태양전지가 수직인지 아닌지는 광센서를 이용하면 알 수 있습니다.
수직이 아니면, 수직이 아닌 정도를 계산해, 계산된 양만큼 서보모터를 움직입니다. 
현재 광센서의 값은 휴대폰으로 전송되도록, 블루투스를 이용하였습니다.

작업 과정
작업 과정은 다음과 같습니다.

작업 과정 기록 영상 (2016년 8월 중순 ~ 2016년 9월 말)

1. 재료준비
태양전지, 충전지 1.2V 두개, 아두이노나노, 블루투스(파란이빨아님) HC06, 서보모터2개, 전압센서


2. 패널조립 및 가공



3. 코딩


소스코드

SoftwareSerial mySerial(10, 11); // RX, TX
Servo horzServo;  // 수평서보모터 변수
Servo vertServo;  // 수직서보모터 변수

int horzAngle = 90; // 정수형변수 초기값은 90
int vertAngle = 90; // 정수형변수 초기값은 90
    
void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600); // 시리얼 비긴 초당 9600비트 주고받기
  while (!Serial) { // 그동안 Serial 실행
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Goodnight moon!");  // 시리얼 모니터에 "Goodnight moon!" 출력하기 

  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600); // 변수 마이시리얼 비긴 초당 9600비트 주고받기
  mySerial.println("Hello, world?");  // 마이시리얼 모니터에 "Hello, world?" 출력하기 

  // set servo
  horzServo.attach(6); vertServo.attach(5);  // 수평 및 수직서보모터에 붙이기 6, 5

  horzServo.write(80);  
  vertServo.write(80);  

  delay(500); // 기다리기 servoTime만큼
  horzServo.detach(); vertServo.detach();
}

void loop() { // run over and over
  if (mySerial.available()) { // 만약 마이시리얼을 사용 할 수 잇다면 
    Serial.write(mySerial.read());  // 시리얼 쓰기 마이시리얼 읽기
  }
  if (Serial.available()) { // 만약 시리얼을 사용 할 수 잇다면 
    mySerial.write(Serial.read());  // 마이시리얼 쓰기 시리얼 읽기
    
  }

  // 4개의 광센서 값을 analogRead( )로 읽어서, 각각 정수형 변수 leftTop, rightTop, leftBottom, rightBottom 에 넣는다.
  int leftTop = analogRead(A0);
  int rightTop = analogRead(A1);
  int leftBottom = analogRead(A2);
  int rightBottom = analogRead(A4);
  int vol = analogRead(A6);

  float vout = vol / 4.092;           // (vol * 5.0) / 1024.0;
  float vin = vout / 10.0;    // vout / (7500.0 / (30000.0 + 7500.0)); 
     
  mySerial.print(vin);
  mySerial.print(",");
  
  int averLeft = (leftTop + leftBottom) / 2;        // leftTop + leftBottom 광센서 값을 평균내서 averLeft변수에 넣는다.
  int averRight = (rightTop + rightBottom) / 2;     // rightTop + rightBottom 광센서 값을 평균내서 averRight변수에 넣는다.
  int averTop = (leftTop + rightTop) / 2; // leftTop + rightTop 광센서 값을 평균내서 averTop변수에 넣는다.
  int averBottom = (leftBottom + rightBottom) / 2;  // leftBottom + rightBottom 광센서 값을 평균내서 averBottom변수에 넣는다.
  int diffLeftRight = averLeft - averRight; // diffLeftRight변수에 넣는다.
  int diffTopBottom = averBottom - averTop; // diffTopBottom변수에 넣는다.
  mySerial.print((leftTop + leftBottom + rightTop + rightBottom) / 4);
  
  Serial.print(vin);  // 시리얼모니터에 vin 값 출력하기
  Serial.print(", ");
  Serial.print(leftTop);  // 시리얼모니터에 leftTop 값 출력하기
  Serial.print(", ");
  Serial.print(rightTop);  // 시리얼모니터에 rightTop 값 출력하기
  Serial.print(", ");
  Serial.print(leftBottom);  // 시리얼모니터에 leftBottom 값 출력하기
  Serial.print(", ");
  Serial.print(rightBottom);  // 시리얼모니터에 rightBottom 값 출력하기
  Serial.print(", ");
  Serial.print(diffLeftRight);  // 시리얼모니터에 diffLeftRight 값 출력하기
  Serial.print(", ");
  Serial.print(horzAngle);  // 시리얼모니터에 horzAngle 값 출력하기
  Serial.print(", ");
  Serial.print(diffTopBottom);  // 시리얼모니터에 diffTopBottom 값 출력하기
  Serial.print(", ");
  Serial.println(vertAngle);  // 시리얼모니터에 vertAngle 값 출력하기

  int servoTime = 100;  // 정수형 변수 servotime 초기값 100
  int errorValue = 30;  // 정수형 변수 errorValue 초기값 20


  if( -1 * errorValue < diffLeftRight && diffLeftRight < errorValue)  // 만약 마이너스1오류 값 <diffLeftRight 그리고 diffLeftRight <오류 값 으로
  {
    ;
  }
  else if(diffLeftRight < 0 && horzAngle < 150) // 만약 아니면 diffLeftRight < 0 그리고 horzAngle < 180 으로
  {
    horzServo.attach(6); vertServo.attach(5);  // 수평 및 수직서보모터에 붙이기 6, 5   
    horzAngle = horzAngle + 1;
    horzServo.write(horzAngle);
    Serial.println("right");      
    delay(servoTime); // 기다리기 servoTime만큼
    horzServo.detach(); vertServo.detach();
  }
  else if(diffLeftRight > 0 && horzAngle > 30)
  {
    horzServo.attach(6); vertServo.attach(5);  // 수평 및 수직서보모터에 붙이기 6, 5     
    horzAngle = horzAngle - 1;
    horzServo.write(horzAngle);
    Serial.println("left");      
    delay(servoTime); // 기다리기 servoTime만큼
    horzServo.detach(); vertServo.detach();
  }

  if( -1 * errorValue < diffTopBottom && diffTopBottom < errorValue)  // 만약 마이너스1 오류 값 <diffTopBottom 그리고 diffTopBottom <오류 값으로
  {
    ;
  }
  else if(diffTopBottom < 0 && vertAngle < 120) // 만약 아니면 diffTopBottom < 0 그리고 vertAngle < 120으로
  {
    horzServo.attach(6); vertServo.attach(5);  // 수평 및 수직서보모터에 붙이기 6, 5    
    vertAngle = vertAngle + 1;
    vertServo.write(vertAngle); 
    Serial.println("up");  
    delay(servoTime); // 기다리기 servoTime만큼
    horzServo.detach(); vertServo.detach();
  }
  else if(diffTopBottom > 0 && vertAngle > 30) // 만약 아니면 diffTopBottom < 0 그리고 vertAngle < 30으로
  {
    horzServo.attach(6); vertServo.attach(5);  // 수평 및 수직서보모터에 붙이기 6, 5    
    vertAngle = vertAngle - 1;
    vertServo.write(vertAngle);
    Serial.println("down");  
    delay(servoTime); // 기다리기 servoTime만큼
    horzServo.detach(); vertServo.detach();
  }
}


완성된 모습
완성된 모습은 다음과 같습니다.


스마트폰에 조도센서값이 표시되어, 제대로 태양을 추적하는 지를 무선으로 확인할 수 있습니다. 앞으로 스마트폰에 태양전지가 발전한 전력량등을 보완하려 합니다.


댓글 3개:

  1. 발명동기에 "연합뉴스"를 인용한 것이 좋았어요.. 좋은글 계속 부탁드릴게요~^^ 아임 유어 빅팬~

    답글삭제
  2. 이 작품으로 수상을 했잖아요, 전시및 수상과 관련된 사진과 동영상을 블로그에 올려주세요~ 궁금해요~

    답글삭제