Laporan Akhir M4
MODUL 4
Automatic Solar Panel Cleaning System Pada PLTS Pasca Bencana Berbasis STM32BluePill
1. Pendahuluan [kembali]
Pemanfaatan Pembangkit Listrik Tenaga Surya (PLTS) sebagai sumber energi alternatif semakin
penting, terutama pada kondisi pascabencana ketika akses terhadap jaringan listrik konvensional
terbatas. Namun, performa panel surya sangat dipengaruhi oleh kebersihan permukaannya. Debu,
lumpur, abu vulkanik, dan berbagai kotoran lainnya yang sering muncul setelah bencana dapat
menghalangi penyerapan cahaya matahari sehingga menurunkan efisiensi dan daya keluaran panel
surya.
Untuk mengatasi permasalahan tersebut, dirancang sebuah Automatic Solar Panel Cleaning System
berbasis mikrokontroler STM32 Blue Pill yang mampu melakukan pembersihan panel secara
otomatis. Sistem memanfaatkan sensor BH1750 untuk mengukur intensitas cahaya matahari, sensor
INA219 untuk memantau tegangan keluaran panel surya, serta limit switch sebagai pendeteksi posisi
akhir gerakan wiper. Data dari sensor-sensor tersebut digunakan sebagai dasar pengambilan
keputusan dalam proses pembersihan panel.
Sistem ini dilengkapi dengan motor wiper sebagai mekanisme pembersih, pompa air mini DC untuk
membantu proses pencucian permukaan panel, serta LCD sebagai media monitoring kondisi sistem
secara real-time. Dengan adanya sistem pembersihan otomatis ini, diharapkan performa panel surya
dapat tetap optimal tanpa memerlukan pengawasan dan pembersihan manual secara terus-menerus,
sehingga sangat sesuai diterapkan pada PLTS pascabencana.
2. Tujuan [kembali]
1) Menerapkan konsep dan keterampilan yang diperoleh pada praktikum Mikroprosesor dan
Mikrokontroler dalam pengembangan sistem otomatis berbasis STM32 untuk menyelesaikan
permasalahan nyata pada pemeliharaan panel surya.
2) Mengintegrasikan sensor BH1750 dan INA219 untuk memantau intensitas cahaya matahari serta
tegangan keluaran panel surya sebagai indikator kondisi panel.
3) Mengotomatisasi proses pembersihan panel surya menggunakan motor wiper dan pompa air
berdasarkan hasil pembacaan sensor.
4) Mengimplementasikan limit switch sebagai sensor pembatas untuk menghentikan pergerakan
wiper pada posisi akhir pembersihan.
5) Menampilkan kondisi panel surya, status sistem, dan data hasil pembacaan sensor secara real-time
melalui LCD Display.
3. Alat dan Komponen [kembali]
4. Landasan Teori [kembali]
A. Pembangkit Listrik Tenaga Surya (PLTS)
Pembangkit Listrik Tenaga Surya (PLTS) merupakan sistem pembangkit energi listrik yang
memanfaatkan energi radiasi matahari sebagai sumber energi utama. PLTS bekerja dengan
mengubah energi cahaya matahari menjadi energi listrik menggunakan perangkat yang disebut
panel surya atau photovoltaic (PV). Energi listrik yang dihasilkan dapat digunakan secara
langsung untuk menyuplai beban listrik maupun disimpan terlebih dahulu pada baterai untuk
digunakan pada waktu tertentu.
PLTS menjadi salah satu sumber energi terbarukan yang banyak dikembangkan karena ramah
lingkungan, tidak menghasilkan emisi gas buang, dan memanfaatkan sumber energi yang tersedia
secara melimpah. Selain itu, PLTS sangat cocok digunakan pada daerah terpencil maupun wilayah
pascabencana yang mengalami gangguan pasokan listrik dari jaringan utama.
Kinerja PLTS dipengaruhi oleh beberapa faktor, seperti intensitas cahaya matahari, suhu
lingkungan, sudut kemiringan panel, serta kondisi kebersihan permukaan panel surya. Semakin
tinggi intensitas cahaya yang diterima panel, semakin besar energi listrik yang dapat dihasilkan.
Sebaliknya, adanya debu, lumpur, abu vulkanik, atau kotoran lain yang menutupi permukaan panel
dapat mengurangi jumlah cahaya yang diterima sel fotovoltaik sehingga menyebabkan penurunan
tegangan dan daya keluaran panel. Oleh karena itu, diperlukan sistem pemeliharaan yang mampu
menjaga kebersihan panel agar performanya tetap optimal.
B. Mikrokontroler STM32 Blue Pill
STM32 Blue Pill merupakan papan pengembangan berbasis mikrokontroler STM32F103C8T6
yang menggunakan arsitektur ARM Cortex-M3 32-bit. Mikrokontroler ini memiliki kecepatan
pemrosesan hingga 72 MHz, memori Flash sebesar 64 KB, SRAM sebesar 20 KB, serta berbagai
periferal pendukung seperti GPIO, ADC, PWM, USART, SPI, dan I²C.
STM32 Blue Pill banyak digunakan dalam sistem embedded karena memiliki performa yang
tinggi, konsumsi daya yang relatif rendah, serta kemampuan komunikasi yang lengkap. Selain itu,
STM32 dapat diprogram menggunakan bahasa C melalui perangkat lunak STM32CubeIDE.
Pada sistem Automatic Solar Panel Cleaning System, STM32 Blue Pill berfungsi sebagai pusat
pengendali yang bertugas membaca data dari sensor BH1750, sensor INA219, dan limit switch.
Data tersebut kemudian diolah untuk menentukan kondisi panel surya. Berdasarkan hasil
pengolahan data, STM32 akan mengendalikan motor wiper, pompa air, serta menampilkan
informasi kondisi sistem pada LCD.
C. Komunikasi I2C (Inter-integrated Circuit)
Inter-Integrated Circuit (I²C) merupakan protokol komunikasi serial sinkron yang dikembangkan
oleh Philips Semiconductor untuk memfasilitasi komunikasi antarperangkat elektronik
menggunakan dua jalur komunikasi. Jalur tersebut terdiri dari Serial Data (SDA) dan Serial Clock
(SCL).
Pada sistem I²C terdapat perangkat master dan slave. Master bertanggung jawab mengendalikan
jalannya komunikasi, sedangkan slave merespons perintah yang dikirim oleh master. Setiap
perangkat slave memiliki alamat unik sehingga beberapa perangkat dapat dihubungkan dalam satu
jalur komunikasi yang sama.
Keunggulan I²C terletak pada efisiensi penggunaan pin mikrokontroler karena hanya
membutuhkan dua jalur komunikasi meskipun digunakan oleh banyak perangkat. Selain itu, I²C
mendukung komunikasi dua arah sehingga memungkinkan pertukaran data yang fleksibel antara
mikrokontroler dan perangkat eksternal.
Dalam penelitian ini, komunikasi I²C digunakan untuk menghubungkan STM32 Blue Pill dengan
sensor BH1750, sensor INA219, dan LCD.
D. Sensor Intensitas Cahaya BH1750
BH1750 merupakan sensor digital yang digunakan untuk mengukur intensitas cahaya dalam
satuan lux. Sensor ini dilengkapi dengan fotodioda dan ADC internal sehingga mampu mengubah
intensitas cahaya menjadi data digital secara langsung.
BH1750 memiliki tingkat akurasi yang cukup baik serta mampu melakukan pengukuran pada
rentang intensitas cahaya yang luas. Sensor ini juga memiliki konsumsi daya yang rendah
sehingga cocok digunakan pada sistem monitoring berbasis mikrokontroler.
Pada sistem ini, BH1750 digunakan untuk mengukur intensitas cahaya matahari yang diterima
panel surya. Data intensitas cahaya tersebut digunakan sebagai salah satu parameter dalam
menentukan apakah penurunan tegangan panel disebabkan oleh kurangnya cahaya matahari atau
karena adanya kotoran pada permukaan panel.
E. Sensor Tegangan dan Arus INA219
INA219 merupakan sensor digital yang digunakan untuk mengukur tegangan, arus, dan daya
listrik. Sensor ini bekerja menggunakan resistor shunt yang berfungsi menghasilkan tegangan
jatuh kecil ketika arus mengalir melaluinya. Tegangan tersebut kemudian diukur menggunakan
penguat diferensial dan ADC internal.
Selain mengukur arus, INA219 juga mampu mengukur tegangan bus dan menghitung daya listrik
secara otomatis. Hasil pengukuran disimpan dalam register internal dan dapat dibaca oleh
mikrokontroler melalui komunikasi I²C.
Pada penelitian ini, INA219 digunakan untuk memantau tegangan keluaran panel surya. Nilai
tegangan yang diperoleh akan dibandingkan dengan intensitas cahaya yang dibaca oleh BH1750
untuk menentukan kondisi kebersihan panel surya.
F. Limit Switch
Limit switch merupakan sensor mekanik yang digunakan untuk mendeteksi posisi atau batas
gerakan suatu objek. Sensor ini bekerja melalui perubahan kondisi kontak listrik ketika
aktuatornya mendapat tekanan.
Dalam sistem pembersih panel surya otomatis, limit switch dipasang pada ujung lintasan wiper.
Ketika wiper mencapai posisi akhir, limit switch akan mengirimkan sinyal ke STM32 sehingga
motor dapat dihentikan secara otomatis.
G. Driver Motor L298
L298 merupakan driver motor tipe Dual H-Bridge yang digunakan untuk mengendalikan arah dan
kecepatan motor DC. Driver ini memungkinkan mikrokontroler mengendalikan motor yang
membutuhkan arus dan tegangan lebih besar daripada kemampuan keluaran mikrokontroler.
Dalam penelitian ini, L298 digunakan untuk mengendalikan motor wiper yang bergerak sepanjang
permukaan panel surya saat proses pembersihan berlangsung.
H. Pulse Width Modulation (PWM)
PWM merupakan teknik pengaturan daya listrik menggunakan sinyal digital dengan cara
mengubah lebar pulsa dalam satu periode tertentu. Parameter utama PWM adalah duty cycle yang
menunjukkan persentase waktu sinyal berada pada kondisi HIGH dalam satu periode.
Semakin besar duty cycle, semakin besar daya rata-rata yang diberikan kepada beban. Teknik
PWM banyak digunakan dalam pengendalian motor karena lebih efisien dibandingkan metode
pengaturan tegangan secara langsung.
Pada sistem ini, PWM digunakan untuk mengendalikan kecepatan motor wiper sehingga proses
pembersihan panel dapat berlangsung lebih stabil dan efisien.
I. LCD Display
Liquid Crystal Display (LCD) merupakan perangkat output yang digunakan untuk menampilkan
informasi dalam bentuk karakter, angka, maupun simbol. LCD bekerja dengan memanfaatkan sifat
kristal cair yang dapat mengatur intensitas cahaya ketika diberikan medan listrik. Berbeda dengan
OLED yang setiap pikselnya dapat memancarkan cahaya sendiri, LCD memerlukan sumber cahaya
tambahan berupa backlight agar karakter yang ditampilkan dapat terlihat oleh pengguna.
LCD LM016L merupakan salah satu jenis LCD karakter 16×2 yang mampu menampilkan 16
karakter pada setiap baris dan terdiri dari dua baris tampilan. Modul ini menggunakan pengendali
(controller) HD44780 yang telah menjadi standar pada sebagian besar LCD karakter. LCD
LM016L memiliki 16 pin yang terdiri dari pin catu daya, pin pengatur kontras, pin kontrol, serta
pin data. Komunikasi antara mikrokontroler dan LCD dapat dilakukan menggunakan mode 8-bit
maupun 4-bit. Pada mode 4-bit, jumlah pin yang digunakan lebih sedikit sehingga lebih
menghemat penggunaan pin mikrokontroler.
Prinsip kerja LCD LM016L dimulai ketika mikrokontroler mengirimkan data atau perintah ke LCD
melalui pin data dan pin kontrol. Data yang diterima akan diproses oleh pengendali HD44780 dan
ditampilkan dalam bentuk karakter pada layar LCD. Karakter yang ditampilkan tersusun dari
matriks titik (dot matrix) sehingga dapat membentuk huruf, angka, maupun simbol tertentu. Selain
menampilkan data, LCD juga dapat digunakan untuk menampilkan status operasi sistem secara
real-time sehingga memudahkan pengguna dalam melakukan pemantauan.
Pada sistem Automatic Solar Panel Cleaning System, LCD LM016L digunakan sebagai media
antarmuka pengguna (Human Machine Interface/HMI) untuk menampilkan informasi kondisi
sistem secara langsung. Informasi yang ditampilkan meliputi nilai intensitas cahaya yang dibaca
sensor BH1750, tegangan keluaran panel surya yang diukur oleh sensor INA219, status kondisi
panel surya, serta status kerja motor wiper dan pompa air. Dengan adanya LCD, pengguna dapat
memantau kondisi sistem secara real-time tanpa memerlukan perangkat tambahan seperti komputer
atau smartphone.
J. Sistem Pembersihan Panel Surya Otomatis
Sistem pembersihan panel surya otomatis merupakan sistem yang dirancang untuk menjaga
kebersihan panel surya tanpa intervensi pengguna. Sistem bekerja dengan memanfaatkan data dari
sensor BH1750 dan INA219 untuk menentukan kondisi panel surya.
Apabila intensitas cahaya yang diterima panel tinggi namun tegangan keluaran panel lebih rendah
dari nilai referensi, maka sistem mengidentifikasi adanya penurunan performa akibat kotoran pada
permukaan panel. Selanjutnya STM32 akan mengaktifkan pompa air untuk membasahi permukaan
panel dan menggerakkan motor wiper untuk melakukan pembersihan. Setelah wiper mencapai
ujung panel dan menekan limit switch, motor akan dihentikan sehingga proses pembersihan selesai.
Dengan mekanisme tersebut, panel surya dapat dipertahankan dalam kondisi bersih sehingga
efisiensi pembangkitan energi listrik tetap optimal.
5. Flowchart dan Listing Program [kembali]
A. Flowchart
#include "main.h"
/* ===================== HANDLE ===================== */
ADC_HandleTypeDef hadc1;
/* ===================== LCD LM016L PIN ===================== */
#define LCD_RS_PORT GPIOB
#define LCD_RS_PIN GPIO_PIN_10
#define LCD_E_PORT GPIOB
#define LCD_E_PIN GPIO_PIN_11
#define LCD_D4_PORT GPIOB
#define LCD_D4_PIN GPIO_PIN_12
#define LCD_D5_PORT GPIOB
#define LCD_D5_PIN GPIO_PIN_13
#define LCD_D6_PORT GPIOB
#define LCD_D6_PIN GPIO_PIN_14
#define LCD_D7_PORT GPIOB
#define LCD_D7_PIN GPIO_PIN_15
/* ===================== L298 PIN ===================== */
/*
OUT1-OUT2 = Motor Wiper
OUT3-OUT4 = Motor Pompa
*/
#define MOTOR1_IN1_PORT GPIOA
#define MOTOR1_IN1_PIN GPIO_PIN_3
#define MOTOR1_IN2_PORT GPIOA
#define MOTOR1_IN2_PIN GPIO_PIN_4
#define MOTOR1_EN_PORT GPIOA
#define MOTOR1_EN_PIN GPIO_PIN_5
#define MOTOR2_IN3_PORT GPIOA
#define MOTOR2_IN3_PIN GPIO_PIN_6
#define MOTOR2_IN4_PORT GPIOA
#define MOTOR2_IN4_PIN GPIO_PIN_7
#define MOTOR2_EN_PORT GPIOB
#define MOTOR2_EN_PIN GPIO_PIN_0
/* ===================== BUTTON PIN ===================== */
#define BUTTON_PORT GPIOA
#define BUTTON_PIN GPIO_PIN_2
/* ===================== THRESHOLD ===================== */
/*
LDR pull-up:
Banyak cahaya = nilai ADC kecil.
Jika LDR kamu terlalu sensitif, ubah nilai ini.
*/
#define LDR_BANYAK_CAHAYA_THRESHOLD 800
/*
Potensiometer:
60% dari ADC 12-bit = 0.6 x 4095 = 2457.
POT < 60% berarti nilai ADC PA1 kurang dari 2457.
*/
#define POT_60_PERCENT_THRESHOLD 2457
/* ===================== KONDISI STATUS LCD ===================== */
/*
4 kondisi status sistem:
STATUS_AMAN_BERSIH : Cahaya TERANG + Tegangan TINGGI
→ Panel bersih, tidak perlu pembersihan
→ Semua motor OFF
STATUS_AMAN_MENDUNG : Cahaya GELAP + Tegangan RENDAH
→ Kemungkinan malam/mendung
→ Semua motor OFF
STATUS_AMAN_TIDAK_PERLU : Cahaya GELAP + Tegangan TINGGI
→ Malam/gelap tapi panel masih bagus
→ Semua motor OFF
STATUS_KOTOR : Cahaya TERANG + Tegangan RENDAH
→ Panel kotor, butuh pembersihan
→ Motor Wiper ON (kecuali button ditekan)
→ Motor Pompa ON jika button ditekan
*/
typedef enum {
STATUS_AMAN_BERSIH = 0,
STATUS_AMAN_MENDUNG = 1,
STATUS_AMAN_TIDAK_PERLU = 2,
STATUS_KOTOR = 3
} StatusSistem;
/* ===================== VARIABEL ===================== */
uint16_t ldr_value = 0;
uint16_t pot_value = 0;
StatusSistem status_lama = 255; // nilai awal tidak valid, supaya LCD update pertama kali
/*
Flag pompa_aktif:
Di-set 1 saat button ditekan ketika panel kotor.
Di-reset 0 saat status sudah bukan kotor lagi.
Tujuannya agar motor pompa tetap menyala meski button sudah dilepas,
sampai kondisi panel benar-benar bersih.
*/
uint8_t pompa_aktif = 0;
/* ===================== PROTOTYPE ===================== */
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
uint16_t Read_ADC_Channel(uint32_t channel);
void LCD_Enable(void);
void LCD_Send4Bit(uint8_t data);
void LCD_SendCommand(uint8_t cmd);
void LCD_SendData(uint8_t data);
void LCD_Init(void);
void LCD_Clear(void);
void LCD_SetCursor(uint8_t row, uint8_t col);
void LCD_Print(const char *str);
void LCD_PrintLine(uint8_t row, const char *str);
void LCD_ShowStatus(StatusSistem status);
void Motor1_ON(void);
void Motor1_OFF(void);
void Motor2_ON(void);
void Motor2_OFF(void);
void All_Motor_OFF(void);
void Error_Handler(void);
/* ===================== MAIN ===================== */
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
HAL_ADCEx_Calibration_Start(&hadc1);
All_Motor_OFF();
LCD_Init();
LCD_Clear();
LCD_PrintLine(0, "SOLAR CLEANER");
LCD_PrintLine(1, "SYSTEM READY");
HAL_Delay(1500);
LCD_Clear();
while (1)
{
ldr_value = Read_ADC_Channel(ADC_CHANNEL_0); // PA0 = LDR
pot_value = Read_ADC_Channel(ADC_CHANNEL_1); // PA1 = POT
GPIO_PinState button_state = HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN);
/*
LDR pull-up:
Banyak cahaya = ADC kecil.
*/
uint8_t ldr_terang = (ldr_value < LDR_BANYAK_CAHAYA_THRESHOLD);
/*
Potensiometer:
Tegangan tinggi = ADC >= 2457 (>= 60%).
Tegangan rendah = ADC < 2457 (< 60%).
*/
uint8_t pot_tegangan_tinggi = (pot_value >= POT_60_PERCENT_THRESHOLD);
/*
Button pull-down eksternal:
Tidak ditekan = LOW (GPIO_PIN_RESET)
Ditekan = HIGH (GPIO_PIN_SET)
*/
uint8_t button_ditekan = (button_state == GPIO_PIN_SET);
/* ---- Tentukan status sistem dari kombinasi sensor ---- */
StatusSistem status_sekarang;
if (ldr_terang && pot_tegangan_tinggi)
{
/*
Cahaya TERANG + Tegangan TINGGI
→ Panel bersih, kondisi normal
*/
status_sekarang = STATUS_AMAN_BERSIH;
}
else if (!ldr_terang && !pot_tegangan_tinggi)
{
/*
Cahaya GELAP + Tegangan RENDAH
→ Kemungkinan malam atau mendung tebal
*/
status_sekarang = STATUS_AMAN_MENDUNG;
}
else if (!ldr_terang && pot_tegangan_tinggi)
{
/*
Cahaya GELAP + Tegangan TINGGI
→ Malam/gelap, panel masih dalam kondisi baik
*/
status_sekarang = STATUS_AMAN_TIDAK_PERLU;
}
else
{
/*
Cahaya TERANG + Tegangan RENDAH
→ Panel kotor, butuh pembersihan segera
*/
status_sekarang = STATUS_KOTOR;
}
/* ---- Update LCD hanya jika status berubah ---- */
LCD_ShowStatus(status_sekarang);
/* ---- Kontrol motor berdasarkan status ---- */
if (status_sekarang == STATUS_KOTOR)
{
if (button_ditekan)
{
/*
Button ditekan saat panel kotor:
Tandai flag pompa_aktif supaya pompa tetap menyala
meski button nanti dilepas.
*/
pompa_aktif = 1;
}
if (pompa_aktif)
{
/*
Flag pompa_aktif sudah di-set:
Motor Wiper (OUT1-OUT2) berhenti.
Motor Pompa (OUT3-OUT4) menyala dan tetap menyala.
*/
Motor1_OFF();
Motor2_ON();
}
else
{
/*
Panel kotor, button belum pernah ditekan:
Motor Wiper (OUT1-OUT2) menyala.
Motor Pompa (OUT3-OUT4) mati.
*/
Motor1_ON();
Motor2_OFF();
}
}
else
{
/*
Status sudah AMAN:
Reset flag pompa_aktif dan matikan semua motor.
Siklus pembersihan berikutnya dimulai dari awal.
*/
pompa_aktif = 0;
All_Motor_OFF();
}
HAL_Delay(100);
}
}
/* ===================== ADC FUNCTION ===================== */
uint16_t Read_ADC_Channel(uint32_t channel)
{
ADC_ChannelConfTypeDef sConfig = {0};
uint16_t adc_value = 0;
sConfig.Channel = channel;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)
{
adc_value = HAL_ADC_GetValue(&hadc1);
}
HAL_ADC_Stop(&hadc1);
return adc_value;
}
/* ===================== LCD FUNCTION ===================== */
void LCD_Enable(void)
{
HAL_GPIO_WritePin(LCD_E_PORT, LCD_E_PIN, GPIO_PIN_SET);
HAL_Delay(1);
HAL_GPIO_WritePin(LCD_E_PORT, LCD_E_PIN, GPIO_PIN_RESET);
HAL_Delay(1);
}
void LCD_Send4Bit(uint8_t data)
{
HAL_GPIO_WritePin(LCD_D4_PORT, LCD_D4_PIN, (data & 0x01) ? GPIO_PIN_SET :
GPIO_PIN_RESET);
HAL_GPIO_WritePin(LCD_D5_PORT, LCD_D5_PIN, (data & 0x02) ? GPIO_PIN_SET :
GPIO_PIN_RESET);
HAL_GPIO_WritePin(LCD_D6_PORT, LCD_D6_PIN, (data & 0x04) ? GPIO_PIN_SET :
GPIO_PIN_RESET);
HAL_GPIO_WritePin(LCD_D7_PORT, LCD_D7_PIN, (data & 0x08) ? GPIO_PIN_SET :
GPIO_PIN_RESET);
LCD_Enable();
}
void LCD_SendCommand(uint8_t cmd)
{
HAL_GPIO_WritePin(LCD_RS_PORT, LCD_RS_PIN, GPIO_PIN_RESET);
LCD_Send4Bit(cmd >> 4);
LCD_Send4Bit(cmd & 0x0F);
HAL_Delay(2);
}
void LCD_SendData(uint8_t data)
{
HAL_GPIO_WritePin(LCD_RS_PORT, LCD_RS_PIN, GPIO_PIN_SET);
LCD_Send4Bit(data >> 4);
LCD_Send4Bit(data & 0x0F);
HAL_Delay(1);
}
void LCD_Init(void)
{
HAL_Delay(50);
HAL_GPIO_WritePin(LCD_RS_PORT, LCD_RS_PIN, GPIO_PIN_RESET);
LCD_Send4Bit(0x03);
HAL_Delay(5);
LCD_Send4Bit(0x03);
HAL_Delay(5);
LCD_Send4Bit(0x03);
HAL_Delay(1);
LCD_Send4Bit(0x02);
HAL_Delay(1);
LCD_SendCommand(0x28); // 4-bit, 2 line
LCD_SendCommand(0x0C); // display ON, cursor OFF
LCD_SendCommand(0x06); // entry mode
LCD_SendCommand(0x01); // clear display
HAL_Delay(2);
}
void LCD_Clear(void)
{
LCD_SendCommand(0x01);
HAL_Delay(2);
}
void LCD_SetCursor(uint8_t row, uint8_t col)
{
if (row == 0)
{
LCD_SendCommand(0x80 + col);
}
else
{
LCD_SendCommand(0xC0 + col);
}
}
void LCD_Print(const char *str)
{
while (*str)
{
LCD_SendData((uint8_t)(*str));
str++;
}
}
void LCD_PrintLine(uint8_t row, const char *str)
{
char buffer[17];
uint8_t i;
for (i = 0; i < 16; i++)
{
if (str[i] != '\0')
{
buffer[i] = str[i];
}
else
{
buffer[i] = ' ';
}
}
buffer[16] = '\0';
LCD_SetCursor(row, 0);
LCD_Print(buffer);
}
void LCD_ShowStatus(StatusSistem status)
{
/*
LCD hanya di-update kalau status berubah,
supaya tulisan tidak flicker.
*/
if (status == status_lama)
{
return;
}
status_lama = status;
LCD_Clear();
switch (status)
{
case STATUS_AMAN_BERSIH:
/*
Cahaya TERANG + Tegangan TINGGI
Baris 1: "STATUS AMAN"
Baris 2: "PANEL BERSIH"
*/
LCD_PrintLine(0, "STATUS AMAN");
LCD_PrintLine(1, "PANEL BERSIH");
break;
case STATUS_AMAN_MENDUNG:
/*
Cahaya GELAP + Tegangan RENDAH
Baris 1: "STATUS AMAN"
Baris 2: "MENDUNG/MALAM"
*/
LCD_PrintLine(0, "STATUS AMAN");
LCD_PrintLine(1, "MENDUNG/MALAM");
break;
case STATUS_AMAN_TIDAK_PERLU:
/*
Cahaya GELAP + Tegangan TINGGI
Baris 1: "STATUS AMAN"
Baris 2: "TDK PERLU BERSIH"
*/
LCD_PrintLine(0, "STATUS AMAN");
LCD_PrintLine(1, "TDK PERLU BERSIH");
break;
case STATUS_KOTOR:
/*
Cahaya TERANG + Tegangan RENDAH
Baris 1: "PANEL KOTOR"
Baris 2: "MEMBERSIHKAN..."
*/
LCD_PrintLine(0, "PANEL KOTOR");
LCD_PrintLine(1, "MEMBERSIHKAN...");
break;
default:
LCD_PrintLine(0, "STATUS UNKNOWN");
LCD_PrintLine(1, " ");
break;
}
}
/* ===================== MOTOR FUNCTION ===================== */
void Motor1_ON(void)
{
/*
Motor Wiper (OUT1-OUT2) ON
*/
HAL_GPIO_WritePin(MOTOR1_EN_PORT, MOTOR1_EN_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR1_IN1_PORT, MOTOR1_IN1_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR1_IN2_PORT, MOTOR1_IN2_PIN, GPIO_PIN_RESET);
}
void Motor1_OFF(void)
{
/*
Motor Wiper (OUT1-OUT2) OFF
*/
HAL_GPIO_WritePin(MOTOR1_EN_PORT, MOTOR1_EN_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR1_IN1_PORT, MOTOR1_IN1_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR1_IN2_PORT, MOTOR1_IN2_PIN, GPIO_PIN_RESET);
}
void Motor2_ON(void)
{
/*
Motor Pompa (OUT3-OUT4) ON
*/
HAL_GPIO_WritePin(MOTOR2_EN_PORT, MOTOR2_EN_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR2_IN3_PORT, MOTOR2_IN3_PIN, GPIO_PIN_SET);
HAL_GPIO_WritePin(MOTOR2_IN4_PORT, MOTOR2_IN4_PIN, GPIO_PIN_RESET);
}
void Motor2_OFF(void)
{
/*
Motor Pompa (OUT3-OUT4) OFF
*/
HAL_GPIO_WritePin(MOTOR2_EN_PORT, MOTOR2_EN_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR2_IN3_PORT, MOTOR2_IN3_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(MOTOR2_IN4_PORT, MOTOR2_IN4_PIN, GPIO_PIN_RESET);
}
void All_Motor_OFF(void)
{
Motor1_OFF();
Motor2_OFF();
}
/* ===================== CLOCK CONFIG ===================== */
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK |
RCC_CLOCKTYPE_SYSCLK |
RCC_CLOCKTYPE_PCLK1 |
RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/* ===================== ADC INIT ===================== */
static void MX_ADC1_Init(void)
{
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
}
/* ===================== GPIO INIT ===================== */
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_ADC1_CLK_ENABLE();
HAL_GPIO_WritePin(GPIOA,
GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 |
GPIO_PIN_6 | GPIO_PIN_7,
GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,
GPIO_PIN_0 | GPIO_PIN_10 | GPIO_PIN_11 |
GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 |
GPIO_PIN_15,
GPIO_PIN_RESET);
/*
PA0 = LDR
PA1 = POT
*/
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*
PA2 = BUTTON pull-down eksternal
Tidak ditekan = LOW, Ditekan = HIGH
*/
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*
PA3 = IN1 (Motor Wiper)
PA4 = IN2 (Motor Wiper)
PA5 = ENA (Motor Wiper)
PA6 = IN3 (Motor Pompa)
PA7 = IN4 (Motor Pompa)
*/
GPIO_InitStruct.Pin = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5 |
GPIO_PIN_6 | GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*
PB0 = ENB (Motor Pompa)
PB10 = LCD RS
PB11 = LCD E
PB12 = LCD D4
PB13 = LCD D5
PB14 = LCD D6
PB15 = LCD D7
*/
GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_10 | GPIO_PIN_11 |
GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 |
GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/* ===================== ERROR HANDLER ===================== */
void Error_Handler(void)
{
__disable_irq();
while (1)
{
All_Motor_OFF();
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif
6. Rangkaian Simulasi dan Prinsip Kerja [kembali]
Prinsip Kerja:
Sistem Automatic Solar Panel Cleaning System bekerja dengan memanfaatkan mikrokontroler
STM32 Blue Pill sebagai pusat kendali yang menerima data dari sensor BH1750, sensor INA219, dan
limit switch. Setelah sistem dinyalakan, STM32 melakukan inisialisasi seluruh komponen, kemudian
secara berkala membaca nilai intensitas cahaya matahari dan tegangan keluaran panel surya. Hasil
pembacaan sensor ditampilkan secara real-time pada LCD LM016L sehingga pengguna dapat
memantau kondisi sistem secara langsung.
Sensor LDR digunakan sebagai simulasi untuk sensor BH1750 dikarenakan adanya keterbatasan
library pada software proteus. Sensor ini digunakan untuk mengukur intensitas cahaya yang diterima
panel surya. Ketika intensitas cahaya berada di bawah ambang batas yang telah ditentukan, sistem
menganggap kondisi lingkungan sedang mendung atau malam hari sehingga proses pembersihan
tidak dilakukan. Pada kondisi ini, sistem hanya melakukan pemantauan dan menampilkan informasi
pada LCD.
Apabila sensor BH1750 mendeteksi intensitas cahaya yang tinggi, STM32 akan membaca data
tegangan keluaran panel surya dari sensor INA219. Nilai tegangan tersebut kemudian dibandingkan
dengan nilai referensi yang telah ditentukan. Jika tegangan panel masih berada pada kondisi normal,
sistem menganggap panel surya dalam keadaan bersih sehingga tidak diperlukan proses pembersihan.
Sebaliknya, apabila intensitas cahaya tinggi tetapi tegangan keluaran panel berada di bawah nilai
referensi, sistem mengindikasikan bahwa terjadi penurunan performa panel akibat adanya debu atau
kotoran pada permukaannya. STM32 kemudian mengaktifkan pompa air untuk membasahi
permukaan panel dan menggerakkan motor wiper melalui driver motor L298N untuk melakukan
proses pembersihan secara otomatis.
Selama proses pembersihan berlangsung, wiper akan bergerak hingga mencapai ujung panel surya.
Pada posisi tersebut, limit switch akan tertekan dan mengirimkan sinyal ke mikrokontroler. Setelah
sinyal limit switch diterima, STM32 akan menghentikan motor wiper dan mematikan pompa air
sehingga proses pembersihan selesai. Status pembersihan dan kondisi panel kemudian ditampilkan
pada LCD LM016L, selanjutnya sistem kembali ke mode pemantauan untuk melakukan pembacaan
sensor secara berulang.
7. Video Simulasi [kembali]
8. Download File [kembali]

Komentar
Posting Komentar