Laporan Akhir M2 Percobaan 7

 




 1. Prosedur  [kembali]

  1. 1. Persiapan Alat dan Bahan

  • STM32F103C8T6

  • 1 buah Soil Moisture Sensor

  • 1 buah push button

  • 1 buah Buzzer

  • 1 buah LED RGB

  • 3 buah Resistor

  • 1 buah potentiometer

  • Kabel jumper

  • Aplikasi Proteus 8.17

            

  1. 2. Perakitan Rangkaian

  1. Rakit rangkaian sesuai skema Section 3. Pastikan GND bersama antara sensor dan MCU.
  2. Nyalakan board dan pastikan ADC dapat membaca (bisa tampilkan di serial monitor untuk debugging).
  3. Kalibrasi sensor seperti langkah 4, catat dry_val, normal_val, wet_val, hitung T1, T2.
  4. Upload program dengan ambang yang dihitung atau program kalibrasi otomatis.
  5. Uji kondisi kering: angkat probe dari tanah → seharusnya LED hijau, buzzer mati. Catat pembacaan ADC.
  6. Uji kondisi normal: tanam probe di tanah dengan kelembaban biasa → LED merah, buzzer mati. Catat ADC.
  7. Uji kondisi basah: celupkan probe ke air atau tanah sangat basah → LED biru, buzzer berbunyi.
  8. Tekan tombol saat buzzer berbunyi → buzzer harus mati. Lepas tombol → tergantung implementasi, bisa tetap mati (latching) atau kembali menyala jika masih basah (jika Anda ingin reset otomatis, hapus latch).
  9. Ulangi beberapa kali untuk verifikasi stabilitas & adjust ambang jika perlu.

2. Hardware dan Diagram Blok [kembali]


2.1 Daftar Komponen

  • 1 × Mikrokontroler STM32F103C8T6

Otak utama sistem, memproses input dari sensor dan tombol lalu mengontrol output (LED dan buzzer).
Gambar STM32F103C8T6

Spesifikasi Mikrokontroler STM32F103C8T6

  • 1 × Buzzer (aktif atau pasif — rekomendasi: buzzer aktif 3.3V)

Gambar Buzzer


  • 1 × Soil Moisture Sensor Obstacle

Gambar Soil Moisture Sensor


  • 1 × Push button (tact switch)

.
Gambar Push Button (tact Switch)

  • 1 x LED RGB (Common Cathode) 

Menampilkan warna berdasarkan kondisi input.


  • Resistor (R1, R2, R3, R4)

Pembatas arus untuk LED dan tombol, mencegah kerusakan komponen.


  • 1 x Potentiometer

Gambar Potentiometer


  • Kabel Jumper

Gambar Kabel Jumper

2.2 Diagram Blok





3. Rangkaian Simulasi dan Prinsip Kerja [kembali]

3.1 Rangkaian Simulasi


Gambar Rangkaian Percobaan 7

3.2 Prinsip Kerja

Prinsip kerja rangkaian ini adalah mikrokontroler membaca nilai kelembaban tanah melalui sensor yang terhubung pada pin ADC. Nilai tersebut kemudian dibandingkan dengan batas ambang yang telah ditentukan untuk menentukan kondisi tanah. Jika tanah dalam keadaan kering maka LED hijau akan menyala dan buzzer tetap mati, sedangkan jika tanah berada pada kondisi normal maka LED merah akan menyala dan buzzer juga tidak aktif. Namun, ketika tanah terdeteksi basah maka LED biru akan menyala dan buzzer diaktifkan dengan sinyal PWM sebagai tanda peringatan. Buzzer ini dapat dimatikan sementara oleh pengguna dengan menekan push button, sehingga sistem tidak terus-menerus mengeluarkan bunyi meskipun kondisi tanah masih basah. Dengan demikian, rangkaian ini bekerja sebagai indikator visual melalui LED RGB sekaligus sebagai indikator suara melalui buzzer untuk memberikan informasi kondisi kelembaban tanah secara real time.



4. Flowchart dan Listing Program [kembali]
    
4.1 Flow Chart



4.2 Listing Program

/* USER CODE BEGIN Header */

/**

******************************************************************************

* @file : main.c

* @brief : Main program body

******************************************************************************

*/

/* USER CODE END Header */


/* Includes ------------------------------------------------------------------*/

#include "main.h"

#include "stm32f1xx_hal.h"

#include "stm32f1xx_hal_tim.h"


/* Private define ------------------------------------------------------------*/

#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


/* USER CODE BEGIN PD */

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

/* USER CODE END PD */


/* Private variables ---------------------------------------------------------*/

ADC_HandleTypeDef hadc1;

TIM_HandleTypeDef htim2;

uint8_t sound_pattern = 0;


/* Private 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 update_leds_and_buzzer(uint32_t adc_val, uint8_t btn_state);

void change_sound_pattern(void);

void Error_Handler(void);


/* -------------------------------------------------------------------------- */

/* Main program */

/* -------------------------------------------------------------------------- */

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


/* Baca ADC tiap 200 ms */

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

}

}


/* Ubah pola suara tiap 1 detik jika tombol ditekan dan ADC rendah */

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

}

}


/* -------------------------------------------------------------------------- */

/* Function Implementations */

/* -------------------------------------------------------------------------- */

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

}

}


/* -------------------------------------------------------------------------- */

/* Peripheral Initialization */

/* -------------------------------------------------------------------------- */


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_TIM2_Init(void)

{

TIM_OC_InitTypeDef sConfigOC = {0};


htim2.Instance = TIM2;

htim2.Init.Prescaler = 72 - 1; // Timer clock 1 MHz (jika HCLK 72 MHz)

htim2.Init.CounterMode = TIM_COUNTERMODE_UP;

htim2.Init.Period = 1000 - 1; // Default period = 1 kHz

htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

if (HAL_TIM_PWM_Init(&htim2) != 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();

}

}


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


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


/* PB0 sebagai input tombol */

GPIO_InitStruct.Pin = BUTTON_PIN;

GPIO_InitStruct.Mode = GPIO_MODE_INPUT;

GPIO_InitStruct.Pull = GPIO_NOPULL;

HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct);


/* 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);

}


void Error_Handler(void)

{

__disable_irq();

while (1) { }

}


Penjelasan listing program:

1. Bagian Header & Include
#include "main.h"
#include "stm32f1xx_hal.h"
#include "stm32f1xx_hal_tim.h"
  • Menggunakan library HAL STM32F1xx untuk GPIO, ADC, dan Timer (PWM).
2. Define Pin & Threshold
#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
  • LED RGB ada di PB12, PB13, PB14.

  • Tombol ada di PB0.

  • Nilai ADC dibagi menjadi 3 zona:

    • >= 3000tinggi.

    • 1500–2999sedang.

    • < 1500rendah.

3. Variabel Global
const uint32_t pwm_periods[] = {1000, 50000, 719999};
uint8_t sound_pattern = 0;
  • pwm_periods[] → berisi 3 nilai periode PWM untuk menghasilkan frekuensi bunyi buzzer yang berbeda.

  • sound_pattern → penanda pola suara (0–2).


4. Inisialisasi Peripheral
  • SystemClock_Config: Konfigurasi clock system (pakai HSI internal).

  • MX_GPIO_Init: Mengatur PB0 sebagai input tombol, PB12–PB14 sebagai output LED.

  • MX_ADC1_Init: Mengaktifkan ADC1 untuk membaca channel 0.

  • MX_TIM2_Init: Timer2 channel 3 sebagai PWM untuk buzzer

Prescaler = 71 → clock timer jadi 1 MHz.

5. Fungsi Utama (main)
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);
  • Inisialisasi semua modul.

  • Mulai PWM pada TIM2_CH3 (awal duty = 0 → buzzer diam).

  • Mulai ADC1.

Loop utama
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);
  • Simpan waktu terakhir pembacaan ADC dan perubahan pola suara.

  • Baca status tombol (PB0).

a. Baca ADC setiap 200 ms
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);
  }
}
  • Setiap 200 ms, baca nilai ADC.

  • Hasil ADC digunakan untuk mengatur LED dan buzzer lewat fungsi update_leds_and_buzzer().

b. Ubah pola suara tiap 1 detik
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();
  }
}
  • Jika tombol ditekan dan ADC < 1500 (zona rendah), maka setiap 1 detik pola bunyi buzzer diganti.
6. Fungsi Kontrol LED & Buzzer
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);

Pertama, matikan semua LED.

  • ADC >= 3000 → LED hijau ON, buzzer mati

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);
}
  • 1500–2999 → LED biru ON, buzzer mati
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);
}
  • < 1500 → LED merah ON, buzzer aktif jika tombol ditekan
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);
  }
}

7. Fungsi Ganti Pola Suara
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);
  }
}
  • Setiap kali dipanggil, pola suara (sound_pattern) bergeser: 0 → 1 → 2 → kembali ke 0.

  • Kalau ADC rendah dan tombol dilepas, buzzer langsung mainkan pola suara baru.

8. Prinsip Kerja (Ringkas)
  • ADC membaca nilai sensor → dipakai untuk menentukan LED mana yang menyala (Hijau, Biru, atau Merah).

  • Buzzer (PWM) hanya aktif kalau sensor dalam kondisi rendah (<1500) dan tombol ditekan.

  • Pola bunyi buzzer bisa diubah dengan cara menahan tombol saat ADC rendah, pola berubah setiap 1 detik.

  • Ada 3 pola suara (frekuensi berbeda) sesuai isi array pwm_periods[].





5. Video Demo [kembali]







6. Kondisi [kembali]
    
Buatlah rangkaian seperti gambar pada percobaan 7. Buatlah ketika soil moisture sensor mendeteksi kelembaban tanah kering maka LED RGB akan menampilkan warna Hijau dan ketika kelembaban tanah normal maka LED RGB menampilkan warna merah dan ketika kelembabannya basah maka LED RGB akan menampilkan warna biru dan Buzzer aktif. ketika push button ditekan maka buzzer akan mati. 
    

7. Video Simulasi [kembali]   







8. Download File  [kembali]
   
   Download rangkaian simulasi [link]
    Download Video Simulasi [link]
    Download Video Demo [link]
    Download Datasheet STM32F103C8T6 [link]
    Download Datasheet Soil Moisture Sensor [link]
    Download Datasheet Buzzer [link]       
    Download Datasheet Push Button [link]
    Download Datasheet LED RGB [link]
    Download Datasheet Resistor [link]
   

Comments

Popular posts from this blog