LAPORAN AKHIR 1 MODUL 2
PERCOBAAN 4

1. Prosedur 
[Kembali]

    1. Siapkan seluruh alat dan komponen yang diperlukan sesuai daftar yang tercantum dalam modul praktikum.

2. Buat rangkaian sesuai skema di atas breadboard, pastikan setiap koneksi sesuai dan kuat.

3. Unduh dan buka aplikasi ST-Link Utility atau gunakan STM32CubeIDE, kemudian masukkan program yang telah disiapkan ke dalam proyek.

4. Sambungkan perangkat STM32 ke komputer menggunakan kabel ST-Link untuk menghubungkan hardware ke software.

5. Lakukan proses upload dan jalankan program, lalu amati hasilnya sesuai dengan fungsi rangkaian.


2. Hardware dan Diagram Blok [Kembali]

Hardware :

1. STM32F103C8

Berfungsi sebagai otak utama sistem, yang mengendalikan dan memproses data dari sensor serta mengatur perangkat output seperti LED dan buzzer.

2. Soil Moisture Sensor

Berfungsi untuk mendeteksi kadar air di tanah, memberikan data kelembaban berupa sinyal analog ke mikrokontroler.

3. Resistor

Berfungsi membatasi arus listrik dalam rangkaian agar komponen seperti LED atau buzzer tidak rusak akibat arus berlebih.

4. RGB LED

Berfungsi sebagai indikator visual multicolor yang dapat menyala dalam berbagai warna tergantung input PWM dari mikrokontroler.

5. Push Button

Berfungsi sebagai input manual dari pengguna, misalnya untuk mengaktifkan atau menonaktifkan sistem secara langsung.

6. Buzzer

Berfungsi memberikan umpan balik suara, biasanya sebagai alarm atau tanda bahwa suatu kondisi telah tercapai (misalnya tanah terlalu kering).



Diagram blok :



3. Rangkaian Simulasi dan Prinsip Kerja [Kembali]

Rangkaian Simulasi 





Prinsip Kerja : 

Prinsip kerja sistem otomatisasi ini berfokus pada pengendalian motor stepper menggunakan mikrokontroler STM32 yang dipadukan dengan sensor kelembapan tanah untuk memonitor kondisi tanah. Sensor kelembapan tanah bekerja dengan mendeteksi konduktivitas tanah, yang berubah seiring dengan tingkat kelembapan tanah. Sensor ini menghasilkan sinyal analog yang dikirim ke mikrokontroler melalui pin ADC, yang kemudian mengubahnya menjadi nilai digital yang dapat diproses lebih lanjut.

Berdasarkan hasil pembacaan nilai ADC, sistem akan menentukan mode operasi motor stepper. Terdapat tiga mode yang dikendalikan sesuai dengan tingkat kelembapan tanah yang terdeteksi. Jika nilai ADC menunjukkan tingkat kelembapan rendah (kurang dari 1365), motor stepper akan berputar searah jarum jam (CW), dan LED RGB akan menyala merah sebagai indikator. Jika nilai ADC berada di antara 1365 hingga 2730, motor akan bergerak berlawanan arah jarum jam (CCW), dengan LED hijau sebagai tanda. Apabila nilai ADC lebih dari 2730, motor akan berputar bolak-balik (mode Oscillate), dengan LED biru yang menyala.

Motor stepper dioperasikan dengan mengirimkan sinyal digital ke driver ULN2003 atau langsung ke motor, melalui pin kontrol yang mengatur urutan langkah motor. Urutan langkah ini diprogram dalam pola STEP_SEQ_CW dan STEP_SEQ_CCW yang memastikan motor bergerak dengan mulus sesuai arah yang ditentukan. Fungsi utama yang mengendalikan motor adalah RunStepper(), yang bertugas mengatur langkah-langkah motor sesuai dengan arah dan kecepatan yang diinginkan, serta menyalakan LED RGB untuk menandakan status sistem.

  

4. Flowchart dan Listing Program [Kembali]

Flowchart :







Listing Program :

#include "stm32f1xx_hal.h"

ADC_HandleTypeDef hadc1;
TIM_HandleTypeDef htim2;

uint8_t sound_pattern = 0;

// Pin definisi
#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 ADC_THRESH_HIGH 3000
#define ADC_THRESH_MID  1500

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

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); // Buzzer off
  }
  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); // Buzzer off
  }
  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); // Buzzer off
    }
  }
}

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};

  /** Initializes the RCC Oscillators */
  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();

  /** Initializes the CPU, AHB and APB buses 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;
  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 Output
  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 Input
  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 Demo [Kembali]











6. Analisa [Kembali]






















7. Download File [Kembali]

Download HTML [Download]
Download Video Demo [Download]
Download Listing Program [Download