LA2 MODUL 2




1. Prosedur [Kembali]

Percobaan ini bertujuan untuk membuat sistem peringatan berbasis cahaya menggunakan sensor LDR dan buzzer dengan mikrokontroler STM32F103C8. Alat dan bahan yang diperlukan dalam rangkaian ini adalah satu buah mikrokontroler STM32F103C8 (Blue Pill), sebuah sensor LDR, sebuah buzzer, satu buah transistor BD139, sebuah resistor 10kΩ sebagai pull-down, sebuah resistor 2.2kΩ untuk basis transistor, kabel jumper, breadboard, dan sumber daya 3.3V serta 5V.

Langkah pertama, siapkan semua alat dan bahan yang diperlukan dan pastikan dalam kondisi baik. Selanjutnya, pasang sensor LDR dengan cara menghubungkan salah satu kakinya ke jalur +3.3V, sementara kaki lainnya dihubungkan pada mikrokontroler STM32F103C8. Pada kaki LDR yang terhubung seri resistor 10kΩ sebagai pull-down dengan menghubungkannya ke ground, agar nilai pada pin ADC tetap stabil saat tidak ada cahaya.

Kemudian, rangkai buzzer dengan cara menghubungkan kaki positif buzzer ke jalur +5V, dan kaki negatifnya ke kaki kolektor transistor BD139. Kaki emitor transistor dihubungkan ke ground, sedangkan kaki basis transistor dihubungkan ke pin PA0 pada STM32F103C8 melalui resistor 2.2kΩ. Setelah itu, sambungkan jalur 3.3V ke pin VDDA dan VDD mikrokontroler, serta pastikan semua ground dari komponen dihubungkan ke ground bersama.

Setelah perakitan selesai, program mikrokontroler menggunakan STM32CubeIDE atau software sejenis. Program berfungsi untuk membaca nilai ADC dari LDR dan menentukan kondisi cahaya di sekitar. Jika nilai lux lebih rendah dari ambang batas yang ditentukan, maka pin PA0 akan aktif (HIGH) sehingga transistor BD139 mengalirkan arus ke buzzer dan buzzer berbunyi. Sebaliknya, saat cahaya cukup terang, buzzer akan mati.

Langkah terakhir adalah melakukan pengujian dengan cara menutup atau membuka sumber cahaya di sekitar LDR. Amati apakah buzzer berbunyi saat kondisi cahaya rendah dan berhenti saat cahaya terang. Selain itu, nilai ADC atau lux yang terbaca dapat ditampilkan di terminal untuk memastikan sensor LDR bekerja dengan baik. Jika semua berfungsi sesuai yang diharapkan, maka rangkaian telah selesai dibuat dan diuji.

2. Hardware dan Diagram Blog [Kembali]

Hardware 
  • STM32F103C8


STM32F103C8 adalah mikrokontroler 32-bit yang diproduksi oleh STMicroelectronics. Mikrokontroler ini termasuk dalam keluarga STM32 yang menggunakan inti ARM Cortex-M3. STM32F103C8 dilengkapi dengan berbagai fitur, seperti memori flash 64KB, SRAM 20KB, dan banyak pin I/O (Input/Output) untuk berbagai aplikasi.
  • Resistor 10K dan 2.2k ohm
Resistor adalah komponen elektronik yang berfungsi untuk menghambat arus listrik dalam suatu rangkaian. Nilai hambatan resistor diukur dalam ohm (Ω) dan sering digunakan untuk mengontrol tegangan, membatasi arus, serta melindungi komponen lain seperti LED dari kerusakan akibat arus berlebih. Resistor tersedia dalam berbagai jenis, seperti tetap, variabel (potensiometer), dan termistor yang peka terhadap suhu.

  • Push Button
Push button adalah sakelar mekanik yang bekerja saat ditekan dan kembali ke posisi semula saat dilepas. Komponen ini digunakan untuk mengaktifkan atau menonaktifkan sirkuit listrik, seperti dalam sistem kontrol, input pengguna pada perangkat elektronik, dan tombol reset atau start dalam rangkaian mikroprosesor. Push button sering dikombinasikan dengan mikrokontroler untuk menangkap input pengguna dalam berbagai aplikasi interaktif.
  • LDR


LDR (Light Dependent Resistor) adalah jenis resistor yang nilai resistansinya berubah tergantung pada intensitas cahaya yang diterimanya. Ketika cahaya jatuh pada permukaan LDR, resistansinya akan menurun, sementara dalam kondisi gelap, resistansinya akan meningkat. Fungsi utama LDR adalah untuk mendeteksi tingkat cahaya, yang sering digunakan dalam aplikasi seperti pengaturan otomatis pencahayaan, sensor cahaya pada perangkat elektronik, serta sebagai input pada sistem pengukuran intensitas cahaya atau pengendalian pencahayaan secara otomatis.
  • Buzzer


Buzzer adalah komponen elektronik yang menghasilkan suara sebagai output dari sinyal listrik yang diterimanya. Buzzer biasanya digunakan untuk memberi tanda atau peringatan melalui suara dalam berbagai perangkat, seperti alarm, perangkat pengingat, atau sistem kontrol. Terdapat dua jenis buzzer, yaitu piezoelectric dan elektromagnetik. Buzzer piezoelectric bekerja dengan mengubah sinyal listrik menjadi getaran mekanik yang menghasilkan suara, sedangkan buzzer elektromagnetik menghasilkan suara dengan cara menggerakkan membran menggunakan medan magnet. Buzzer sering digunakan dalam aplikasi yang membutuhkan pemberitahuan atau peringatan suara, seperti alarm keamanan, timer, atau indikator status perangkat.
  • Motor DC


Motor DC (Direct Current) adalah jenis motor listrik yang beroperasi menggunakan arus searah (DC). Motor ini mengubah energi listrik menjadi energi mekanik untuk menghasilkan gerakan rotasi. Motor DC memiliki dua komponen utama, yaitu stator (bagian diam) dan rotor (bagian yang berputar). Motor DC digunakan dalam berbagai aplikasi untuk menggerakkan perangkat mekanik, seperti dalam robotika, kendaraan listrik, kipas angin, dan sistem penggerak otomatis lainnya. Motor DC dapat dikendalikan kecepatan rotasinya dengan mengubah tegangan atau arus yang diberikan.

Blok Diagram :





Rangkaian ini dirancang untuk mengendalikan motor DC dan buzzer berdasarkan input dari sensor LDR yang terhubung dengan mikrokontroler STM32F103C8 melalui pembacaan nilai ADC. Sensor LDR akan mendeteksi intensitas cahaya dan menghasilkan sinyal analog yang dikonversi menjadi nilai digital oleh ADC. Nilai ADC yang diterima akan digunakan untuk mengatur kecepatan motor DC melalui PWM pada TIM1. Terdapat tiga kondisi yang berbeda berdasarkan nilai ADC: jika nilai ADC kurang dari 1500, motor akan berputar dengan kecepatan rendah; jika nilai ADC antara 1500 dan 3000, motor akan berputar dengan kecepatan sedang; dan jika nilai ADC lebih dari 3000, motor akan berputar dengan kecepatan tinggi.

Selain itu, buzzer yang terhubung ke TIM2 akan berbunyi saat nilai ADC kurang dari 1500, dengan frekuensi buzzer yang berubah setiap 500 ms. Frekuensi buzzer ini dikontrol melalui perioda timer yang diatur dalam array buzzer_periods[]. Jika nilai ADC lebih dari 1500, buzzer akan dimatikan. Terdapat juga kontrol manual untuk mematikan buzzer, yaitu dengan menekan tombol yang terhubung ke PB0. Jika tombol ditekan, buzzer akan dimatikan paksa, dan PWM pada TIM2 akan dihentikan, mematikan buzzer secara langsung.

Secara keseluruhan, rangkaian ini mengintegrasikan sensor LDR, motor DC, buzzer, dan tombol untuk menciptakan sistem yang merespons perubahan cahaya dengan mengubah kecepatan motor dan menghasilkan suara dari buzzer, serta memungkinkan kontrol manual untuk mematikan buzzer.

4. Flowchart dan Listing Program [Kembali]

- Flowchart






-  Listing Program
#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. Video Demo [Kembali]



6. Kondisi [Kembali]

Ketika nilai ADC dari sensor LDR kurang dari 1500, motor DC berputar pelan (duty cycle 10%) dan buzzer aktif dengan frekuensi berubah. Jika nilai ADC antara 1500-3000, motor berputar sedang (duty cycle 1%) dan buzzer mati. Jika nilai ADC lebih dari 3000, motor berputar cepat (duty cycle 90%) dan buzzer tetap mati. Tombol PB0 dapat mematikan buzzer secara paksa meskipun motor tetap berputar

7. Analisa [Kembali]

ANALISA MODUL 2: PWM, ADC, INTERRUPT, & MILLIS 

1. Analisa bagaimana perbedaan implementasi PWM antara STM32 dan Raspberry Pi Pico serta dampaknya terhadap kontrol motor dan buzzer
jawab:
STM32 memiliki timer khusus yang lebih fleksibel dan presisi untuk menghasilkan sinyal PWM, memungkinkan kontrol motor dan buzzer yang sangat halus dan akurat. Konfigurasi melibatkan register-register timer dan pemilihan fungsi alternatif pin.
Raspberry Pi Pico juga dapat menghasilkan PWM, seringkali dengan kontrol perangkat lunak atau blok PWM khusus yang mungkin tidak sefleksibel STM32 dalam pengaturan detail. Namun, untuk banyak aplikasi dasar, performanya sudah memadai.


2. Analisa bagaimana cara pembacaan nilai sensor analog (LDR) menggunakan ADC pada STM32 dan Raspberry Pi Pico
jawab:
 STM32 biasanya memiliki beberapa saluran ADC dengan resolusi tinggi (misalnya 12-bit), memungkinkan pembacaan nilai analog dengan akurasi tinggi melalui konfigurasi register ADC.
 Raspberry Pi Pico juga memiliki ADC, meskipun spesifikasinya bisa berbeda. Pembacaan nilai analog dilakukan melalui fungsi-fungsi yang disediakan oleh SDK Pico.


3. Analisa bagaimana penggunaan interrupt eksternal dalam mendeteksi input dari sensor atau tombo pada STM32 dan Raspberry Pi Pico.
jawab:
Baik STM32 maupun Raspberry Pi Pico mendukung interrupt eksternal, yang memungkinkan mikrokontroler merespon perubahan sinyal pada pin tertentu tanpa perlu terus-menerus melakukan polling.
Konfigurasi melibatkan pemilihan pin dan jenis pemicu interrupt. STM32 seringkali menawarkan lebih banyak pilihan konfigurasi interrupt dibandingkan Pico.


4. Analisa bagaimana cara kerja fungsi utime.ticks_ms() pada Raspberry Pi Pico dalam menghitung waktu sejak sistem dinyalakan
jawab:
Fungsi utime.ticks_ms() pada Raspberry Pi Pico bekerja dengan membaca nilai counter dari timer internal (bagian dari chip RP2040) yang terus berjalan sejak sistem dinyalakan. Nilai yang dikembalikan adalah jumlah milisekon yang telah berlalu.
STM32 juga memiliki mekanisme serupa menggunakan SysTick timer atau general-purpose timer yang perlu dikonfigurasi untuk menghitung waktu

5. Analisa bagaimana perbedaan konfigurasi dan kontrol pin PWM serta pemanfaatan timer internal pada STM32 dan Raspberry Pi Pico dalam menghasilkan sinyal gelombang persegi.
jawab:
STM32 memberikan kontrol yang lebih mendalam dalam konfigurasi pin PWM (melalui fungsi alternatif dan register timer) dan pemanfaatan timer internal untuk menghasilkan sinyal gelombang persegi dengan frekuensi dan duty cycle yang sangat presisi.
Raspberry Pi Pico juga menggunakan timer internal untuk menghasilkan PWM, tetapi konfigurasinya seringkali lebih disederhanakan melalui fungsi-fungsi SDK. Tingkat kontrol detail mungkin tidak sebanyak pada STM32.

8. Download File [Kembali]

Tidak ada komentar:

Posting Komentar

  BAHAN PRESENTASI UNTUK MATA KULIAH  SISTEM DIGITAL 2024 OLEH: Afifah Febry Nabilla 2210952001 Dosen Pengampu: Darwison, M.T Referensi:  a....