1. Prosedur [kembali]
Buat rangkaian di Proteus sesuai dengan skenario pada percobaan.
-
Kembangkan program mikrokontroler STM32F103C8 menggunakan STM32CubeIDE.
-
Kompilasi program menjadi file berekstensi
.hex
, lalu unggah ke mikrokontroler. -
Jalankan simulasi rangkaian yang telah dibuat di Proteus.
-
Proses selesai.
2. Hardware dan Diagram Blok [kembali]
Hardware :
1. Mikrokontroler STM32F103C8

2. Touch Sensor
3. Power Supply
4. Motor DC (Dinamo DC)
5. Motor Stepper
6. ULN2003A
7. Potensiometer
Diagram Blok:
3. Rangkaian Simulasi dan Prinsip Kerja [kembali]
Rangkaian

Prinsip Kerja
Deklarasi Variabel:
ADC_HandleTypeDef hadc1;
untuk menginisialisasi ADC.current_mode
untuk menentukan apakah motor berputar searah jarum jam (CW) atau berlawanan arah jarum jam (CCW).
Urutan Langkah Stepper:
STEP_SEQ_CW
danSTEP_SEQ_CCW
mendefinisikan urutan langkah motor untuk berputar searah atau berlawanan arah jarum jam.
Fungsi
RunStepper
:Digunakan untuk menggerakkan motor stepper sesuai dengan urutan langkah yang diberikan (
STEP_SEQ_CW
atauSTEP_SEQ_CCW
).
Fungsi
MX_ADC_Init
danMX_GPIO_Init
:MX_ADC_Init
mengonfigurasi ADC untuk membaca nilai dari saluran yang diinginkan.MX_GPIO_Init
mengonfigurasi GPIO untuk output motor dan input sensor.
Fungsi
SystemClock_Config
:Mengonfigurasi clock sistem, yang memastikan bahwa MCU bekerja dengan frekuensi yang benar.
Loop Utama:
Dalam loop utama, ADC dibaca dan motor stepper dijalankan berdasarkan nilai ADC (mode CW atau CCW).
Prinsip kerja dari kode ini terhadap rangkaian adalah sebagai berikut: mikrokontroler membaca nilai tegangan analog dari sebuah sensor melalui modul ADC (Analog to Digital Converter) yang telah dikonfigurasi menggunakan fungsi MX_ADC_Init
. Nilai ADC ini digunakan untuk menentukan arah putaran motor stepper, apakah searah jarum jam (CW) atau berlawanan arah jarum jam (CCW), dengan mengatur variabel current_mode
. Berdasarkan nilai ini, fungsi RunStepper
akan dipanggil untuk mengaktifkan urutan sinyal yang sesuai dari array STEP_SEQ_CW
atau STEP_SEQ_CCW
, dan sinyal tersebut dikirimkan ke pin-pin GPIO yang telah dikonfigurasi melalui fungsi MX_GPIO_Init
.
Secara fisik, sensor analog (seperti potensiometer atau sensor tekanan) dihubungkan ke salah satu pin ADC mikrokontroler (misalnya PA0). Kemudian, beberapa pin GPIO output (misalnya PA1–PA4) dihubungkan ke input driver motor stepper (seperti ULN2003 atau A4988). Driver ini bertugas menerima sinyal dari mikrokontroler dan mengatur arus ke fasa-fasa motor stepper. Output dari driver dihubungkan ke empat kabel fasa motor stepper, sehingga motor dapat berputar sesuai arah yang ditentukan. Catu daya eksternal (misalnya 12V) digunakan untuk memberi daya pada motor stepper melalui driver, sementara mikrokontroler mendapat catu daya terpisah melalui USB atau regulator (misalnya 5V/3.3V). Fungsi SystemClock_Config
memastikan sistem bekerja dengan frekuensi yang stabil. Dengan demikian, rangkaian ini bekerja secara otomatis dan dinamis, di mana perubahan nilai analog dari sensor langsung memengaruhi arah putaran motor stepper melalui kontrol logika yang dilakukan oleh mikrokontroler.
4. Flowchart dan Listing Program [kembali]
Flowchart
Listing Program
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private define ------------------------------------------------------------*/
// Konfigurasi PIN
#define STEPPER_PORT GPIOB
#define IN1_PIN GPIO_PIN_8
#define IN2_PIN GPIO_PIN_9
#define IN3_PIN GPIO_PIN_10
#define IN4_PIN GPIO_PIN_11
#define TOUCH_SENSOR_PORT GPIOB
#define TOUCH_SENSOR_PIN GPIO_PIN_0
#define MOTOR_DC_PORT GPIOB
#define MOTOR_DC_PIN GPIO_PIN_7
/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
const uint8_t STEP_SEQ_CCW[4] = {
(1<<0), // IN1
(1<<3), // IN4
(1<<2), // IN3
(1<<1) // IN2
};
const uint8_t STEP_SEQ_OSC[4] = {
(1<<0),
(1<<1),
(1<<2),
(1<<3)
};
uint8_t step_index = 0;
uint8_t osc_direction = 1;
uint32_t last_step_time = 0;
/* Function prototypes -------------------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
void RunStepperCCW(const uint8_t *sequence, uint8_t speed);
void RunStepperOscillate(const uint8_t *sequence, uint8_t speed);
void Error_Handler(void);
/* Main function -------------------------------------------------------------*/
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_ADC1_Init();
while (1)
{
GPIO_PinState touchState = HAL_GPIO_ReadPin(TOUCH_SENSOR_PORT, TOUCH_SENSOR_PIN);
if (touchState == GPIO_PIN_SET)
{
HAL_GPIO_WritePin(MOTOR_DC_PORT, MOTOR_DC_PIN, GPIO_PIN_SET); // DC ON
HAL_GPIO_WritePin(STEPPER_PORT, IN1_PIN | IN2_PIN | IN3_PIN | IN4_PIN, GPIO_PIN_RESET); // Stepper OFF
}
else
{
HAL_GPIO_WritePin(MOTOR_DC_PORT, MOTOR_DC_PIN, GPIO_PIN_RESET); // DC OFF
HAL_ADC_Start(&hadc1);
if (HAL_ADC_PollForConversion(&hadc1, 10) == HAL_OK)
{
uint16_t adc_val = HAL_ADC_GetValue(&hadc1);
if (adc_val >= 2048)
{
RunStepperCCW(STEP_SEQ_CCW, 5);
}
else
{
RunStepperOscillate(STEP_SEQ_OSC, 5);
}
}
HAL_ADC_Stop(&hadc1);
}
HAL_Delay(1);
}
}
/* Stepper CCW Rotation ------------------------------------------------------*/
void RunStepperCCW(const uint8_t *sequence, uint8_t speed)
{
if (HAL_GetTick() - last_step_time >= speed)
{
HAL_GPIO_WritePin(STEPPER_PORT, IN1_PIN, (sequence[step_index] & (1<<0)) ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(STEPPER_PORT, IN2_PIN, (sequence[step_index] & (1<<1)) ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(STEPPER_PORT, IN3_PIN, (sequence[step_index] & (1<<2)) ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(STEPPER_PORT, IN4_PIN, (sequence[step_index] & (1<<3)) ? GPIO_PIN_SET : GPIO_PIN_RESET);
step_index = (step_index + 1) % 4;
last_step_time = HAL_GetTick();
}
}
/* Stepper Oscillation Mode --------------------------------------------------*/
void RunStepperOscillate(const uint8_t *sequence, uint8_t speed)
{
if (HAL_GetTick() - last_step_time >= speed)
{
HAL_GPIO_WritePin(STEPPER_PORT, IN1_PIN, (sequence[step_index] & (1<<0)) ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(STEPPER_PORT, IN2_PIN, (sequence[step_index] & (1<<1)) ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(STEPPER_PORT, IN3_PIN, (sequence[step_index] & (1<<2)) ? GPIO_PIN_SET : GPIO_PIN_RESET);
HAL_GPIO_WritePin(STEPPER_PORT, IN4_PIN, (sequence[step_index] & (1<<3)) ? GPIO_PIN_SET : GPIO_PIN_RESET);
if (osc_direction) {
step_index++;
if (step_index >= 3) osc_direction = 0;
} else {
if (step_index == 0) osc_direction = 1;
else step_index--;
}
last_step_time = HAL_GetTick();
}
}
/* ADC1 Init -----------------------------------------------------------------*/
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; // PA0
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
Error_Handler();
}
}
/* GPIO Init -----------------------------------------------------------------*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
// Touch Sensor
GPIO_InitStruct.Pin = TOUCH_SENSOR_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(TOUCH_SENSOR_PORT, &GPIO_InitStruct);
// DC Motor
GPIO_InitStruct.Pin = MOTOR_DC_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(MOTOR_DC_PORT, &GPIO_InitStruct);
// Stepper Motor
GPIO_InitStruct.Pin = IN1_PIN | IN2_PIN | IN3_PIN | IN4_PIN;
HAL_GPIO_Init(STEPPER_PORT, &GPIO_InitStruct);
}
/* Clock Config --------------------------------------------------------------*/
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();
}
}
/* Error Handler -------------------------------------------------------------*/
void Error_Handler(void)
{
__disable_irq();
while (1) {}
}
Percobaan 8 Kondisi 4
Buatlah rangkaian seperti gambar pada percobaan 8. Jika touch sensor mendeteksi maka motor dc berputar. Jika potensiometer bernilai besar maka motor stepper bergerak berlawanan jarum jam dan jika bernilai rendah maka motor stepper bergerak dengan Oscillate Mode0
6. Video Simulasi [kembali]
Tidak ada komentar:
Posting Komentar