LAPORAN AKHIR 2 MODUL 2

 By: Rahmad Fajril Ilhami

2210951016





1. Jurnal
 [Kembali]


2. Alat dan Bahan [Kembali]

Soil Sensor 


LED RGB

Push Button 

Resistor 

STM32 

Buzzer



3. Rangkaian [Kembali]


4. Prinsip Kerja Rangkaian [Kembali]

Program ini dirancang untuk membaca nilai dari potensiometer menggunakan pin ADC (Analog to Digital Converter) dan mengendalikannya ke dua perangkat output: motor servo dan buzzer. Potensiometer terhubung ke pin GP26 pada mikrokontroler Raspberry Pi Pico yang mendukung fungsi ADC. Nilai yang terbaca dari potensiometer merupakan data 16-bit (rentang 0 hingga 65535), yang mencerminkan posisi fisik dari potensiometer. Nilai ini dibaca dalam loop while True secara terus-menerus untuk memperoleh data real-time.

Setelah membaca nilai potensiometer, program menggunakan fungsi map_value() untuk mengubah rentang nilai ADC (0–65535) menjadi sudut yang dapat dimengerti oleh motor servo, yaitu 0° hingga 180°. Kemudian, sudut ini dikonversi lagi menjadi nilai duty cycle PWM yang sesuai dengan sinyal kontrol servo. Duty cycle dalam bentuk 16-bit (duty_u16) dikalkulasi dari sudut tersebut ke nilai antara 1500 hingga 7500, karena sebagian besar servo motor standar menerima sinyal PWM dengan lebar pulsa antara 0.5 ms (0°) sampai 2.5 ms (180°) dalam periode 20 ms (frekuensi 50 Hz). Duty cycle ini dikirim ke pin PWM (GP16) yang terhubung ke motor servo, sehingga posisi lengan servo menyesuaikan dengan perubahan nilai potensiometer.

Untuk komponen buzzer, program juga menggunakan nilai yang sama dari potensiometer untuk mengatur frekuensi suara. Namun, buzzer hanya akan aktif apabila sudut servo berada antara lebih dari 0° dan kurang dari 180° — artinya, selama potensiometer tidak berada di posisi ujung minimum atau maksimum. Nilai ADC dari potensiometer digunakan untuk menghasilkan frekuensi buzzer antara 200 Hz sampai 2000 Hz, yang dihitung secara linier. Buzzer diatur menggunakan pin PWM (GP14) dengan duty cycle sebesar 30000 (dari total 65535), yang memberikan volume suara tertentu.

Dengan prinsip kerja seperti ini, pengguna dapat mengontrol arah servo motor dan sekaligus mendengar perubahan nada buzzer cukup hanya dengan memutar potensiometer. Program ini efektif untuk mendemonstrasikan prinsip pengolahan sinyal analog menjadi kontrol digital terhadap perangkat output melalui mikrokontroler. Pendekatan ini sering digunakan dalam aplikasi interaktif seperti kendali posisi, sistem alarm berbasis sensor, atau pembelajaran dasar mekatronika dan kontrol servo berbasis PWM.



#include "stm32f1xx_hal.h"

 

// Handle untuk ADC dan Timer

ADC_HandleTypeDef hadc1;

TIM_HandleTypeDef htim2;

 

// Variabel Global

uint8_t sound_pattern = 0;

 

// Definisi Pin

#define LED_RED_PIN    GPIO_PIN_12

#define LED_GREEN_PIN  GPIO_PIN_13

#define LED_BLUE_PIN   GPIO_PIN_14

#define LED_PORT       GPIOB

#define BUTTON_PIN     GPIO_PIN_0

#define BUTTON_PORT    GPIOB

#define BUZZER_PIN     GPIO_PIN_2

 

// Threshold ADC

#define ADC_THRESH_HIGH  3000

#define ADC_THRESH_MID   1500

 

// Periode PWM untuk buzzer

const uint32_t pwm_periods[] = {1000, 50000, 719999};

 

// Function Prototype

void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_ADC1_Init(void);

static void MX_TIM2_Init(void);

void update_leds_and_buzzer(uint32_t adc_val, uint8_t btn_state);

void change_sound_pattern(void);

void Error_Handler(void);

 

int main(void) {

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();

    MX_ADC1_Init();

    MX_TIM2_Init();

 

    HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3);

    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);

    HAL_ADC_Start(&hadc1);

 

    while (1) {

        static uint32_t last_adc_tick = 0;

        static uint32_t last_sound_change = 0;

 

        uint8_t button_state = HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN);

 

        if (HAL_GetTick() - last_adc_tick > 200) {

            last_adc_tick = HAL_GetTick();

            HAL_ADC_Start(&hadc1);

 

            if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK) {

                update_leds_and_buzzer(HAL_ADC_GetValue(&hadc1), button_state);

            }

        }

 

        if (button_state == GPIO_PIN_RESET && (HAL_ADC_GetValue(&hadc1) < ADC_THRESH_MID)) {

            if (HAL_GetTick() - last_sound_change > 1000) {

                last_sound_change = HAL_GetTick();

                change_sound_pattern();

            }

        }

 

        HAL_Delay(10);

    }

}

 

void update_leds_and_buzzer(uint32_t adc_val, uint8_t btn_state) {

    HAL_GPIO_WritePin(LED_PORT, LED_RED_PIN | LED_GREEN_PIN | LED_BLUE_PIN, GPIO_PIN_RESET);

 

    if (adc_val >= ADC_THRESH_HIGH) {

        HAL_GPIO_WritePin(LED_PORT, LED_GREEN_PIN, GPIO_PIN_SET);

        __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);

    }

    else if (adc_val >= ADC_THRESH_MID) {

        HAL_GPIO_WritePin(LED_PORT, LED_BLUE_PIN, GPIO_PIN_SET);

        __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);

    }

    else {

        HAL_GPIO_WritePin(LED_PORT, LED_RED_PIN, GPIO_PIN_SET);

 

        if (btn_state == GPIO_PIN_RESET) {

            __HAL_TIM_SET_AUTORELOAD(&htim2, pwm_periods[sound_pattern]);

            __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, pwm_periods[sound_pattern] / 2);

        } else {

            __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0);

        }

    }

}

 

void change_sound_pattern(void) {

    sound_pattern = (sound_pattern + 1) % 3;

 

    if (HAL_ADC_GetValue(&hadc1) < ADC_THRESH_MID && HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN) == GPIO_PIN_SET) {

        __HAL_TIM_SET_AUTORELOAD(&htim2, pwm_periods[sound_pattern]);

        __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, pwm_periods[sound_pattern] / 2);

    }

}

 

void SystemClock_Config(void) {

    RCC_OscInitTypeDef RCC_OscInitStruct = {0};

    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

 

    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();

 

    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();

 

    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;

    PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;

    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) Error_Handler();

}

 

static void MX_ADC1_Init(void) {

    ADC_ChannelConfTypeDef sConfig = {0};

 

    hadc1.Instance = ADC1;

    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;

    if (HAL_ADC_Init(&hadc1) != HAL_OK) Error_Handler();

 

    sConfig.Channel = ADC_CHANNEL_0;

    sConfig.Rank = ADC_REGULAR_RANK_1;

    sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;

    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) Error_Handler();

}

 

static void MX_TIM2_Init(void) {

    TIM_MasterConfigTypeDef sMasterConfig = {0};

    TIM_OC_InitTypeDef sConfigOC = {0};

 

    htim2.Instance = TIM2;

    htim2.Init.Prescaler = 0;

    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_PWM_Init(&htim2) != HAL_OK) Error_Handler();

 

    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

    if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) Error_Handler();

 

    sConfigOC.OCMode = TIM_OCMODE_PWM1;

    sConfigOC.Pulse = 0;

    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

    if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) Error_Handler();

 

    HAL_TIM_MspPostInit(&htim2);

}

 

static void MX_GPIO_Init(void) {

    GPIO_InitTypeDef GPIO_InitStruct = {0};

 

    __HAL_RCC_GPIOA_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();

 

    // LED Pins

    GPIO_InitStruct.Pin = LED_RED_PIN | LED_GREEN_PIN | LED_BLUE_PIN;

    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

    HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);

 

    // Button Pin

    GPIO_InitStruct.Pin = BUTTON_PIN;

    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;

    GPIO_InitStruct.Pull = GPIO_PULLUP;

    HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct);

}

 

void Error_Handler(void) {

    __disable_irq();

    while (1) {}

}

5. Video Rangkaian [Kembali]


6. Analisa [Kembali]






7. Link Download [Kembali]

Download video Rangkaian [Download]


Komentar

Postingan populer dari blog ini

MATA KULIAH ELEKTRONIKA

PRATIKUM SISTEM DIGITAL

PRATIKUM MIKROKONTROLEL DAN MIKROPROSESOR