移动机器人开发全攻略:从STM32底层代码到APP控制实战
2026/7/26 13:10:01 网站建设 项目流程

在机器人技术快速发展的今天,很多开发者和小型团队都希望快速搭建自己的移动机器人平台,但往往卡在底层代码、硬件设计和软件控制这些基础环节。风扬科技提供的这套移动机器人完整资源包,正好解决了从硬件电路到上层应用的全链路开发需求,特别适合智能产品开发、嵌入式系统学习、传感器应用以及移动物联网项目的实践。

本文将完整拆解这套资源的核心内容,带你一步步理解移动机器人底层代码架构、电路设计原理图解析、APP控制端开发,并分享在实际嵌入式系统开发中的关键技术和避坑指南。无论你是嵌入式初学者还是有一定经验的开发者,都能从中获得可直接复用的技术方案。

1. 移动机器人系统架构概述

移动机器人系统是一个典型的嵌入式综合应用,涉及硬件控制、传感器数据处理、通信协议和上层应用开发多个层面。理解整体架构是后续开发的基础。

1.1 系统组成模块

一个完整的移动机器人系统通常包含以下核心模块:

  • 主控单元:负责整个系统的调度和控制,常见的有STM32、ESP32、树莓派等嵌入式处理器
  • 运动控制模块:包括电机驱动电路、编码器反馈、PID控制算法等
  • 传感器模块:超声波、红外、陀螺仪、摄像头等环境感知设备
  • 通信模块:Wi-Fi、蓝牙、4G等无线通信接口
  • 电源管理模块:电池充放电管理、电压转换、功耗控制
  • 上层应用:手机APP、Web控制端、PC端监控软件

1.2 风扬科技机器人架构特点

基于网络资料中提到的移动智能小车架构,风扬科技的方案具有以下特点:

  • 采用分层设计,硬件驱动层与业务逻辑层分离
  • 模块化接口设计,便于传感器扩展和功能定制
  • 支持多种通信协议,适应不同应用场景需求
  • 提供完整的开发文档和示例代码,降低学习门槛

2. 开发环境准备与工具链配置

在开始具体开发前,需要搭建完整的嵌入式开发环境。以下以常见的STM32平台为例说明环境配置。

2.1 硬件环境要求

  • 主控板:STM32F103C8T6最小系统板或类似型号
  • 下载器:ST-Link V2编程器
  • 电机驱动:L298N或TB6612FNG电机驱动模块
  • 传感器:HC-SR04超声波模块、MPU6050陀螺仪等
  • 电源:18650电池组或锂电池,输出7.4V-12V

2.2 软件工具安装

嵌入式开发需要一系列专业工具,以下是必备软件列表:

Keil MDK-ARM开发环境配置:

# 安装Keil MDK-ARM,注册并安装STM32器件支持包 # 配置ST-Link驱动,确保设备识别正常 # 安装串口调试工具,如SecureCRT或Putty

STM32CubeMX图形化配置工具:

// 使用STM32CubeMX生成初始化代码 // 配置时钟树、GPIO、外设参数 // 生成基于HAL库的工程框架

手机APP开发环境:

  • Android开发:Android Studio + Java/Kotlin
  • iOS开发:Xcode + Swift/Objective-C
  • 跨平台:Flutter或React Native

2.3 工程目录结构规范

建立清晰的工程目录结构有助于团队协作和后期维护:

MobileRobot_Project/ ├── Hardware/ # 硬件设计文件 │ ├── Schematic/ # 电路原理图 │ ├── PCB/ # PCB设计文件 │ └── BOM/ # 物料清单 ├── Firmware/ # 嵌入式固件 │ ├── Core/ # 核心驱动 │ ├── Drivers/ # 外设驱动 │ ├── Middleware/ # 中间件 │ └── Application/ # 应用逻辑 ├── Software/ # 上层软件 │ ├── Android/ # Android应用 │ ├── iOS/ # iOS应用 │ └── Documentation/ # 开发文档 └── Tests/ # 测试代码

3. 机器人底层代码深度解析

底层代码是机器人控制的核心,直接关系到机器人的运动精度和响应速度。风扬科技提供的底层代码采用了模块化设计,便于理解和二次开发。

3.1 主控制循环架构

机器人的主控制循环负责调度各个功能模块,确保实时性和稳定性:

// 文件路径:Firmware/Core/Src/main.c #include "main.h" #include "motor_control.h" #include "sensor.h" #include "communication.h" int main(void) { // 硬件初始化 HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); MX_TIM1_Init(); // 模块初始化 Motor_Init(); Sensor_Init(); Communication_Init(); // 主循环 while (1) { // 传感器数据采集 Sensor_Update(); // 通信数据处理 Communication_Process(); // 运动控制计算 Motion_Control(); // 系统状态监控 System_Monitor(); // 延时控制,典型值10-50ms HAL_Delay(20); } }

3.2 电机驱动与控制算法

电机控制是移动机器人的关键技术,直接影响运动性能。以下是PID控制算法的实现:

// 文件路径:Firmware/Application/motor_control.c #include "motor_control.h" // PID参数结构体 typedef struct { float Kp; // 比例系数 float Ki; // 积分系数 float Kd; // 微分系数 float integral; // 积分项 float prev_error; // 上一次误差 float output; // 输出值 } PID_Controller; // PID控制器初始化 void PID_Init(PID_Controller* pid, float kp, float ki, float kd) { pid->Kp = kp; pid->Ki = ki; pid->Kd = kd; pid->integral = 0; pid->prev_error = 0; pid->output = 0; } // PID计算函数 float PID_Calculate(PID_Controller* pid, float setpoint, float actual) { float error = setpoint - actual; // 比例项 float proportional = pid->Kp * error; // 积分项(带抗饱和) pid->integral += error; if (pid->integral > INTEGRAL_LIMIT) pid->integral = INTEGRAL_LIMIT; else if (pid->integral < -INTEGRAL_LIMIT) pid->integral = -INTEGRAL_LIMIT; float integral = pid->Ki * pid->integral; // 微分项 float derivative = pid->Kd * (error - pid->prev_error); pid->prev_error = error; // 输出计算 pid->output = proportional + integral + derivative; return pid->output; } // 电机速度控制函数 void Motor_Speed_Control(int left_speed, int right_speed) { // 限制速度范围 left_speed = constrain(left_speed, -255, 255); right_speed = constrain(right_speed, -255, 255); // 设置PWM占空比控制电机 __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, abs(left_speed)); __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, abs(right_speed)); // 设置电机方向 if (left_speed >= 0) { HAL_GPIO_WritePin(MOTOR_LEFT_DIR_GPIO_Port, MOTOR_LEFT_DIR_Pin, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(MOTOR_LEFT_DIR_GPIO_Port, MOTOR_LEFT_DIR_Pin, GPIO_PIN_RESET); } if (right_speed >= 0) { HAL_GPIO_WritePin(MOTOR_RIGHT_DIR_GPIO_Port, MOTOR_RIGHT_DIR_Pin, GPIO_PIN_SET); } else { HAL_GPIO_WritePin(MOTOR_RIGHT_DIR_GPIO_Port, MOTOR_RIGHT_DIR_Pin, GPIO_PIN_RESET); } }

3.3 传感器数据采集与处理

传感器数据的准确采集和滤波处理对机器人感知环境至关重要:

// 文件路径:Firmware/Application/sensor.c #include "sensor.h" // 超声波测距函数(均值滤波) float Ultrasonic_GetDistance(void) { float distances[5]; float sum = 0; // 连续采集5次数据 for (int i = 0; i < 5; i++) { // 触发测量 HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_SET); HAL_Delay(1); HAL_GPIO_WritePin(TRIG_GPIO_Port, TRIG_Pin, GPIO_PIN_RESET); // 等待回波 while (HAL_GPIO_ReadPin(ECHO_GPIO_Port, ECHO_Pin) == GPIO_PIN_RESET); // 计算高电平持续时间 uint32_t start_time = HAL_GetTick(); while (HAL_GPIO_ReadPin(ECHO_GPIO_Port, ECHO_Pin) == GPIO_PIN_SET); uint32_t duration = HAL_GetTick() - start_time; // 计算距离(声速340m/s) distances[i] = (duration * 0.034) / 2; sum += distances[i]; HAL_Delay(50); // 测量间隔 } // 排序并取中值 bubble_sort(distances, 5); return distances[2]; // 返回中值 } // 陀螺仪数据读取(I2C通信) void MPU6050_ReadData(float* accel, float* gyro) { uint8_t buffer[14]; // 读取14字节传感器数据 HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, ACCEL_XOUT_H, I2C_MEMADD_SIZE_8BIT, buffer, 14, 100); // 加速度数据处理 accel[0] = (int16_t)((buffer[0] << 8) | buffer[1]) / 16384.0; accel[1] = (int16_t)((buffer[2] << 8) | buffer[3]) / 16384.0; accel[2] = (int16_t)((buffer[4] << 8) | buffer[5]) / 16384.0; // 陀螺仪数据处理 gyro[0] = (int16_t)((buffer[8] << 8) | buffer[9]) / 131.0; gyro[1] = (int16_t)((buffer[10] << 8) | buffer[11]) / 131.0; gyro[2] = (int16_t)((buffer[12] << 8) | buffer[13]) / 131.0; }

4. 电路设计原理图详解

电路设计是机器人硬件的基石,合理的电路设计能确保系统稳定运行。风扬科技提供的原理图涵盖了电源管理、电机驱动、传感器接口等关键部分。

4.1 电源管理电路设计

移动机器人通常采用电池供电,电源管理电路需要满足不同电压等级的需求:

电源管理模块包含: - 锂电池输入:7.4V-12V - 降压电路1:5V输出(传感器、通信模块) - 降压电路2:3.3V输出(主控芯片) - 充电管理:TP4056充电芯片 - 电压监控:分压电路+ADC采样

原理图关键部分说明:

# 5V降压电路(LM2596) 输入:7.4V-12V 输出:5V/3A 特点:效率高,带过流保护 # 3.3V LDO电路(AMS1117-3.3) 输入:5V 输出:3.3V/1A 特点:纹波小,成本低 # 电池电压监测 采样电阻:100K+100K分压 ADC通道:PA0 计算公式:Vbat = ADC_value * 3.3 / 4096 * 2

4.2 电机驱动电路设计

电机驱动电路需要提供足够的电流输出,并支持正反转控制:

// TB6612FNG电机驱动芯片配置 // 控制逻辑表: // | AIN1 | AIN2 | PWM | 电机状态 | // |------|------|-----|----------| // | 0 | 0 | X | 停止 | // | 1 | 0 | PWM | 正转 | // | 0 | 1 | PWM | 反转 | // | 1 | 1 | X | 刹车 | // STM32 GPIO配置 GPIO_InitTypeDef GPIO_InitStruct = {0}; // 电机方向控制引脚 GPIO_InitStruct.Pin = MOTOR_LEFT_DIR_Pin | MOTOR_RIGHT_DIR_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // PWM输出引脚(定时器通道) GPIO_InitStruct.Pin = MOTOR_LEFT_PWM_Pin | MOTOR_RIGHT_PWM_Pin; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF1_TIM1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

4.3 传感器接口电路

各种传感器需要不同的接口电路,设计时需考虑信号电平和抗干扰:

超声波传感器接口:

  • 触发信号:GPIO输出,3.3V电平
  • 回波信号:GPIO输入,支持5V耐受(使用电平转换或分压)

陀螺仪接口:

  • I2C通信:SCL、SDA上拉4.7K电阻
  • 中断输出:可选,用于数据就绪中断

红外避障传感器:

  • 数字输出:直接连接GPIO输入
  • 模拟输出:连接ADC引脚,用于距离估计

5. APP控制端开发实战

手机APP作为机器人的上层控制界面,需要实现实时控制、状态显示、参数配置等功能。风扬科技提供了Android和iOS双平台源码。

5.1 Android控制端核心代码

Android端采用Java开发,基于Socket通信与机器人建立连接:

// 文件路径:Software/Android/app/src/main/java/com/fengyang/robotcontroller/MainActivity.java package com.fengyang.robotcontroller; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import java.io.IOException; import java.net.Socket; public class MainActivity extends AppCompatActivity { private Socket clientSocket; private CommunicationThread commThread; private TextView statusText; private Button forwardBtn, backwardBtn, leftBtn, rightBtn, stopBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initUI(); setupButtonListeners(); // 启动连接线程 new ConnectThread().start(); } private void initUI() { statusText = findViewById(R.id.status_text); forwardBtn = findViewById(R.id.forward_btn); backwardBtn = findViewById(R.id.backward_btn); leftBtn = findViewById(R.id.left_btn); rightBtn = findViewById(R.id.right_btn); stopBtn = findViewById(R.id.stop_btn); } private void setupButtonListeners() { forwardBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { sendControlCommand("FORWARD"); } }); backwardBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { sendControlCommand("BACKWARD"); } }); // 其他按钮监听器... } private void sendControlCommand(String command) { if (commThread != null && commThread.isConnected()) { commThread.sendMessage(command); } } // 连接线程 private class ConnectThread extends Thread { @Override public void run() { try { clientSocket = new Socket("192.168.4.1", 8080); // 机器人AP热点 commThread = new CommunicationThread(clientSocket, handler); commThread.start(); handler.sendEmptyMessage(MSG_CONNECT_SUCCESS); } catch (IOException e) { handler.sendMessage(handler.obtainMessage(MSG_CONNECT_FAIL, e.getMessage())); } } } // 消息处理器 private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_CONNECT_SUCCESS: statusText.setText("连接成功"); break; case MSG_CONNECT_FAIL: statusText.setText("连接失败: " + msg.obj); break; case MSG_DATA_RECEIVED: updateSensorData((String) msg.obj); break; } } }; }

5.2 通信协议设计

机器人控制器与APP之间需要定义清晰的通信协议:

// 文件路径:Software/Android/app/src/main/java/com/fengyang/robotcontroller/Protocol.java public class Protocol { // 命令格式:<CMD><SEPARATOR><DATA><TERMINATOR> public static final String SEPARATOR = ":"; public static final String TERMINATOR = "\n"; // 控制命令 public static final String CMD_FORWARD = "FWD"; public static final String CMD_BACKWARD = "BWD"; public static final String CMD_LEFT = "LFT"; public static final String CMD_RIGHT = "RGT"; public static final String CMD_STOP = "STP"; public static final String CMD_SPEED = "SPD"; // 数据请求命令 public static final String CMD_GET_SENSOR = "SEN"; public static final String CMD_GET_BATTERY = "BAT"; // 构建命令字符串 public static String buildCommand(String command, String data) { return command + SEPARATOR + data + TERMINATOR; } // 解析接收到的数据 public static Command parseCommand(String received) { String[] parts = received.split(SEPARATOR); if (parts.length == 2) { return new Command(parts[0], parts[1].replace(TERMINATOR, "")); } return null; } public static class Command { public String type; public String data; public Command(String type, String data) { this.type = type; this.data = data; } } }

5.3 实时数据展示界面

APP需要实时显示机器人传感器数据和状态信息:

<!-- 文件路径:Software/Android/app/src/main/res/layout/activity_main.xml --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <!-- 状态显示区域 --> <TextView android:id="@+id/status_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="未连接" android:textSize="18sp" android:gravity="center"/> <!-- 传感器数据区域 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/distance_text" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="距离: -- cm"/> <TextView android:id="@+id/battery_text" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="电量: -- %"/> </LinearLayout> <!-- 控制按钮区域 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:gravity="center"> <Button android:id="@+id/forward_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="前进"/> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:id="@+id/left_btn" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="左转"/> <Button android:id="@+id/stop_btn" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="停止"/> <Button android:id="@+id/right_btn" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="右转"/> </LinearLayout> <Button android:id="@+id/backward_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="后退"/> </LinearLayout> </LinearLayout>

6. 嵌入式系统开发关键技术

嵌入式系统开发有其特殊性,需要关注实时性、资源限制、功耗控制等关键问题。

6.1 实时操作系统(RTOS)应用

对于复杂的机器人应用,使用RTOS可以提高系统的实时性和可靠性:

// 文件路径:Firmware/Middleware/rtos_tasks.c #include "cmsis_os.h" // 定义任务句柄 osThreadId_t motorTaskHandle; osThreadId_t sensorTaskHandle; osThreadId_t commTaskHandle; // 电机控制任务 void Motor_Task(void *argument) { while (1) { // 读取控制指令 Motion_Command cmd = get_motion_command(); // 执行运动控制 execute_motion_control(cmd); // 任务延时10ms osDelay(10); } } // 传感器采集任务 void Sensor_Task(void *argument) { while (1) { // 采集所有传感器数据 update_sensor_data(); // 数据滤波处理 filter_sensor_data(); // 任务延时20ms osDelay(20); } } // 通信处理任务 void Communication_Task(void *argument) { while (1) { // 检查接收数据 process_received_data(); // 发送状态数据 send_status_data(); // 任务延时50ms osDelay(50); } } // 创建任务函数 void create_rtos_tasks(void) { // 定义任务属性 const osThreadAttr_t motorTask_attributes = { .name = "MotorTask", .stack_size = 512, .priority = osPriorityHigh, }; const osThreadAttr_t sensorTask_attributes = { .name = "SensorTask", .stack_size = 1024, .priority = osPriorityNormal, }; const osThreadAttr_t commTask_attributes = { .name = "CommTask", .stack_size = 512, .priority = osPriorityBelowNormal, }; // 创建任务 motorTaskHandle = osThreadNew(Motor_Task, NULL, &motorTask_attributes); sensorTaskHandle = osThreadNew(Sensor_Task, NULL, &sensorTask_attributes); commTaskHandle = osThreadNew(Communication_Task, NULL, &commTask_attributes); }

6.2 低功耗设计策略

移动机器人通常由电池供电,低功耗设计至关重要:

// 文件路径:Firmware/Application/power_management.c #include "power_management.h" // 系统功耗模式定义 typedef enum { POWER_MODE_NORMAL = 0, // 正常工作模式 POWER_MODE_IDLE, // 空闲模式 POWER_MODE_SLEEP, // 睡眠模式 POWER_MODE_DEEP_SLEEP // 深度睡眠模式 } PowerMode_t; // 当前功耗模式 static PowerMode_t current_power_mode = POWER_MODE_NORMAL; // 进入低功耗模式 void enter_low_power_mode(PowerMode_t mode) { switch (mode) { case POWER_MODE_IDLE: // 关闭部分外设时钟 __HAL_RCC_TIM2_CLK_DISABLE(); __HAL_RCC_USART2_CLK_DISABLE(); break; case POWER_MODE_SLEEP: // 进入睡眠模式 HAL_SuspendTick(); HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); HAL_ResumeTick(); break; case POWER_MODE_DEEP_SLEEP: // 配置唤醒源 HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1); // 进入停止模式 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI); // 唤醒后系统时钟重新配置 SystemClock_Config(); break; } current_power_mode = mode; } // 功耗状态监控 void power_management_task(void) { static uint32_t last_activity_time = 0; uint32_t current_time = HAL_GetTick(); // 检测系统活动 if (system_has_activity()) { last_activity_time = current_time; if (current_power_mode != POWER_MODE_NORMAL) { restore_normal_power(); } } // 无活动超时处理 if ((current_time - last_activity_time) > POWER_SAVE_TIMEOUT) { if (current_power_mode == POWER_MODE_NORMAL) { enter_low_power_mode(POWER_MODE_IDLE); } else if ((current_time - last_activity_time) > DEEP_SLEEP_TIMEOUT) { enter_low_power_mode(POWER_MODE_DEEP_SLEEP); } } }

7. 传感器数据融合与决策算法

多传感器数据融合能提高机器人环境感知的准确性和可靠性,是智能移动机器人的核心技术。

7.1 多传感器数据融合

// 文件路径:Firmware/Application/sensor_fusion.c #include "sensor_fusion.h" // 传感器数据结构体 typedef struct { float ultrasonic_distance; // 超声波距离 float infrared_distance; // 红外距离 float imu_accel[3]; // 加速度计数据 float imu_gyro[3]; // 陀螺仪数据 uint32_t timestamp; // 时间戳 } SensorData_t; // 融合后的环境信息 typedef struct { float obstacle_distance; // 障碍物距离(融合结果) bool obstacle_detected; // 障碍物检测标志 float robot_pose[3]; // 机器人位姿[x,y,theta] float motion_speed[2]; // 运动速度[线速度,角速度] } EnvironmentInfo_t; // 卡尔曼滤波器实现 typedef struct { float q; // 过程噪声协方差 float r; // 测量噪声协方差 float x; // 状态值 float p; // 估计误差协方差 float k; // 卡尔曼增益 } KalmanFilter_t; // 卡尔曼滤波器初始化 void kalman_init(KalmanFilter_t* kf, float q, float r) { kf->q = q; kf->r = r; kf->p = 0; kf->x = 0; } // 卡尔曼滤波更新 float kalman_update(KalmanFilter_t* kf, float measurement) { // 预测更新 kf->p = kf->p + kf->q; // 测量更新 kf->k = kf->p / (kf->p + kf->r); kf->x = kf->x + kf->k * (measurement - kf->x); kf->p = (1 - kf->k) * kf->p; return kf->x; } // 多传感器距离数据融合 float fuse_distance_data(SensorData_t* data) { static KalmanFilter_t ultrasonic_kf; static KalmanFilter_t infrared_kf; static bool initialized = false; if (!initialized) { kalman_init(&ultrasonic_kf, 0.1, 0.5); // 超声波滤波器参数 kalman_init(&infrared_kf, 0.2, 1.0); // 红外滤波器参数 initialized = true; } // 分别对两种传感器数据进行滤波 float ultrasonic_filtered = kalman_update(&ultrasonic_kf,>// 文件路径:Firmware/Application/obstacle_avoidance.c #include "obstacle_avoidance.h" // 避障决策状态机 typedef enum { STATE_NORMAL = 0, // 正常行进 STATE_OBSTACLE_NEAR, // 障碍物接近 STATE_TURNING, // 转向避障 STATE_BACKING, // 后退 STATE_SEARCHING // 搜索路径 } AvoidanceState_t; // 避障控制器 typedef struct { AvoidanceState_t state; uint32_t state_timer; float safe_distance; float turn_direction; // 正数右转,负数左转 } AvoidanceController_t; // 避障决策函数 AvoidanceCommand obstacle_avoidance_decision(EnvironmentInfo_t* env_info, AvoidanceController_t* controller) { AvoidanceCommand cmd = {0}; switch (controller->state) { case STATE_NORMAL: if (env_info->obstacle_detected) { controller->state = STATE_OBSTACLE_NEAR; controller->state_timer = HAL_GetTick(); } cmd.speed = NORMAL_SPEED; cmd.steering = 0; break; case STATE_OBSTACLE_NEAR: if (!env_info->obstacle_detected) { controller->state = STATE_NORMAL; } else if (env_info->obstacle_distance < CRITICAL_DISTANCE) { controller->state = STATE_BACKING; controller->state_timer = HAL_GetTick(); } else { // 根据障碍物位置选择转向方向 controller->turn_direction = choose_turn_direction(env_info); controller->state = STATE_TURNING; controller->state_timer = HAL_GetTick(); } cmd.speed = SLOW_SPEED; break; case STATE_TURNING: if (HAL_GetTick() - controller->state_timer > TURNING_TIME) { controller->state = STATE_NORMAL; } cmd.speed = TURNING_SPEED; cmd.steering = controller->turn_direction; break; case STATE_BACKING: if (HAL_GetTick() - controller->state_timer > BACKING_TIME) { controller->state = STATE_SEARCHING; controller->state_timer = HAL_GetTick(); } cmd.speed = -BACKING_SPEED; // 负值表示后退 break; case STATE_SEARCHING: // 搜索新路径的复杂逻辑 cmd = search_new_path(env_info, controller); break; } return cmd; } // 选择转向方向(基于多传感器数据) float choose_turn_direction(EnvironmentInfo_t* env_info) { // 简化版:随机选择左右转向 // 实际项目中会根据左右传感器数据选择更安全的方向 return (rand() % 2) ? 1.0 : -1.0; }

8. 常见问题与解决方案

在移动机器人开发过程中会遇到各种问题,以下是典型问题及解决方案。

8.1 硬件相关问题

问题现象可能原因解决方案
电机不转或转动异常电源供电不足、驱动芯片故障、接线错误检查电源电压电流、测量驱动芯片输出、核对接线
传感器数据不稳定电源噪声、信号干扰、传感器故障增加滤波电容、使用屏蔽线、更换传感器
通信连接经常断开信号干扰、距离过远、协议错误检查天线连接、减少通信距离、验证协议一致性

8.2 软件相关问题

问题现象可能原因解决方案
程序跑飞或死机堆栈溢出、中断冲突、硬件故障增加堆栈大小、优化中断优先级、检查硬件
控制响应延迟大任务调度不合理、算法复杂度高使用RTOS、优化算法、提高主频
数据通信错误缓冲区溢出、校验错误、波特率不匹配增加缓冲区大小、添加校验机制、统一波特率

8

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询