CP2119/CP3119 电机驱动的 ESP-IDF 驱动程序

此驱动程序使用 ESP32 的 LEDC 外设来控制 CP2119/CP3119 电机驱动器。

CP3119M.hpp

CP3119M.hpp
#pragma once
#include <cstdio>
#include <cstdint>
#include <cmath>
#include <driver/gpio.h>
#include <driver/ledc.h>

class CP3119M {
public:
    CP3119M(gpio_num_t pwmA, gpio_num_t pwmB, ledc_channel_t channelA, ledc_channel_t channelB);

    void Start(uint16_t speed, bool reverse=false);
    void Stop();

    /**
     * @brief 设置电机的速度和方向。
     *
     * 此函数根据提供的值调整电机速度。如果速度为零或无效 (NaN),
     * 则停止电机。否则,速度将转换为 0-1023 范围内的占空比,电机
     * 将以指定方向启动。
     *
     * @param speed 电机的所需速度,为浮点值。正值表示正向
     *              方向,负值表示反向方向。该值被缩放到
     *              0-1023 范围用于 PWM 控制。
     * @param reverse 可选参数,用于显式设置反向方向。默认为 false。如果速度
     *                为负,则自动设置反向方向。
     */
    inline void SetSpeed(float speed, bool reverse=false) {
        if(speed == 0.0f || isnanf(speed)) {
            Stop();
            return;
        }
        // 将速度转换为 0-1023 范围
        uint16_t duty = static_cast<uint16_t>(fabs(1.0-speed) * 1023.0f);
        Start(duty, speed < 0.0f ? true : false);
    }
private:
    gpio_num_t pwmA;
    gpio_num_t pwmB;
    ledc_channel_t channelA;
    ledc_channel_t channelB;
};

CP3119M.cpp

CP3119M.cpp
#include "CP3119M.hpp"
#include <algorithm>


CP3119M::CP3119M(gpio_num_t pwmA, gpio_num_t pwmB, ledc_channel_t channelA, ledc_channel_t channelB) {
    // 存储引脚号
    this->pwmA = pwmA;
    this->pwmB = pwmB;
    this->channelA = channelA;
    this->channelB = channelB;

    // 配置 LEDC 定时器用于 PWM 生成
    ledc_timer_config_t ledc_timer = {
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .duty_resolution = LEDC_TIMER_10_BIT,  // 8 位分辨率 (0-255)
        .timer_num = LEDC_TIMER_0,
        .freq_hz = 20000,  // 设置频率为 20kHz
        .clk_cfg = LEDC_AUTO_CLK
    };
    ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));

    // 为 pwmA 配置 LEDC 通道
    ledc_channel_config_t ledc_channel_a = {
        .gpio_num = pwmA,
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .channel = channelA,
        .intr_type = LEDC_INTR_DISABLE,
        .timer_sel = LEDC_TIMER_0,
        .duty = 0,  // 以 0 占空比初始化
        .hpoint = 0
    };
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel_a));

    // 为 pwmB 配置 LEDC 通道
    ledc_channel_config_t ledc_channel_b = {
        .gpio_num = pwmB,
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .channel = channelB,
        .intr_type = LEDC_INTR_DISABLE,
        .timer_sel = LEDC_TIMER_0,
        .duty = 0,  // 以 0 占空比初始化
        .hpoint = 0
    };
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel_b));

}

void CP3119M::Start(uint16_t speed, bool reverse) {
    uint16_t duty = std::min(speed, (uint16_t)1023);  // 将速度限制在 0-4095 范围内
    // 设置方向和占空比
    if (reverse) {
        ledc_set_duty(LEDC_LOW_SPEED_MODE, channelB, duty);
        ledc_update_duty(LEDC_LOW_SPEED_MODE, channelB);
        ledc_set_duty(LEDC_LOW_SPEED_MODE, channelA, 1023);
        ledc_update_duty(LEDC_LOW_SPEED_MODE, channelA);
    } else {
        ledc_set_duty(LEDC_LOW_SPEED_MODE, channelA, duty);
        ledc_update_duty(LEDC_LOW_SPEED_MODE, channelA);
        ledc_set_duty(LEDC_LOW_SPEED_MODE, channelB, 1023); // 100%
        ledc_update_duty(LEDC_LOW_SPEED_MODE, channelB);
    }
}

void CP3119M::Stop() {
    // 将两个通道设置为 100% 占空比(即制动)
    ledc_set_duty(LEDC_LOW_SPEED_MODE, channelA, 1023);
    ledc_update_duty(LEDC_LOW_SPEED_MODE, channelA);
    ledc_set_duty(LEDC_LOW_SPEED_MODE, channelB, 1023);
    ledc_update_duty(LEDC_LOW_SPEED_MODE, channelB);
}

使用示例

cp3119_example.cpp
#include "CP3119M.hpp"
#include <driver/gpio.h>

extern "C" void app_main() {
    // 在 GPIO 18 和 19 上初始化 CP3119 电机驱动器,使用 LEDC 通道 0 和 1
    CP3119M motor(gpio_num_t::GPIO_NUM_18, gpio_num_t::GPIO_NUM_19, LEDC_CHANNEL_0, LEDC_CHANNEL_1);

    // 以全速正向启动电机
    motor.SetSpeed(1.0f);

    // 运行一段时间
    vTaskDelay(pdMS_TO_TICKS(5000));

    // 停止电机
    motor.Stop();

    return 0;
}

Check out similar posts by category: ESP32, C/C++, Embedded