LA 2 P2




Percobaan 2
Led RGB, Motor Stepper & Soil Moisture

1. Prosedur[Kembali]

  1. Rangkai dengan inputnya yaitu Soil Moisture dan outputnya yaitu 1 LED RGB dan 1 Motor Stepper.
  2. Buatlah program dengan konfigurasi pin input dan output berdasarkan pada pin GPIO STM32 yang telah dirangkai sebelumnya. Kemudian buatlah program untuk menghasilkan output LED RGB dan Motor Stepper
  3. Run program, masukkan sensor soil moisture ke tanah lembap dan lihat perubahan pada LED RGB menjadi merah dan Motor Stepper aktif
  4. Program selesai

2. Hardware dan Diagram Blok[Kembali]

A. Hardware






B. Blok Diagram







3. Rangkaian Simulasi dan Prinsip Kerja[Kembali]

A. Rangkaian Simulasi






B. Prinsip Kerja

Rangkaian dan program ini dirancang untuk mengendalikan arah dan mode gerak motor stepper berdasarkan nilai kelembaban tanah yang dibaca melalui sensor soil moisture, dengan mikrokontroler STM32 sebagai unit pengolah utama. Sensor kelembaban tanah menghasilkan sinyal analog yang kemudian dibaca oleh ADC1 pada STM32. Nilai ADC tersebut digunakan untuk menentukan salah satu dari tiga mode penggerakan motor stepper: searah jarum jam (CW), berlawanan arah jarum jam (CCW), atau bolak-balik (oscillate). Ketika kelembaban tanah sangat rendah (nilai ADC < 1365), sistem memilih mode CW dan menyalakan LED merah sebagai indikator. Jika nilai berada di tengah (1365–2730), motor bergerak CCW dan LED hijau menyala. Bila kelembaban tinggi (ADC > 2730), sistem mengaktifkan mode oscillate dan menyalakan LED biru.

Motor stepper dikendalikan melalui empat output dari pin GPIOB (IN1–IN4), menggunakan urutan bit tertentu yang disimpan dalam array STEP_SEQ_CW dan STEP_SEQ_CCW, sesuai arah rotasi. Fungsi RunStepper mengatur langkah demi langkah motor dengan delay sesuai kecepatan. Sistem ini menggunakan LED indikator untuk memberikan umpan balik visual tentang mode yang sedang aktif, dan dirancang sedemikian rupa agar dapat beradaptasi otomatis terhadap kondisi lingkungan (kelembaban tanah) tanpa intervensi manual. Secara keseluruhan, prinsip kerja ini mencerminkan pemanfaatan ADC dan GPIO pada STM32 untuk sistem kendali berbasis kondisi lingkungan secara real-time.


4. Flowchart dan Listing Program[Kembali]






#include "main.h"


ADC_HandleTypeDef hadc1;

TIM_HandleTypeDef htim1;

TIM_HandleTypeDef htim2;


void SystemClock_Config(void);

static void MX_GPIO_Init(void);

static void MX_ADC1_Init(void);

static void MX_TIM1_Init(void);

static void MX_TIM2_Init(void);


int main(void)

{

  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();

  MX_ADC1_Init();

  MX_TIM1_Init();

  MX_TIM2_Init();


  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); // Motor PWM

  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_3); // Buzzer PWM

  HAL_ADC_Start(&hadc1);


  uint8_t buzzer_enabled = 1;

  uint32_t last_buzzer_change = 0;

  uint8_t buzzer_freq_index = 0;


  const uint32_t buzzer_periods[] = {143999, 71999, 47999}; // Frekuensi berbeda


  // Threshold (dari rendah → sedang → tinggi)

  const uint16_t THRESH_LOW = 1500;

  const uint16_t THRESH_MID = 3000;


  while (1)

  {

    HAL_ADC_Start(&hadc1);

    HAL_ADC_PollForConversion(&hadc1, 10);

    uint32_t adc_val = HAL_ADC_GetValue(&hadc1);


    // --- Motor Control ---

    if (adc_val < THRESH_LOW)

    {

      __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 6553); // Lambat

    }

    else if (adc_val < THRESH_MID)

    {

      __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 600); // Sedang

    }

    else

    {

      __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, 58981); // Cepat

    }


    // --- Buzzer Logic ---

    if (adc_val < THRESH_LOW && buzzer_enabled)

    {

      // Ubah frekuensi buzzer setiap 500ms

      if (HAL_GetTick() - last_buzzer_change >= 500)

      {

        last_buzzer_change = HAL_GetTick();

        buzzer_freq_index = (buzzer_freq_index + 1) % 3;


        uint32_t period = buzzer_periods[buzzer_freq_index];

        __HAL_TIM_SET_AUTORELOAD(&htim2, period);

        __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, period / 2); // 50% duty

      }

    }

    else

    {

      __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0); // Matikan buzzer

    }


    // --- Button Logic (PB0 ditekan = nonaktifkan buzzer) ---

    if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_0) == GPIO_PIN_SET)

    {

      buzzer_enabled = 0;

      __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_3, 0); // Paksa matikan buzzer

    }


    HAL_Delay(10);

  }

}



void SystemClock_Config(void)

{

  RCC_OscInitTypeDef RCC_OscInitStruct = {0};

  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};


  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_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_TIM1_Init(void)

{


  TIM_MasterConfigTypeDef sMasterConfig = {0};

  TIM_OC_InitTypeDef sConfigOC = {0};

  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};


  htim1.Instance = TIM1;

  htim1.Init.Prescaler = 0;

  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;

  htim1.Init.Period = 65535;

  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

  htim1.Init.RepetitionCounter = 0;

  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)

  {

    Error_Handler();

  }

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;

  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;

  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)

  {

    Error_Handler();

  }

  sConfigOC.OCMode = TIM_OCMODE_PWM1;

  sConfigOC.Pulse = 0;

  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;

  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;

  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;

  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;

  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)

  {

    Error_Handler();

  }

  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;

  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;

  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;

  sBreakDeadTimeConfig.DeadTime = 0;

  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;

  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;

  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;

  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)

  {

    Error_Handler();

  }


  HAL_TIM_MspPostInit(&htim1);


}


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

  __HAL_RCC_GPIOA_CLK_ENABLE();

  __HAL_RCC_GPIOB_CLK_ENABLE();


  /*Configure GPIO pin : PB0 */

  GPIO_InitStruct.Pin = GPIO_PIN_0;

  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;

  GPIO_InitStruct.Pull = GPIO_PULLUP;

  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


}


void Error_Handler(void)

{


  __disable_irq();

  while (1)

  {

  }


}


#ifdef  USE_FULL_ASSERT

void assert_failed(uint8_t *file, uint32_t line)

{


}

#endif /* USE_FULL_ASSERT */


5. Analisa[Kembali]









7. Download File[Kembali]

Video Demo Klik Disini

DataSheet STM32 Klik Disini

DataSheet Sensor Soil Moisture Klik Disini

DataSheet Buzzer Klik Disini

DataSheet LED RGB Klik disini

DataSheet Resistor Klik disini

Library Sensor Soil Moisture Klik Disini

Tidak ada komentar:

Posting Komentar