/* * Copyright (c) 2024, YourName * 项目:基于 RT-Thread 的电机 ESC 控制(移植自 Arduino) * 功能:通过串口接收指令控制电机转速、LED、蜂鸣器 * 已移除:超声波、光敏电阻、自动急停 * 新增:所有速度档位切换必须平滑加减速(逐步 ±1,每次延时 50ms) */ #include #include #include #include "hal_data.h" // ====================== 引脚 / 设备 宏定义 ====================== #define PWM_DEV_NAME "pwm12" // PWM设备名,请根据实际连接修改 #define PWM_CHANNEL 0 // PWM通道 #define LED_PIN BSP_IO_PORT_00_PIN_01 // LED引脚(根据实际修改) #define BUZZER_PIN BSP_IO_PORT_05_PIN_05 // 蜂鸣器引脚(根据实际修改) #define SERIAL_DEVICE_NAME "uart2" // 串口设备名,如USB转串口 / 蓝牙模块 // ====================== 速度档位定义 ====================== volatile int item = 100; // 当前速度值 const int speed_level = 100; // 启动速度 const int speed_min = 80; // 最低速度 const int speed_one = 135; // 档位1 const int speed_two = 150; // 档位2 const int speed_three = 175; // 档位3 const int speed_max = 200; // 档位4(最高速) const int speed_add = 10; // 每次调整步进 // ====================== 全局变量 ====================== static struct rt_device_pwm *pwm_dev; static rt_device_t serial_dev; char rx_buffer[64]; int rx_len = 0; static bool is_started = false; // 系统是否已启动 // ====================== 蜂鸣器控制 ====================== void buzzer_beep(int count, int duration_ms) { for (int i = 0; i < count; i++) { rt_pin_write(BUZZER_PIN, PIN_HIGH); rt_thread_mdelay(duration_ms); rt_pin_write(BUZZER_PIN, PIN_LOW); rt_thread_mdelay(duration_ms); } } // ====================== LED 控制 ====================== void led_on(void) { rt_pin_write(LED_PIN, PIN_HIGH); } void led_off(void) { rt_pin_write(LED_PIN, PIN_LOW); } // ====================== 平滑加减速函数(核心新增)====================== // 从当前 item 逐步变化到 target,每次 ±1,延时 50ms,调用 rt_pwm_set() static void smooth_set_speed(int target) { int step = (target > item) ? 1 : -1; rt_kprintf("[Smooth] Changing speed from %d to %d...\r\n", item, target); while (item != target) { item += step; // 防止超过目标 if ((step > 0 && item > target) || (step < 0 && item < target)) { item = target; } // 计算脉冲宽度:假设 1ms(1000000ns) ~ 2ms(2000000ns) 对应 speed_min ~ speed_max int pulse = 1000000 + (item - speed_min) * (1000000 / (speed_max - speed_min)); // 限制 pulse 在合理范围(可选,根据需求) if (pulse < 1000000) pulse = 1000000; if (pulse > 2000000) pulse = 2000000; // 设置 PWM rt_pwm_set(pwm_dev, PWM_CHANNEL, 20000000, pulse); // 20ms 周期 rt_thread_mdelay(50); // 每步延时 50ms,形成平滑过渡 rt_kprintf("[Smooth] Now at: %d\r\n", item); // 调试输出,可选 } rt_kprintf("[Smooth] Reached target: %d\r\n", item); } // ====================== 指令动作处理函数 ====================== void action(const char *throttle) { rt_kprintf("[Action] Received: %s\r\n", throttle); if (strcmp(throttle, "stop") == 0) { smooth_set_speed(speed_level); led_off(); buzzer_beep(1, 500); rt_kprintf("[Action] STOPPED. Speed set to level.\r\n"); is_started = false; } else if (strcmp(throttle, "decrease") == 0) { int target = item - speed_add; if (target < speed_level) target = speed_level; smooth_set_speed(target); buzzer_beep(1, 100); rt_kprintf("[Action] DECREASED (smooth). Speed: %d\r\n", item); } else if (strcmp(throttle, "increase") == 0) { int target = item + speed_add; if (target > speed_max) target = speed_max; smooth_set_speed(target); buzzer_beep(1, 200); rt_kprintf("[Action] INCREASED (smooth). Speed: %d\r\n", item); } else if (strcmp(throttle, "one") == 0) { smooth_set_speed(speed_one); buzzer_beep(1, 150); rt_kprintf("[Action] SPEED 1 (smooth). Speed: %d\r\n", item); } else if (strcmp(throttle, "two") == 0) { smooth_set_speed(speed_two); buzzer_beep(2, 150); rt_kprintf("[Action] SPEED 2 (smooth). Speed: %d\r\n", item); } else if (strcmp(throttle, "three") == 0) { smooth_set_speed(speed_three); buzzer_beep(3, 150); rt_kprintf("[Action] SPEED 3 (smooth). Speed: %d\r\n", item); } else if (strcmp(throttle, "four") == 0) { smooth_set_speed(speed_max); buzzer_beep(4, 150); rt_kprintf("[Action] SPEED 4 (MAX, smooth). Speed: %d\r\n", item); } else if (strcmp(throttle, "turn on") == 0) { led_on(); buzzer_beep(1, 200); rt_kprintf("[Action] LED ON\r\n"); } else if (strcmp(throttle, "turn off") == 0) { led_off(); buzzer_beep(1, 200); rt_kprintf("[Action] LED OFF\r\n"); } else if (strcmp(throttle, "buzzer on") == 0) { buzzer_beep(2, 300); rt_kprintf("[Action] BUZZER ON\r\n"); } else if (strcmp(throttle, "buzzer off") == 0) { buzzer_beep(2, 100); rt_kprintf("[Action] BUZZER OFF\r\n"); } else { rt_kprintf("[Action] Unknown command: %s\r\n", throttle); } } // ====================== 串口指令线程 ====================== static void serial_cmd_thread_entry(void *parameter) { rt_size_t len; while (1) { memset(rx_buffer, 0, sizeof(rx_buffer)); len = rt_device_read(serial_dev, 0, rx_buffer, sizeof(rx_buffer) - 1); if (len > 0) { rx_buffer[len] = '\0'; rt_kprintf("[Serial] Rx: %s\r\n", rx_buffer); if (!is_started) { if (strcmp(rx_buffer, "start") == 0) { is_started = true; rt_kprintf("[System] System STARTED.\r\n"); buzzer_beep(2, 300); } else { rt_kprintf("[System] ERROR: System NOT STARTED. Send 'start' first.\r\n"); } } else { action(rx_buffer); } rx_buffer[0] = '\0'; } rt_thread_mdelay(10); } } // ====================== 初始化函数 ====================== int motor_control_app_init(void) { // 1. 初始化 PWM pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME); if (pwm_dev == RT_NULL) { rt_kprintf("Cannot find PWM device: %s\r\n", PWM_DEV_NAME); return -1; } int base_pulse = 1000000; // 1ms int pulse_range = 1000000; // 1ms -> 1000us ~ 2000us int item_pulse = base_pulse + (item - speed_min) * (pulse_range / (speed_max - speed_min)); rt_pwm_set(pwm_dev, PWM_CHANNEL, 20000000, item_pulse); rt_pwm_enable(pwm_dev, PWM_CHANNEL); rt_kprintf("PWM ESC initialized. Channel %d, Period 20ms.\r\n", PWM_CHANNEL); // 2. 初始化 LED & 蜂鸣器 rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); rt_pin_mode(BUZZER_PIN, PIN_MODE_OUTPUT); led_off(); rt_pin_write(BUZZER_PIN, PIN_LOW); // 3. 打开串口 serial_dev = rt_device_find(SERIAL_DEVICE_NAME); if (serial_dev == RT_NULL) { rt_kprintf("Cannot find serial device: %s\r\n", SERIAL_DEVICE_NAME); return -1; } rt_device_open(serial_dev, RT_DEVICE_FLAG_INT_RX); // 4. 创建串口指令线程 rt_thread_t tid = rt_thread_create("serial_cmd", serial_cmd_thread_entry, RT_NULL, 1024, 20, 10); if (tid != RT_NULL) { buzzer_beep(2, 300); rt_thread_startup(tid); rt_kprintf("Serial command thread started.\r\n"); } else { rt_kprintf("Failed to create serial command thread.\r\n"); } return 0; } // ====================== 导出组件初始化 ====================== INIT_APP_EXPORT(motor_control_app_init);