Menggunakan Stepper Motor Pada ESP32

Pendahuluan

Banyak tipe motor, salah satunya adalah stepper motor, digunakan ketika dibutuhkan presisi dan speed control. Contohnya adalah printers, plotters, atau computer numerical control
(CNC).

Untuk menjalankan stepper motor diperlukan component tambahan yatiu open-loop stepper
driver chip. Microcontroller akan mengirimkan perintah ke stepper driver chip untuk mengatur posisi dan speed.

Kekurangan dari stepper motor adalah selalu menggunakan arus maksimum terlepas apakah itu berputar atau tidak, jadi diperlukan power source.

Pada contoh project, kita akan jalankan stepper motor berdasarkan input dari rotary encoder.

Component

  • 28BYJ-48 stepper motor
  • A4988 motor driver module
  • pull-up resistor (4.7 k ohm)
  • decoupling capacitor (100uF)—(optional)
  • rotary encoder

Diagram

A rotary encoder menyediakan 2 outputs ke microcontroller: Output A (CLK) dan Output B (DT). Dengan membaca outputs terebut kita dapat mengetahui arah dan posisi dari rotary encoder.

Koneksi dari rotary encoder adalah:

  • Output A to GPIO19
  • Output B to GPIO21

Module lainnya adalah A4988 motor driver module. Kita tidak dapat drive motor secara langsung dikarenakan motor memerlukan power. Perlu digunakan intermediary chip, disebut motor driver chip. Yang akan menyediakan interfaces untuk microcontroller dan motor.

Koneksi motor driver module dengan ESP32

  • Pin-1 (EN) to LOW
  • Pin-2 (MS1) , Pin-3 (MS2), and Pin-4 (MS3) to LOW
  • Pin-5 (RST) and Pin-6 (SLP) to HIGH
  • Pin-7 (STEP) to ESP32/GPIO23
  • Pin-8 (DIR) to ESP32/GPIO22
  • Pin-9 (GND) to GND
  • Pin-10 (VDD) to 3.3 V

Untuk koneksi pada motor, perlu membaca datasheet dari motor. Pada contoh digunakan 28BYJ-48, koneksi yang digunakan seperti berikut

  • Pin-11 (1B) to motor/orange
  • Pin-12 (1A) to motor/yellow
  • Pin-13 (2A) to motor/pink
  • Pin-14 (2B) to motor/blue
  • Pin-15 (GND) to GND
  • Pin-16 (VMOT) to 12 V

Ada beberapa tindakan pencegahan penting yang perlu dilakukan sebelum menggunakan A4988 motor driver module:

  • Pastikan motor terhubung (four pins) dengan benar dan kuat dengan module pins sebelum dinyalakan.
  • Module memiliki fitur current-limiting. Terdapat pot on untuk set current limit. (silakan lihat datasheet). Value yang aman sekitar 0.10 V.
  • Anda dapat gunakan decoupling capacitor, 100uF, diantara VMOT dan GND untuk melindungi module dari voltage spikes. Jika Anda menggunakan power source yang teregulasi dengan baik, Anda tidak perlu menggunakan capacitor.
  • Gunakan heatsink pada A4988 chip untuk mencegah overheat. Biasanya sudah disediakan bersama module.

Code

Pada code diperlukan rotenc library untuk menjalankan rotary encoder. download di https://drive.google.com/drive/folders/1jyCJCxBmLzERb3MSnpfYRJLGNGWnbzsI?usp=sharing

Simpan pada direktory lib pada project Anda.

//bagian import library
#include <stdio.h>
#include <stddef.h>
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "rotenc.h"
#include "driver/mcpwm.h"
#include "soc/mcpwm_periph.h"
#define ROTENC_CLK_PIN 19
#define ROTENC_DT_PIN 21
#define MOTOR_DIR_PIN 22
#define MOTOR_STEP_PIN 23

//bagian init hardware
static void init_hw(void)
{
    rotenc_init(ROTENC_CLK_PIN, ROTENC_DT_PIN);
    gpio_config_t io_conf;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.pull_down_en = 0;
    io_conf.pull_up_en = 0;
    io_conf.pin_bit_mask = 0;
    io_conf.pin_bit_mask |= (1ULL << MOTOR_DIR_PIN);
    gpio_config(&io_conf);
    mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, MOTOR_STEP_PIN);
    mcpwm_config_t pwm_config;
    pwm_config.frequency = 250;
    pwm_config.cmpr_a = 0;
    pwm_config.cmpr_b = 0;
    pwm_config.counter_mode = MCPWM_UP_COUNTER;
    pwm_config.duty_mode = MCPWM_DUTY_MODE_0;
    mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config);
}

//bagian menampilkan pos
static int rotenc_pos = 0;
static int motor_pos = 0;
static void print_rotenc_pos(void *arg)
{
    while (1)
    {
        rotenc_pos = rotenc_getPos();
        printf("pos: %d\n", rotenc_pos);
        vTaskSuspend(NULL);
    }
}

//bagian main app
void app_main()
{
    init_hw();
    rotenc_setPosChangedCallback(print_rotenc_pos);
    mcpwm_set_duty_in_us(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_GEN_A, 4000);
    int steps;
    int step_delay = 100;
    while (1)
    {
        if (motor_pos == rotenc_pos)
        {
            vTaskDelay(100);
            continue;
        }
        steps = rotenc_pos - motor_pos;
        motor_pos = rotenc_pos;
        gpio_set_level((gpio_num_t)MOTOR_DIR_PIN, steps > 0);
        vTaskDelay(10);
        mcpwm_set_duty(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_GEN_A, 50);
        mcpwm_set_duty_type(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_GEN_A, MCPWM_DUTY_MODE_0);
        vTaskDelay(step_delay * abs(steps) / portTICK_PERIOD_MS);
        mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_GEN_A);
    }
}

Penjelasan Code

Bagian Import library

Pada bagian ini kita include files header yang diperlukan dan define the pins. Rotary encoder driver functionality didefinisikan pada file rotenc.h.

Untuk drive motor, kita gunakan Motor Control PWM (MCPWM) library dari ESP-IDF.

Bagian hardware init

Pada fungsi init_hw, kita inisialisasi GPIO pins, baik untuk rotary encoder dan motor driver.

rotenc_init akan mengkofigurasi rotary encoder pins sebagai input. Set MOTOR_DIR_PIN sebagai output.

Kemudian kita inisialisasi MCPWM signal pin dengan perintah mcpwm_gpio_init, dengan parameter:

  • MCPWM unit. ESP32 memiliki 2 PWM yang dapat digunakan.
  • Output channel. Setiap MCPWM unit memiliki 3 pasang output channels.
  • GPIO pin yang terhubung dengan channel.

Kita hanya memerlukan satu channel untuk menjalankan motor dengan menghubungkan GPIO pin ke direction signal dari motor.

Fungsi mcpwm_init akan meng-inisialisasi MCPWM dengan menggunakan default
values. Kita juga spesifikasikan timer yang akan digunakan oleh unit.

Bagian menampilkan pos

Digunakan dua global variables untuk position. rotenc_pos untuk current rotary
encoder position, yang dapat diakase melalui rotenc_getPos.

Fungsi print_rotenc_pos adalah task function yang dilanjutkan oleh ISR dari pin input rotary encoder.

Bagian fungsi utama

Pada fungsi app_main, kita set position changed callback function dengan memanggil rotenc_setPosChangedCallback untuk mengetahui posisi rotary encoder.

Kemudian kita jalankan mcpwm_set_duty_in_us untuk mengatur PWM duty duration menjadi 4
ms—makin pendek durasi, motor berputar makin cepat. Motor akan melakukan 1 step setiap duty.

Pada while loop, kita track posisi rotary encoder, dan ubah posisi motor ke posisi yang sama menggunakan MCPWM.

Pertama, kita set direction dengan memeriksa sign dari steps.

Untuk menjalankan PWM, kita panggil 2 fungsi, mcpwm_set_duty dan mcpwm_set_duty_type.

MCPWM akan mengenerate signal pada step signal pin, dimana dihitung menggunakan step_delay * abs(steps) /portTICK_PERIOD_MS ms.

Karena duty cycle adalah 4 ms, kita dapat mengetahui berapa steps dengan membagi dengan 4. Nilai ini adalah real steps yang akan dilakukan oleh motor.

Setelah delay, kita panggil mcpwm_set_signal_low untuk memberhentikan MCPWM dan motor.

Sampai disini kita sudah berhasil menjalankan stepper motor. Pada modul berikutnya akan membahas penggunaan display, agar pengguna dapat melihat output pada screen.

Sharing is caring:

Leave a Comment