Skip to content

Instantly share code, notes, and snippets.

@fajarlabs
Created July 6, 2025 14:06
Show Gist options
  • Save fajarlabs/c785acf3596944f81b157813fefba787 to your computer and use it in GitHub Desktop.
Save fajarlabs/c785acf3596944f81b157813fefba787 to your computer and use it in GitHub Desktop.
Pembalik plat berbasis servo L298n
#include <stdio.h>
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_timer.h"
// === Pin Mapping ===
// Tombol
#define BUTTON_PIN GPIO_NUM_32
// Motor Depan
#define ENA_DEPAN GPIO_NUM_4
#define ENB_DEPAN GPIO_NUM_16
#define IN1_DEPAN GPIO_NUM_17
#define IN2_DEPAN GPIO_NUM_18
#define IN3_DEPAN GPIO_NUM_19
#define IN4_DEPAN GPIO_NUM_21
#define HALL1_DEPAN GPIO_NUM_24
#define HALL2_DEPAN GPIO_NUM_35
// Motor Belakang
#define ENA_BELAKANG GPIO_NUM_22
#define ENB_BELAKANG GPIO_NUM_25
#define IN1_BELAKANG GPIO_NUM_26
#define IN2_BELAKANG GPIO_NUM_27
#define IN3_BELAKANG GPIO_NUM_13
#define IN4_BELAKANG GPIO_NUM_23
#define HALL1_BELAKANG GPIO_NUM_39
#define HALL2_BELAKANG GPIO_NUM_36
// PWM Konfigurasi
#define LEDC_TIMER LEDC_TIMER_0
#define LEDC_MODE LEDC_HIGH_SPEED_MODE
#define LEDC_FREQ_HZ 1000
#define LEDC_DUTY_RES LEDC_TIMER_10_BIT
#define DUTY_MAX ((1 << LEDC_DUTY_RES) - 1)
void set_motor_pwm(gpio_num_t en_pin, ledc_channel_t channel, uint8_t duty_percent)
{
ledc_channel_config_t ledc_channel = {
.channel = channel,
.duty = (duty_percent * DUTY_MAX) / 100,
.gpio_num = en_pin,
.speed_mode = LEDC_MODE,
.hpoint = 0,
.timer_sel = LEDC_TIMER
};
ledc_channel_config(&ledc_channel);
ledc_set_duty(LEDC_MODE, channel, (duty_percent * DUTY_MAX) / 100);
ledc_update_duty(LEDC_MODE, channel);
}
void motor_forward(gpio_num_t in1, gpio_num_t in2)
{
gpio_set_level(in1, 1);
gpio_set_level(in2, 0);
}
void motor_stop(gpio_num_t in1, gpio_num_t in2)
{
gpio_set_level(in1, 0);
gpio_set_level(in2, 0);
}
bool hall_triggered(gpio_num_t hall_pin)
{
return gpio_get_level(hall_pin) == 1; // aktif HIGH karena pull-down
}
void wait_for_hall(gpio_num_t hall1, gpio_num_t hall2)
{
while (!(hall_triggered(hall1) && hall_triggered(hall2))) {
vTaskDelay(pdMS_TO_TICKS(10));
}
}
void setup_gpio()
{
// Output pin
gpio_config_t io_out = {
.pin_bit_mask =
(1ULL << IN1_DEPAN) | (1ULL << IN2_DEPAN) |
(1ULL << IN3_DEPAN) | (1ULL << IN4_DEPAN) |
(1ULL << IN1_BELAKANG) | (1ULL << IN2_BELAKANG) |
(1ULL << IN3_BELAKANG) | (1ULL << IN4_BELAKANG),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = 0,
.pull_down_en = 0,
.intr_type = GPIO_INTR_DISABLE
};
gpio_config(&io_out);
// Input pin (button dan hall sensor)
gpio_config_t io_in = {
.pin_bit_mask =
(1ULL << BUTTON_PIN) |
(1ULL << HALL1_DEPAN) | (1ULL << HALL2_DEPAN) |
(1ULL << HALL1_BELAKANG) | (1ULL << HALL2_BELAKANG),
.mode = GPIO_MODE_INPUT,
.pull_up_en = 0,
.pull_down_en = 1, // Semua pull-down
.intr_type = GPIO_INTR_DISABLE
};
gpio_config(&io_in);
// PWM Timer
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_MODE,
.timer_num = LEDC_TIMER,
.duty_resolution = LEDC_DUTY_RES,
.freq_hz = LEDC_FREQ_HZ,
.clk_cfg = LEDC_AUTO_CLK
};
ledc_timer_config(&ledc_timer);
}
bool button_held_1s()
{
if (gpio_get_level(BUTTON_PIN) == 1) {
int64_t start = esp_timer_get_time();
while (gpio_get_level(BUTTON_PIN) == 1) {
if ((esp_timer_get_time() - start) >= 1000000) {
return true;
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
return false;
}
void app_main()
{
setup_gpio();
while (1) {
if (button_held_1s()) {
printf("Tombol ditekan >1 detik, mulai menjalankan motor\n");
// ===== MOTOR DEPAN =====
motor_forward(IN1_DEPAN, IN2_DEPAN);
motor_forward(IN3_DEPAN, IN4_DEPAN);
set_motor_pwm(ENA_DEPAN, LEDC_CHANNEL_0, 80);
set_motor_pwm(ENB_DEPAN, LEDC_CHANNEL_1, 80);
wait_for_hall(HALL1_DEPAN, HALL2_DEPAN);
motor_stop(IN1_DEPAN, IN2_DEPAN);
motor_stop(IN3_DEPAN, IN4_DEPAN);
set_motor_pwm(ENA_DEPAN, LEDC_CHANNEL_0, 0);
set_motor_pwm(ENB_DEPAN, LEDC_CHANNEL_1, 0);
printf("Motor depan selesai.\n");
// ===== MOTOR BELAKANG =====
motor_forward(IN1_BELAKANG, IN2_BELAKANG);
motor_forward(IN3_BELAKANG, IN4_BELAKANG);
set_motor_pwm(ENA_BELAKANG, LEDC_CHANNEL_2, 80);
set_motor_pwm(ENB_BELAKANG, LEDC_CHANNEL_3, 80);
wait_for_hall(HALL1_BELAKANG, HALL2_BELAKANG);
motor_stop(IN1_BELAKANG, IN2_BELAKANG);
motor_stop(IN3_BELAKANG, IN4_BELAKANG);
set_motor_pwm(ENA_BELAKANG, LEDC_CHANNEL_2, 0);
set_motor_pwm(ENB_BELAKANG, LEDC_CHANNEL_3, 0);
printf("Motor belakang selesai.\n");
}
vTaskDelay(pdMS_TO_TICKS(100)); // polling delay
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment