Laporan Project M4




1. Prosedur [Kembali]

  1. Persiapan Peralatan dan Komponen
    Semua komponen disiapkan sesuai dengan kebutuhan sistem. Komponen meliputi mikrokontroler STM32F103C8T6, sensor suhu LM35, flame sensor, sensor PIR HC-SR501, LCD 16x2, LED merah dan hijau, buzzer, resistor, switch, breadboard, adaptor 5V, serta kabel jumper sebagai penghubung antar komponen.

  2. Penyediaan Sumber Tegangan
    Adaptor 5V dihubungkan ke breadboard sebagai sumber daya utama. Jalur tegangan (VCC) dan ground (GND) kemudian didistribusikan ke seluruh rangkaian untuk mendukung kerja mikrokontroler, sensor, dan perangkat output.

  3. Perakitan Mikrokontroler
    Mikrokontroler STM32F103C8T6 dipasang pada rangkaian dan dihubungkan dengan sumber tegangan serta jalur input-output. Pin ADC digunakan untuk membaca sensor analog, sedangkan pin GPIO digunakan untuk membaca sensor digital dan mengontrol perangkat output.

  4. Perakitan Sensor Suhu LM35
    Sensor LM35 dihubungkan ke pin ADC pada mikrokontroler. Sensor ini digunakan untuk mendeteksi perubahan suhu lingkungan. Output berupa tegangan analog akan dikonversi menjadi data digital oleh ADC untuk dianalisis oleh sistem.

  5. Perakitan Flame Sensor
    Flame sensor dihubungkan ke pin input digital pada mikrokontroler. Sensor ini berfungsi untuk mendeteksi keberadaan api secara langsung dengan memberikan sinyal logika HIGH atau LOW sesuai kondisi yang terdeteksi.

  6. Perakitan Sensor PIR
    Sensor PIR HC-SR501 dipasang dan dihubungkan ke pin input digital mikrokontroler. Sensor ini digunakan untuk mendeteksi keberadaan atau pergerakan manusia di area pemantauan.

  7. Integrasi Perangkat Output
    LED hijau dan LED merah dihubungkan ke pin output mikrokontroler sebagai indikator kondisi sistem. Buzzer dipasang sebagai alarm peringatan. LCD 16x2 dihubungkan untuk menampilkan informasi kondisi sistem secara real-time.

  8. Pemrograman Mikrokontroler
    Program ditulis dan diunggah ke mikrokontroler STM32 untuk mengolah data dari sensor. Logika program dirancang untuk menentukan kondisi aman, suhu tinggi, atau kebakaran berdasarkan data yang diterima dari sensor.

  9. Pengujian Sistem
    Sistem diuji dengan mensimulasikan kondisi lingkungan. Sensor suhu diuji dengan meningkatkan suhu, flame sensor diuji dengan sumber api, dan sensor PIR diuji dengan pergerakan manusia. Respons LED, buzzer, dan tampilan LCD diamati untuk memastikan sistem bekerja sesuai desain.

  10. Verifikasi dan Kalibrasi
    Dilakukan pemeriksaan ulang terhadap seluruh rangkaian dan program. Nilai ambang suhu serta sensitivitas sensor disesuaikan agar sistem dapat mendeteksi kondisi secara akurat dan memberikan peringatan yang tepat.

2. Alat dan Komponen[Kembali]

    Hardware

  1. Adaptor 5V


Sebagai sumber tegangan utama sebesar 5V untuk mensuplai seluruh rangkaian sistem.
  1. Kabel Jumper

Kabel jumper berfungsi untuk menghubungkan antar komponen elektronik pada breadboard.
  1. Breadboard

Digunakan sebagai media perakitan rangkaian elektronik tanpa perlu proses penyolderan.

  1. STM32F103C8T6 Microcontroller



Berfungsi sebagai pusat kendali sistem yang mengolah seluruh data dari sensor dan mengatur keluaran ke perangkat indikator.

  1. Sensor Suhu LM35


Digunakan untuk mendeteksi perubahan suhu lingkungan. Sensor ini menghasilkan sinyal analog yang akan dibaca oleh mikrokontroler melalui ADC.
  1. Flame Sensor

Berfungsi untuk mendeteksi keberadaan api secara langsung dengan memberikan sinyal digital sebagai input ke mikrokontroler.
  1. Sensor PIR HC-SR501

Digunakan untuk mendeteksi keberadaan atau pergerakan manusia di area pemantauan.
  1. LCD 16x2 I2C

Berfungsi untuk menampilkan informasi kondisi sistem secara real-time, seperti kondisi aman, suhu tinggi, atau kebakaran terdeteksi.
  1. LED


LED hijau digunakan sebagai indikator kondisi aman, sedangkan LED merah digunakan sebagai indikator kondisi bahaya atau peringatan kebakaran.
  1. Buzzer

Berfungsi sebagai alarm suara yang akan aktif ketika sistem mendeteksi adanya kebakaran.
  1. Resistor

Digunakan untuk membatasi arus listrik agar tidak merusak komponen seperti LED dan mikrokontroler.
  1. Switch

Berfungsi sebagai saklar untuk menghidupkan atau mematikan sistem.

3. Rangkaian Simulasi dan Prinsip Kerja[Kembali]

Rangkaian Simulasi

Prinsip Kerja

Sistem Smart Fire Early Warning System bekerja berdasarkan pendeteksian kondisi lingkungan yang berpotensi menyebabkan kebakaran, yaitu kenaikan suhu, keberadaan api, dan keberadaan manusia. Tiga jenis sensor digunakan sebagai input utama. Sensor suhu LM35 berfungsi mendeteksi perubahan suhu dalam bentuk tegangan analog. Flame sensor mendeteksi keberadaan api melalui radiasi inframerah dan menghasilkan sinyal digital. Sensor PIR mendeteksi pergerakan manusia berdasarkan perubahan radiasi panas tubuh. Seluruh sinyal dari sensor tersebut dikirim ke mikrokontroler STM32F103C8T6 untuk diolah menjadi keputusan sistem.

Pada kondisi normal, suhu lingkungan berada di bawah batas ambang dan tidak terdeteksi adanya api. Sensor LM35 menghasilkan tegangan rendah, flame sensor tidak aktif (LOW), dan sensor PIR hanya memberikan informasi keberadaan manusia tanpa memicu alarm. Mikrokontroler mengolah kondisi ini sebagai keadaan aman. LED hijau menyala sebagai indikator aman, buzzer dalam keadaan mati, dan LCD menampilkan status “SYSTEM SAFE”.

Kondisi suhu tinggi terjadi ketika sensor LM35 mendeteksi kenaikan suhu melebihi nilai ambang yang telah ditentukan. Tegangan output sensor meningkat dan dibaca oleh ADC pada mikrokontroler. Sistem menginterpretasikan kondisi ini sebagai potensi awal kebakaran. LED merah mulai menyala sebagai peringatan, buzzer tetap tidak aktif, dan LCD menampilkan pesan “HIGH TEMP” untuk memberikan informasi kepada pengguna.

Kondisi kebakaran terdeteksi terjadi ketika flame sensor mendeteksi adanya api. Sensor menghasilkan sinyal digital aktif (HIGH) yang langsung diproses oleh mikrokontroler. Dalam kondisi ini, sistem masuk ke status bahaya. LED merah menyala, buzzer aktif menghasilkan suara alarm, dan LCD menampilkan “FIRE DETECTED” sebagai peringatan utama.

Sensor PIR bekerja sebagai pendukung informasi dengan mendeteksi keberadaan atau pergerakan manusia di area pemantauan. Ketika manusia terdeteksi, mikrokontroler menampilkan status “HUMAN DETECTED” pada LCD. Namun, sensor ini tidak mengaktifkan buzzer karena tidak berkaitan langsung dengan kondisi kebakaran. Informasi ini penting untuk mengetahui apakah terdapat penghuni saat kondisi darurat terjadi.

Secara keseluruhan, sistem bekerja secara otomatis dengan mengubah fenomena fisik berupa suhu, cahaya api, dan radiasi panas manusia menjadi sinyal listrik. Mikrokontroler STM32 mengolah sinyal tersebut menggunakan logika pemrograman untuk menentukan kondisi sistem. LED berfungsi sebagai indikator visual, buzzer sebagai peringatan suara, dan LCD sebagai media informasi. Sistem ini mampu memberikan peringatan dini secara cepat dan akurat sehingga dapat membantu mengurangi risiko kebakaran pada area permukiman padat.

4. Flowchart dan Listing Program[Kembali]

Flowchart

Listing Program

/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file main.c * @brief Smart Fire Early Warning System * STM32F103C8T6 | HSE 8MHz + PLL = 72MHz | HAL * * PIN MAPPING: * INPUT * PA0 LM35 Sensor Suhu (ADC1_IN0, Analog) * PA1 Flame Sensor (GPIO Input, PULLDOWN, logic 1=api 0=tidak ada) * PA2 PIR HC-SR501 (GPIO Input, PULLDOWN, logic 1=manusia 0=tidak ada) * PA3 Push Button Reset (GPIO Input, PULLUP, logic 0=ditekan 1=tidak) * * OUTPUT * PB5 Buzzer DC (GPIO Output, HIGH=bunyi) * PB1 LED Hijau (GPIO Output, HIGH=nyala) * PB10 LED Merah (GPIO Output, HIGH=nyala) * * LCD 16x2 I2C (PCF8574 backpack) * PB6 SCL | PB7 SDA * Alamat default 0x27 (ubah ke 0x3F jika perlu) * * LOGIKA SISTEM: * Prioritas 1 — Flame=1 : LED Merah ON, Buzzer ON, "FIRE DETECTED" * Prioritas 2 — Suhu >= 40 C : LED Merah ON, Buzzer OFF, "HIGH TEMP:XX.XC" * Default — Aman : LED Hijau ON, Buzzer OFF, "SYSTEM SAFE" * Baris 2 LCD selalu tampilkan status PIR / suhu * * PUSH BUTTON RESET — TOGGLE LATCH (PA3): * - Tekan 1x : TERKUNCI kondisi aman + LCD tampilkan "RESET MODE" * - Tekan 1x lagi : kembali baca sensor asli * * PENGGABUNGAN: * [Doc1] Clock: HSE 8MHz + PLL x9 = 72MHz (lebih stabil untuk real-time) * [Doc1] ADC ContinuousConvMode = ENABLE * [Doc1] Pin naming CubeMX (LED_GREEN_Pin, LED_RED_Pin, BUZZER_Pin, dst.) * [Doc2] Seluruh logika sistem, LCD I2C driver, sensor, reset mode * [Doc2] HAL_ADCEx_Calibration_Start untuk akurasi ADC * [Doc2] DWT microsecond delay * [Doc2] Error_Handler dengan blink LED Merah ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include <string.h> /* USER CODE BEGIN Includes */ /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define TEMP_THRESHOLD_C 40 /* Batas suhu bahaya (derajat Celcius) */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* ============================================================ * LCD I2C — PCF8574 backpack * Alamat 7-bit: 0x27 (A2=A1=A0=1) atau 0x3F (PCF8574A) * HAL memakai 8-bit address (7-bit << 1) * * Bit mapping PCF8574 -> HD44780: * P7 P6 P5 P4 | P3 P2 P1 P0 * D7 D6 D5 D4 | BL EN RW RS * ============================================================ */ #define LCD_I2C_ADDR (0x27 << 1) #define LCD_BL_BIT (1 << 3) /* Backlight ON */ #define LCD_EN_BIT (1 << 2) /* Enable pulse */ #define LCD_RW_BIT (1 << 1) /* RW — selalu 0 (write) */ #define LCD_RS_BIT (1 << 0) /* RS: 0=command, 1=data */ /* Private variables ---------------------------------------------------------*/ ADC_HandleTypeDef hadc1; I2C_HandleTypeDef hi2c1; /* USER CODE BEGIN PV */ /* Flag toggle latch push button 0 = mode normal (baca sensor asli) 1 = mode reset (paksa kondisi aman, tampil RESET MODE) */ static volatile uint8_t g_reset_active = 0; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_ADC1_Init(void); static void MX_I2C1_Init(void); /* USER CODE BEGIN PFP */ /* DWT delay */ static void DWT_Init(void); void delay_us(uint32_t us); void delay_ms(uint32_t ms); /* LCD internal */ static void LCD_I2C_Write(uint8_t data); static void LCD_PulseEnable(uint8_t data); void LCD_SendNibble(uint8_t nibble, uint8_t rs); void LCD_SendByte(uint8_t byte, uint8_t rs); void LCD_Command(uint8_t cmd); void LCD_Char(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); static void LCD_PrintTemp(int temp_x10); /* Sensor & aktuator */ uint16_t ADC_Read(void); int Read_Temperature_x10(void); uint8_t Read_Flame(void); uint8_t Read_PIR(void); uint8_t Read_Button(void); void Set_LED_Green(uint8_t state); void Set_LED_Red(uint8_t state); void Set_Buzzer(uint8_t state); void Update_System(int temp_x10, uint8_t flame, uint8_t pir); static void Show_Reset_Mode(void); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* ============================================================ * DWT — delay microsecond * ============================================================ */ static void DWT_Init(void) { CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; } /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration -------------------------------------------------------*/ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ SystemCoreClockUpdate(); DWT_Init(); /* USER CODE END SysInit */ MX_GPIO_Init(); MX_ADC1_Init(); MX_I2C1_Init(); /* USER CODE BEGIN 2 */ /* Inisialisasi LCD & splash screen */ LCD_Init(); LCD_Clear(); LCD_SetCursor(0, 0); LCD_Print(" FIRE EARLY SYS "); LCD_SetCursor(1, 0); LCD_Print(" INITIALIZING "); delay_ms(2000); LCD_Clear(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ int temp_x10; uint8_t flame, pir; while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ /* ------------------------------------------------------------ * CEK PUSH BUTTON RESET — TOGGLE LATCH dengan debounce * ------------------------------------------------------------ */ if (Read_Button()) { delay_ms(20); /* debounce tekan */ if (Read_Button()) /* konfirmasi masih ditekan */ { g_reset_active ^= 1; /* toggle flag */ if (g_reset_active) Show_Reset_Mode(); /* langsung tampil reset mode */ while (Read_Button()); /* tunggu tombol dilepas */ delay_ms(20); /* debounce lepas */ } } /* ------------------------------------------------------------ * BACA SENSOR * ------------------------------------------------------------ */ temp_x10 = Read_Temperature_x10(); flame = Read_Flame(); pir = Read_PIR(); /* ------------------------------------------------------------ * UPDATE SISTEM * ------------------------------------------------------------ */ if (g_reset_active) Show_Reset_Mode(); else Update_System(temp_x10, flame, pir); delay_ms(500); } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * HSE 8MHz + PLL x9 = 72MHz (dari Dokumen 1 — lebih stabil) * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /* HSE + PLL */ 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; /* 8MHz x9 = 72MHz */ if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) Error_Handler(); /* Bus 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; /* HCLK = 72MHz */ RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; /* PCLK1 = 36MHz (max) */ RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; /* PCLK2 = 72MHz */ if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) Error_Handler(); /* ADC clock = PCLK2 / 6 = 12MHz (max 14MHz) */ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) Error_Handler(); } /** * @brief ADC1 Initialization * PA0, single conversion + ContinuousConvMode ON + kalibrasi * @retval None */ static void MX_ADC1_Init(void) { /* USER CODE BEGIN ADC1_Init 0 */ /* USER CODE END ADC1_Init 0 */ ADC_ChannelConfTypeDef sConfig = {0}; /* USER CODE BEGIN ADC1_Init 1 */ /* USER CODE END ADC1_Init 1 */ hadc1.Instance = ADC1; hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; hadc1.Init.ContinuousConvMode = ENABLE; /* [Doc1] continuous mode */ 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(); sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5; /* sampling panjang untuk akurasi LM35 */ if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) Error_Handler(); /* [Doc2] Kalibrasi ADC — wajib untuk akurasi */ HAL_ADCEx_Calibration_Start(&hadc1); /* USER CODE BEGIN ADC1_Init 2 */ /* USER CODE END ADC1_Init 2 */ } /** * @brief I2C1 Initialization — PB6 SCL, PB7 SDA, 100 kHz * @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 GPIO Initialization * Menggunakan pin naming CubeMX dari Dokumen 1 * dan konfigurasi PULLDOWN/PULLUP dari Dokumen 2 * @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(); /* HSE pada PD0/PD1 */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /* --- OUTPUT GPIOB: PB1 LED Hijau, PB5 Buzzer, PB10 LED Merah --- */ HAL_GPIO_WritePin(GPIOB, LED_GREEN_Pin | LED_RED_Pin | BUZZER_Pin, GPIO_PIN_RESET); /* semua LOW saat startup */ GPIO_InitStruct.Pin = LED_GREEN_Pin | LED_RED_Pin; 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); GPIO_InitStruct.Pin = BUZZER_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; HAL_GPIO_Init(BUZZER_GPIO_Port, &GPIO_InitStruct); /* --- INPUT PA1 Flame Sensor & PA2 PIR — PULLDOWN --- */ GPIO_InitStruct.Pin = SENSOR_FLAME_Pin | PIR_SENSOR_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLDOWN; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* --- INPUT PA3 Push Button Reset — PULLUP (aktif LOW) --- */ GPIO_InitStruct.Pin = PUSH_BUTTON_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(PUSH_BUTTON_GPIO_Port, &GPIO_InitStruct); /* PA0 : dikonfigurasi analog otomatis oleh HAL_ADC_Init */ /* PB6 SCL, PB7 SDA : dikonfigurasi otomatis oleh HAL_I2C_Init */ /* USER CODE BEGIN MX_GPIO_Init_2 */ /* USER CODE END MX_GPIO_Init_2 */ } /* USER CODE BEGIN 4 */ /* ============================================================ * LOGIKA UTAMA — prioritas: api > suhu tinggi > aman * ============================================================ */ void Update_System(int temp_x10, uint8_t flame, uint8_t pir) { /* --- PRIORITAS 1: API TERDETEKSI --- */ if (flame == 1) { Set_LED_Red(1); Set_LED_Green(0); Set_Buzzer(1); LCD_SetCursor(0, 0); LCD_Print("!!FIRE DETECTED!"); LCD_SetCursor(1, 0); LCD_Print(pir == 1 ? "HUMAN IN DANGER!" : "EVACUATE AREA!! "); return; } /* --- PRIORITAS 2: SUHU TINGGI --- */ if (temp_x10 >= (TEMP_THRESHOLD_C * 10)) { Set_LED_Red(1); Set_LED_Green(0); Set_Buzzer(0); LCD_SetCursor(0, 0); LCD_Print("HIGH TEMP: "); LCD_SetCursor(0, 10); LCD_PrintTemp(temp_x10); LCD_SetCursor(1, 0); LCD_Print(pir == 1 ? "HUMAN DETECTED " : "NO HUMAN FOUND "); return; } /* --- KONDISI AMAN --- */ Set_LED_Red(0); Set_Buzzer(0); Set_LED_Green(1); LCD_SetCursor(0, 0); LCD_Print("SYSTEM SAFE "); LCD_SetCursor(1, 0); if (pir == 1) { LCD_Print("HUMAN DETECTED "); } else { LCD_Print("TEMP: "); LCD_SetCursor(1, 5); LCD_PrintTemp(temp_x10); } } /* ============================================================ * TAMPILAN RESET MODE * Dipanggil saat g_reset_active = 1 * Semua alarm dimatikan, LED hijau ON sebagai tanda override * ============================================================ */ static void Show_Reset_Mode(void) { Set_LED_Red(0); Set_Buzzer(0); Set_LED_Green(1); LCD_SetCursor(0, 0); LCD_Print("** RESET MODE **"); LCD_SetCursor(1, 0); LCD_Print("SYSTEM OVERRIDE "); } /* ============================================================ * KONTROL OUTPUT * ============================================================ */ void Set_LED_Green(uint8_t state) { HAL_GPIO_WritePin(GPIOB, LED_GREEN_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); } void Set_LED_Red(uint8_t state) { HAL_GPIO_WritePin(GPIOB, LED_RED_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); } void Set_Buzzer(uint8_t state) { HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, state ? GPIO_PIN_SET : GPIO_PIN_RESET); } /* ============================================================ * BACA SENSOR * ============================================================ */ uint16_t ADC_Read(void) { HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); uint16_t val = HAL_ADC_GetValue(&hadc1); HAL_ADC_Stop(&hadc1); return val; } /* * Read_Temperature_x10 * Mengembalikan suhu dalam satuan 0.1 derajat Celcius * Contoh: 275 = 27.5 C * * LM35: output 10 mV per derajat Celcius * ADC 12-bit, Vref = 3.3 V * * Rumus: * mV = raw * 3300 / 4095 (tegangan dalam mV) * temp_x10 = mV / 10 (satuan 0.1 C) */ int Read_Temperature_x10(void) { uint16_t raw = ADC_Read(); uint32_t mv = ((uint32_t)raw * 3300UL) / 4095UL; int temp_x10 = (int)(mv / 10UL); return temp_x10; } uint8_t Read_Flame(void) { /* Flame sensor DO: HIGH = api terdeteksi */ return (HAL_GPIO_ReadPin(GPIOA, SENSOR_FLAME_Pin) == GPIO_PIN_SET) ? 1u : 0u; } uint8_t Read_PIR(void) { /* PIR HC-SR501: HIGH = gerakan manusia terdeteksi */ return (HAL_GPIO_ReadPin(GPIOA, PIR_SENSOR_Pin) == GPIO_PIN_SET) ? 1u : 0u; } uint8_t Read_Button(void) { /* Tombol aktif LOW (PULLUP): kembalikan 1 jika ditekan */ return (HAL_GPIO_ReadPin(PUSH_BUTTON_GPIO_Port, PUSH_BUTTON_Pin) == GPIO_PIN_RESET) ? 1u : 0u; } /* ============================================================ * DELAY * ============================================================ */ void delay_us(uint32_t us) { uint32_t start = DWT->CYCCNT; uint32_t ticks = us * (SystemCoreClock / 1000000UL); while ((DWT->CYCCNT - start) < ticks); } void delay_ms(uint32_t ms) { HAL_Delay(ms); } /* ============================================================ * HELPER CETAK SUHU KE LCD * Format output: "XX.XC " (7 karakter termasuk spasi trailing) * Contoh: 27.5C / 40.0C / 5.0C * ============================================================ */ static void LCD_PrintTemp(int temp_x10) { char buf[8]; int whole = temp_x10 / 10; int frac = temp_x10 % 10; if (frac < 0) frac = -frac; if (whole >= 100) { buf[0] = '0' + (whole / 100); buf[1] = '0' + (whole / 10) % 10; buf[2] = '0' + (whole % 10); buf[3] = '.'; buf[4] = '0' + frac; buf[5] = 'C'; buf[6] = ' '; buf[7] = '\0'; } else if (whole >= 10) { buf[0] = '0' + (whole / 10); buf[1] = '0' + (whole % 10); buf[2] = '.'; buf[3] = '0' + frac; buf[4] = 'C'; buf[5] = ' '; buf[6] = ' '; buf[7] = '\0'; } else { buf[0] = ' '; buf[1] = '0' + whole; buf[2] = '.'; buf[3] = '0' + frac; buf[4] = 'C'; buf[5] = ' '; buf[6] = ' '; buf[7] = '\0'; } LCD_Print(buf); } /* ============================================================ * DRIVER LCD 16x2 I2C (PCF8574 backpack) * * Bit layout PCF8574 (standar library LiquidCrystal_I2C): * bit7 bit6 bit5 bit4 | bit3 bit2 bit1 bit0 * D7 D6 D5 D4 | BL EN RW RS * ============================================================ */ /* Kirim 1 byte ke PCF8574 via I2C */ static void LCD_I2C_Write(uint8_t data) { HAL_I2C_Master_Transmit(&hi2c1, LCD_I2C_ADDR, &data, 1, HAL_MAX_DELAY); } /* Buat pulsa EN: EN=1 → tahan → EN=0 */ static void LCD_PulseEnable(uint8_t data) { LCD_I2C_Write(data | LCD_EN_BIT); delay_us(1); LCD_I2C_Write(data & ~LCD_EN_BIT); delay_us(50); } /* Kirim nibble 4-bit ke HD44780 nibble : nilai 4-bit (0x0–0xF) untuk D7–D4 rs : 0 = command, 1 = data */ void LCD_SendNibble(uint8_t nibble, uint8_t rs) { uint8_t data = (nibble << 4) | LCD_BL_BIT; if (rs) data |= LCD_RS_BIT; LCD_PulseEnable(data); } /* Kirim 1 byte penuh: high nibble dulu, lalu low nibble */ void LCD_SendByte(uint8_t byte, uint8_t rs) { LCD_SendNibble((byte >> 4) & 0x0F, rs); LCD_SendNibble( byte & 0x0F, rs); } void LCD_Command(uint8_t cmd) { LCD_SendByte(cmd, 0); if (cmd == 0x01 || cmd == 0x02) delay_ms(3); else delay_us(100); } void LCD_Char(uint8_t data) { LCD_SendByte(data, 1); delay_us(50); } /* Inisialisasi LCD sesuai datasheet HD44780 untuk mode 4-bit */ void LCD_Init(void) { delay_ms(50); LCD_SendNibble(0x03, 0); delay_ms(5); LCD_SendNibble(0x03, 0); delay_us(200); LCD_SendNibble(0x03, 0); delay_us(200); LCD_SendNibble(0x02, 0); delay_us(200); /* aktifkan mode 4-bit */ LCD_Command(0x28); /* Function Set: 4-bit, 2 baris, font 5x8 */ LCD_Command(0x08); /* Display OFF */ LCD_Command(0x01); /* Clear Display */ LCD_Command(0x06); /* Entry Mode: increment cursor, no shift */ LCD_Command(0x0C); /* Display ON, cursor OFF, blink OFF */ } void LCD_Clear(void) { LCD_Command(0x01); delay_ms(3); } /* row: 0 = baris atas, 1 = baris bawah | col: 0–15 */ void LCD_SetCursor(uint8_t row, uint8_t col) { uint8_t addr = (row == 0) ? (0x80 + col) : (0xC0 + col); LCD_Command(addr); } void LCD_Print(const char *str) { while (*str) LCD_Char((uint8_t)*str++); } /* USER CODE END 4 */ /** * @brief Error Handler * Jika terjadi error HAL, LED Merah (PB10) berkedip cepat * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ __disable_irq(); __HAL_RCC_GPIOB_CLK_ENABLE(); /* Konfigurasi PB10 output secara langsung (bypass HAL) */ GPIOB->CRH &= ~(0xFUL << 8); GPIOB->CRH |= (0x2UL << 8); /* Output PP 2MHz */ while (1) { GPIOB->ODR ^= GPIO_PIN_10; for (volatile uint32_t i = 0; i < 400000UL; i++); } /* 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. */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ (void)file; (void)line; /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */

5. Video Demo dan Video Simulasi[Kembali]

Video Demo


Video Simulasi

6. Download File[Kembali]














   



Komentar

Postingan populer dari blog ini