MODUL 4

Automatic Solar Panel Cleaning System Pada PLTS Pasca Bencana Berbasis STM32BluePill



1. Pendahuluan [kembali]
    Pembangkit Listrik Tenaga Surya (PLTS) merupakan salah satu sumber energi terbarukan yang banyak digunakan karena ramah lingkungan dan memanfaatkan energi matahari yang tersedia secara melimpah. Dalam kondisi pasca bencana, PLTS sering digunakan sebagai sumber listrik darurat untuk mendukung berbagai kebutuhan seperti penerangan, komunikasi, dan pengoperasian peralatan penting. Namun, pemasangan panel surya di lingkungan terbuka menyebabkan permukaannya rentan terkena debu, lumpur, abu, dan berbagai kotoran lainnya.
    Penumpukan kotoran pada permukaan panel surya dapat menghalangi cahaya matahari yang masuk ke sel surya sehingga menurunkan efisiensi konversi energi. Akibatnya, tegangan keluaran panel menjadi lebih rendah dibandingkan kondisi normal meskipun intensitas cahaya matahari yang diterima lingkungan sekitar masih tinggi. Jika kondisi ini dibiarkan dalam waktu yang lama, maka kinerja sistem PLTS dapat menurun dan mengurangi ketersediaan energi listrik yang dihasilkan.
    Proses pembersihan panel surya umumnya masih dilakukan secara manual sehingga membutuhkan tenaga manusia dan pemeriksaan berkala. Pada kondisi pasca bencana, ketersediaan sumber daya manusia sering kali terbatas sehingga perawatan panel surya tidak dapat dilakukan secara optimal. Oleh karena itu, diperlukan suatu sistem yang mampu mendeteksi kondisi panel secara otomatis dan melakukan pembersihan tanpa campur tangan operator.
    Pada praktikum ini dirancang sebuah sistem Automatic Solar Panel Cleaning System berbasis mikrokontroler STM32 Blue Pill. Sistem memanfaatkan sensor BH1750 untuk mengukur intensitas cahaya, sensor INA219 untuk memantau tegangan keluaran panel surya, serta limit switch sebagai pendeteksi posisi akhir wiper pembersih. Data dari sensor digunakan sebagai dasar pengambilan keputusan untuk mengaktifkan motor wiper dan pompa air ketika panel terindikasi mengalami penurunan performa akibat kotoran.
    Melalui perancangan sistem ini diharapkan proses pemantauan dan pembersihan panel surya dapat dilakukan secara otomatis sehingga kinerja PLTS tetap terjaga. Selain itu, proyek ini juga menjadi implementasi penerapan sensor, aktuator, dan sistem kendali berbasis mikrokontroler dalam mendukung keandalan pembangkit listrik tenaga surya.


2. Tujuan [kembali]
    1. Merancang dan mengimplementasikan sistem pembersih panel surya otomatis berbasis
        mikrokontroler STM32 Blue Pill.
    2. Menerapkan sensor dan aktuator sebagai pendukung proses pemantauan serta pembersihan panel
        surya secara otomatis.
    3. Mengembangkan sistem yang mampu mendeteksi kondisi panel surya dan melakukan pembersihan
        berdasarkan parameter yang telah ditentukan.
    4. Menganalisis kinerja sistem pembersih panel surya otomatis dalam menjaga performa panel surya.


3. Alat dan Komponen [kembali]
    1. STM32 Blue Pill

    2. Sensor BH1750
        

    3. Sensor INA219

    4. Limit Switch Sensor

    5. LCD LM016L

    6. Driver Motor L298

    7. Pompa Air

    8. Motor DC

    9. Breadboard

    10. Jumper


4. Landasan Teori [kembali]
A. Pembangkit Listrik Tenaga Surya (PLTS)
     Pembangkit Listrik Tenaga Surya (PLTS) merupakan sistem pembangkit listrik yang mengubah
energi cahaya matahari menjadi energi listrik melalui proses fotovoltaik. Komponen utama pada PLTS adalah panel surya yang tersusun dari sel-sel fotovoltaik. Ketika cahaya matahari mengenai permukaan sel surya, energi foton akan membebaskan elektron sehingga menghasilkan arus listrik searah (DC).
     Kinerja panel surya sangat dipengaruhi oleh intensitas cahaya yang diterima permukaan panel. Selain
itu, faktor lingkungan seperti debu, lumpur, daun kering, dan abu dapat mengurangi jumlah cahaya yang mencapai sel surya. Akibatnya, efisiensi konversi energi menurun sehingga tegangan dan daya keluaran panel menjadi lebih rendah dibandingkan kondisi normal.
     Pada kondisi pasca bencana, panel surya umumnya ditempatkan di area terbuka dan rentan terhadap
penumpukan kotoran. Oleh karena itu diperlukan sistem pembersihan otomatis untuk menjaga performa panel agar tetap optimal.

B. Mikrokontroler STM32F103C8T6 Blue Pill
     STM32F103C8T6 atau yang lebih dikenal sebagai STM32 Blue Pill merupakan papan
mikrokontroler berbasis ARM Cortex-M3 yang diproduksi oleh STMicroelectronics. Mikrokontroler ini memiliki kecepatan clock hingga 72 MHz, memori Flash sebesar 64 KB, SRAM sebesar 20 KB, serta mendukung berbagai antarmuka komunikasi seperti UART, SPI, dan I2C.
     Pada sistem yang dirancang, STM32 Blue Pill berfungsi sebagai pusat kendali yang menerima data
dari sensor BH1750 dan INA219, kemudian memproses data tersebut untuk menentukan kondisi panel surya. Berdasarkan hasil pengolahan data, STM32 mengendalikan motor wiper, pompa air, dan LCD sebagai media informasi sistem.
     Keunggulan STM32 Blue Pill antara lain memiliki performa tinggi, konsumsi daya rendah, serta
jumlah pin I/O yang cukup banyak sehingga sesuai digunakan pada sistem otomasi berbasis sensor dan aktuator.

C. Sensor Intensitas Cahaya BH1750
     BH1750 merupakan sensor cahaya digital yang digunakan untuk mengukur intensitas cahaya dalam
satuan lux. Sensor ini menggunakan komunikasi I2C sehingga proses pembacaan data menjadi lebih sederhana dibandingkan sensor analog. BH1750 memiliki rentang pengukuran yang luas yaitu sekitar 1 hingga 65535 lux dengan resolusi pengukuran tinggi.
     Sensor BH1750 bekerja dengan mengubah energi cahaya yang diterima fotodioda menjadi data
digital 16-bit. Data tersebut kemudian dikirimkan ke mikrokontroler melalui komunikasi I2C. Karakteristik respons spektral sensor dirancang menyerupai sensitivitas mata manusia sehingga hasil pengukuran lebih representatif terhadap kondisi pencahayaan lingkungan.
     Dalam sistem ini, sensor BH1750 digunakan untuk menentukan apakah panel surya sedang
menerima cahaya matahari yang cukup. Nilai lux yang tinggi menunjukkan kondisi siang hari atau pencahayaan optimal, sedangkan nilai lux rendah menunjukkan kondisi mendung atau malam hari. Parameter utama BH1750:
  • Interface : I2C
  • Resolusi : 16 bit
  • Rentang pengukuran : 1 – 65535 lux
  • Tegangan kerja : 2,4 – 3,6 V (modul umumnya mendukung 3,3–5 V)
  • Sensitivitas puncak : sekitar 560 nm

D. Sensor Tegangan INA219
     INA219 merupakan sensor digital yang mampu mengukur tegangan, arus, dan daya listrik
menggunakan komunikasi I2C. Sensor ini dikembangkan oleh Texas Instruments dan memiliki ADC internal sehingga proses pengukuran dapat dilakukan dengan akurasi yang baik. INA219 mampu mengukur tegangan hingga 26 V dan arus hingga ±3,2 A tergantung konfigurasi resistor shunt yang digunakan.
     Prinsip kerja INA219 adalah mengukur beda tegangan pada resistor shunt untuk menghitung arus
yang mengalir, sekaligus mengukur tegangan bus pada sistem yang diamati. Data hasil pengukuran dikonversi menjadi data digital dan dikirimkan ke mikrokontroler melalui jalur I2C.
     Pada proyek ini, INA219 digunakan untuk memonitor tegangan keluaran panel surya. Nilai tegangan
panel digunakan sebagai indikator performa panel. Apabila intensitas cahaya tinggi namun tegangan panel rendah, maka sistem mengidentifikasi adanya kemungkinan penumpukan kotoran pada permukaan panel. 
Parameter utama INA219:
  • Interface : I2C
  • Tegangan pengukuran : 0 – 26 V
  • Resolusi ADC : 12 bit
  • Akurasi tinggi dengan teknologi zero-drift
  • Dapat mengukur tegangan, arus, dan daya

E. Limit Switch
    Limit switch merupakan sensor mekanis yang digunakan untuk mendeteksi posisi atau batas gerakan suatu mekanisme. Sensor ini bekerja berdasarkan kontak fisik yang akan berubah kondisi ketika tuas atau tombolnya ditekan.
     Pada sistem pembersih panel surya, limit switch digunakan untuk mendeteksi posisi ujung lintasan
wiper. Ketika wiper mencapai ujung panel, limit switch akan aktif dan mengirimkan sinyal ke STM32 sehingga motor dapat dihentikan secara otomatis.
     Penggunaan limit switch bertujuan untuk meningkatkan ketepatan posisi berhenti wiper sekaligus
mencegah kerusakan mekanis akibat motor yang terus bergerak.

F. Motor DC
    Motor DC merupakan aktuator yang mengubah energi listrik menjadi energi mekanik berupa gerakan putar. Pada sistem ini motor DC digunakan untuk menggerakkan mekanisme wiper yang bertugas menyapu permukaan panel surya.
     Motor dikendalikan melalui driver motor L298N yang berfungsi sebagai penguat arus dan pengatur
arah putaran motor. STM32 memberikan sinyal kendali kepada driver motor untuk menentukan kondisi motor hidup, mati, maupun arah gerak wiper.

G. Pompa Air DC
     Pompa air DC digunakan untuk menyemprotkan air ke permukaan panel surya sebelum proses
penyapuan dilakukan. Air berfungsi membantu melarutkan dan mengangkat debu atau kotoran yang menempel pada panel sehingga proses pembersihan menjadi lebih efektif.
     Pompa akan aktif bersamaan dengan motor wiper ketika sistem mendeteksi kondisi panel yang
terindikasi kotor.

H. LCD 16×2 Berbasis I2C
    LCD 16×2 merupakan perangkat display yang mampu menampilkan 16 karakter pada dua baris. Pada
proyek ini LCD dilengkapi modul I2C sehingga hanya memerlukan dua jalur komunikasi data yaitu SDA dan SCL.
    LCD digunakan sebagai media antarmuka antara sistem dan pengguna. Informasi yang ditampilkan meliputi nilai intensitas cahaya, tegangan panel surya, status panel, serta status proses pembersihan. Dengan adanya LCD, pengguna dapat memantau kondisi sistem secara real-time tanpa memerlukan perangkat tambahan.

I. Prinsip Deteksi Panel Kotor
     Prinsip utama sistem adalah membandingkan kondisi intensitas cahaya lingkungan dengan tegangan
keluaran panel surya. Ketika intensitas cahaya tinggi, seharusnya panel menghasilkan tegangan yang relatif tinggi. Namun apabila tegangan yang dihasilkan lebih rendah dari nilai yang telah ditentukan, maka terdapat indikasi bahwa permukaan panel tertutup kotoran sehingga proses konversi energi tidak berlangsung optimal. Berdasarkan prinsip tersebut, sistem menerapkan logika:
  1. Intensitas cahaya rendah dan tegangan rendah → kondisi malam atau mendung.
  2. Intensitas cahaya tinggi dan tegangan tinggi → panel dalam kondisi bersih.
  3. Intensitas cahaya tinggi dan tegangan rendah → panel terindikasi kotor dan perlu dibersihkan.
Metode ini memungkinkan sistem melakukan pembersihan hanya saat diperlukan sehingga penggunaan energi menjadi lebih efisien.


5. Flowchart dan Listing Program [kembali]
A. Flowchart

B. Listing Program
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Solar Cleaner System - Full Hardware Implementation
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "lcd_i2c.h" // Menggunakan library lcd_i2c.h milikmu
#include "ina219.h"
#include <stdio.h>

// Driver BH1750 Sederhana (Digital Lux Sensor via I2C)
#define BH1750_ADDRESS (0x23 << 1)
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef enum {
    STATUS_AMAN_BERSIH      = 0,
    STATUS_AMAN_MENDUNG     = 1,
    STATUS_AMAN_TIDAK_PERLU = 2,
    STATUS_KOTOR            = 3
} StatusSistem;

typedef enum {
    ARAH_MAJU   = 0,
    ARAH_MUNDUR = 1
} ArahWiper;
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define LUX_TERANG_THRESHOLD        1000   // Batas Lux untuk kondisi terang
#define VOLTAGE_TINGGI_THRESHOLD    4.5f  // Batas tegangan panel (Volt) dari INA219
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

TIM_HandleTypeDef htim1;

/* USER CODE BEGIN PV */
float lux_value = 0.0f;
float panel_voltage = 0.0f;

StatusSistem status_sekarang;
StatusSistem status_lama = 255;

// State untuk kontrol arah wiper saat proses cleaning (STATUS_KOTOR)
static ArahWiper arah_wiper = ARAH_MAJU;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
static void MX_TIM1_Init(void);
/* USER CODE BEGIN PFP */
void BH1750_Init(void);
float BH1750_ReadLux(void);
void LCD_ShowStatus(StatusSistem status);
void Control_Actuators(StatusSistem status, uint8_t limit_kanan_ditekan, uint8_t limit_kiri_ditekan);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void BH1750_Init(void)
{
    uint8_t opMode = 0x10; // Continuously H-Resolution Mode
    HAL_I2C_Master_Transmit(&hi2c1, BH1750_ADDRESS, &opMode, 1, 100);
}

float BH1750_ReadLux(void)
{
    uint8_t data[2];
    if (HAL_I2C_Master_Receive(&hi2c1, BH1750_ADDRESS, data, 2, 100) == HAL_OK)
    {
        uint16_t raw_lux = (data[0] << 8) | data[1];
        return (float)raw_lux / 1.2f;
    }
    return 0.0f;
}

void Motor_Forward(void)
{
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 800); // Wiper Jalan Maju
}

void Motor_Backward(void)
{
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 800); // Wiper Jalan Mundur
}

void Motor_Stop(void)
{
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 0);    // Wiper Berhenti
}

void Pompa_ON(void) {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, 999); // PWM
}
void Pompa_OFF(void)
{
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, 0);   // Pompa Air OFF
}

void All_Actuators_OFF(void)
{
    Motor_Stop();
    Pompa_OFF();
}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
  // Mengaktifkan kanal PWM pada Timer 1
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); // PWM Driver Wiper
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2); // PWM Driver Pompa

  All_Actuators_OFF();

  // Inisialisasi perangkat eksternal jalur I2C
  LCD_Init();
  BH1750_Init();
  INA219_Init(&hi2c1);

  // Tampilan Selamat Datang pada LCD
  LCD_Clear();
  LCD_Set_Cursor(0, 0);
  LCD_Send_String("STM32 READY");
  LCD_Set_Cursor(1, 0);
  LCD_Send_String("SOLAR CLEANER");
  HAL_Delay(3000);
  LCD_Clear();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
      // 1. Akuisisi Data Sensor Digital
      lux_value = BH1750_ReadLux();
      panel_voltage = INA219_ReadBusVoltage();

      // Membaca status 2 Limit Switch -> Menggunakan internal Pull-Up (Ditekan = LOW / RESET)
      uint8_t limit_kanan_ditekan = (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == GPIO_PIN_RESET); // Ujung kanan jalur wiper
      uint8_t limit_kiri_ditekan  = (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == GPIO_PIN_RESET); // Ujung kiri jalur wiper

      uint8_t cahaya_terang = (lux_value >= LUX_TERANG_THRESHOLD);
      uint8_t tegangan_tinggi = (panel_voltage >= VOLTAGE_TINGGI_THRESHOLD);

      // 2. Evaluasi Logika Sistem (State Machine)
      if (cahaya_terang && tegangan_tinggi)            status_sekarang = STATUS_AMAN_BERSIH;
      else if (!cahaya_terang && !tegangan_tinggi)     status_sekarang = STATUS_AMAN_MENDUNG;
      else if (!cahaya_terang && tegangan_tinggi)      status_sekarang = STATUS_AMAN_TIDAK_PERLU;
      else                                             status_sekarang = STATUS_KOTOR;

      // 3. Eksekusi Visual LCD dan Aktuator L298N
      LCD_ShowStatus(status_sekarang);
      Control_Actuators(status_sekarang, limit_kanan_ditekan, limit_kiri_ditekan);

      HAL_Delay(200);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 100000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief TIM1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM1_Init(void)
{

  /* USER CODE BEGIN TIM1_Init 0 */

  /* USER CODE END TIM1_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

  /* USER CODE BEGIN TIM1_Init 1 */

  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 71;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 999;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 0;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */

  /* USER CODE END TIM1_Init 2 */
  HAL_TIM_MspPostInit(&htim1);

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  /* USER CODE BEGIN MX_GPIO_Init_1 */

  /* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0|GPIO_PIN_1, GPIO_PIN_RESET);

  /*Configure GPIO pins : PA0 PA5 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /*Configure GPIO pins : PA1 PA2 PA3 PA4 */
  GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4;
  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);
  __HAL_RCC_GPIOB_CLK_ENABLE(); // PASTIKAN BARIS INI ADA!

  /*Configure GPIO pins : PB0 PB1 */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
  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);

  /* USER CODE BEGIN MX_GPIO_Init_2 */

  /* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */
void LCD_ShowStatus(StatusSistem status)
{
    // Cegah LCD flicker dengan mendeteksi perubahan state
    if (status == status_lama) return;
    status_lama = status;

    LCD_Clear();
    switch (status)
    {
        case STATUS_AMAN_BERSIH:
            LCD_Set_Cursor(0, 0);  LCD_Send_String("STATUS: AMAN");
            LCD_Set_Cursor(1, 0);  LCD_Send_String("PANEL BERSIH");
            break;
        case STATUS_AMAN_MENDUNG:
            LCD_Set_Cursor(0, 0);  LCD_Send_String("STATUS: AMAN");
            LCD_Set_Cursor(1, 0);  LCD_Send_String("MENDUNG/MALAM");
            break;
        case STATUS_AMAN_TIDAK_PERLU:
            LCD_Set_Cursor(0, 0);  LCD_Send_String("STATUS: AMAN");
            LCD_Set_Cursor(1, 0);  LCD_Send_String("TDK PERLU SAPU");
            break;
        case STATUS_KOTOR:
            LCD_Set_Cursor(0, 0);  LCD_Send_String("PANEL KOTOR!");
            LCD_Set_Cursor(1, 0);  LCD_Send_String("CLEANING MODE");
            break;
    }
}

void Control_Actuators(StatusSistem status, uint8_t limit_kanan_ditekan, uint8_t limit_kiri_ditekan)
{
    if (status == STATUS_KOTOR)
    {
        // Arah wiper ditentukan langsung oleh posisi fisik (limit switch),
        // bukan toggle, supaya selalu konsisten dengan ujung jalur yang sebenarnya.
        if (limit_kanan_ditekan)
        {
            arah_wiper = ARAH_MUNDUR; // sudah sampai ujung kanan (PA0) -> balik mundur
        }
        else if (limit_kiri_ditekan)
        {
            arah_wiper = ARAH_MAJU;   // sudah sampai ujung kiri (PA5) -> balik maju
        }

        // Gerakkan wiper sesuai arah saat ini
        if (arah_wiper == ARAH_MAJU)
        {
            Motor_Forward();
        }
        else
        {
            Motor_Backward();
        }

        // Pompa selalu menyala bersamaan dengan wiper selama panel masih kotor
        Pompa_ON();
    }
    else
    {
        All_Actuators_OFF();
    }
}
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */


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. Video Demo [kembali]


9. Kesimpulan dan Saran [kembali]
A. Kesimpulan
      Berdasarkan hasil perancangan dan implementasi yang telah dilakukan, sistem Automatic Solar
Panel Cleaning System Pada PLTS Pasca Bencana Berbasis STM32 Blue Pill berhasil direalisasikan dan berfungsi sesuai dengan tujuan yang telah ditetapkan. Sistem mampu melakukan pemantauan kondisi panel surya menggunakan sensor BH1750 untuk mengukur intensitas cahaya dan sensor INA219 untuk mengukur tegangan keluaran panel surya.
     Logika deteksi yang diterapkan berhasil membedakan beberapa kondisi panel berdasarkan kombinasi
nilai intensitas cahaya dan tegangan panel, yaitu kondisi panel bersih, kondisi mendung atau malam hari, kondisi tidak memerlukan pembersihan, serta kondisi panel kotor. Ketika terdeteksi kondisi panel kotor, sistem secara otomatis mengaktifkan pompa air dan motor wiper untuk melakukan proses pembersihan.
     Penggunaan limit switch sebagai sensor batas gerakan wiper mampu mengontrol arah pergerakan
wiper sehingga proses pembersihan dapat berlangsung secara otomatis dan aman. Selain itu, LCD 16×2 berhasil menampilkan status sistem sebagai media monitoring bagi pengguna.
     Secara keseluruhan, sistem yang dirancang mampu menerapkan konsep otomasi berbasis
mikrokontroler untuk membantu menjaga kebersihan panel surya dan mendukung peningkatan keandalan operasional PLTS.

B. Saran
    1. Menambahkan fitur pencatatan data (data logging) untuk menyimpan riwayat intensitas cahaya,
        tegangan panel, dan aktivitas pembersihan.
    2. Menggunakan mekanisme penggerak yang lebih presisi untuk meningkatkan efektivitas dan
        keandalan sistem pembersihan.
    3. Melakukan pengujian pada panel surya dengan ukuran yang lebih besar untuk mengetahui
        performa sistem pada kondisi operasional yang sebenarnya.


10. Download File [kembali]
  • Download rangkaian simulasi project disini
  • Download listing program project disini
  • Download datasheet STM32F103C8 disini
  • Download datasheet sensor BH1750 disini
  • Download datasheet sensor INA219 disini


Komentar

Postingan populer dari blog ini