前言
前面已经使用语音可以控制智能小车,这章主要是优化,增加自动巡航模式,单独启动一个线程处理小车运动

1:硬件及环境
esp-idf5.4.*
win11
小智AI全套(基于esp32s3(n16r8) 44pin 小智ai1.9.2版本) 增加一个HC-RS04 超声波(位置有限,下层想加舵机,没位置装)
小车 全套(2个层板,2个L298N,4个电机,4个轮子,2个节锂电池)
一个船型开关,控制电源开关
杜邦线 若干

2:主要代码
boards\bread-compact-wifi\compact_wifi_board.cc
有些GPIO 拿来他用了,所以屏蔽了(ENBALE_CONTROL_BUTTON 不用定义(默认)就可以了)

    void InitializeButtons() {

        boot_button_.OnClick([this]() {
            auto& app = Application::GetInstance();
            if (app.GetDeviceState() == kDeviceStateStarting && !WifiStation::GetInstance().IsConnected()) {
                ResetWifiConfiguration();
            }
            app.ToggleChatState();
        });
        #ifdef  ENBALE_CONTROL_BUTTON
        touch_button_.OnPressDown([this]() {
            Application::GetInstance().StartListening();
        });
        touch_button_.OnPressUp([this]() {
            Application::GetInstance().StopListening();
        });

        volume_up_button_.OnClick([this]() {
            auto codec = GetAudioCodec();
            auto volume = codec->output_volume() + 10;
            if (volume > 100) {
                volume = 100;
            }
            codec->SetOutputVolume(volume);
            GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume));
        });

        volume_up_button_.OnLongPress([this]() {
            GetAudioCodec()->SetOutputVolume(100);
            GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME);
        });

        volume_down_button_.OnClick([this]() {
            auto codec = GetAudioCodec();
            auto volume = codec->output_volume() - 10;
            if (volume < 0) {
                volume = 0;
            }
            codec->SetOutputVolume(volume);
            GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume));
        });

        volume_down_button_.OnLongPress([this]() {
            GetAudioCodec()->SetOutputVolume(0);
            GetDisplay()->ShowNotification(Lang::Strings::MUTED);
        });
     #endif   
    }

application.cc 修改处

void Application::Start() {
//........省略
   Ota ota;
    CheckNewVersion(ota);

    //########################by eh add  2025////就增加了这两句
     auto carcontrol = board.GetSmartCarControl();
     carcontrol->car_init_config();
    //########################
    // Initialize the protocol
    display->SetStatus(Lang::Strings::LOADING_PROTOCOL);
//........省略
}
void Application::SetDeviceState(DeviceState state) {
//........省略

    //////////////////////////////////////////////////////////////
    //kDeviceStateIdle,
    if(state ==kDeviceStateListening  &&( previous_state == kDeviceStateIdle ||previous_state == kDeviceStateConnecting)){
        //auto carcontrol = board.GetSmartCarControl();
    // carcontrol->car_init_config();
        board.GetSmartCarControl()->car_resume();
    }else if(state ==kDeviceStateIdle &&(previous_state == kDeviceStateListening ||previous_state == kDeviceStateSpeaking)){
        board.GetSmartCarControl()->car_suspend();
    }
    //////////////////////////////////////////////////////////////
}

bool Application::CanEnterSleepMode() {
    if (device_state_ != kDeviceStateIdle) {
        return false;
    }

    if (protocol_ && protocol_->IsAudioChannelOpened()) {
        return false;
    }

    if (!audio_service_.IsIdle()) {
        return false;
    }
    //by eh add 2025 这里根本就不条用,改了也显示出来吧//////////////////////
    auto& board = Board::GetInstance();
     auto carcontrol = board.GetSmartCarControl();
     if(!carcontrol->car_is_stop_state()){
        return false;
     }
     ////////////////////////////////////////////////
     

    // Now it is safe to enter sleep mode
    return true;
}

board.h

//........省略
class SmartCarControl; //2025 eh add
class Board {
//........省略
 virtual SmartCarControl* GetSmartCarControl();////2025 eh add
}

board.cc

//........省略
#include "smartcar/smart_car_run.h"   //2025 eh add
//........省略
SmartCarControl* Board::GetSmartCarControl()////2025 eh add
{
    static SmartCarControl smart_car;
    return &smart_car;
}

mcp_server.cc

//........省略
#include "smartcar/smart_car_run.h"
//........省略
void McpServer::AddCommonTools() {
//........省略
 /////////////////////////////////////////////////////////////////////////////////
    auto carcontrol = board.GetSmartCarControl();
    if(carcontrol){
        //前进
    AddTool("self.car.go_forward",
    "Control the car to move forward. Use this tool to make the car move in the forward direction.\n"
    "Parameters:\n"
    "  duration: Moving duration in milliseconds. Default is 500ms.\n"
    "Usage scenarios:\n"
    "1. When the user asks the car to move forward\n"
    "2. When traveling straight on a road\n"
    "3. When needing to advance to a specific location",
    PropertyList({
        Property("duration", kPropertyTypeInteger, 100, 5000)
    }),
    [carcontrol](const PropertyList& properties) -> ReturnValue {
        int duration = properties["duration"].value<int>();
        carcontrol->car_forward(duration);
      //  return CarControlTurnRight(angle, speed);
      ESP_LOGI(TAG, "self.car.go_backward %d",duration);
      return true;
    });
//后退
AddTool("self.car.go_backward", 
    "Control the car to move backward. Use this tool to make the car move in the reverse direction.\n"
    "Parameters:\n"
    "  duration: Moving duration in milliseconds. Default is 500ms.\n"
    "Usage scenarios:\n"
    "1. When the user asks the car to move backward\n"
    "2. When reversing from a parking space\n"
    "3. When needing to back away from obstacles",
    PropertyList({
        Property("duration", kPropertyTypeInteger, 100, 5000)
    }),
    [carcontrol](const PropertyList& properties) -> ReturnValue {
        int duration = properties["duration"].value<int>();
      //  return CarControlTurnRight(angle, speed);
      carcontrol->car_backward(duration);
      ESP_LOGI(TAG, "self.car.go_backward %d",duration);
      return true;
    });

AddTool("self.car.stop",
    "Control the car to stop moving. Use this tool to bring the car to a complete halt.\n"
    "Usage scenarios:\n"
    "1. When the user asks the car to stop\n"
    "2. When encountering obstacles or danger\n"
    "3. When reaching the destination\n"
    "4. In emergency situations requiring immediate stopping",
    PropertyList(),
    [carcontrol](const PropertyList& properties) -> ReturnValue {
      //  int duration = properties["duration"].value<int>();
      //  return CarControlTurnRight(angle, speed);
      carcontrol->car_stop();
      ESP_LOGI(TAG, "self.car.stop");
      return true;
    });

AddTool("self.car.auto_cruise",
    "Control the car to enter automatic cruise mode. Use this tool to enable autonomous driving with obstacle avoidance for 30 seconds.\n"
    "Parameters:\n"
    "  duration: Cruise duration in seconds. Default is 30 seconds.\n"
    "Usage scenarios:\n"
    "1. When the user wants hands-free driving\n"
    "2. For long distance highway driving\n"
    "3. When maintaining consistent speed is desired\n"
    "4. When adaptive cruise control is needed",
    PropertyList({
        Property("duration", kPropertyTypeInteger, 5, 50)
    }),
    [carcontrol](const PropertyList& properties) -> ReturnValue {
        int duration = properties["duration"].value<int>();
      //  return CarControlTurnRight(angle, speed);
      carcontrol->car_auto_cruise(duration); //自动巡航 单位秒
      ESP_LOGI(TAG, "self.car.auto_cruise %d",duration);
      return true;
    });
    /////
    AddTool("self.car.turn_left",
    "Control the car to turn rleftight. Use this tool to make the car turn to the left side.\n"
    "Parameters:\n"
    "  duration: Moving duration in milliseconds, range 0-5000. Default is 500ms.\n"
    "  speed: Turning speed, range 0-1000. Default is 800 (half speed).\n"
    "Usage scenarios:\n"
    "1. When the user asks the car to turn left\n"
    "2. When avoiding obstacles\n"
    "3. When changing direction is needed",
    PropertyList({
        Property("duration", kPropertyTypeInteger, 0, 5000),
        Property("speed", kPropertyTypeInteger, 0, 1000)
    }),
    [carcontrol](const PropertyList& properties) -> ReturnValue {
        int duration = properties["duration"].value<int>();
      //  int speed = properties["speed"].value<int>();
      //  return CarControlTurnRight(angle, speed);
       carcontrol->car_turn_left(duration);
      ESP_LOGI(TAG, "self.car.turn_right %d",duration);
      return true;
    });

AddTool("self.car.turn_right",
    "Control the car to turn right. Use this tool to make the car turn to the right side.\n"
    "Parameters:\n"
    "  duration: Moving duration in milliseconds, range 0-5000. Default is 500ms.\n"
    "  speed: Turning speed, range 0-1000. Default is 800 (half speed).\n"
    "Usage scenarios:\n"
    "1. When the user asks the car to turn right\n"
    "2. When avoiding obstacles\n"
    "3. When changing direction is needed",
    PropertyList({
        Property("duration", kPropertyTypeInteger, 0, 5000),
        Property("speed", kPropertyTypeInteger, 0, 1000)
    }),
    [carcontrol](const PropertyList& properties) -> ReturnValue {
        int duration = properties["duration"].value<int>();
        int speed = properties["speed"].value<int>();
      //  return CarControlTurnRight(angle, speed);
      carcontrol->car_turn_right(duration);
      ESP_LOGI(TAG, "self.car.turn_right %d-%d",duration,speed);
      return true;
    });
    }
// Restore the original tools list to the end of the tools list
    tools_.insert(tools_.end(), original_tools.begin(), original_tools.end());
}

增加的6个文件
在这里插入图片描述
smart_car_run.h

#ifndef SMART_CAR_RUN_H
#define SMART_CAR_RUN_H
//void car_run_main();
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"

enum car_state
{
    CAR_STATE_STOP,
    CAR_STATE_FORWARD,
    CAR_STATE_BACKWARD,
    CAR_STATE_TURN_LEFT,
    CAR_STATE_TURN_RIGHT,
    CAR_STATE_AUTO_CRUISE,
};

struct smart_car_event
{
    car_state  state;
    int delay_ms;
};
class MotorControl;
class Senor_Manager;
class SmartCarControl{
public:
    SmartCarControl();
    ~SmartCarControl();
    void car_init_config();
    void car_forward(int ms);
    void car_backward(int ms);
    void car_turn_left(int ms);
    void car_turn_right(int ms);
    void car_stop();
    void car_auto_cruise(int seconds); //自动巡航

    bool car_is_stop_state();
    void car_setup();
    void car_exit();
private:
    MotorControl* getMotorControl();
    Senor_Manager* getSenorManager();
private:
    smart_car_event ev_data;
    void _car_forward(int ms,bool bupdateSate=true);
    void _car_backward(int ms,bool bupdateSate=true);
    void _car_turn_left(int ms,bool bupdateSate=true);
    void _car_turn_right(int ms,bool bupdateSate=true);
    void _car_stop(bool bupdateSate=true);
    void _car_auto_cruise(int seconds); //自动巡航 //暂时用不上

    void _car_run();
    void _logic_auto_cruise(); //巡航过程
    void _auto_cruise_forward(int ms); //巡航时前进,
private:
    volatile int  current_state;
    QueueHandle_t control_evt_queue ;
    TaskHandle_t xTask1Handle;
    volatile bool  run_flag;
    bool  car_state_is_stop ;//是否为停止状态
    void clear_queue();
    
    int  get_current_state();
    void set_current_state(int state);

    void exit_loop();
    
public:
    void car_resume();
    void car_suspend();

};
#endif

smart_car_run.cc

#include "motor_control.h"
#include "smart_car_run.h"
#include "senor_control.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"

#define TAG  "SMARTCAR"

#define  QUEUE_SIZE   10

#define  MIN_DELAY_MS   300
#define MAX_DELAY_MS   2000
#define  CHECK_MS_COMMON(X) if(X<MIN_DELAY_MS){X=MIN_DELAY_MS;}else if(X>MAX_DELAY_MS){X = MAX_DELAY_MS;}

//巡航间隔
#define  MIN_AUTO_CRISE_DELAY_MS   300
#define  MAX_AUTO_CRISE_DELAY_MS   2000
#define  CHECK_MS_AUTO_CRISE(X) if(X<MIN_DELAY_MS){X=MIN_DELAY_MS;}else if(X>MAX_DELAY_MS){X = MAX_DELAY_MS;}

#define MIN_AUTO_CRUISE_MS   10
#define MAX_AUTO_CRUISE_MS   80
#define CHECK_SEC_AUTO_CRUISE(X) if(X<MIN_AUTO_CRUISE_MS){X=MIN_AUTO_CRUISE_MS;}else if(X>MAX_AUTO_CRUISE_MS){X = MAX_AUTO_CRUISE_MS;}

#define STANDARD_ACTION_MS   500   //标准动作持续时间
#define AUTO_CRUISE_ACTION_MS  60  //巡航标准时间50ms

#define  CAR_RUN_HIGH_SPEED    850
#define  CAR_RUN_COMMON_SPEED  800
#define  CAR_RUN_LOW_SPEED     750
#define  CHANGE_CAR_STATE_TO_STOP(X)  if(!X){ X=true;}
#define  CHANGE_CAR_STATE_TO_RUN(X)  if(X){ X=false;}

#define  AUTO_CRUISE_SET_SPEED(X)  (X?CAR_RUN_COMMON_SPEED:CAR_RUN_LOW_SPEED) 
// if(X){ return CAR_RUN_COMMON_SPEED;}else{return CAR_RUN_LOW_SPEED;}
//#define   DIRECT_SHELL   
#define CALL_TARGET_FUNC(cls, obj,funname,...) (obj)->cls##::_##funname(__VA_ARGS__)

#define TEST_MODE   0 //1 小车 不运动  0  会动
#define CHECK_TESTING() if(TEST_MODE){ return ;}

SmartCarControl::SmartCarControl(){
    current_state=0;
    run_flag= false;
    control_evt_queue= NULL;
    xTask1Handle= NULL;
    car_state_is_stop= true;
}
SmartCarControl::~SmartCarControl(){
    if(control_evt_queue){
        vQueueDelete(control_evt_queue); 
        control_evt_queue = NULL;
    }
}
void SmartCarControl::car_init_config(){
    getMotorControl()->motor_control_init();
    control_evt_queue = xQueueCreate( QUEUE_SIZE, sizeof(smart_car_event) );
    getSenorManager()->init_all_senors(); //超声波初始化
    ESP_LOGI(TAG, "-------------------car_init_config-----------------");
}
void SmartCarControl::car_forward(int ms){
    CHECK_MS_COMMON(ms)
    #ifdef DIRECT_SHELL
   // CALL_TARGET_FUNC(SmartCarControl,this,car_forward,ms);
     _car_forward(ms);
    #else
    ev_data.state = CAR_STATE_FORWARD;  
    ev_data.delay_ms = ms;  
    BaseType_t xStatus = xQueueSend(control_evt_queue, &ev_data, pdMS_TO_TICKS(200));
    if (xStatus == pdPASS) {
    //   printf("发送成功:ID=%d, 温度=%.1f℃, 湿度=%.1f%%\n",
    //          data.id, data.temperature, data.humidity);
    } else {
     ESP_LOGI(TAG, "car_forward xQueueSend fail");
    }
    #endif
    // auto motor=getMotorControl();
    // motor->car_control(CAR_FORWARD, 800); // 中等速度
    // vTaskDelay(pdMS_TO_TICKS(ms)); //500
    // motor->car_control(CAR_STOP, 0);
    // vTaskDelay(pdMS_TO_TICKS(1000));
}
void SmartCarControl::car_backward(int ms){
    CHECK_MS_COMMON(ms)
    #ifdef DIRECT_SHELL
   // CALL_TARGET_FUNC(SmartCarControl,this,car_forward,ms);
     _car_backward(ms);
    #else
    ev_data.state = CAR_STATE_BACKWARD;  
    ev_data.delay_ms = ms;  
    BaseType_t xStatus = xQueueSend(control_evt_queue, &ev_data, pdMS_TO_TICKS(200));
    if (xStatus == pdPASS) {
    //   printf("发送成功:ID=%d, 温度=%.1f℃, 湿度=%.1f%%\n",
    //          data.id, data.temperature, data.humidity);
    } else {
     // printf("入队失败!\n");
     ESP_LOGI(TAG, "car_backward xQueueSend fail");
    }
    #endif
    // auto motor=getMotorControl();
    // motor->car_control(CAR_BACKWARD, 800); // 中等速度
    // vTaskDelay(pdMS_TO_TICKS(ms));
    // motor->car_control(CAR_STOP, 0);
    // vTaskDelay(pdMS_TO_TICKS(1000));
}
void SmartCarControl::car_turn_left(int ms){
    CHECK_MS_COMMON(ms)
     #ifdef DIRECT_SHELL
   // CALL_TARGET_FUNC(SmartCarControl,this,car_forward,ms);
     _car_turn_left(ms);
    #else
    ev_data.state = CAR_STATE_TURN_LEFT;  
    ev_data.delay_ms = ms;  
    BaseType_t xStatus = xQueueSend(control_evt_queue, &ev_data, pdMS_TO_TICKS(200));
    if (xStatus == pdPASS) {
    //   printf("发送成功:ID=%d, 温度=%.1f℃, 湿度=%.1f%%\n",
    //          data.id, data.temperature, data.humidity);
    } else {
     // printf("入队失败!\n");
     ESP_LOGI(TAG, "car_turn_left xQueueSend fail");
    }
    #endif
    // auto motor=getMotorControl();
    // motor->car_control(CAR_LEFT, 800);
    // vTaskDelay(pdMS_TO_TICKS(ms));
    // motor-> car_control(CAR_STOP, 0);
    // vTaskDelay(pdMS_TO_TICKS(1000));
}
void SmartCarControl::car_turn_right(int ms){
    CHECK_MS_COMMON(ms)
    #ifdef DIRECT_SHELL
   // CALL_TARGET_FUNC(SmartCarControl,this,car_forward,ms);
     _car_turn_right(ms);
    #else
    ev_data.state = CAR_STATE_TURN_RIGHT;  
    ev_data.delay_ms = ms;  
    BaseType_t xStatus = xQueueSend(control_evt_queue, &ev_data, pdMS_TO_TICKS(200));
    if (xStatus == pdPASS) {
    //   printf("发送成功:ID=%d, 温度=%.1f℃, 湿度=%.1f%%\n",
    //          data.id, data.temperature, data.humidity);
    } else {
     // printf("入队失败!\n");
     ESP_LOGI(TAG, "car_turn_right xQueueSend fail");
    }
    #endif
    // auto motor=getMotorControl();
    // motor->car_control(CAR_RIGHT, 800);
    // vTaskDelay(pdMS_TO_TICKS(ms));
    // motor-> car_control(CAR_STOP, 0);
    // vTaskDelay(pdMS_TO_TICKS(1000));
}
void SmartCarControl::car_stop(){
    #ifdef DIRECT_SHELL
   // CALL_TARGET_FUNC(SmartCarControl,this,car_forward,ms);
     _car_stop();
    #else
    ev_data.state = CAR_STATE_STOP;  
    ev_data.delay_ms = 0;  
    BaseType_t xStatus = xQueueSend(control_evt_queue, &ev_data, pdMS_TO_TICKS(200));
    if (xStatus == pdPASS) {
    //   printf("发送成功:ID=%d, 温度=%.1f℃, 湿度=%.1f%%\n",
    //          data.id, data.temperature, data.humidity);
    } else {
     // printf("入队失败!\n");
     ESP_LOGI(TAG, "car_stop xQueueSend fail");
    }
    #endif
    // auto motor=getMotorControl();
    // motor-> car_control(CAR_STOP, 0);
    // vTaskDelay(pdMS_TO_TICKS(500));
}
void SmartCarControl::car_auto_cruise(int seconds)//自动巡航
{
    CHECK_SEC_AUTO_CRUISE(seconds)
    #ifdef DIRECT_SHELL
   // CALL_TARGET_FUNC(SmartCarControl,this,car_forward,ms);
   //  _car_turn_right(ms);
    #else
    ev_data.state = CAR_STATE_AUTO_CRUISE;  
    ev_data.delay_ms = seconds;  //秒
    BaseType_t xStatus = xQueueSend(control_evt_queue, &ev_data, pdMS_TO_TICKS(200));
    if (xStatus == pdPASS) {
    //   printf("发送成功:ID=%d, 温度=%.1f℃, 湿度=%.1f%%\n",
    //          data.id, data.temperature, data.humidity);
    } else {
     // printf("入队失败!\n");
     ESP_LOGI(TAG, "car_turn_right xQueueSend fail");
    }
    #endif
}

//private
void SmartCarControl::clear_queue(){
    if(control_evt_queue){
        smart_car_event  ev;
        int count = QUEUE_SIZE;
        while (xQueueReceive(control_evt_queue, &ev, 0) == pdTRUE) {
            if(--count <=   0) break;
        }
    }
    
}
int  SmartCarControl::get_current_state(){
    return current_state;
}
void SmartCarControl::set_current_state(int state){
  current_state=state;
}

 MotorControl* SmartCarControl::getMotorControl(){
    static MotorControl motor_control;
    return &motor_control;
 }

  Senor_Manager* SmartCarControl::getSenorManager(){
    static Senor_Manager senor_manager;
    return &senor_manager;
 }

 bool SmartCarControl::car_is_stop_state(){
    return  get_current_state() == CAR_STATE_STOP ;
 }

 void SmartCarControl::car_setup(){
    #ifndef DIRECT_SHELL
    // smart_car_event  ev;
    // bool is_continue_shell= false;
    run_flag =true;
  //  xTaskCreate(key_task, "key_task", 2048, NULL, 5, NULL);
   xTaskCreate([](void* arg) {
        SmartCarControl* control = (SmartCarControl*)arg;
        control->_car_run();
        vTaskDelete(NULL);
        control->exit_loop();
    }, "car_setup", 2048 * 2, this, 8, &xTask1Handle);//&audio_input_task_handle_);
    #endif

 }

 void SmartCarControl::car_exit(){
    run_flag =false;
    // if(control_evt_queue){
    //     xQueueDelete(control_evt_queue);
    //     control_evt_queue= NULL;
    // }
    // if(xTask1Handle){
    //     vTaskDelete(xTask1Handle);
    //     xTask1Handle=NULL;
    // }
    
 }

 void SmartCarControl::exit_loop(){
    if(control_evt_queue){
        vQueueDelete(control_evt_queue);
        control_evt_queue= NULL;
    }
     xTask1Handle=NULL;
 }

 void SmartCarControl::car_resume(){
    if(!run_flag){car_setup();}  //没与启动就启动
    else if(xTask1Handle)vTaskResume(xTask1Handle);
 }
void SmartCarControl::car_suspend(){
    if(run_flag){
        clear_queue();
        if(xTask1Handle)vTaskSuspend(xTask1Handle);
    }
    
}
//////////////////////////////////////////////////////////
//private
 void SmartCarControl:: _logic_auto_cruise(){//巡航过程
        //超声波看下前面有没有障碍物
        int distance = getSenorManager()->get_senor_distance(Senor_Ultrasonic,Senor_Direction_Forward);
     //   ESP_LOGI(TAG, "#######[auto]_logic_auto_cruise get_senor_distance=%d cm",distance);
        if(distance <0){
            ESP_LOGE(TAG, "get_senor_distance fail");
            return ;
        }
        
        if(distance < 20){  //障碍物
        //向左 或向右 或后退
            _car_backward(STANDARD_ACTION_MS,false);
            if(xTaskGetTickCount()&1){
                _car_turn_left(STANDARD_ACTION_MS,false);
            }else{
                _car_turn_right(STANDARD_ACTION_MS,false);
            }
        }else{
            //_car_forward(STANDARD_ACTION_MS,false);
            _auto_cruise_forward(AUTO_CRUISE_ACTION_MS);
        }

 }

 void SmartCarControl::_auto_cruise_forward(int ms){ //巡航时前进,
  //  CHECK_MS_AUTO_CRISE(ms)
    auto motor=getMotorControl();
    motor->car_control(CAR_FORWARD, AUTO_CRUISE_SET_SPEED(car_state_is_stop)); // 中等速度 800->700
    vTaskDelay(pdMS_TO_TICKS(ms)); //500
    CHANGE_CAR_STATE_TO_RUN(car_state_is_stop)
    // motor->car_control(CAR_STOP, 0);
    // vTaskDelay(pdMS_TO_TICKS(1000));
 }

 void SmartCarControl::_car_run(){
    smart_car_event  ev;
    bool  bAuto_cruise = false;
    TickType_t start_ticks,end_ticks;
    while(run_flag){
        if(bAuto_cruise){
            if(xQueueReceive(control_evt_queue, &ev, 0) == pdTRUE){
             //   ESP_LOGI(TAG, "#######[auto]car_run state=%d,time=%d",ev.state,ev.delay_ms);
                if(ev.state != CAR_STATE_AUTO_CRUISE)
                {
                     bAuto_cruise =false;
                    _car_stop();
                    switch (ev.state)
                    {
                    case CAR_STATE_FORWARD:
                        _car_forward(ev.delay_ms);
                        break;
                    case CAR_STATE_BACKWARD:
                        _car_backward(ev.delay_ms);
                        break;
                    case CAR_STATE_TURN_LEFT:
                        _car_turn_left(ev.delay_ms);
                        break;
                    case CAR_STATE_TURN_RIGHT:
                        _car_turn_right(ev.delay_ms);
                        break;    
                    default:
                        break;
                    }
                }else{
                    //原有的数据上更新
                    start_ticks=xTaskGetTickCount()/configTICK_RATE_HZ;
                    CHECK_SEC_AUTO_CRUISE(ev.delay_ms)
                    end_ticks = start_ticks+ev.delay_ms;
                }
            }
            if (bAuto_cruise)
            {
                start_ticks=xTaskGetTickCount()/configTICK_RATE_HZ;
                if(start_ticks >= end_ticks){
                    bAuto_cruise =false;
                    start_ticks= end_ticks =0;
                    _car_stop();
                    //自动巡航结束 
                }else{
                    //继续执行
                    _logic_auto_cruise();
                }
            }
            
        }else if (xQueueReceive(control_evt_queue, &ev, portMAX_DELAY)){
            if(ev.state == get_current_state()){
                continue;
            }else{
                set_current_state(ev.state);
            }
            ESP_LOGI(TAG, "#######car_run state=%d,time=%d",ev.state,ev.delay_ms);
            switch (ev.state)
            {
            case CAR_STATE_STOP:
                _car_stop();
                break;
            case CAR_STATE_FORWARD:
                _car_forward(ev.delay_ms);
                break;
            case CAR_STATE_BACKWARD:
                _car_backward(ev.delay_ms);
                break;
            case CAR_STATE_TURN_LEFT:
                _car_turn_left(ev.delay_ms);
                break;
            case CAR_STATE_TURN_RIGHT:
                _car_turn_right(ev.delay_ms);
                break;    
            case CAR_STATE_AUTO_CRUISE:
                {
                  //  _car_auto_cruise(ev.delay_ms);
                    start_ticks=xTaskGetTickCount()/configTICK_RATE_HZ;
                    CHECK_SEC_AUTO_CRUISE(ev.delay_ms)
                    end_ticks = start_ticks+ev.delay_ms;
                    bAuto_cruise = true;
                }
                break;   
            default:
                break;
            }
        }
    }
 }

 ///////////////////////////////////////
 //private
 void SmartCarControl::_car_forward(int ms,bool bupdateSate){
     CHECK_TESTING()
    auto motor=getMotorControl();
    motor->car_control(CAR_FORWARD, CAR_RUN_COMMON_SPEED); // 中等速度
    vTaskDelay(pdMS_TO_TICKS(ms)); //500
    motor->car_control(CAR_STOP, 0);
    vTaskDelay(pdMS_TO_TICKS(1000));
    if(bupdateSate)set_current_state(CAR_STATE_STOP);
    CHANGE_CAR_STATE_TO_STOP(car_state_is_stop)
 }
void SmartCarControl::_car_backward(int ms,bool bupdateSate){
     CHECK_TESTING()
     auto motor=getMotorControl();
    motor->car_control(CAR_BACKWARD, CAR_RUN_COMMON_SPEED); // 中等速度
    vTaskDelay(pdMS_TO_TICKS(ms));
    motor->car_control(CAR_STOP, 0);
    vTaskDelay(pdMS_TO_TICKS(1000));
    if(bupdateSate)set_current_state(CAR_STATE_STOP);
    CHANGE_CAR_STATE_TO_STOP(car_state_is_stop)
}
void SmartCarControl::_car_turn_left(int ms,bool bupdateSate){
     CHECK_TESTING()
    auto motor=getMotorControl();
    motor->car_control(CAR_LEFT, CAR_RUN_COMMON_SPEED);
    vTaskDelay(pdMS_TO_TICKS(ms));
    motor-> car_control(CAR_STOP, 0);
    vTaskDelay(pdMS_TO_TICKS(1000));
    if(bupdateSate)set_current_state(CAR_STATE_STOP);
    CHANGE_CAR_STATE_TO_STOP(car_state_is_stop)
}
void SmartCarControl::_car_turn_right(int ms,bool bupdateSate){
     CHECK_TESTING()
     auto motor=getMotorControl();
    motor->car_control(CAR_RIGHT, CAR_RUN_COMMON_SPEED);
    vTaskDelay(pdMS_TO_TICKS(ms));
    motor-> car_control(CAR_STOP, 0);
    vTaskDelay(pdMS_TO_TICKS(1000));
    if(bupdateSate)set_current_state(CAR_STATE_STOP);
    CHANGE_CAR_STATE_TO_STOP(car_state_is_stop)
}
void SmartCarControl::_car_stop(bool bupdateSate){
     CHECK_TESTING()
    auto motor=getMotorControl();
    motor-> car_control(CAR_STOP, 0);
    vTaskDelay(pdMS_TO_TICKS(500));
    if(bupdateSate)set_current_state(CAR_STATE_STOP);
    CHANGE_CAR_STATE_TO_STOP(car_state_is_stop)
}
void SmartCarControl::_car_auto_cruise(int seconds){ //自动巡航
}  

senor_control.h

#ifndef SENOR_CONTROL_H
#define SENOR_CONTROL_H 

#include <cstdint>
#include "driver/gpio.h"
#include "driver/ledc.h"
///////////////////////////////////////////////////////////////////
enum Senor_Type{
    Senor_Unknown,
    Senor_Ultrasonic,


    Senor_Total,
};

enum Senor_Direction{
    Senor_Direction_Unknown,
    Senor_Direction_Forward,
    Senor_Direction_Backward,
    Senor_Direction_Left,
    Senor_Direction_Right,


    Senor_Direction_Total,
};

#define CURRENT_ULTRASONIC_SENNOR_COUNT   1  //超声波当前1个
// 超声波模块///////////////////////////////////////////
// 硬件引脚定义
#define TRIG_PIN      GPIO_NUM_12
#define ECHO_PIN      GPIO_NUM_13

// #define RIGHT_PWM_PIN   GPIO_NUM_12    //使能RIGHT
// // 方向控制引脚 
// #define FWD_RIGHT_PIN   GPIO_NUM_13    // 右IN1 IN3
// #define BWD_RIGHT_PIN   GPIO_NUM_14    // 右IN2 IN4

// 超声波模块参数
#define MAX_DISTANCE_CM     400   // 最大测量距离 4米
#define SOUND_SPEED_CM_US   0.034  // 声速 340m/s = 0.034 cm/μs = 34cm/ms = 34*1000 cm /S = 340m/s
#define TIMEOUT_US          (MAX_DISTANCE_CM * 58)  // 超时时间(微秒) 400cm /(34cm/ms) = 11.7647ms  //40/34=1.176470588235

// typedef struct {
//     float distance_cm;
//     bool success;
//     uint32_t duration_us;
// } ultrasonic_measurement_t;

//#define ULTRASONIC_PIN_LIST
const uint64_t ULTRASONIC_PIN_LIST[Senor_Direction_Total][2]={{0,0},{GPIO_NUM_12,GPIO_NUM_13},
{0,0},{0,0},{0,0}};
///////////////////////////////////////////////////////////////////
class Senor_Object
{
private:
    /* data */
    Senor_Type  senor_type;
    Senor_Direction  senor_direction;
public:
    Senor_Object(Senor_Type senortype,Senor_Direction senordirection);
    virtual ~Senor_Object();
public:
    // void set_senor_type(Senor_Type type);
    // void set_senor_direction(Senor_Direction direction);
    virtual void init_senor()=0;
    virtual int get_senor_distance()=0;
};
////////////////////////////////////////////////////////////////////

class ultrasonic_control:public Senor_Object
{
private:
    /* data */
public:
    ultrasonic_control(Senor_Direction senordirection);
    ~ultrasonic_control();
    void init_senor();
    int get_senor_distance();
public:
    void ultrasonic_init();
    int ultrasonic_measure_distance();
};



// 传感器管理//////////////////////////////////////////
class Senor_Manager
{
private:
    ultrasonic_control* get_ultrasonic_senor(Senor_Direction direction);
public:
    Senor_Manager(/* args */);
    ~Senor_Manager();
public:
    void init_all_senors();
    int get_senor_distance(Senor_Type ty,Senor_Direction direction);
};

#endif

senor_control.cc

#include "senor_control.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"  // Add this line to fix ESP_LOGI

#define TAG  "SENOR"

Senor_Object::Senor_Object(Senor_Type senortype,Senor_Direction senordirection){
    senor_type=senortype;
    senor_direction=senordirection;
}
Senor_Object::~Senor_Object(){

}

int Senor_Object::get_senor_distance(){
    return senor_direction;
}

/// @brief /////////////////////////////////////////////////////////
/// @param senordirection 
ultrasonic_control::ultrasonic_control(Senor_Direction senordirection):Senor_Object(Senor_Ultrasonic,senordirection)
{
}

ultrasonic_control::~ultrasonic_control()
{
}

void ultrasonic_control::init_senor(){
    ultrasonic_init();
}

int ultrasonic_control::get_senor_distance(){
    return ultrasonic_measure_distance();
}
void ultrasonic_control::ultrasonic_init(){
    auto pins =  ULTRASONIC_PIN_LIST[get_senor_distance()];
    uint64_t trig_pin = pins[0]; 
    uint64_t echo_pin = pins[1];
     // 配置 TRIG 引脚为输出
    gpio_config_t trig_config = {
        .pin_bit_mask = (1ULL << TRIG_PIN),
        .mode = GPIO_MODE_OUTPUT,
        .pull_up_en = GPIO_PULLUP_DISABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE,
    };
    gpio_config(&trig_config);

    // 配置 ECHO 引脚为输入
    gpio_config_t echo_config = {
        .pin_bit_mask = (1ULL << ECHO_PIN),
        .mode = GPIO_MODE_INPUT,
        .pull_up_en = GPIO_PULLUP_DISABLE,
        .pull_down_en = GPIO_PULLDOWN_ENABLE,  // 下拉确保默认低电平
        .intr_type = GPIO_INTR_DISABLE,
    };
    gpio_config(&echo_config);

    // 初始状态:TRIG 低电平
    gpio_set_level(TRIG_PIN, 0);
    
    ESP_LOGI(TAG, "---Ultrasonic sensor initialized");
}

int ultrasonic_control::ultrasonic_measure_distance(){ 
    //  ultrasonic_measurement_t result = {
    //     .distance_cm = 0.0f,
    //     .success = false,
    //     .duration_us = 0
    // };
    int  result = -1;
    // 1. 发送 10us 的触发脉冲
    gpio_set_level(TRIG_PIN, 1);
    esp_rom_delay_us(10);  // 精确延迟 10us
    gpio_set_level(TRIG_PIN, 0);

    // 2. 等待 ECHO 变为高电平(开始信号)
    int64_t start_time = esp_timer_get_time();
    int64_t timeout_time = start_time + 1000*60;  // 数字小了会导致Timeout //这里使用60ms 超时(一般20-30够用)
    
    while (gpio_get_level(ECHO_PIN) == 0) {
        if (esp_timer_get_time() > timeout_time) {
            ESP_LOGW(TAG, "Timeout waiting for echo start");
            return result;
        }else{
            // vTaskDelay(pdMS_TO_TICKS(1)); //1ms
             esp_rom_delay_us(2);  // 精确延迟 10us
        }
    }

    // 3. 记录 Echo 开始时间
    int64_t echo_start = esp_timer_get_time();
    timeout_time = echo_start + TIMEOUT_US;

    // 4. 等待 ECHO 变为低电平(结束信号)
    while (gpio_get_level(ECHO_PIN) == 1) {
        if (esp_timer_get_time() > timeout_time) {
            ESP_LOGW(TAG, "Timeout waiting for echo end");
            return result;
        }else{
            esp_rom_delay_us(2);  // 精确延迟 10us
        }
    }

    // 5. 记录 Echo 结束时间
    int64_t echo_end = esp_timer_get_time();

    uint32_t  duration_us = (uint32_t)(echo_end - echo_start);
    uint32_t  distance_cm = (duration_us * SOUND_SPEED_CM_US) / 2.0f;
    if(distance_cm > MAX_DISTANCE_CM) distance_cm = distance_cm;
 //   ESP_LOGW(TAG, "###ultrasonic_measure_distance %d",(int)distance_cm);
    return  (int)distance_cm;
    // 6. 计算持续时间
   // result.duration_us = (uint32_t)(echo_end - echo_start);
   
    
    // 7. 计算距离(单位:cm)
    // 距离 = (时间 * 声速) / 2 (往返时间所以要除以2)
    // result.distance_cm = (result.duration_us * SOUND_SPEED_CM_US) / 2.0f;
    // result.success = true;

   // return result;
}

//////////////////////////////////////////////////////////////////////////
//senor manager
Senor_Manager::Senor_Manager(){

}
Senor_Manager::~Senor_Manager(){

}
void Senor_Manager::init_all_senors(){
    get_ultrasonic_senor(Senor_Direction_Forward)->ultrasonic_init();
}

int Senor_Manager::get_senor_distance(Senor_Type ty,Senor_Direction direction){
    if(ty == Senor_Ultrasonic){
        switch(direction){
            case Senor_Direction_Forward:return get_ultrasonic_senor(direction)->get_senor_distance(); break;
            default:
            break;
        }
    }
    return -1;
}

//private
ultrasonic_control* Senor_Manager::get_ultrasonic_senor(Senor_Direction direction){
    //暂时只有一个,参数无用,后续增加再修改
    static  ultrasonic_control ultrasonic(Senor_Direction_Forward);
    return &ultrasonic;
   // static  ultrasonic_control ultrasonic[Senor_Direction_Total];
   // return &ultrasonic[direction];
}

motor_control.h

#ifndef MOTOR_CONTROL_H
#define MOTOR_CONTROL_H

#include "driver/gpio.h"
#include "driver/ledc.h"
#include "esp_log.h"

#define SIMPLE_GPIO_CONTROL
#define ESP32_S3
//SIMPLE_MODE//////////////////////////////////////////////
// L298N模块1 (控制左侧两个电机):
// ENA  → GPIO_2 (PWM)
// IN1  → GPIO_4 (FWD_LEFT) → 同时连接到电机1和电机3的方向控制
// IN2  → GPIO_5 (BWD_LEFT) → 同时连接到电机1和电机3的方向控制  
// IN3  → GPIO_4 (FWD_LEFT) → 并联到IN1
// IN4  → GPIO_5 (BWD_LEFT) → 并联到IN2

// L298N模块2 (控制右侧两个电机):
// ENA  → GPIO_3 (PWM) 
// IN1  → GPIO_6 (FWD_RIGHT) → 同时连接到电机2和电机4的方向控制
// IN2  → GPIO_7 (BWD_RIGHT) → 同时连接到电机2和电机4的方向控制
// IN3  → GPIO_6 (FWD_RIGHT) → 并联到IN1
// IN4  → GPIO_7 (BWD_RIGHT) → 并联到IN2
////////////////////////////////////////////////
// 电机引脚定义 - 请根据实际接线修改
#ifdef  SIMPLE_GPIO_CONTROL
// PWM控制引脚
#ifndef  ESP32_S3
#define LEFT_PWM_PIN    GPIO_NUM_0   //使能LEFT

#define RIGHT_PWM_PIN   GPIO_NUM_10    //使能RIGHT


// #define FWD_RIGHT_PIN   GPIO_NUM_3    // 右轮前进
// #define BWD_RIGHT_PIN   GPIO_NUM_2    // 右轮后退
// 方向控制引脚  
#define FWD_LEFT_PIN    GPIO_NUM_2    // 左边 IN1 IN3
#define BWD_LEFT_PIN    GPIO_NUM_3   // 左边 IN2 IN4
//
#define FWD_RIGHT_PIN   GPIO_NUM_18    // 右IN1 IN3
#define BWD_RIGHT_PIN   GPIO_NUM_12    // 右IN2 IN4

// #define FWD_LEFT_PIN    GPIO_NUM_12    // 左轮前进
// #define BWD_LEFT_PIN    GPIO_NUM_18   // 左轮后退



// PWM通道
#define LEFT_PWM_CH     LEDC_CHANNEL_1
#define RIGHT_PWM_CH    LEDC_CHANNEL_2
#else
#define LEFT_PWM_PIN    GPIO_NUM_9   //使能LEFT
// 方向控制引脚  
// #define FWD_LEFT_PIN    GPIO_NUM_10    // 左边 IN1 IN3
// #define BWD_LEFT_PIN    GPIO_NUM_11  // 左边 IN2 IN4

#define FWD_LEFT_PIN    GPIO_NUM_11    // 左边 IN1 IN3
#define BWD_LEFT_PIN    GPIO_NUM_10  // 左边 IN2 IN4

// #define RIGHT_PWM_PIN   GPIO_NUM_12    //使能RIGHT
// // 方向控制引脚 
// #define FWD_RIGHT_PIN   GPIO_NUM_13    // 右IN1 IN3
// #define BWD_RIGHT_PIN   GPIO_NUM_14    // 右IN2 IN4
//35->38 不要用 只有输入功能没输出功能
// #define RIGHT_PWM_PIN   GPIO_NUM_38    //使能RIGHT
// // 方向控制引脚 
// #define FWD_RIGHT_PIN   GPIO_NUM_37    // 右IN1 IN3
// #define BWD_RIGHT_PIN   GPIO_NUM_36    // 右IN2 IN4

#define RIGHT_PWM_PIN   GPIO_NUM_45    //使能RIGHT
// 方向控制引脚 
#define FWD_RIGHT_PIN   GPIO_NUM_40    // 右IN1 IN3
#define BWD_RIGHT_PIN   GPIO_NUM_39    // 右IN2 IN4



// PWM通道
#define LEFT_PWM_CH     LEDC_CHANNEL_0
#define RIGHT_PWM_CH    LEDC_CHANNEL_1
#endif

#else
//c3  右边 GPIO
#define MOTOR1_IN1     GPIO_NUM_2
#define MOTOR1_IN2     GPIO_NUM_3
#define MOTOR1_ENA     GPIO_NUM_10

#define MOTOR2_IN1     GPIO_NUM_6
#define MOTOR2_IN2     GPIO_NUM_7
#define MOTOR2_ENB     GPIO_NUM_5

//左边 GPIO
#define MOTOR3_IN1     GPIO_NUM_0
#define MOTOR3_IN2     GPIO_NUM_1
#define MOTOR3_ENA     GPIO_NUM_12

#define MOTOR4_IN1     GPIO_NUM_18
#define MOTOR4_IN2     GPIO_NUM_19
#define MOTOR4_ENB     GPIO_NUM_13

// 电机通道定义
#define MOTOR1_PWM_CH           LEDC_CHANNEL_0
#define MOTOR2_PWM_CH           LEDC_CHANNEL_1
#define MOTOR3_PWM_CH           LEDC_CHANNEL_2
#define MOTOR4_PWM_CH           LEDC_CHANNEL_3

#endif

// PWM配置
#ifndef  ESP32_S3
#define LEDC_TIMER              LEDC_TIMER_1
#else
#define LEDC_TIMER              LEDC_TIMER_3
#endif
#define LEDC_MODE               LEDC_LOW_SPEED_MODE
#define LEDC_DUTY_RES           LEDC_TIMER_10_BIT
#define LEDC_FREQUENCY          5000
// 电机结构体
typedef struct {
    gpio_num_t in1;
    gpio_num_t in2;
    ledc_channel_t pwm_ch;
} motor_t;

// 运动方向枚举
typedef enum {
    CAR_FORWARD,
    CAR_BACKWARD,
    CAR_LEFT,
    CAR_RIGHT,
    CAR_STOP
} car_direction_t;
class MotorControl{ 
public:
    MotorControl();
    ~MotorControl();
    // 函数声明
    void motor_control_init(void);
    void set_motor_speed(ledc_channel_t channel, uint32_t duty);
    void motor_forward(motor_t motor);
    void motor_backward(motor_t motor);
    void motor_stop(motor_t motor);
    void car_control(car_direction_t direction, uint32_t speed);
    void car_differential_control(int left_speed, int right_speed);
};

#endif

motor_control.cc

#include "motor_control.h"
#include <driver/ledc.h>

#define TAG  "MOTORCON"



#ifdef SIMPLE_GPIO_CONTROL
#define TOTAL_DIR   2
#else
#define TOTAL_DIR 4;
#endif

#ifdef SIMPLE_GPIO_CONTROL
//电机对象定义
static motor_t motors[TOTAL_DIR]= {
    {FWD_LEFT_PIN, BWD_LEFT_PIN, LEFT_PWM_CH}, // 左边轮
    {FWD_RIGHT_PIN, BWD_RIGHT_PIN, RIGHT_PWM_CH} // 右边轮
};
#else
// 电机对象定义
static motor_t motors[TOTAL_DIR] = {
    {MOTOR1_IN1, MOTOR1_IN2, MOTOR1_PWM_CH}, // 左前轮
    {MOTOR2_IN1, MOTOR2_IN2, MOTOR2_PWM_CH}, // 右前轮
    {MOTOR3_IN1, MOTOR3_IN2, MOTOR3_PWM_CH}, // 左后轮
    {MOTOR4_IN1, MOTOR4_IN2, MOTOR4_PWM_CH}  // 右后轮
};
#endif

MotorControl::MotorControl(){}
MotorControl::~MotorControl(){}
void MotorControl::motor_control_init(void) {
    ESP_LOGI(TAG, "Initializing motor control...");
    
    // GPIO配置
    #ifdef SIMPLE_GPIO_CONTROL

     gpio_config_t io_conf = {
        .pin_bit_mask = (1ULL << FWD_LEFT_PIN) | (1ULL << BWD_LEFT_PIN) |
                       (1ULL << FWD_RIGHT_PIN) | (1ULL << BWD_RIGHT_PIN),
        .mode = GPIO_MODE_OUTPUT,
        .pull_up_en = GPIO_PULLUP_DISABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE
    };
    #else
    gpio_config_t io_conf = {
        .pin_bit_mask = (1ULL << MOTOR1_IN1) | (1ULL << MOTOR1_IN2) |
                       (1ULL << MOTOR2_IN1) | (1ULL << MOTOR2_IN2) |
                       (1ULL << MOTOR3_IN1) | (1ULL << MOTOR3_IN2) |
                       (1ULL << MOTOR4_IN1) | (1ULL << MOTOR4_IN2),
        .mode = GPIO_MODE_OUTPUT,
        .pull_up_en = GPIO_PULLUP_DISABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE
    };
    
    #endif
    gpio_config(&io_conf);
    
    // 初始化所有电机为停止状态
    for (int i = 0; i < TOTAL_DIR; i++) {
        gpio_set_level(motors[i].in1, 0);
        gpio_set_level(motors[i].in2, 0);
    }

    //
    //freq = source_clock / (prescaler * (2^resolution - 1))
//source_clock = 80MHz (APB_CLK)
// prescaler = 分频系数 (1-65535)
// resolution = 占空比分辨率位数
// 你的配置计算:
// source_clock = 80,000,000 Hz
// resolution = 10位 → (2^10 - 1) = 1023
// desired_freq = 5000 Hz
// 所需分频系数 = 80,000,000 / (5000 * 1023) ≈ 15.64
// 实际使用分频系数 = 16
// 实际频率 = 80,000,000 / (16 * 1023) ≈ 4885 Hz
// 这个实际频率(4885Hz)非常接近你设定的5000Hz,是完全可接受的
    
    // PWM定时器配置
    ledc_timer_config_t ledc_timer = {
        .speed_mode = LEDC_MODE,    //高速模式-LEDC_LOW_SPEED_MODE,低速模式-LEDC_SPEED_MODE_MAX
        .duty_resolution = LEDC_DUTY_RES, // LEDC通道占空比分辨率  10bit  0-1023
        .timer_num = LEDC_TIMER,  //通道的定时器源(0 -> LEDC_TIMER_MAX - 1)
        .freq_hz = LEDC_FREQUENCY,  //LEDC定时器频率(赫兹)0到2^(8)-1 =>0->255 // 0->(2^(PWM_RESOLUTION) -1)
        .clk_cfg = LEDC_AUTO_CLK
    };
    ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));

    #ifdef SIMPLE_GPIO_CONTROL
     // PWM通道配置
    ledc_channel_config_t ledc_channel[TOTAL_DIR] = {
        {
        .gpio_num = LEFT_PWM_PIN,
        .speed_mode = LEDC_MODE,
        .channel = LEFT_PWM_CH,
        .intr_type = LEDC_INTR_DISABLE,
        .timer_sel = LEDC_TIMER,
        .duty = 0,
        .hpoint = 0
        },
        {
            .gpio_num = RIGHT_PWM_PIN,
            .speed_mode = LEDC_MODE,
            .channel = RIGHT_PWM_CH,
            .intr_type = LEDC_INTR_DISABLE,
            .timer_sel = LEDC_TIMER,
            .duty = 0,
            .hpoint = 0
        }
        
    };

    for (int i = 0; i < TOTAL_DIR; i++) {
        ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel[i]));
    }
    #else

    // PWM通道配置
    ledc_channel_config_t ledc_channel[TOTAL_DIR] = {
        {
            .speed_mode = LEDC_MODE,
            .channel = MOTOR1_PWM_CH,
            .timer_sel = LEDC_TIMER,
            .intr_type = LEDC_INTR_DISABLE,
            .gpio_num = MOTOR1_ENA,
            .duty = 0,
            .hpoint = 0
        },
        {
            .speed_mode = LEDC_MODE,
            .channel = MOTOR2_PWM_CH,
            .timer_sel = LEDC_TIMER,
            .intr_type = LEDC_INTR_DISABLE,
            .gpio_num = MOTOR2_ENB,
            .duty = 0,
            .hpoint = 0
        },
        {
            .speed_mode = LEDC_MODE,
            .channel = MOTOR3_PWM_CH,
            .timer_sel = LEDC_TIMER,
            .intr_type = LEDC_INTR_DISABLE,
            .gpio_num = MOTOR3_ENA,
            .duty = 0,
            .hpoint = 0
        },
        {
            .speed_mode = LEDC_MODE,
            .channel = MOTOR4_PWM_CH,
            .timer_sel = LEDC_TIMER,
            .intr_type = LEDC_INTR_DISABLE,
            .gpio_num = MOTOR4_ENB,
            .duty = 0,
            .hpoint = 0
        }
    };
    
    for (int i = 0; i < TOTAL_DIR; i++) {
        ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel[i]));
    }
    #endif
    ESP_LOGI(TAG, "Motor control initialized successfully");
}

void MotorControl::set_motor_speed(ledc_channel_t channel, uint32_t duty) {
    // 限制占空比在0-1023范围内 (10位分辨率)
    if (duty > 1023) {
        duty = 1023;
    }
    ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, channel, duty));
    ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, channel));
}

void MotorControl::motor_forward(motor_t motor) {
    gpio_set_level(motor.in1, 1);
    gpio_set_level(motor.in2, 0);
}

void MotorControl::motor_backward(motor_t motor) {
    gpio_set_level(motor.in1, 0);
    gpio_set_level(motor.in2, 1);
}

void MotorControl::motor_stop(motor_t motor) {
    gpio_set_level(motor.in1, 0);
    gpio_set_level(motor.in2, 0);
    set_motor_speed(motor.pwm_ch, 0);
}

void MotorControl::car_control(car_direction_t direction, uint32_t speed) {
    switch (direction) {
        case CAR_FORWARD:
            // 所有电机前进
            for (int i = 0; i < TOTAL_DIR; i++) {
                motor_forward(motors[i]);
                set_motor_speed(motors[i].pwm_ch, speed);
            }
            ESP_LOGI(TAG, "Car moving FORWARD at speed: %lu", speed);
            break;
            
        case CAR_BACKWARD:
            // 所有电机后退
            for (int i = 0; i < TOTAL_DIR; i++) {
                motor_backward(motors[i]);
                set_motor_speed(motors[i].pwm_ch, speed);
            }
            ESP_LOGI(TAG, "Car moving BACKWARD at speed: %lu", speed);
            break;
            
        case CAR_LEFT:
            {
                #ifdef SIMPLE_GPIO_CONTROL
                 motor_forward(motors[1]); // 右前
                 motor_backward(motors[0]); // 左前
                #else
                    // 右侧电机前进,左侧电机后退或停止实现左转
                motor_forward(motors[1]); // 右前
                motor_forward(motors[3]); // 右后
                motor_backward(motors[0]); // 左前
                motor_backward(motors[2]); // 左后
                #endif
                for (int i = 0; i < TOTAL_DIR; i++) {
                    set_motor_speed(motors[i].pwm_ch, speed);
                }

                ESP_LOGI(TAG, "Car turning LEFT at speed: %lu", speed);
            }
            break;
            
        case CAR_RIGHT:
            {
                #ifdef SIMPLE_GPIO_CONTROL
                    motor_forward(motors[0]); // 左前
                    motor_backward(motors[1]); // 右前
                    for (int i = 0; i < TOTAL_DIR; i++) {
                        set_motor_speed(motors[i].pwm_ch, speed);
                    }
                #else
                // 左侧电机前进,右侧电机后退或停止实现右转
                motor_forward(motors[0]); // 左前
                motor_forward(motors[2]); // 左后
                motor_backward(motors[1]); // 右前
                motor_backward(motors[3]); // 右后
                #endif
                for (int i = 0; i < TOTAL_DIR; i++) {
                    set_motor_speed(motors[i].pwm_ch, speed);
                }
                ESP_LOGI(TAG, "Car turning RIGHT at speed: %lu", speed);
            }
            break;
            
        case CAR_STOP:
            // 所有电机停止
            for (int i = 0; i < TOTAL_DIR; i++) {
                motor_stop(motors[i]);
            }
         //   ESP_LOGI(TAG, "Car STOPPED");
            break;
    }
}

void MotorControl::car_differential_control(int left_speed, int right_speed) {
    // 确保速度值在有效范围内
    if (left_speed > 1023) left_speed = 1023;
    if (left_speed < -1023) left_speed = -1023;
    if (right_speed > 1023) right_speed = 1023;
    if (right_speed < -1023) right_speed = -1023;
    
    // 控制左侧电机 (0和2)
    if (left_speed > 0) {
        motor_forward(motors[0]);
        #ifndef SIMPLE_GPIO_CONTROL
        motor_forward(motors[2]);
        #endif
        set_motor_speed(motors[0].pwm_ch, left_speed);
        #ifndef SIMPLE_GPIO_CONTROL
        set_motor_speed(motors[2].pwm_ch, left_speed);
        #endif
    } else if (left_speed < 0) {
        motor_backward(motors[0]);
        #ifndef SIMPLE_GPIO_CONTROL
        motor_backward(motors[2]);
        #endif
        set_motor_speed(motors[0].pwm_ch, -left_speed);
        #ifndef SIMPLE_GPIO_CONTROL
        set_motor_speed(motors[2].pwm_ch, -left_speed);
        #endif
    } else {
        motor_stop(motors[0]);
        #ifndef SIMPLE_GPIO_CONTROL
        motor_stop(motors[2]);
        #endif
    }
    
    // 控制右侧电机 (1和3)
    if (right_speed > 0) {
        motor_forward(motors[1]);
        #ifndef SIMPLE_GPIO_CONTROL
        motor_forward(motors[3]);
        #endif
        set_motor_speed(motors[1].pwm_ch, right_speed);
        #ifndef SIMPLE_GPIO_CONTROL
        set_motor_speed(motors[3].pwm_ch, right_speed);
        #endif
    } else if (right_speed < 0) {
        motor_backward(motors[1]);
        #ifndef SIMPLE_GPIO_CONTROL
        motor_backward(motors[3]);
        #endif
        set_motor_speed(motors[1].pwm_ch, -right_speed);
        #ifndef SIMPLE_GPIO_CONTROL
        set_motor_speed(motors[3].pwm_ch, -right_speed);
        #endif
    } else {
        motor_stop(motors[1]);
        #ifndef SIMPLE_GPIO_CONTROL
        motor_stop(motors[3]);
        #endif
    }
}

2:代码说明
设置为1 测试模式下, 小车轮子是不动的,用于测试 命令是否执行,也可以测试超声波,反正小车不会动
设置为0 就是正常模式了
在这里插入图片描述
还有就是,如果不小心把工程清理了,重新编译 会遇到问题,按照下面的修改就可以了,
espressif2022 的2个依赖 版本变了,老的没有了,详细的自己去github上查看
在这里插入图片描述
当前位置没合适孔,临时绑了下超声波模块,
在自动巡航时,会用到超声波测距,其他暂时不用,因为时间比较短,没加,可以自行增加超声波障碍物检测
在这里插入图片描述
3:测试结果 如果对你又帮助,麻烦点个赞,加个关注

esp32_auto_cruise

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐