ESP32 S3 와 DM556 을 사용해서 스태핑 모터를 제어하는 방법이다.
다른 ESP32시리즈나 A4988 등 다른 드라이버를 사용해도 동일과정으로 구동할 수 있다.
VSCODE 에서 ESP-IDF 프레임워크를 사용한 방식이다.

ESP-IDF Welcome 페이지에서 New Project생성 후 탬플릿 선택에서 ESP-IDF 선택하고 step 을 검색하면 RMT 를 사용한 스태핑 모터 드라이벙 제어 예제가 나온다.

기본적으로 DRV8825 를 기준으로 한 예제 소스코드가 생성되고 이 상태에서 사용하는 드라이버나 핀에 알맞게 연결해서 사용 할 수 있다.

연결 모습
에노드 방식으로 연결 했고 ESP32 S3 를 전압 변경 없이 직접 연결했다.
DM556 에는 시그널 입력을 5~24V 입력하도록 되어있으나 테스트삼아 3.3v 로 직접 연결 했는데 간단한 테스트하기에 무리는 없는것 같다.
물론 드라이버의 전원은 24V 를 공급 해줘야 한다.
주의해야할 점은 처음 구동할 때 저속으로 제어하려고
#define STEP_MOTOR_RESOLUTION_HZ 을 100 으로 수정하고 빌드 - 플래쉬하는 과정에는 문제가 없었으나
플래쉬 후 모니터링 해보니 clock divider 값이 유효 범위(1~256)를 벗어났다는 오류와 함께 지속적으로 재부팅 되는 문제가 있었다.
큰 수정 없이 사용 가능한 최저속도는 312500Hz 로 테스트할 수 있다.
테스트 소스코드
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/rmt_tx.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "stepper_motor_encoder.h"
// DM556 연결 방식으로 수정한 핀 정보
#define STEP_MOTOR_GPIO_ENA 6
#define STEP_MOTOR_GPIO_DIR 5
#define STEP_MOTOR_GPIO_STEP 4
// Common Anode 방식으로 연결 시
#define STEP_MOTOR_ENABLE_LEVEL 1 // ENA 핀이 HIGH 여야 모터가 동작한다는것을 저장
#define STEP_MOTOR_SPIN_DIR_CLOCKWISE 0 //DIR은 LOW 일 때 시계방향임을 저장
#define STEP_MOTOR_SPIN_DIR_COUNTERCLOCKWISE !STEP_MOTOR_SPIN_DIR_CLOCKWISE // 반시계방향인 경우 !STEP_MOTOR_SPIN_DIR_CLOCKWISE 임
// #define STEP_MOTOR_RESOLUTION_HZ 312500 // 최저속도
#define STEP_MOTOR_RESOLUTION_HZ 1000000
static const char *TAG = "example";
void app_main(void)
{
ESP_LOGI(TAG, "Initialize EN + DIR GPIO");
gpio_config_t en_dir_gpio_config = {
.mode = GPIO_MODE_OUTPUT,
.intr_type = GPIO_INTR_DISABLE,
.pin_bit_mask = 1ULL << STEP_MOTOR_GPIO_DIR | 1ULL << STEP_MOTOR_GPIO_ENA,
};
ESP_ERROR_CHECK(gpio_config(&en_dir_gpio_config));
ESP_LOGI(TAG, "Create RMT TX channel");
rmt_channel_handle_t motor_chan = NULL;
rmt_tx_channel_config_t tx_chan_config = {
.clk_src = RMT_CLK_SRC_DEFAULT, // select clock source
.gpio_num = STEP_MOTOR_GPIO_STEP,
.mem_block_symbols = 64,
.resolution_hz = STEP_MOTOR_RESOLUTION_HZ,
.trans_queue_depth = 10, // set the number of transactions that can be pending in the background
};
ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &motor_chan));
ESP_LOGI(TAG, "Set spin direction");
gpio_set_level(STEP_MOTOR_GPIO_DIR, STEP_MOTOR_SPIN_DIR_CLOCKWISE);
ESP_LOGI(TAG, "Enable step motor");
gpio_set_level(STEP_MOTOR_GPIO_ENA, STEP_MOTOR_ENABLE_LEVEL);
ESP_LOGI(TAG, "Create motor encoders");
stepper_motor_curve_encoder_config_t accel_encoder_config = {
.resolution = STEP_MOTOR_RESOLUTION_HZ,
.sample_points = 500,
.start_freq_hz = 500,
.end_freq_hz = 1500,
};
rmt_encoder_handle_t accel_motor_encoder = NULL;
ESP_ERROR_CHECK(rmt_new_stepper_motor_curve_encoder(&accel_encoder_config, &accel_motor_encoder));
stepper_motor_uniform_encoder_config_t uniform_encoder_config = {
.resolution = STEP_MOTOR_RESOLUTION_HZ,
};
rmt_encoder_handle_t uniform_motor_encoder = NULL;
ESP_ERROR_CHECK(rmt_new_stepper_motor_uniform_encoder(&uniform_encoder_config, &uniform_motor_encoder));
stepper_motor_curve_encoder_config_t decel_encoder_config = {
.resolution = STEP_MOTOR_RESOLUTION_HZ,
.sample_points = 500,
.start_freq_hz = 1500,
.end_freq_hz = 500,
};
rmt_encoder_handle_t decel_motor_encoder = NULL;
ESP_ERROR_CHECK(rmt_new_stepper_motor_curve_encoder(&decel_encoder_config, &decel_motor_encoder));
ESP_LOGI(TAG, "Enable RMT channel");
ESP_ERROR_CHECK(rmt_enable(motor_chan));
ESP_LOGI(TAG, "Spin motor for 6000 steps: 500 accel + 5000 uniform + 500 decel");
rmt_transmit_config_t tx_config = {
.loop_count = 0,
};
const static uint32_t accel_samples = 500;
const static uint32_t uniform_speed_hz = 1500;
const static uint32_t decel_samples = 500;
while (1)
{
// acceleration phase
tx_config.loop_count = 0;
ESP_ERROR_CHECK(rmt_transmit(motor_chan, accel_motor_encoder, &accel_samples, sizeof(accel_samples), &tx_config));
// uniform phase
tx_config.loop_count = 5000;
ESP_ERROR_CHECK(rmt_transmit(motor_chan, uniform_motor_encoder, &uniform_speed_hz, sizeof(uniform_speed_hz), &tx_config));
// deceleration phase
tx_config.loop_count = 0;
ESP_ERROR_CHECK(rmt_transmit(motor_chan, decel_motor_encoder, &decel_samples, sizeof(decel_samples), &tx_config));
// wait all transactions finished
ESP_ERROR_CHECK(rmt_tx_wait_all_done(motor_chan, -1));
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
'ESP32 > ESP32-S3' 카테고리의 다른 글
| ESP-IDF ESP32 (ESP32-S3) 이산화 탄소 농도 센서 MH-Z19B 읽기 (1) | 2025.04.20 |
|---|---|
| ESP32 S3 디버그/업로드(USB OTG) 포트 시리얼 메세지 출력하는법 (0) | 2024.12.13 |