LM35 adalah sensor suhu analog yang menghasilkan tegangan output sebesar 10 mV per °C. Output LM35 (pin VOUT) terhubung ke PA0 pada STM32, yang dikonfigurasi sebagai input ADC channel 0. Program membaca nilai ADC lalu mengkonversinya ke suhu dengan rumus:
2. Tombol ON/OFF — Interrupt PA4
Ini memungkinkan pengguna mematikan atau menghidupkan seluruh sistem secara instan tanpa mengganggu loop utama.
TIM1 dikonfigurasi dengan period 65535 dan prescaler 0, menghasilkan resolusi PWM 16-bit penuh. Output PWM dari TIM1 Channel 1 masuk ke pin ENA pada driver L298 (U3), yang mengontrol kecepatan motor DC. IN1 dan IN2 pada L298 menentukan arah putaran (dalam rangkaian ini dikonfigurasi tetap satu arah).
Untuk rentang 30–40°C, kecepatan kipas naik secara proporsional menggunakan rumus:
Semakin mendekati 40°C, PWM semakin besar, artinya kipas berputar semakin cepat.
#include "main.h" // Library utama STM32 HAL
ADC_HandleTypeDef hadc1; // Handle untuk ADC1
TIM_HandleTypeDef htim1; // Handle untuk Timer1 (PWM)
// Prototype fungsi
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM1_Init(void);
// Variabel global
uint32_t adcValue = 0; // Menyimpan nilai ADC (0–4095)
float voltage = 0; // Tegangan hasil konversi ADC
float temperature = 0; // Suhu dalam derajat Celcius
volatile uint8_t system_on = 1; // Status sistem (1=ON, 0=OFF)
int main(void)
{
HAL_Init(); // Inisialisasi HAL library
SystemClock_Config(); // Konfigurasi clock sistem
MX_GPIO_Init(); // Inisialisasi GPIO
MX_ADC1_Init(); // Inisialisasi ADC
MX_TIM1_Init(); // Inisialisasi Timer PWM
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); // Mulai PWM pada TIM1 Channel 1
while (1)
{
HAL_ADC_Start(&hadc1); // Mulai konversi ADC
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); // Tunggu sampai konversi selesai
adcValue = HAL_ADC_GetValue(&hadc1); // Ambil nilai ADC
// Konversi ADC ke Tegangan
voltage = (adcValue / 4095.0) * 3.3; // ADC 12-bit, Vref = 3.3V
// Konversi Tegangan ke Suhu (misal sensor LM35)
temperature = (voltage * 100.0); // 10mV = 1°C
if (system_on) // Jika sistem ON
{
if (temperature >= 40.0) // Jika suhu ≥ 40°C
{
// Kipas dimatikan (mode proteksi)
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); // LED Merah OFF
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET); // LED Hijau ON
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 0); // PWM 0% (kipas mati)
}
else if (temperature >= 30.0 && temperature < 40.0) // Jika suhu 30–40°C
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET); // LED Merah ON
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET); // LED Hijau OFF
float ratio = (temperature - 30.0) / 10.0; // Normalisasi suhu (0–1)
// Hitung PWM dari 20% sampai 100%
uint32_t pwm_value = (uint32_t)(13107 + (ratio * (65535 - 13107)));
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pwm_value); // Set kecepatan kipas
}
else // Jika suhu < 30°C
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET); // LED Merah ON
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET); // LED Hijau OFF
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 13107); // PWM 20% (kipas pelan)
}
}
else // Jika sistem OFF
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); // LED Merah OFF
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET); // LED Hijau OFF
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 0); // Kipas mati
}
HAL_Delay(200); // Delay 200 ms
}
}
// ================= CLOCK CONFIG =================
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0}; // Struktur konfigurasi oscillator
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; // Struktur konfigurasi clock
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; // Struktur clock peripheral
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; // Gunakan HSI (internal clock)
RCC_OscInitStruct.HSIState = RCC_HSI_ON; // Aktifkan HSI
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // Tidak pakai PLL
HAL_RCC_OscConfig(&RCC_OscInitStruct); // Terapkan konfigurasi
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; // Jenis clock
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; // Sumber clock dari HSI
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0); // Terapkan konfigurasi
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; // Pilih clock ADC
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV2; // Divider ADC
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit); // Terapkan
}
// ================= ADC CONFIG =================
static void MX_ADC1_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0}; // Struktur konfigurasi channel
hadc1.Instance = ADC1; // Gunakan ADC1
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; // Tidak scan multiple channel
hadc1.Init.ContinuousConvMode = DISABLE; // Tidak continuous
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // Trigger manual
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // Align kanan
hadc1.Init.NbrOfConversion = 1; // 1 channel
HAL_ADC_Init(&hadc1); // Inisialisasi ADC
sConfig.Channel = ADC_CHANNEL_0; // Channel 0
sConfig.Rank = ADC_REGULAR_RANK_1; // Rank 1
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5; // Waktu sampling
HAL_ADC_ConfigChannel(&hadc1, &sConfig); // Terapkan channel
}
// ================= TIMER PWM =================
static void MX_TIM1_Init(void)
{
TIM_OC_InitTypeDef sConfigOC = {0}; // Struktur konfigurasi PWM
htim1.Instance = TIM1; // Gunakan Timer 1
htim1.Init.Prescaler = 0; // Prescaler 0 (kecepatan tinggi)
htim1.Init.CounterMode = TIM_COUNTERMODE_UP; // Counter naik
htim1.Init.Period = 65535; // Resolusi 16-bit
HAL_TIM_PWM_Init(&htim1); // Inisialisasi PWM
sConfigOC.OCMode = TIM_OCMODE_PWM1; // Mode PWM1
sConfigOC.Pulse = 0; // Duty awal 0%
sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;// Polaritas low
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1); // Konfigurasi channel
HAL_TIM_MspPostInit(&htim1); // Inisialisasi GPIO PWM
}
// ================= GPIO =================
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0}; // Struktur GPIO
__HAL_RCC_GPIOA_CLK_ENABLE(); // Aktifkan clock GPIOA
GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_3; // Pin LED
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // Output push-pull
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; // Kecepatan rendah
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Terapkan
GPIO_InitStruct.Pin = GPIO_PIN_4; // Pin tombol
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; // Interrupt rising edge
GPIO_InitStruct.Pull = GPIO_PULLUP; // Pull-up
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // Terapkan
HAL_NVIC_SetPriority(EXTI4_IRQn, 0, 0); // Set prioritas interrupt
HAL_NVIC_EnableIRQ(EXTI4_IRQn); // Aktifkan interrupt
}
// ================= INTERRUPT =================
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_4) // Jika tombol ditekan
{
system_on = !system_on; // Toggle ON/OFF sistem
}
}
// ================= ERROR =================
void Error_Handler(void)
{
__disable_irq(); // Disable interrupt
while (1) {} // Loop selamanya jika error
}
Komentar
Posting Komentar