Prinsip kerja rangkaian Wokwi yang menggunakan sensor PIR, sensor LDR, dan mikrokontroler STM32 adalah sebagai sistem lampu otomatis yang bekerja berdasarkan kondisi lingkungan dan adanya gerakan. Pada saat sistem dinyalakan, mikrokontroler akan melakukan inisialisasi GPIO dan ADC, kemudian LED berada dalam kondisi mati sebagai kondisi awal. Selanjutnya, sistem secara terus-menerus membaca nilai dari sensor LDR untuk mengetahui intensitas cahaya dan sensor PIR untuk mendeteksi adanya gerakan. Sensor LDR akan menentukan apakah lingkungan berada dalam kondisi gelap atau terang berdasarkan nilai threshold yang telah ditentukan, sedangkan sensor PIR akan memberikan sinyal HIGH jika terdeteksi gerakan.
Mikrokontroler kemudian memproses kedua input tersebut dengan logika tertentu, yaitu jika kondisi lingkungan terdeteksi gelap (nilai LDR melebihi batas threshold) dan sensor PIR mendeteksi adanya gerakan, maka LED akan menyala sangat terang sebagai bentuk respon sistem. Pada saat LED menyala, mikrokontroler juga mengaktifkan timer internal untuk menghitung durasi waktu penyalaan. LED akan tetap menyala selama 5 detik, kemudian setelah waktu tersebut tercapai, LED akan dimatikan secara otomatis meskipun kondisi masih gelap atau masih terdapat gerakan. Setelah LED mati, sistem akan kembali ke kondisi monitoring dan terus mengulangi proses pembacaan sensor. Dengan demikian, rangkaian ini mampu bekerja sebagai lampu otomatis yang efisien karena hanya menyala saat kondisi gelap dan terdapat aktivitas di sekitarnya, serta mati secara otomatis setelah waktu tertentu.
#include "main.h"
#include <stdio.h>
/* Handle */
ADC_HandleTypeDef hadc1;
/* Variabel */
uint16_t ldrValue = 0;
uint8_t pirState = 0;
uint32_t lastMotionTime = 0;
uint8_t ledActive = 0;
/* Threshold LDR */
#define LDR_GELAP_THRESHOLD 1000 // Bisa diturunkan jika terlalu sensitif
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
printf("=== Sistem Lampu Jalan - Kondisi 6 ===\r\n\r\n");
LED_Off();
while (1)
{
/* Baca LDR (ADC) */
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
ldrValue = HAL_ADC_GetValue(&hadc1);
/* Baca PIR */
pirState = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_1);
/* === LOGIKA UTAMA === */
if (ledActive == 0 && ldrValue > LDR_GELAP_THRESHOLD && pirState == GPIO_PIN_SET)
{
printf(">>> Gelap + ada gerakan → LED ON 5 detik\r\n");
LED_On();
lastMotionTime = HAL_GetTick();
ledActive = 1;
}
/* Matikan LED setelah 5 detik */
if (ledActive == 1 && (HAL_GetTick() - lastMotionTime) >= 5000)
{
LED_Off();
ledActive = 0;
printf("LED mati setelah 5 detik\r\n");
}
/* Monitoring status */
static uint32_t lastPrint = 0;
if (HAL_GetTick() - lastPrint > 800)
{
printf("LDR: %4d | PIR: %d | LED: %s\r\n",
ldrValue,
pirState,
ledActive ? "NYALA" : "MATI");
lastPrint = HAL_GetTick();
}
HAL_Delay(100);
}
}
/* ================= LED CONTROL ================= */
void LED_On(void)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
}
void LED_Off(void)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);
}
/* ================= SYSTEM CONFIG ================= */
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK |
RCC_CLOCKTYPE_SYSCLK |
RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
}
/* ================= GPIO ================= */
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/* LED PA6 */
GPIO_InitStruct.Pin = GPIO_PIN_6;
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);
/* PIR PA1 */
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Push Button PB1 (Interrupt) */
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
HAL_NVIC_SetPriority(EXTI0_1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
}
/* ================= ADC ================= */
void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
HAL_ADC_Init(&hadc1);
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_79CYCLES_5;
HAL_ADC_ConfigChannel(&hadc1, &sConfig);
}
/* ================= INTERRUPT ================= */
void HAL_GPIO_EXTICallback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_1)
{
printf(">>> Tombol PB1 ditekan!\r\n");
}
}
/* ================= ERROR ================= */
void Error_Handler(void)
{
while (1) {}
}
Komentar
Posting Komentar