본문 바로가기
생활 취미 만들기

Arduino를 사용한 MPPT 태양열 충전 컨트롤러 설계

by 굿뜨클랑 2023. 4. 19.
728x90
반응형

Arduino 기반 MPPT(Maximum Power Point Tracking) 태양광 충전 컨트롤러 설계

개요

이 프로젝트에서 우리는 Arduino를 사용하고 많은 능동-수동 전자 장치를 결합하여 자체 MPPT 태양열 충전 컨트롤러를 구축할 것입니다. MPPT는 최대 전력 점 추적 컨트롤러를 의미합니다. 대부분의 태양 전지판은 12V 배터리를 충전하는 데 필요한 것보다 훨씬 더 높은 전압을 생성합니다. 12V 충전 패널은 조건에 따라 실제로 16-18볼트를 생성하지만 대부분의 14.6V 배터리를 충전하는 데 약 12볼트만 필요합니다. 대부분의 전압이 낭비됩니다. MPPT 충전 기술을 사용하여 과도한 전압을 전류로 변환 할 수 있으므로 효율성을 높일 수 있습니다.

 태양광 발전 충전 기술에 대해 알아보고 MPPT 충전 기술에 대해 알아보겠습니다. 나중에 Arduino 및 많은 전자 부품을 사용하여 MPPT 충전 컨트롤러용 회로도 및 PCB를 설계합니다. 그런 다음 Arduino C 코드를 작성하여 Arduino Nano를 프로그래밍하여 20×4 LCD 화면에서 MPPT 태양열 충전 컨트롤러와 관련된 모든 충전 매개 변수를 시각화 할 수 있습니다. 이 코드에는 태양 전지판 전압, 전류, 전력, 배터리 전압, 충전기 상태, SOC, PWM 듀티 사이클, 부하 상태를 측정하는 모든 매개변수와 기능이 있습니다.

나중에 하루 종일 충전기를 테스트하고 완벽하게 작동하는지 여부를 확인할 수 있습니다. 이 디자인은 일반적으로 사용되는 50V 납산 배터리를 충전하기 위해 12W 태양 전지판에 적합합니다. 이 기사는 우리가 논의할 많은 설명과 디자인 방법으로 매우 상세합니다.

자재 명세서

프로젝트에서 다음 구성 요소를 사용하여 Arduino 기반 MPPT 태양열 충전 컨트롤러를 구축합니다.

증권 시세 표시기구성 요소양구매 링크
1 아두이노 나노 1 아마존 | 알리익스프레스
2 20x4 LCD 디스플레이 1 아마존 | 알리익스프레스
3 ACS712 전류 센서 1 아마존 | 알리익스프레스
4 IR2104 IC 1 아마존 | 알리익스프레스
5 모스펫 IRFZ44 4 아마존 | 알리익스프레스
6 트랜지스터 2N2222A 1 아마존 | 알리익스프레스
7 다이오드 P6KE36CA 1 아마존 | 알리익스프레스
8 다이오드 1N4007 1 아마존 | 알리익스프레스
9 다이오드 1N4148 2 아마존 | 알리익스프레스
10 푸시 버튼 스위치 2 아마존 | 알리익스프레스
11 저항기 100K 1 아마존 | 알리익스프레스
12 저항기 20K 2 아마존 | 알리익스프레스
13 저항기 470K 1 아마존 | 알리익스프레스
14 저항기 10K 3 아마존 | 알리익스프레스
15 저항기 1K 1 아마존 | 알리익스프레스
16 저항기 220Ω 6 아마존 | 알리익스프레스
17 커패시터 220uF 1 아마존 | 알리익스프레스
18 커패시터 10uF 2 아마존 | 알리익스프레스
19 커패시터 0.1uF 6 아마존 | 알리익스프레스
20 인덕터 33uH 1 아마존 | 알리익스프레스
21 적색 LED 1 아마존 | 알리익스프레스
22 녹색 LED 1 아마존 | 알리익스프레스
23 청색 LED 1 아마존 | 알리익스프레스
24 태양 전지판(12/24/36V) 1 아마존 | 알리익스프레스
25 납축전지 12V 1 아마존 | 알리익스프레스
26 단자대 3 아마존 | 알리익스프레스
27 여성 헤더 2 세트 아마존 | 알리익스프레스
28 DC 잭 1 아마존 | 알리익스프레스

주어진 링크에서 모든 구성 요소를 구입할 수 있습니다.

 

태양열 충전 컨트롤러란 무엇입니까?

태양열 충전 컨트롤러는 태양 전지판에서 배터리 또는 배터리 뱅크로의 전류 흐름을 조절하는 전자 장치입니다.

배터리가 과충전되거나 과충전되지 않도록 하여 배터리를 손상시키고 전체 수명을 단축시킬 수 있습니다. 태양열 충전 컨트롤러는 또한 야간에 태양 전지판을 통해 배터리가 다시 방전되는 것을 방지합니다. 태양광 발전 시스템의 중요한 구성 요소입니다.


충전 컨트롤러의 종류

배터리가 있는 모든 태양광 패널 시스템에는 충전 컨트롤러가 필요합니다. 그 목적은 태양 전지판에서 배터리로 들어오는 전력을 조절하고 제어하여 배터리의 상태를 연장하는 것입니다.

충전 컨트롤러에는 세 가지 유형이 있습니다.

  1. 간단한 온-오프 컨트롤러(ON OFF)
  2. 펄스 폭 변조 컨트롤러(PWM)
  3. 최대 전력 점 추적 컨트롤러 (MPPT)

온-오프 컨트롤러는 매우 간단한 장치입니다. 그들이 하는 일은 배터리 뱅크의 전압을 감지하고 전원을 켜거나 끄는 것뿐입니다.

펄스 폭 변조 컨트롤러는 온-오프 컨트롤러보다 약간 더 빠르게 충전된 다음 배터리가 가득 차면 전압이 가늘어집니다. 배터리가 가득 차면 컨트롤러는 플로트 충전 프로필로 전환되며, 이는 기본적으로 배터리에 전류가 유입되어 방전되지 않도록 합니다. PWM 컨트롤러는 단순한 온-오프 컨트롤러보다 배터리 수명을 연장합니다.

 

최대 전력 점 추적 컨트롤러 (MPPT)

MPPT(Maximum Power Point Tracking) 충전 컨트롤러는 배터리에 저장된 태양 전지판의 전력량을 최대화하여 태양 전지판의 배터리 충전을 조절하는 전자 장치입니다. 배터리의 최적 충전 전압과 일치하도록 태양 전지판의 전압과 전류를 지속적으로 조정하여 이를 수행합니다. 이를 통해 배터리를 보다 빠르고 효율적으로 충전할 수 있으며 태양계의 전체 전력 출력도 높일 수 있습니다.

최대 PowerPoint 추적 컨트롤러는 위에서 언급한 두 가지 이전 유형보다 훨씬 더 발전되고 훨씬 더 효율적입니다. 이 컨트롤러는 초과 전압을 일반적으로 PWM 컨트롤러에 의해 낭비되는 추가 전류로 변환할 수 있을 만큼 충분히 스마트합니다.

대부분의 태양 전지판은 12V 배터리를 충전하는 데 필요한 것보다 훨씬 더 높은 전압을 생성하거나 해당 구성이 있는 경우 24볼트 또는 48볼트를 생성합니다. 12V 충전 패널은 조건에 따라 실제로 16-18볼트를 생성하지만 대부분의 14.6V 배터리를 충전하는 데 약 12볼트만 필요합니다. 따라서 MPPT 컨트롤러는 이러한 추가 전압을 더 많은 전류로 변환하여 배터리를 더 빠르고 효율적으로 충전할 수 있습니다.


MPPT 태양열 충전 컨트롤러의 장점 및 단점

MPPT 컨트롤러는 이러한 추가 전압을 더 많은 전류로 변환하여 배터리를 더 빠르고 효율적으로 충전할 수 있습니다. MPPT 컨트롤러의 또 다른 장점은 전압 강하 또는 라인 손실을 최소화하기 위해 태양 전지판의 훨씬 더 높은 전압 구성을 처리할 수 있다는 것입니다. 즉, 입력 전압을 높이기 위해 더 많은 태양 전지판을 직렬로 배선할 수 있으므로 더 작은 게이지 와이어를 실행하거나 큰 손실 없이 패널과 충전 컨트롤러 사이의 훨씬 더 먼 거리를 이동할 수 있습니다. 또한 이러한 이점을 통해 PWM 컨트롤러로 일반적으로 할 수 있는 것보다 더 큰 패널 어레이를 실행할 수 있습니다.

따라서 그리드에 연결되어 있고 백업 전원을 위해 배터리를 추가하려는 경우 MPPT가 유일한 방법입니다. MPPT 컨트롤러는 약 94%에서 99%의 효율을 가지며, 이는 유사한 PWM 컨트롤러보다 최대 30% 더 효율적일 수 있습니다. 그러나 일반적으로 PWM보다 <>-<>배 더 비쌉니다. MPPT는 여전히 새로운 기술이기 때문입니다. 또한 일반적으로 PWM 컨트롤러보다 훨씬 큽니다.

MPPT 컨트롤러는 사용 가능한 모든 태양광 발전을 추출할 수 있기 때문에 추운 기후 또는 구름이 많은 지역의 독립형 태양광 패널 시스템에 매우 중요합니다. MPPT의 유일한 다른 단점 중 하나는 최대 전력의 스위트 스폿을 찾는 데 어려움을 겪기 때문에 저조도 조건에서 잘 작동하지 않는다는 것입니다. 운 좋게도 이러한 조건은 그리 오래 지속되지 않으며 하루 종일 그것을 만회하는 것 이상입니다.

Arduino를 사용한 MPPT 태양열 충전 컨트롤러 설계

이제 Arduino를 사용하여 MPPT 태양열 충전 컨트롤러 프로젝트를 설계해 보겠습니다. 이 프로젝트를 설계하는 동안 많은 계산과 복잡한 알고리즘이 고려됩니다.

이 프로젝트는 opengreenenergy  asmlektor 디자인에서 가져온 참조로 설계되었습니다. 우리는 우리의 요구 사항에 따라 디자인을 수정했습니다.


특징 & 명세

충전 컨트롤러에는 다음과 같은 기능이 있습니다.

  • MPPT 알고리즘 기반
  • 충전 상태에 대한 다중 LED 표시
  • 전압, 전류, 전력, 부하 상태 등을 표시하기 위한 20×4자 LCD 디스플레이
  • 과전압 / 낙뢰 보호
  • 단락, 과부하 및 역극성 보호
  • 정격 전압 = 12V
  • 최대 전류 = 5A
  • 최대 부하 전류 = 10A
  • 입력 전압 = 12에서 25V까지 개방 회로 전압을 가진 태양 전지판
  • 태양 전지판 전력 = 50W

회로도/회로 설계

태양 전지판은 태양 전지판의 햇빛의 양, 연결된 하중 및 온도와 같은 다양한 매개변수에 따라 다른 전압을 생성합니다.

이 프로젝트는 여러 단계로 구성되며 많은 설계 계산이 필요합니다. 이 섹션에서는 모든 단계에 대해 설명합니다. 다음은 이 프로젝트의 전체 회로도입니다.

햇빛의 양은 하루 종일 변합니다. 따라서 태양 전지판에서 생성되는 전압은 지속적으로 변합니다. 다양한 전압으로 인해 다양한 전류가 생성됩니다. 주어진 전압에 대해 암페어로 생성되는 전류의 양은 다음과 같은 IV 곡선이라는 그래프에 의해 결정됩니다.

이 그래프에서 파란색 선은 약 30.6A의 전류에 해당하는 2V의 태양 전지판 전압을 나타냅니다. 녹색 선은 35V의 전압이 5A의 전류에 해당함을 나타냅니다.

우리는 Power = V x I를 알고 있습니다.

위의 그래프에는 전압에 해당 전류를 곱하면 최대 전력이 생성되는 지점이 있습니다. 이 최대 전력을 MPPT(Maximum Power Point Tracking)라고 합니다.

우리 프로젝트에 사용된 태양 전지판에는 아래 이미지와 같이 정의된 다음 매개변수가 있습니다.

설계 고려 사항 및 올바른 구성 요소 선택

50W 태양 전지판과 12V 납산 배터리 부하의 경우 벅 컨버터를 설계해야 합니다. 우리의 경우 벅 컨버터는 인덕터, 커패시터 및 MOSFET을 사용하여 설계되었습니다. 스위칭 주파수는 인덕터와 커패시터의 크기에 반비례하고 MOSFET의 스위칭 손실에 정비례합니다.

이러한 제약 조건을 고려하여 선택한 주파수는 50KHz입니다. 이 주파수를 달성하기 위해 33uH의 인덕터와 220uF의 커패시터를 사용했습니다. MOSFET부는, 입수하기 쉽기 때문에 IRFZ44N MOSFET를 사용했습니다. IRFZ44N MOSFET Vds 및 Ids 값은 충분한 마진 및 낮은 Rds(On) 값을 갖습니다. MOSFET을 구동하려면 MOSFET 드라이버 IC가 필요합니다. IR2104 하프 브리지 드라이버는 이 애플리케이션에 가장 적합합니다. 이 IC는 마이크로 컨트롤러에서 들어오는 PWM 신호를 받아 하이 측 및 로우 측 MOSFET에 대해 두 개의 출력을 구동합니다.


회로의 작동

태양 전지판 voltage는 입력 전압으로 공급됩니다. 벅 컨버터는 동기식 MOSFET 스위치 Q4 및 Q5와 에너지 저장 장치 인덕터 L1 및 커패시터 C4 및 C9로 구성됩니다. 인덕터는 스위칭 전류를 평활화하고 C4와 함께 출력 전압을 평활화합니다. 커패시터 C3 및 저항 R4는 인덕터의 스위칭 전류에 의해 생성된 인덕터 전압의 링잉을 줄이는 데 사용되는 스너버 네트워크입니다.

MOSFET Q3는 시스템이 야간에 배터리 전원이 태양 전지판으로 역류하는 것을 차단할 수 있도록 추가되었습니다. Q3는 전압에서 D4까지 Q2가 켜지면 켜집니다. R3는 Q3의 게이트의 전압을 소모하므로 Q4가 꺼지면 꺼집니다.

IC IR2104는 하프 브리지 MOSFET 게이트 드라이버입니다. 이 소자는 Arduino 핀 D6의 PWM 신호를 사용하여 하이사이드 및 로우사이드 MOSFET을 구동합니다. IR2104는 핀 5에 있는 Arduino의 D3 핀에서 나오는 제어 신호로 종료할 수도 있습니다. D4 및 C6은 Q3 및 Q4에 대한 하이 사이드 게이트 구동 전압을 생성하는 부트스트랩 회로의 일부입니다. 소프트웨어는 PWM 듀티 사이클을 추적하며 100% 또는 항상 켜짐을 허용하지 않습니다. PWM 듀티 사이클을 99.9%로 제한하여 차지 펌프가 계속 작동하도록 한다.

태양 전지판과 배터리 전압을 각각 측정하기 위한 두 개의 전압 분배기 회로(R1, R2 및 R7, R8)가 있습니다. 분배기의 출력은 전압 신호를 Arduino의 아날로그 핀 A0 및 A2에 공급합니다.

다이오드 D3는 변환기를 보다 효율적으로 만들어야 합니다. 다이오드 D1 및 D5는 태양 전지판 및 부하 측의 과전압 보호에 사용되는 TVS 다이오드입니다. MOSFET Q2는 부하를 제어하는 데 사용됩니다. 이 MOSFET의 드라이버는 2N2222 트랜지스터 Q1과 저항 R5 및 R6으로 구성됩니다.

전류 센서 ACS712는 태양 전지판의 전류를 감지하여 Arduino 아날로그 핀 A1에 공급합니다. 3개의 LED는 마이크로 컨트롤러의 디지털 핀에 연결되며 충전 상태를 표시하는 출력 인터페이스 역할을 합니다. 백라이트 스위치는 LCD 디스플레이의 백라이트를 제어하는 것입니다. 사용자가 스위치를 누르면 15초 동안 켜졌다가 다시 꺼집니다.


하드웨어 어셈블리

납땜하기 전에 전원 및 제어 신호에 대해 명확히 해야 합니다. 그들 사이에 섞이지 마십시오. 그렇지 않으면 모든 것을 튀길 것입니다.

회로도에 따라 모든 구성 요소를 조립하기 위해 Zero PCB 또는 Vero Board를 사용했습니다.

우리 프로젝트에서는 24V 태양 전지판을 사용했습니다. 태양 전지판은 거대하고 많은 양의 빛을 모을 수 있습니다. 태양 전지판은 조립된 회로의 입력 단자에 연결됩니다. 마찬가지로 12V, 7Ah 납산 배터리가 배터리 단자로 연결됩니다. 부하는 필요한 전압을 출력할 수 있습니다. 부하는 인버터 또는 일부 배터리로 작동되는 장치에 직접 연결할 수 있습니다.

Arduino Nano Board 및 회로의 다른 부분에 전원을 공급하기 위해 5V-9V DC 어댑터를 사용할 수 있습니다.

 


아두이노 소스 코드/프로그램

Arduino IDE를 사용하여 MPPT 태양열 충전 컨트롤러 프로젝트 코드를 작성할 수 있습니다. 이 코드에는 태양 전지판 전압, 전류, 전력, 배터리 전압, 충전기 상태, SOC, PWM 듀티 사이클, 부하 상태를 측정하는 모든 매개변수와 기능이 있습니다. 20×4 LCD 디스플레이는 이 매개변수의 실시간 상태를 표시합니다.

이 코드에는 컴파일을 위해 I2C LCD 라이브러리와 TimerOne 라이브러리가 필요합니다.

다음 코드를 복사하여 Arduino Nano Board에 업로드합니다.

#include "TimerOne.h"
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#define ENABLE_DATALOGGER 0
 
#define LOAD_ALGORITHM 0
 
#define SOL_AMPS_CHAN 1
#define SOL_VOLTS_CHAN 0
#define BAT_VOLTS_CHAN 2
#define AVG_NUM 8
#define SOL_AMPS_SCALE  0.026393581
#define SOL_VOLTS_SCALE 0.029296875
#define BAT_VOLTS_SCALE 0.029296875
#define PWM_PIN 6
#define PWM_ENABLE_PIN 5
#define PWM_FULL 1023
#define PWM_MAX 100
#define PWM_MIN 60
#define PWM_START 90
#define PWM_INC 1
 
#define TRUE 1
#define FALSE 0
#define ON TRUE
#define OFF FALSE
 
#define TURN_ON_MOSFETS digitalWrite(PWM_ENABLE_PIN, HIGH)
#define TURN_OFF_MOSFETS digitalWrite(PWM_ENABLE_PIN, LOW)
 
#define ONE_SECOND 50000
 
#define LOW_SOL_WATTS 5.00
#define MIN_SOL_WATTS 1.00
#define MIN_BAT_VOLTS 11.00
#define MAX_BAT_VOLTS 14.10
#define BATT_FLOAT 13.60
#define HIGH_BAT_VOLTS 13.00
#define LVD 11.5
#define OFF_NUM 9
#define LED_YELLOW 12
#define LED_GREEN 11
#define LED_RED 10
#define LOAD_PIN 4
#define BACK_LIGHT_PIN 3
byte battery_icons[6][8] =
{{
    0b01110,
    0b11011,
    0b10001,
    0b10001,
    0b10001,
    0b10001,
    0b10001,
    0b11111,
  },
  {
    0b01110,
    0b11011,
    0b10001,
    0b10001,
    0b10001,
    0b10001,
    0b11111,
    0b11111,
  },
  {
    0b01110,
    0b11011,
    0b10001,
    0b10001,
    0b10001,
    0b11111,
    0b11111,
    0b11111,
  },
  {
    0b01110,
    0b11011,
    0b10001,
    0b11111,
    0b11111,
    0b11111,
    0b11111,
    0b11111,
  },
  {
    0b01110,
    0b11011,
    0b11111,
    0b11111,
    0b11111,
    0b11111,
    0b11111,
    0b11111,
  },
  {
    0b01110,
    0b11111,
    0b11111,
    0b11111,
    0b11111,
    0b11111,
    0b11111,
    0b11111,
  }
};
#define SOLAR_ICON 6
byte solar_icon[8] =
{
  0b11111,
  0b10101,
  0b11111,
  0b10101,
  0b11111,
  0b10101,
  0b11111,
  0b00000
};
#define PWM_ICON 7
byte _PWM_icon[8] =
{
  0b11101,
  0b10101,
  0b10101,
  0b10101,
  0b10101,
  0b10101,
  0b10101,
  0b10111,
};
byte backslash_char[8] =
{
  0b10000,
  0b10000,
  0b01000,
  0b01000,
  0b00100,
  0b00100,
  0b00010,
  0b00010,
};
 
float sol_amps;
float sol_volts;
float bat_volts;
float sol_watts;
float old_sol_watts = 0;
unsigned int seconds = 0;
unsigned int prev_seconds = 0;
unsigned int interrupt_counter = 0;
unsigned long time = 0;
int delta = PWM_INC;
int pwm = 0;
int back_light_pin_State = 0;
boolean load_status = false;
 
enum charger_mode {off, on, bulk, bat_float} charger_state;
LiquidCrystal_I2C lcd(0x27, 20, 4);
 
 
void setup()
{
  pinMode(PWM_ENABLE_PIN, OUTPUT);
  TURN_OFF_MOSFETS;
  charger_state = off;
  lcd.init();
  lcd.backlight();
  for (int batchar = 0; batchar <   6; ++batchar)
  {
    lcd.createChar(batchar, battery_icons[batchar]);
  }
  lcd.createChar(PWM_ICON, _PWM_icon);
  lcd.createChar(SOLAR_ICON, solar_icon);
  lcd.createChar('\\', backslash_char);
  pinMode(LED_RED, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_YELLOW, OUTPUT);
  Timer1.initialize(20);
  Timer1.pwm(PWM_PIN, 0);
  Timer1.attachInterrupt(callback);
  Serial.begin(9600);
  pwm = PWM_START;
  pinMode(BACK_LIGHT_PIN, INPUT);
  pinMode(LOAD_PIN, OUTPUT);
  digitalWrite(LOAD_PIN, LOW);
  digitalWrite(BACK_LIGHT_PIN, LOW);
  lcd.setCursor(0, 0);
  lcd.print("SOL");
  lcd.setCursor(4, 0);
  lcd.write(SOLAR_ICON);
  lcd.setCursor(8, 0);
  lcd.print("BAT");
}
 
 
void loop()
{
  read_data();
  run_charger();
  print_data();
  load_control();
  led_output();
  lcd_display();
 
}
 
 
int read_adc(int channel)
{
  int sum = 0;
  int temp;
  int i;
 
  for (i = 0; i < AVG_NUM; i++)
  {
    temp = analogRead(channel);
    sum += temp;
    delayMicroseconds(50);
  }
  return (sum / AVG_NUM);
}
 
 
void read_data(void)
{
  sol_amps = (read_adc(SOL_AMPS_CHAN) * SOL_AMPS_SCALE - 13.51);
  sol_volts = read_adc(SOL_VOLTS_CHAN) * SOL_VOLTS_SCALE;
  bat_volts = read_adc(BAT_VOLTS_CHAN) * BAT_VOLTS_SCALE;
  sol_watts = sol_amps * sol_volts ;
}
 
 
void callback()
{
  if (interrupt_counter++ > ONE_SECOND)
  {
    interrupt_counter = 0;
    seconds++;
  }
}
 
 
void set_pwm_duty(void)
{
 
  if (pwm > PWM_MAX) {
    pwm = PWM_MAX;
  }
  else if (pwm < PWM_MIN) {
    pwm = PWM_MIN;
  }
  if (pwm < PWM_MAX) {
    Timer1.pwm(PWM_PIN, (PWM_FULL * (long)pwm / 100), 20);
  }
  else if (pwm == PWM_MAX) {
    Timer1.pwm(PWM_PIN, (PWM_FULL - 1), 20);
 
  }
}
 
 
void run_charger(void)
{
 
  static int off_count = OFF_NUM;
 
  switch (charger_state)
  {
    case on:
      if (sol_watts < MIN_SOL_WATTS)
      {
        charger_state = off;
        off_count = OFF_NUM;
        TURN_OFF_MOSFETS;
      }
      else if (bat_volts > (BATT_FLOAT - 0.1))
      {
        charger_state = bat_float;
      }
      else if (sol_watts < LOW_SOL_WATTS) {
        pwm = PWM_MAX;
        set_pwm_duty();
      }
      else {
        pwm = ((bat_volts * 10) / (sol_volts / 10)) + 5;
        charger_state = bulk;
      }
      break;
    case bulk:
      if (sol_watts < MIN_SOL_WATTS)
      {
        charger_state = off;
        off_count = OFF_NUM;
        TURN_OFF_MOSFETS;
      }
      else if (bat_volts > BATT_FLOAT)
      {
        charger_state = bat_float;
      }
      else if (sol_watts < LOW_SOL_WATTS)
      {
        charger_state = on;
        TURN_ON_MOSFETS;
      }
      else {
        if (old_sol_watts >= sol_watts)
        {
          delta = -delta;
        }
        pwm += delta;
        old_sol_watts = sol_watts;
        set_pwm_duty();
      }
      break;
    case bat_float:
 
      if (sol_watts < MIN_SOL_WATTS)
      {
        charger_state = off;
        off_count = OFF_NUM;
        TURN_OFF_MOSFETS;
        set_pwm_duty();
      }
      else if (bat_volts > BATT_FLOAT)
      {
        TURN_OFF_MOSFETS;
        pwm = PWM_MAX;
        set_pwm_duty();
      }
      else if (bat_volts < BATT_FLOAT)
      {
        pwm = PWM_MAX;
        set_pwm_duty();
        TURN_ON_MOSFETS;
        if (bat_volts < (BATT_FLOAT - 0.1))
        {
          charger_state = bulk;
        }
      }
      break;
    case off:
      TURN_OFF_MOSFETS;
      if (off_count > 0)
      {
        off_count--;
      }
      else if ((bat_volts > BATT_FLOAT) && (sol_volts > bat_volts)) {
        charger_state = bat_float;
        TURN_ON_MOSFETS;
      }
      else if ((bat_volts > MIN_BAT_VOLTS) && (bat_volts < BATT_FLOAT) && (sol_volts > bat_volts)) {
        charger_state = bulk;
        TURN_ON_MOSFETS;
      }
      break;
    default:
      TURN_OFF_MOSFETS;
      break;
  }
}
 
 
 
void load_control()
{
#if LOAD_ALGORITHM == 0
  load_on(sol_watts < MIN_SOL_WATTS && bat_volts > LVD);
#else
  load_on(sol_watts > MIN_SOL_WATTS && bat_volts > BATT_FLOAT);
#endif
}
 
void load_on(boolean new_status)
{
  if (load_status != new_status)
  {
    load_status = new_status;
    digitalWrite(LOAD_PIN, new_status ? HIGH : LOW);
  }
}
 
void print_data(void)
{
 
  Serial.print(seconds, DEC);
  Serial.print("      ");
 
  Serial.print("Charging = ");
  if (charger_state == on) Serial.print("on   ");
  else if (charger_state == off) Serial.print("off  ");
  else if (charger_state == bulk) Serial.print("bulk ");
  else if (charger_state == bat_float) Serial.print("float");
  Serial.print("      ");
 
  Serial.print("pwm = ");
  if (charger_state == off)
    Serial.print(0, DEC);
  else
    Serial.print(pwm, DEC);
  Serial.print("      ");
 
  Serial.print("Current (panel) = ");
  Serial.print(sol_amps);
  Serial.print("      ");
 
  Serial.print("Voltage (panel) = ");
  Serial.print(sol_volts);
  Serial.print("      ");
 
  Serial.print("Power (panel) = ");
  Serial.print(sol_volts);
  Serial.print("      ");
 
  Serial.print("Battery Voltage = ");
  Serial.print(bat_volts);
  Serial.print("      ");
 
  Serial.print("\n\r");
 
}
 
void light_led(char pin)
{
  static char last_lit;
  if (last_lit == pin)
    return;
  if (last_lit != 0)
    digitalWrite(last_lit, LOW);
  digitalWrite(pin, HIGH);
  last_lit = pin;
}
 
void led_output(void)
{
  static char last_lit;
  if (bat_volts > 14.1 )
    light_led(LED_YELLOW);
  else if (bat_volts > 11.9)
    light_led(LED_GREEN);
  else
    light_led(LED_RED);
}
 
void lcd_display()
{
  static bool current_backlight_state = -1;
  back_light_pin_State = digitalRead(BACK_LIGHT_PIN);
  if (current_backlight_state != back_light_pin_State) {
    current_backlight_state = back_light_pin_State;
    if (back_light_pin_State == HIGH)
      lcd.backlight();
    else
      lcd.noBacklight();
  }
 
  if (back_light_pin_State == HIGH)
  {
    time = millis();
  }
 
  lcd.setCursor(0, 1);
  lcd.print(sol_volts);
  lcd.print("V ");
  lcd.setCursor(0, 2);
  lcd.print(sol_amps);
  lcd.print("A");
  lcd.setCursor(0, 3);
  lcd.print(sol_watts);
  lcd.print("W ");
  lcd.setCursor(8, 1);
  lcd.print(bat_volts);
  lcd.setCursor(8, 2);
 
  if (charger_state == on)
    lcd.print("on   ");
  else if (charger_state == off)
    lcd.print("off  ");
  else if (charger_state == bulk)
    lcd.print("bulk ");
  else if (charger_state == bat_float)
  {
    lcd.print("     ");
    lcd.setCursor(8, 2);
    lcd.print("float");
  }
 
  int pct = 100.0 * (bat_volts - 11.3) / (12.7 - 11.3);
  if (pct < 0)
    pct = 0;
  else if (pct > 100)
    pct = 100;
 
  lcd.setCursor(12, 0);
  lcd.print((char)(pct * 5 / 100));
 
  lcd.setCursor(8, 3);
  pct = pct - (pct % 10);
  lcd.print(pct);
  lcd.print("%  ");
  lcd.setCursor(15, 0);
  lcd.print("PWM");
  lcd.setCursor(19, 0);
  lcd.write(PWM_ICON);
  lcd.setCursor(15, 1);
  lcd.print("   ");
  lcd.setCursor(15, 1);
  if ( charger_state == off)
    lcd.print(0);
  else
    lcd.print(pwm);
  lcd.print("% ");
  lcd.setCursor(15, 2);
  lcd.print("Load");
  lcd.setCursor(15, 3);
  if (load_status)
  {
    lcd.print("On  ");
  }
  else
  {
    lcd.print("Off ");
  }
  spinner();
  backLight_timer();
}
 
 
void backLight_timer()
{
  if ((millis() - time) <= 15000)
    lcd.backlight();
  else
    lcd.noBacklight();
}
 
void spinner(void)
{
  static int cspinner;
  static char spinner_chars[] = { '*', '*', '*', ' ', ' '};
  cspinner++;
  lcd.print(spinner_chars[cspinner % sizeof(spinner_chars)]);
}

Arduino MPPT 태양열 충전 컨트롤러 테스트

이제 Arduino MPPT 태양열 충전 컨트롤러 프로젝트의 최종 테스트를 수행하고 얼마나 효율적인지 알아보겠습니다.

처음에는 전류를 정확하게 측정할 수 있도록 ACS712 전류 센서를 교정해야 합니다. ACS712 센서는 전류 값을 읽고 관련 전압 값으로 변환합니다. 센서를 교정하려면 ACS712 교정 코드를 다운로드할 수 있습니다.

보정에 문제가 없는 경우 위의 기본 소스 코드를 업로드할 수 있습니다. 코드를 업로드하면 LCD에 다음 매개변수가 표시됩니다.

LCD는 현재 태양 전지판, 부하, 배터리를 연결하지 않았기 때문에 모든 전압을 0으로 표시합니다.

태양 전지판을 외부에 노출시키면 거의 20V의 전압을 제공합니다.

태양 전지판을 회로의 입력 단자에 연결하면 LCD는 첫 번째 열에 태양 전지판 전압, 전류 및 전력 값을 표시합니다.

배터리를 회로에 연결하면 LCD에 배터리 전압, 충전기 상태 및 SOC가 표시됩니다.

마지막으로 상태를 테스트하기 위해 모든 부하를 부하 터미널에 연결할 수 있습니다. LCD는 3번째 열에 PWM 듀티 사이클과 부하 상태를 표시합니다.

빨간색, 녹색 및 노란색 LED는 배터리 용량을 나타내는 데 사용됩니다.tage 수준.

  • 낮은 볼륨tage — > 빨간색 LED
  • 정상 전압 -> 녹색 LED
  • 완전히 충전됨 –> 노란색 LED

테스트하는 동안 태양 전지판의 전압이 처음에 증가하고 출력 전력이 증가하면 출력 전력이 감소하기 시작할 때까지 전압이 계속 증가하는 것을 알 수 있습니다. 출력 전력이 감소하기 시작하면 태양 전지판의 전압은 최대 전력에 도달할 때까지 감소합니다. 이 프로세스는 MPPT에 도달할 때까지 계속됩니다. 이 결과는 MPP 주변의 출력 전력의 진동입니다.

이것이 Arduino를 사용하여 자신만의 MPPT 태양열 충전 컨트롤러를 설계하고 개발하는 방법입니다. 우리는 더 나은 결과로 효율성을 높이기 위해 많은 수정을 수행하고 추가 기능으로 회로를 설계할 수 있습니다.

 

728x90
반응형

댓글