前言:
前面用stm32f103c8t6 rt-thread 寫了個智能小車程序
這章用esp32-c3 重新來遍
1:環境
vscode+idf5.4
esp32-3c
找到一塊MIN的底板 湊合用(138 cm左右)
一個L298N
一個船型開關,
一個665mm 2腳按鈕
鋰電池 186502 及電池盒(串聯)
一個HC-RS04 超聲波
2:接線及GPIO
超聲波
#define TRIG_GPIO GPIO_NUM_6
#define ECHO_GPIO GPIO_NUM_7
PWM //如果接反,自行 修改 IN1 到IN4的 引腳 序號就可以,
這里已經用蓋冒使能了,所以只要4個GPIO作為 PWM,.
也可以用 2個GPIO EN PWM ,再用4個GPIO 作為輸出
#define IN1 GPIO_NUM_5
#define IN2 GPIO_NUM_4
#define IN3 GPIO_NUM_3
#define IN4 GPIO_NUM_2
// 按鍵引腳定義
#define KEY_GPIO GPIO_NUM_8
2節鋰電池 直接 給L298N VS: 電機電壓供應引腳,注意不是邏輯引腳,(邏輯引腳靠近 IN1-IN4)
接7-12V 電池,剛好 邏輯引腳可以輸出 給MCU 供電,省了一個降壓模塊
超聲波支架斷了,用繩子綁下 湊合下
3:上代碼
#include <stdio.h>
#include "driver/gpio.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_rom_sys.h" // 添加此頭文件以使用 esp_rom_delay_us()//pwm
#include "driver/ledc.h"//wifi
// WiFi配置
#include "esp_wifi.h"
#include "esp_event.h"
#include "nvs_flash.h"
#define WIFI_SSID "*****"
#define WIFI_PASSWORD "*******"
#define SERVER_HOST "192.168.1.3"
static EventGroupHandle_t s_wifi_event_group;
const int WIFI_CONNECTED_BIT = BIT0;// 引腳定義
// #define TRIG_GPIO GPIO_NUM_0
// #define ECHO_GPIO GPIO_NUM_1#define TRIG_GPIO GPIO_NUM_6
#define ECHO_GPIO GPIO_NUM_7// 超時時間(毫秒),對應約5米距離
#define MEASURE_TIMEOUT_MS 300 //50m 左右,足夠足夠了// 超聲波測量距離閾值(cm)
#define OBSTACLE_THRESHOLD 20
//#define TAG "test_sr04"
// 增加超時時間(對應約10米)// L298N電機驅動引腳定義
// #define IN1 GPIO_NUM_12
// #define IN2 GPIO_NUM_13
// #define IN3 GPIO_NUM_19
// #define IN4 GPIO_NUM_18
// #define IN1 GPIO_NUM_4
// #define IN2 GPIO_NUM_5
// #define IN3 GPIO_NUM_2
// #define IN4 GPIO_NUM_3#define IN1 GPIO_NUM_5
#define IN2 GPIO_NUM_4#define IN3 GPIO_NUM_3
#define IN4 GPIO_NUM_2// 按鍵引腳定義
#define KEY_GPIO GPIO_NUM_8// PWM配置參數
#define PWM_FREQ_HZ 1000 // 電機PWM頻率(1kHz)
#define PWM_RESOLUTION LEDC_TIMER_8_BIT // 8位分辨率(0-255)
#define PWM_TIMER LEDC_TIMER_0 // 定時器編號
#define PWM_CH_IN1 LEDC_CHANNEL_0
#define PWM_CH_IN2 LEDC_CHANNEL_1
#define PWM_CH_IN3 LEDC_CHANNEL_2
#define PWM_CH_IN4 LEDC_CHANNEL_3// 任務句柄
static TaskHandle_t auto_nav_task_handle = NULL;// 狀態變量
static volatile bool is_running = false;
static volatile bool key_pressed = false;// 日志標簽
static const char *TAG = "esp32c3_car";// 事件隊列
QueueHandle_t ultrasonic_event_queue = NULL;// 測量狀態
typedef enum {MEASURE_IDLE,WAITING_ECHO_START,WAITING_ECHO_END
} measure_state_t;// 事件類型
typedef enum {ECHO_RISING_EDGE,ECHO_FALLING_EDGE,MEASURE_TIMEOUT
} ultrasonic_event_t;typedef struct
{int64_t curtick;ultrasonic_event_t event;}ultrasonic_queue_t;// 測量數據結構
typedef struct {int64_t start_time;int64_t end_time;measure_state_t state;esp_timer_handle_t timeout_timer;
} ultrasonic_measure_t;// 全局測量實例
ultrasonic_measure_t measure;volatile bool g_carstate = false; // false 停止 true 運行
//////PWM///////////////////////////////////////////////////////
// PWM初始化函數
void motor_pwm_init() {{gpio_config_t motor_lock_conf = {.pin_bit_mask = (1ULL << IN1) | (1ULL << IN2) | (1ULL << IN3) | (1ULL << IN4),.mode = GPIO_MODE_OUTPUT,.pull_up_en = GPIO_PULLUP_DISABLE,.pull_down_en = GPIO_PULLDOWN_ENABLE, // 啟用內部下拉.intr_type = GPIO_INTR_DISABLE};gpio_config(&motor_lock_conf);// 強制拉低所有引腳gpio_set_level(IN1, 0);gpio_set_level(IN2, 0);gpio_set_level(IN3, 0);gpio_set_level(IN4, 0);// 添加硬件級延時(不可中斷)esp_rom_delay_us(5000); // 5ms延時確保電平穩定ESP_LOGI(TAG, "IN1-IN4 LOW FINISH");}//LEDC_TIMER_13_BIT// 配置PWM定時器ledc_timer_config_t timer_cfg = {.speed_mode = LEDC_LOW_SPEED_MODE,//高速模式-LEDC_LOW_SPEED_MODE,低速模式-LEDC_SPEED_MODE_MAX.timer_num = PWM_TIMER, //通道的定時器源(0 -> LEDC_TIMER_MAX - 1).duty_resolution = PWM_RESOLUTION, // LEDC通道占空比分辨率.freq_hz = PWM_FREQ_HZ, //LEDC定時器頻率(赫茲)0到2^(8)-1 =>0->255 // 0->(2^(PWM_RESOLUTION) -1).clk_cfg = LEDC_AUTO_CLK};ESP_ERROR_CHECK(ledc_timer_config(&timer_cfg));// 配置4個PWM通道(IN1-IN4)ledc_channel_config_t ch_cfg[] = {{.gpio_num = IN1,.speed_mode = LEDC_LOW_SPEED_MODE,.channel = PWM_CH_IN1,.timer_sel = PWM_TIMER, //選擇通道的定時器源(0 - LEDC_TIMER_MAX - 1).duty = 0, //LEDC通道占空比,占空比設置范圍是[0, (2^占空比分辨率)].hpoint = 0},{.gpio_num = IN2,.speed_mode = LEDC_LOW_SPEED_MODE,.channel = PWM_CH_IN2,.timer_sel = PWM_TIMER,.duty = 0,.hpoint = 0},{.gpio_num = IN3,.speed_mode = LEDC_LOW_SPEED_MODE,.channel = PWM_CH_IN3,.timer_sel = PWM_TIMER,.duty = 0,.hpoint = 0},{.gpio_num = IN4,.speed_mode = LEDC_LOW_SPEED_MODE,.channel = PWM_CH_IN4,.timer_sel = PWM_TIMER,.duty = 0,.hpoint = 0}};for (int i = 0; i < 4; i++) {ESP_ERROR_CHECK(ledc_channel_config(&ch_cfg[i]));}ESP_LOGI(TAG, "電機PWM初始化完成");
}// 設置PWM占空比
static void set_pwm_duty(ledc_channel_t ch, uint8_t duty) {// duty=0;ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, ch, duty));ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, ch));
}// 電機控制函數(帶PWM調速)
void motor_forward(uint8_t speed) {g_carstate = true;set_pwm_duty(PWM_CH_IN1, speed);set_pwm_duty(PWM_CH_IN2, 0);set_pwm_duty(PWM_CH_IN3, speed);set_pwm_duty(PWM_CH_IN4, 0);
}void motor_backward(uint8_t speed) {g_carstate = true;set_pwm_duty(PWM_CH_IN1, 0);set_pwm_duty(PWM_CH_IN2, speed);set_pwm_duty(PWM_CH_IN3, 0);set_pwm_duty(PWM_CH_IN4, speed);
}void motor_turn_left(uint8_t speed) {g_carstate = true;// set_pwm_duty(PWM_CH_IN1, 0);// set_pwm_duty(PWM_CH_IN2, 0);// set_pwm_duty(PWM_CH_IN3, speed);// set_pwm_duty(PWM_CH_IN4, 0);set_pwm_duty(PWM_CH_IN1, 0);set_pwm_duty(PWM_CH_IN2, 0);set_pwm_duty(PWM_CH_IN3, speed);set_pwm_duty(PWM_CH_IN4, 0);}void motor_turn_spin_eft(uint8_t speed) {g_carstate = true;set_pwm_duty(PWM_CH_IN1, 0);set_pwm_duty(PWM_CH_IN2, speed);set_pwm_duty(PWM_CH_IN3, speed);set_pwm_duty(PWM_CH_IN4, 0);
}void motor_turn_right(uint8_t speed) {g_carstate = true;// set_pwm_duty(PWM_CH_IN1, speed);// set_pwm_duty(PWM_CH_IN2, 0);// set_pwm_duty(PWM_CH_IN3, 0);// set_pwm_duty(PWM_CH_IN4, 0);set_pwm_duty(PWM_CH_IN1, speed);set_pwm_duty(PWM_CH_IN2, 0);set_pwm_duty(PWM_CH_IN3, 0);set_pwm_duty(PWM_CH_IN4, 0);
}void motor_turn_spin_right(uint8_t speed) {g_carstate = true;set_pwm_duty(PWM_CH_IN1, speed);set_pwm_duty(PWM_CH_IN2, 0);set_pwm_duty(PWM_CH_IN3, 0);set_pwm_duty(PWM_CH_IN4, speed);
}void motor_stop() {g_carstate = false;set_pwm_duty(PWM_CH_IN1, 0);set_pwm_duty(PWM_CH_IN2, 0);set_pwm_duty(PWM_CH_IN3, 0);set_pwm_duty(PWM_CH_IN4, 0);
}
///////////////////////////////////////////////////////////////
//按鍵
// 按鍵中斷處理
static QueueHandle_t gpio_evt_queue = NULL;
static bool b_keypress = false;
//static volatile bool is_running = false;
static void IRAM_ATTR key_isr_handler(void* arg) {uint32_t gpio_num = (uint32_t) arg;int level = gpio_get_level(gpio_num);if (level == 0) {b_keypress = true;} else {if (b_keypress) {b_keypress = false;xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);}}
}// 按鍵處理任務
static void key_task(void* arg) {uint32_t io_num;while (1) {if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {if (io_num == KEY_GPIO) {is_running = !is_running;if (!is_running) {// motor_stop();} else {vTaskResume(auto_nav_task_handle);}ESP_LOGI(TAG, "statechange: %s", is_running ? "running" : "stop");}}}
}/////////////////////////////////////////////////////////////
// 中斷服務程序
static void IRAM_ATTR echo_isr_handler(void* arg) {BaseType_t xHigherPriorityTaskWoken = pdFALSE;// ultrasonic_event_t event;ultrasonic_queue_t event;// 獲取準確的邊緣類型uint32_t gpio_num = (uint32_t)arg;int level = gpio_get_level(gpio_num);event.curtick = esp_timer_get_time();if (level) {event.event = ECHO_RISING_EDGE;} else {event.event = ECHO_FALLING_EDGE;}// 發送事件到隊列xQueueSendFromISR(ultrasonic_event_queue, &event, &xHigherPriorityTaskWoken);if (xHigherPriorityTaskWoken) {portYIELD_FROM_ISR();}
}// 超時定時器回調
static void timer_timeout_callback(void* arg) {BaseType_t xHigherPriorityTaskWoken = pdFALSE;ultrasonic_queue_t event ;event.event = MEASURE_TIMEOUT;event.curtick = esp_timer_get_time();// 發送超時事件xQueueSendFromISR(ultrasonic_event_queue, &event, &xHigherPriorityTaskWoken);if (xHigherPriorityTaskWoken) {portYIELD_FROM_ISR();}
}// 初始化超聲波模塊
void ultrasonic_init() {// 配置Trig為輸出gpio_config_t trig_conf = {.pin_bit_mask = (1ULL << TRIG_GPIO),.mode = GPIO_MODE_OUTPUT,.pull_up_en = GPIO_PULLUP_DISABLE,.pull_down_en = GPIO_PULLDOWN_DISABLE,.intr_type = GPIO_INTR_DISABLE};gpio_config(&trig_conf);gpio_set_level(TRIG_GPIO, 0);// 配置Echo為輸入,啟用雙邊沿中斷gpio_config_t echo_conf = {.pin_bit_mask = (1ULL << ECHO_GPIO),.mode = GPIO_MODE_INPUT,.pull_up_en = GPIO_PULLUP_DISABLE,.pull_down_en = GPIO_PULLDOWN_ENABLE,.intr_type = GPIO_INTR_ANYEDGE};gpio_config(&echo_conf);// 創建事件隊列ultrasonic_event_queue = xQueueCreate(10, sizeof(ultrasonic_queue_t));// 安裝GPIO中斷服務(使用特定核心)gpio_install_isr_service(ESP_INTR_FLAG_IRAM);// 配置中斷處理程序(傳遞GPIO編號作為參數)gpio_isr_handler_add(ECHO_GPIO, echo_isr_handler, (void*)ECHO_GPIO);// 初始化測量狀態measure.state = MEASURE_IDLE;measure.timeout_timer = NULL;
}// 啟動一次測量
void ultrasonic_start_measurement() {if (measure.state != MEASURE_IDLE) {printf("Measurement already in progress\n");return;}// 確保ECHO引腳空閑(低電平)if (gpio_get_level(ECHO_GPIO) != 0) {printf("WARNING: ECHO not idle before measurement!\n");return;}// 發送10us脈沖gpio_set_level(TRIG_GPIO, 1);esp_rom_delay_us(15);gpio_set_level(TRIG_GPIO, 0);// 設置測量狀態measure.state = WAITING_ECHO_START;// 創建超時定時器const esp_timer_create_args_t timeout_timer_args = {.callback = &timer_timeout_callback,.arg = NULL,.name = "timeout_timer"};ESP_ERROR_CHECK(esp_timer_create(&timeout_timer_args, &measure.timeout_timer));ESP_ERROR_CHECK(esp_timer_start_once(measure.timeout_timer, MEASURE_TIMEOUT_MS * 1000));
}// 處理超聲波事件
float ultrasonic_process_events() {ultrasonic_event_t event;ultrasonic_queue_t eventmain ;float distance = -1.0;// 等待事件(最多100ms)if (xQueueReceive(ultrasonic_event_queue, &eventmain, pdMS_TO_TICKS(100))) {event = eventmain.event ;switch (measure.state) {case WAITING_ECHO_START:if (event == ECHO_RISING_EDGE) {measure.start_time = eventmain.curtick;//esp_timer_get_time();measure.state = WAITING_ECHO_END;// ESP_LOGI(TAG,"Rising edge detected[%lld]",eventmain.curtick);} else if (event == MEASURE_TIMEOUT) {ESP_LOGI(TAG,"Timeout waiting for rising edge. Echo level: %d->%lld", gpio_get_level(ECHO_GPIO),eventmain.curtick);measure.state = MEASURE_IDLE;//這里可能是空曠地,聲波返回不了distance = 99;//默認99cm //給個默認距離好了}break;case WAITING_ECHO_END:if (event == ECHO_FALLING_EDGE) {measure.end_time = eventmain.curtick;//esp_timer_get_time();uint32_t duration = measure.end_time - measure.start_time;//us 1s=340 1ms=0.34m 1us// 有效距離檢查(2cm - 4m)if (duration > 117 && duration < 23529) {distance = (duration * 0.034) / 2.0; //(因為1米=100厘米,所以340米/秒 = 34000厘米/秒 = 34厘米/毫秒 = 0.034厘米/微秒)// ESP_LOGI(TAG,"Falling edge detected[%lld]",eventmain.curtick);} else {ESP_LOGI(TAG,"Invalid duration: %d us\n",(int) duration);}measure.state = MEASURE_IDLE;} else if (event == MEASURE_TIMEOUT) {ESP_LOGI(TAG,"Timeout waiting for falling edge. Echo level: %d->%lld", gpio_get_level(ECHO_GPIO),eventmain.curtick);measure.state = MEASURE_IDLE;}break;default:ESP_LOGI(TAG,"Unexpected event in state: %d\n", (int)(measure.state));break;}// 清理定時器if (measure.timeout_timer && (event == ECHO_FALLING_EDGE || event == MEASURE_TIMEOUT)) {esp_timer_stop(measure.timeout_timer);esp_timer_delete(measure.timeout_timer);measure.timeout_timer = NULL;}} else {ESP_LOGI(TAG,"No event received in ultrasonic_process_events\n");}return distance;
}// 診斷函數:檢查GPIO狀態
void check_gpio_states() {ESP_LOGI(TAG,"TRIG state: %d, ECHO state: %d\n", gpio_get_level(TRIG_GPIO),gpio_get_level(ECHO_GPIO));
}// 手動觸發中斷(用于測試)
void simulate_echo_signal() {ESP_LOGI(TAG,"Simulating ECHO signal...\n");// 模擬上升沿gpio_set_level(ECHO_GPIO, 1);vTaskDelay(pdMS_TO_TICKS(1));// 模擬下降沿(實際距離對應5cm)gpio_set_level(ECHO_GPIO, 0);
}//const float u8_Percent = 100/80 ;
//3.7*2 鋰電池 空占比 要少小點,不然速度太快了,速度可以自行調整
const uint8_t NORMAL_SPEED = 100; // 正常速度(~60%)150
const uint8_t TURN_SPEED = 100; // 轉向速度(~40%)100
const uint8_t BACK_SPEED = 120; // 后退速度(~50%)120
// 自動尋路任務
static void auto_navigation_task(void* arg) {int16_t measured_distance = 0;int16_t flag_run = 0;int64_t loop_start =0;int64_t loop_end =0;#define CHECK_STATE() if(!is_running) continue;while (1) {if (is_running) {flag_run=0;loop_start = esp_timer_get_time();ultrasonic_start_measurement();// 等待測量完成// vTaskDelay(pdMS_TO_TICKS(30)); //額外增加的 34厘米/毫秒 //30ms = 30 *34 = 1m //不要加,要實時取消息處理// // 處理事件直到測量完成或超時float distance = -1.0;while (measure.state != MEASURE_IDLE) {distance = ultrasonic_process_events();vTaskDelay(pdMS_TO_TICKS(1)); // 防止任務阻塞}if(distance >0.0001f){measured_distance = distance ;}else{measured_distance = 0;}// measured_distance =30;// ESP_LOGI(TAG,"Distance: %d cm\n", measured_distance);// measured_distance =0;if (measured_distance <= 0 ) {//|| measured_distance > 5000// 測量錯誤,停止flag_run =1;motor_stop();vTaskDelay(pdMS_TO_TICKS(500));} else if (measured_distance < OBSTACLE_THRESHOLD) {if(g_carstate){motor_stop();vTaskDelay(pdMS_TO_TICKS(500));}CHECK_STATE()// 檢測到障礙物,后退并轉向motor_backward(BACK_SPEED);vTaskDelay(pdMS_TO_TICKS(500));CHECK_STATE()motor_stop();vTaskDelay(pdMS_TO_TICKS(500));CHECK_STATE()// 隨機轉向if (rand() % 2 == 0) {flag_run =2;motor_turn_left(TURN_SPEED);} else {flag_run =3;motor_turn_right(TURN_SPEED);}vTaskDelay(pdMS_TO_TICKS(500));CHECK_STATE()//////////////////////////////////////motor_stop();vTaskDelay(pdMS_TO_TICKS(500));} else {// 無障礙物,前進flag_run =4;motor_forward(NORMAL_SPEED);vTaskDelay(pdMS_TO_TICKS(10)); //額外增加的}loop_end = esp_timer_get_time();// motor_stop();// vTaskDelay(pdMS_TO_TICKS(500));ESP_LOGI(TAG,"Distance: %d cm %d(%lld->%lld)", measured_distance,flag_run,loop_start,loop_end);} else if(g_carstate){motor_stop();vTaskDelay(pdMS_TO_TICKS(500)); //}else{vTaskSuspend(NULL);vTaskDelay(pdMS_TO_TICKS(100));}}
}
//wifi
// WiFi事件處理函數
static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data) {if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {esp_wifi_connect();} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {esp_wifi_connect();xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT);ESP_LOGW(TAG, "WiFi disconnect,try again...");} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;ESP_LOGI(TAG, "get IP address: " IPSTR, IP2STR(&event->ip_info.ip));xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);}
}// WiFi初始化////////////////////////////////////////////////////////
void wifi_init_sta(void) {s_wifi_event_group = xEventGroupCreate();ESP_ERROR_CHECK(esp_netif_init());ESP_ERROR_CHECK(esp_event_loop_create_default());esp_netif_create_default_wifi_sta();wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();ESP_ERROR_CHECK(esp_wifi_init(&cfg));ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));wifi_config_t wifi_config = {.sta = {.ssid = WIFI_SSID,.password = WIFI_PASSWORD,},};ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));ESP_ERROR_CHECK(esp_wifi_start());ESP_LOGI(TAG, "WiFi init finish,connect %s...", WIFI_SSID);
}void init_wifi(){esp_err_t ret = nvs_flash_init();if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {ESP_ERROR_CHECK(nvs_flash_erase());ret = nvs_flash_init();}ESP_ERROR_CHECK(ret);wifi_init_sta();xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT,pdFALSE, pdTRUE, portMAX_DELAY);
}
/////////////////////////////////////////////////////////////////////////////
void test_ultrasonic(){// int64_t loop_start = esp_timer_get_time();ultrasonic_start_measurement();// 等待測量完成// vTaskDelay(pdMS_TO_TICKS(30)); //額外增加的 34厘米/毫秒 //30ms = 30 *34 = 1m //不要加,要實時取消息處理// // 處理事件直到測量完成或超時float distance = -1.0;while (measure.state != MEASURE_IDLE) {distance = ultrasonic_process_events();vTaskDelay(pdMS_TO_TICKS(1)); // 防止任務阻塞} ESP_LOGI(TAG,"test_ultrasonic: %.2f cm", distance);
}//
void test_montor(){{test_ultrasonic();}//測試小車狀態for(int i=0;i<2;i++){ESP_LOGI(TAG, "motor_forward");for(int j=0;j<10;j++){motor_forward(NORMAL_SPEED);vTaskDelay(pdMS_TO_TICKS(500)); //motor_stop();vTaskDelay(pdMS_TO_TICKS(1500)); //}ESP_LOGI(TAG, "motor_backward");for(int j=0;j<3;j++){motor_backward(BACK_SPEED);vTaskDelay(pdMS_TO_TICKS(500)); //motor_stop();vTaskDelay(pdMS_TO_TICKS(1500)); //}ESP_LOGI(TAG, "motor_turn_left");for(int j=0;j<3;j++){motor_turn_left(TURN_SPEED);vTaskDelay(pdMS_TO_TICKS(500)); //motor_stop();vTaskDelay(pdMS_TO_TICKS(1500)); //}ESP_LOGI(TAG, "motor_turn_right");for(int j=0;j<3;j++){motor_turn_right(TURN_SPEED);vTaskDelay(pdMS_TO_TICKS(500)); //motor_stop();vTaskDelay(pdMS_TO_TICKS(1500)); //}{test_ultrasonic();}}}
////////////////////////////////////////////////////////////////////////////////
void app_main() {// 1. 初始化PWM并立即停止電機motor_pwm_init();motor_stop(); // 確保所有占空比為0// 2. 初始化WiFi(如果不需要可以去掉)init_wifi();// 3. 初始化超聲波ultrasonic_init();// 4. 配置按鍵引腳(非PWM的GPIO)// 配置按鍵引腳為輸入,并設置中斷gpio_config_t key_conf = {.pin_bit_mask = (1ULL << KEY_GPIO),.mode = GPIO_MODE_INPUT,.pull_up_en = GPIO_PULLUP_ENABLE,.pull_down_en = GPIO_PULLDOWN_DISABLE,.intr_type = GPIO_INTR_ANYEDGE};gpio_config(&key_conf);// 5. 創建按鍵事件隊列并添加中斷處理gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));gpio_isr_handler_add(KEY_GPIO, key_isr_handler, (void*)KEY_GPIO);// 6. 創建任務xTaskCreate(key_task, "key_task", 2048, NULL, 5, NULL);if(0){vTaskDelay(pdMS_TO_TICKS(2000)); //
// const uint8_t NORMAL_SPEED = 150; // 正常速度(~60%)
// const uint8_t TURN_SPEED = 100; // 轉向速度(~40%)
// const uint8_t BACK_SPEED = 120; // 后退速度(~50%)test_montor();}xTaskCreate(auto_navigation_task, "auto_nav_task", 4096, NULL, 4, &auto_nav_task_handle);ESP_LOGI(TAG, "System initialization complete");
}
4: 測試結果 如果對你又幫助,麻煩點個贊,加個關注
問題,掛電池的那邊 重,有點不平衡,電池沒地方裝了,沒辦法了
其他的 傳感器度沒地方裝啊,底板太小了
測試視頻
esp3c-c3_smartcar