Laporan Akhir 1

 

Percobaan 3 Kondisi 6




1. Prosedur [Kembali]

  1. Pahami terlebih dahulu kondisi yang akan digunakan
  2. Buka software Proteus 8.17
  3. Persiapkan alat dan bahan
  4. Buat rangkaian sesuai dengan kondisi dan modul
  5. Buka software STM32Cube IDE 
  6. Setelah membuka software, pilih perangkat STM32F103C8T6 
  7. Sesuaikan konfigurasi pin sesuai dengan rangkaian proteus 
  8. Buat kode program untuk mengoperasikan rangkaian tersebut sesuai dengan kondisi 
  9. Konfigurasi kan program dengan software Proteus
  10. Jalankan simulasi rangkaian.  
  11. Proses selesai

2. Hardware dan Diagram Blok [Kembali]

  Hardware

STM32F103C8T6

Sensor Suhu Lm35

Kipas DC

Push Button

Motor Driver l298N

Breadboard

Adaptor

Resistor


Diagram Blok

3. Rangkaian Simulasi dan Prinsip Kerja [Kembali]

1. Pembacaan suhu — LM35 ke ADC
LM35 merupakan sensor suhu analog dengan karakteristik output sebesar 10 mV per °C. Pin output (VOUT) dari LM35 dihubungkan ke pin analog mikrokontroler (misalnya PA0) yang dikonfigurasi sebagai ADC channel.
Mikrokontroler membaca nilai digital dari ADC, kemudian mengubahnya menjadi tegangan dan suhu menggunakan persamaan:
voltage = (adcValue / 4095.0) × 3.3 → tegangan (Volt)
temperature = voltage × 100.0 → suhu (°C)
Nilai suhu inilah yang digunakan sebagai parameter untuk menentukan kondisi kipas.


2. Tombol ON — Input Digital
Tombol dihubungkan ke salah satu pin GPIO (misalnya PA1) dan dikonfigurasi sebagai input dengan pull-up. Ketika tombol ditekan, logika berubah dari HIGH menjadi LOW.
Program mendeteksi perubahan ini menggunakan pembacaan pin secara berkala (polling), lalu mengaktifkan kipas dengan logika:
if(button == PRESSED && last_button == RELEASED)
{
fan_status = 1;
}
Pendekatan ini memastikan bahwa:
  • Kipas hanya aktif sekali saat tombol ditekan
  • Tidak terjadi pembacaan berulang saat tombol ditahan

3. Kontrol kipas — Driver Motor (L298)
Kipas DC dikendalikan menggunakan driver motor L298. Dua pin utama digunakan:
  • IN1 → mengaktifkan motor
  • IN2 → menentukan kondisi berhenti
Kondisi dasar:
  • Kipas ON → IN1 = HIGH, IN2 = LOW
  • Kipas OFF → IN1 = LOW, IN2 = LOW
Pada kondisi normal (kipas hidup), motor berputar penuh tanpa PWM hardware.


4. Logika kontrol sistem
Sistem memiliki dua kondisi utama:
KondisiAksi Kipas
Tombol ditekan sekaliKipas menyala
Suhu ≤ 30°CKipas tetap menyala
Suhu > 30°CKipas mati perlahan (5 detik)
Logika program:
  • Saat tombol ditekan → kipas aktif (fan_status = 1)
  • Selama suhu masih ≤ 30°C → kipas tetap hidup
  • Ketika suhu melewati 30°C → sistem masuk proses slow stop

5. Proses berhenti perlahan (Soft Stop 5 detik)
Ketika suhu > 30°C, kipas tidak langsung dimatikan, melainkan diturunkan kecepatannya secara bertahap selama ±5 detik.
Metode yang digunakan adalah software PWM, dengan penurunan duty cycle:
duty: 100 → 0 (step -5)
Setiap nilai duty dipertahankan selama 250 ms:
Total waktu = 20 step × 250 ms = 5000 ms (5 detik)
PWM dibuat dengan mengatur pin ON dan OFF menggunakan delay:
ON time = duty / 5
OFF time = (100 - duty) / 5
Semakin kecil nilai duty:
  • Waktu ON semakin kecil
  • Waktu OFF semakin besar
  • Putaran kipas semakin lambat
Pada akhir proses:
Fan_OFF();
Kipas berhenti sepenuhnya.

4. Flowchart dan Listing Program [Kembali]


Flowchart















Mengupload: 31801 dari 31801 byte diupload.



















#include "main.h" /* ================= PRIVATE VARIABLES ================= */ ADC_HandleTypeDef hadc1; TIM_HandleTypeDef htim2; // Timer untuk PWM dan non-blocking delay /* ================= PRIVATE MACROS ================= */ #define TEMP_THRESHOLD 30.0f #define ADC_MAX_VALUE 4095U #define VREF 3.3f #define LM35_SENSITIVITY 0.01f #define DEBOUNCE_DELAY_MS 50U #define PWM_PERIOD_MS 20U #define PWM_RESOLUTION 100U #define SLOW_STOP_STEP_MS 250U #define MAIN_LOOP_DELAY_MS 100U /* ================= STATE MACHINE ENUM ================= */ typedef enum { FAN_STATE_OFF, FAN_STATE_ON, FAN_STATE_SLOW_STOP } FanState_t; /* ================= GLOBAL VARIABLES ================= */ static FanState_t fan_state = FAN_STATE_OFF; static uint8_t button_last_state = GPIO_PIN_SET; static uint32_t slow_stop_counter = 0; static uint8_t pwm_duty = PWM_RESOLUTION; /* ================= FUNCTION PROTOTYPES ================= */ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_ADC1_Init(void); static void MX_TIM2_Init(void); void Fan_Control(void); uint32_t Read_ADC(void); float Read_Temperature(void); void Button_Process(void); void Slow_Stop_Process(void); void Error_Handler(void); /* ================= MAIN ================= */ int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); MX_TIM2_Init(); HAL_TIM_Base_Start_IT(&htim2); while (1) { float temperature = Read_Temperature(); Button_Process(); Fan_Control(); HAL_Delay(MAIN_LOOP_DELAY_MS); } } /* ================= ADC FUNCTIONS ================= */ uint32_t Read_ADC(void) { uint32_t adc_value; if (HAL_ADC_Start(&hadc1) == HAL_OK) { if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) { adc_value = HAL_ADC_GetValue(&hadc1); } else { adc_value = 0; } HAL_ADC_Stop(&hadc1); } else { adc_value = 0; } return adc_value; } float Read_Temperature(void) { uint32_t adc_value = Read_ADC(); float voltage = (float)adc_value * VREF / ADC_MAX_VALUE; return voltage / LM35_SENSITIVITY; // LM35: 10mV/°C } /* ================= BUTTON HANDLER ================= */ void Button_Process(void) { uint8_t button_current = HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin); // Edge detection: rising edge (button pressed) if (button_current == GPIO_PIN_RESET && button_last_state == GPIO_PIN_SET) { HAL_Delay(DEBOUNCE_DELAY_MS); if (HAL_GPIO_ReadPin(BUTTON_GPIO_Port, BUTTON_Pin) == GPIO_PIN_RESET) { if (fan_state == FAN_STATE_OFF) { fan_state = FAN_STATE_ON; pwm_duty = PWM_RESOLUTION; } } } button_last_state = button_current; } /* ================= FAN CONTROL - STATE MACHINE ================= */ void Fan_Control(void) { float temperature = Read_Temperature(); switch (fan_state) { case FAN_STATE_OFF: HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(IN2_GPIO_Port, IN2_Pin, GPIO_PIN_RESET); break; case FAN_STATE_ON: if (temperature > TEMP_THRESHOLD) { fan_state = FAN_STATE_SLOW_STOP; slow_stop_counter = 0; } else { // Software PWM untuk kehalusan static uint32_t pwm_counter = 0; pwm_counter++; if (pwm_counter >= PWM_PERIOD_MS) { pwm_counter = 0; } if (pwm_counter < pwm_duty) { HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(IN2_GPIO_Port, IN2_Pin, GPIO_PIN_RESET); } else { HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, GPIO_PIN_RESET); } } break; case FAN_STATE_SLOW_STOP: Slow_Stop_Process(); break; } } /* ================= SOFT STOP IMPLEMENTATION ================= */ void Slow_Stop_Process(void) { static uint32_t last_tick = 0; uint32_t current_tick = HAL_GetTick(); if (current_tick - last_tick >= SLOW_STOP_STEP_MS) { last_tick = current_tick; if (pwm_duty > 0) { pwm_duty -= 5; // Kurangi 5% setiap 250ms } else { fan_state = FAN_STATE_OFF; pwm_duty = PWM_RESOLUTION; } } // PWM dengan duty cycle yang menurun static uint32_t pwm_counter = 0; pwm_counter++; if (pwm_counter >= PWM_PERIOD_MS) { pwm_counter = 0; } if (pwm_counter < pwm_duty) { HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, GPIO_PIN_SET); HAL_GPIO_WritePin(IN2_GPIO_Port, IN2_Pin, GPIO_PIN_RESET); } else { HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, GPIO_PIN_RESET); } } /* ================= HARDWARE CONFIG ================= */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; __HAL_RCC_SYSCFG_CLK_ENABLE(); __HAL_RCC_PWR_CLK_ENABLE(); 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(); } } static void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 7999; // 1ms tick dengan 8MHz HSI htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 65535; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim2) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } } static void MX_ADC1_Init(void) { ADC_ChannelConfTypeDef sConfig = {0}; hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; hadc1.Init.Resolution = ADC_RESOLUTION_12B; 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; hadc1.Init.DMAContinuousRequests = DISABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; 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; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); /* OUTPUT: Fan control pins */ HAL_GPIO_WritePin(GPIOA, IN1_Pin | IN2_Pin, GPIO_PIN_RESET); GPIO_InitStruct.Pin = IN1_Pin | IN2_Pin; 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); /* INPUT: Button with pull-up */ GPIO_InitStruct.Pin = BUTTON_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(BUTTON_GPIO_Port, &GPIO_InitStruct); } void Error_Handler(void) { __disable_irq(); while (1) { HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); // Debug LED blink HAL_Delay(200); } } #ifdef USE_FULL_ASSERT void assert_failed(uint8_t *file, uint32_t line) { Error_Handler(); } #endif

/* ================= PRIVATE VARIABLES ================= */
ADC_HandleTypeDef hadc1;
TIM_HandleTypeDef htim2;  // Timer untuk PWM dan non-blocking delay


5. Video Demo [Kembali]


6. Kondisi [Kembali]

Buatlah rangkaian seperti percobaan 3 dengan kondisi ketika sensor tombol ditekan sekali maka kipas hidup dan ketika sensor suhu >30 C maka kipas mati secara perlahan selama 5 detik.

7. Video Simulasi [Kembali]



8. Download File [Kembali]

    Rangkaian dan Program Proteus [tekan disini]

    Video Rangkaian [tekan disini]


Komentar

Postingan populer dari blog ini

Kontrol Rumah Kaca pada Greenhouse

modul 1

Tugas Pendahuluan Percobaan 1 Kondisi 10