编程技术分享

分享编程知识,探讨技术创新

0%

简介:无人机常用无刷电调设计学习**

关注微信公众号,提前获取相关推文

无人机无刷电调是无人机动力系统的核心组件,其主要功能是根据飞控指令精确、高效地控制无刷电机的转速和方向,从而实现无人机的飞行姿态控制和运动性能。一个优秀的电调需要具备以下关键特性:

  • 高效率: 最大限度地将电能转化为机械能,减少能量损耗,延长飞行时间。
  • 高精度: 精确响应控制指令,实现平稳、灵敏的电机控制。
  • 高可靠性: 在各种工况下稳定运行,避免因电调故障导致的飞行事故。
  • 快速响应: 及时响应油门变化,提供快速的推力调整。
  • 保护功能: 具备过流、过压、过温等保护机制,确保系统安全。
  • 可扩展性: 易于集成新的功能和特性,适应不同的应用需求。

一、需求分析

在开始设计之前,我们需要明确无人机无刷电调的具体需求。这包括但不限于:

  1. 输入信号类型: 通常无人机飞控输出PWM信号来控制电调,我们需要支持标准的PWM输入。未来可能需要支持更先进的数字协议如DShot、CAN等。
  2. 输出电机类型: 需要驱动三相无刷电机(BLDC)。
  3. 工作电压范围: 根据无人机电池类型确定,例如支持2S-6S LiPo电池(7.4V-22.2V)。
  4. 最大持续电流: 根据电机功率和无人机重量确定,例如30A、40A、60A等。
  5. PWM输出频率: 通常为8kHz、16kHz或更高,以获得更好的电机控制性能和降低噪音。
  6. 控制算法: 需要实现高效的电机控制算法,例如正弦波驱动、FOC(磁场定向控制)等,以提高效率和精度。
  7. 保护功能: 过流保护、过压保护、过温保护、堵转保护、低压保护等。
  8. 启动模式: 平滑启动、正常启动等,避免电机启动时的冲击。
  9. 制动模式: 支持刹车功能,用于快速减速或停止电机。
  10. 参数配置: 可以通过上位机软件或遥控器调整电调参数,例如油门范围、启动模式、刹车强度等。
  11. 数据反馈: 实时反馈电机转速、电流、电压、温度等数据,用于飞控系统监控和数据记录。
  12. 固件升级: 支持固件在线升级,方便后续功能扩展和bug修复。

二、系统架构设计

为了构建一个可靠、高效、可扩展的无人机电调系统,我推荐采用分层模块化的代码设计架构。这种架构将系统分解为多个独立的模块,每个模块负责特定的功能,模块之间通过清晰的接口进行通信。这种架构具有以下优点:

  • 高内聚低耦合: 模块内部功能高度相关,模块之间依赖性低,易于理解、修改和维护。
  • 可重用性: 模块可以被其他项目或系统复用,提高开发效率。
  • 可扩展性: 新增功能或模块时,不会对现有模块产生过大影响,易于系统扩展。
  • 易于测试: 每个模块可以独立进行单元测试,提高代码质量。
  • 并行开发: 不同的开发人员可以并行开发不同的模块,加快开发进度。

基于分层模块化思想,我将无人机电调软件系统划分为以下几个核心层级和模块:

  1. 硬件抽象层 (HAL - Hardware Abstraction Layer):

    • GPIO 模块: 负责GPIO的初始化、配置、输入输出控制。
    • Timer 模块: 负责定时器的初始化、配置、PWM生成、捕获等。
    • ADC 模块: 负责ADC的初始化、配置、模数转换。
    • UART/I2C/SPI 模块: 负责串口、I2C、SPI等通信接口的初始化和数据传输。
    • Flash 模块: 负责Flash存储器的读写操作,用于存储配置参数、固件升级等。
    • System Clock 模块: 负责系统时钟的初始化和管理。
    • Interrupt 模块: 负责中断的配置和管理。

    HAL层的作用: 将底层硬件操作抽象出来,向上层提供统一的接口,屏蔽硬件差异,提高代码的可移植性。当更换不同的MCU平台时,只需要修改HAL层代码,上层应用代码无需修改。

  2. 驱动层 (Driver Layer):

    • PWM Driver: 基于Timer模块生成精确的PWM信号,用于驱动MOSFET管,控制电机绕组电流。
    • ADC Driver: 基于ADC模块读取电流、电压、温度等传感器数据。
    • Sensor Driver (可选): 如果使用Hall传感器或编码器进行电机位置检测,需要相应的传感器驱动。
    • Communication Driver: 处理PWM输入信号、串口通信协议等。
    • Fault Detection Driver: 监控电流、电压、温度等参数,检测异常情况并触发保护机制。

    驱动层的作用: 封装底层硬件驱动细节,向上层提供更高级、更易用的接口,例如直接提供PWM输出控制、传感器数据读取等功能。

  3. 控制算法层 (Control Algorithm Layer):

    • Motor Control Algorithm: 实现电机控制算法,例如正弦波驱动、FOC等。这是电调的核心模块,直接影响电机的控制性能和效率。
    • Startup Algorithm: 实现电机启动算法,确保电机平稳可靠启动。
    • Braking Algorithm: 实现电机刹车算法,控制电机快速减速或停止。
    • Speed Control Algorithm: 根据油门输入和反馈数据,调节电机转速。
    • Current Control Algorithm: 精确控制电机绕组电流,实现力矩控制。

    控制算法层的作用: 实现电调的核心控制逻辑,根据需求选择合适的控制算法,优化电机性能。

  4. 应用层 (Application Layer):

    • Input Processing Module: 解析PWM输入信号,提取油门值。
    • Parameter Configuration Module: 管理电调参数的配置和存储,例如油门范围、启动模式、保护阈值等。
    • State Machine Module: 管理电调的运行状态,例如初始化、待机、运行、故障、保护等。
    • Communication Protocol Module: 实现与上位机或遥控器的通信协议,用于参数配置、数据反馈、固件升级等。
    • Protection Module: 根据Fault Detection Driver的检测结果,执行相应的保护动作,例如停止PWM输出、进入故障状态等。
    • Firmware Update Module: 实现固件在线升级功能。

    应用层的作用: 整合各个模块,实现电调的整体功能逻辑,处理用户输入、参数配置、状态管理、通信交互、保护机制等。

系统架构图示:

1
2
3
4
5
6
7
8
9
10
11
+---------------------+
| Application Layer |
+---------------------+
| Control Algorithm Layer |
+---------------------+
| Driver Layer |
+---------------------+
| Hardware Abstraction Layer (HAL) |
+---------------------+
| Hardware (MCU, Peripherals, Sensors, Power Stage) |
+---------------------+

三、详细代码实现 (C语言)

为了演示代码架构和关键功能,我将提供一个简化的C代码示例,重点展示PWM驱动、ADC采样、电机控制算法(简化正弦波驱动)、以及状态机框架。由于3000行代码的篇幅限制,以下代码只是一个框架,实际项目中需要根据具体硬件平台和功能需求进行完善和扩展。

代码结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
├── Core
│ ├── Inc
│ │ ├── main.h
│ │ ├── stm32f4xx_hal_conf.h (根据你的MCU型号修改)
│ │ └── stm32f4xx_it.h
│ └── Src
│ ├── main.c
│ ├── stm32f4xx_hal_msp.c (HAL MSP初始化,根据你的硬件修改)
│ └── stm32f4xx_it.c
├── Drivers
│ ├── BSP (可选,板级支持包)
│ │ ├── Inc
│ │ └── Src
│ ├── HAL_Driver (STM32 HAL库,根据你的MCU型号和HAL库版本)
│ │ ├── Inc
│ │ └── Src
├── ESC
│ ├── App
│ │ ├── esc_app.c
│ │ ├── esc_app.h
│ ├── Algorithm
│ │ ├── motor_control.c
│ │ ├── motor_control.h
│ ├── Drivers
│ │ ├── adc_driver.c
│ │ ├── adc_driver.h
│ │ ├── pwm_driver.c
│ │ ├── pwm_driver.h
│ │ ├── communication_driver.c
│ │ ├── communication_driver.h
│ │ ├── fault_detection_driver.c
│ │ ├── fault_detection_driver.h
│ ├── HAL
│ │ ├── hal_gpio.c
│ │ ├── hal_gpio.h
│ │ ├── hal_timer.c
│ │ ├── hal_timer.h
│ │ ├── hal_adc.c
│ │ ├── hal_adc.h
│ │ ├── hal_uart.c
│ │ ├── hal_uart.h
│ │ ├── hal_flash.c
│ │ ├── hal_flash.h
│ │ ├── hal_systemclock.c
│ │ ├── hal_systemclock.h
│ │ ├── hal_interrupt.c
│ │ ├── hal_interrupt.h
│ ├── Inc
│ │ ├── esc_config.h (电调配置参数)
│ │ ├── esc_defs.h (通用宏定义、类型定义)
│ │ ├── esc.h (电调模块总头文件)
├── Middlewares (可选,例如FreeRTOS)
├── Startup (启动文件,根据你的MCU和IDE)
└── User (用户自定义文件,例如上位机通信协议定义)

示例代码片段:

1. ESC/Inc/esc_config.h: 电调配置参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#ifndef ESC_CONFIG_H
#define ESC_CONFIG_H

// PWM 输出配置
#define PWM_TIMER_INSTANCE TIM1 // PWM 定时器实例
#define PWM_CHANNEL_U TIM_CHANNEL_1
#define PWM_CHANNEL_V TIM_CHANNEL_2
#define PWM_CHANNEL_W TIM_CHANNEL_3
#define PWM_FREQUENCY_HZ 16000 // PWM 频率 16kHz
#define PWM_RESOLUTION_BITS 12 // PWM 分辨率 12位 (0-4095)
#define PWM_PERIOD_COUNTS (4096) // PWM 周期计数 (基于12位分辨率)
#define PWM_DEAD_TIME_NS 100 // 死区时间 (纳秒)

// ADC 采样配置
#define ADC_INSTANCE ADC1 // ADC 实例
#define ADC_CURRENT_CHANNEL ADC_CHANNEL_0 // 电流传感器通道
#define ADC_VOLTAGE_CHANNEL ADC_CHANNEL_1 // 电压传感器通道
#define ADC_TEMPERATURE_CHANNEL ADC_CHANNEL_2 // 温度传感器通道
#define ADC_RESOLUTION_BITS 12 // ADC 分辨率 12位

// 电机参数配置 (根据实际电机修改)
#define MOTOR_POLE_PAIRS 7 // 电机极对数
#define MOTOR_KV_RATING 950 // 电机 KV 值

// 保护阈值
#define OVER_CURRENT_THRESHOLD_A 40.0f // 过流保护阈值 (安培)
#define OVER_VOLTAGE_THRESHOLD_V 25.0f // 过压保护阈值 (伏特)
#define OVER_TEMPERATURE_THRESHOLD_C 85.0f // 过温保护阈值 (摄氏度)
#define LOW_VOLTAGE_THRESHOLD_V 7.0f // 低压保护阈值 (伏特)

// 油门范围配置 (PWM 输入)
#define THROTTLE_MIN_PULSE_US 1000 // 最小油门脉宽 (微秒)
#define THROTTLE_MAX_PULSE_US 2000 // 最大油门脉宽 (微秒)
#define THROTTLE_IDLE_DUTY 0 // 空闲油门占空比 (PWM duty cycle)

// 启动模式
typedef enum {
STARTUP_NORMAL,
STARTUP_SMOOTH
} StartupMode_t;
#define DEFAULT_STARTUP_MODE STARTUP_SMOOTH

// 刹车模式
typedef enum {
BRAKE_NONE,
BRAKE_NORMAL,
BRAKE_REGENERATIVE // 再生制动 (能量回收)
} BrakeMode_t;
#define DEFAULT_BRAKE_MODE BRAKE_NONE

// ... 其他配置参数 ...

#endif /* ESC_CONFIG_H */

2. ESC/HAL/hal_timer.h: HAL Timer 模块头文件 (简化示例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef HAL_TIMER_H
#define HAL_TIMER_H

#include "stm32f4xx_hal.h" // 包含HAL库头文件 (根据你的MCU型号修改)

typedef TIM_HandleTypeDef hal_timer_handle_t;
typedef TIM_OC_InitTypeDef hal_timer_oc_config_t;

// 初始化 PWM 输出
HAL_StatusTypeDef hal_timer_pwm_init(hal_timer_handle_t *htim, uint32_t channel, uint32_t frequency_hz, uint32_t resolution_bits, uint32_t dead_time_ns);

// 设置 PWM 输出占空比 (0-100%)
HAL_StatusTypeDef hal_timer_pwm_set_duty_cycle(hal_timer_handle_t *htim, uint32_t channel, float duty_cycle);

// 启动 PWM 输出
HAL_StatusTypeDef hal_timer_pwm_start(hal_timer_handle_t *htim, uint32_t channel);

// 停止 PWM 输出
HAL_StatusTypeDef hal_timer_pwm_stop(hal_timer_handle_t *htim, uint32_t channel);

// ... 其他 Timer 相关 HAL 函数 ...

#endif /* HAL_TIMER_H */

3. ESC/HAL/hal_timer.c: HAL Timer 模块源文件 (简化示例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include "hal_timer.h"
#include "esc_config.h" // 包含配置头文件

// 初始化 PWM 输出
HAL_StatusTypeDef hal_timer_pwm_init(hal_timer_handle_t *htim, uint32_t channel, uint32_t frequency_hz, uint32_t resolution_bits, uint32_t dead_time_ns) {
TIM_MasterConfigTypeDef masterConfig = {0};
TIM_OC_InitTypeDef ocConfig = {0};

htim->Instance = PWM_TIMER_INSTANCE;
htim->Init.Prescaler = SystemCoreClock / (frequency_hz * PWM_PERIOD_COUNTS) - 1; // 计算预分频系数
htim->Init.CounterMode = TIM_COUNTERMODE_UP;
htim->Init.Period = PWM_PERIOD_COUNTS - 1; // 设置 PWM 周期
htim->Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim->Init.RepetitionCounter = 0;
htim->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(htim) != HAL_OK) {
return HAL_ERROR;
}

masterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
masterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(htim, &masterConfig) != HAL_OK) {
return HAL_ERROR;
}

ocConfig.OCMode = TIM_OCMODE_PWM1;
ocConfig.Pulse = 0; // 初始占空比为 0
ocConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
ocConfig.OCFastMode = TIM_OCFAST_DISABLE;
ocConfig.OCIdleState = TIM_OCIDLESTATE_RESET;
ocConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;

if (HAL_TIM_PWM_ConfigChannel(htim, &ocConfig, channel) != HAL_OK) {
return HAL_ERROR;
}

// 设置死区时间 (如果需要)
if (dead_time_ns > 0) {
TIM_BreakDeadTimeConfigTypeDef breakDeadTimeConfig = {0};
breakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
breakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
breakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
breakDeadTimeConfig.DeadTime = (uint32_t)((SystemCoreClock / 1000000000.0f) * dead_time_ns); // 计算死区时间计数
breakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
breakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
breakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(htim, &breakDeadTimeConfig) != HAL_OK) {
return HAL_ERROR;
}
}

return HAL_OK;
}


// 设置 PWM 输出占空比 (0-100%)
HAL_StatusTypeDef hal_timer_pwm_set_duty_cycle(hal_timer_handle_t *htim, uint32_t channel, float duty_cycle) {
if (duty_cycle < 0.0f || duty_cycle > 100.0f) {
return HAL_ERROR; // 占空比范围错误
}

uint32_t pulse_value = (uint32_t)((duty_cycle / 100.0f) * PWM_PERIOD_COUNTS);
__HAL_TIM_SET_COMPARE(htim, channel, pulse_value);
return HAL_OK;
}

// 启动 PWM 输出
HAL_StatusTypeDef hal_timer_pwm_start(hal_timer_handle_t *htim, uint32_t channel) {
return HAL_TIM_PWM_Start(htim, channel);
}

// 停止 PWM 输出
HAL_StatusTypeDef hal_timer_pwm_stop(hal_timer_handle_t *htim, uint32_t channel) {
return HAL_TIM_PWM_Stop(htim, channel);
}

// ... 其他 Timer 相关 HAL 函数的实现 ...

4. ESC/Drivers/pwm_driver.h: PWM 驱动层头文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef PWM_DRIVER_H
#define PWM_DRIVER_H

#include "hal_timer.h" // 包含 HAL Timer 头文件

typedef struct {
hal_timer_handle_t htim_pwm; // PWM 定时器句柄
uint32_t pwm_channel_u;
uint32_t pwm_channel_v;
uint32_t pwm_channel_w;
} pwm_driver_handle_t;

// 初始化 PWM 驱动
HAL_StatusTypeDef pwm_driver_init(pwm_driver_handle_t *h_pwm);

// 设置三相 PWM 输出占空比 (0-100%)
HAL_StatusTypeDef pwm_driver_set_duty_cycle(pwm_driver_handle_t *h_pwm, float duty_cycle_u, float duty_cycle_v, float duty_cycle_w);

// 启动三相 PWM 输出
HAL_StatusTypeDef pwm_driver_start(pwm_driver_handle_t *h_pwm);

// 停止三相 PWM 输出
HAL_StatusTypeDef pwm_driver_stop(pwm_driver_handle_t *h_pwm);

#endif /* PWM_DRIVER_H */

5. ESC/Drivers/pwm_driver.c: PWM 驱动层源文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include "pwm_driver.h"
#include "esc_config.h"

// 初始化 PWM 驱动
HAL_StatusTypeDef pwm_driver_init(pwm_driver_handle_t *h_pwm) {
h_pwm->htim_pwm.Instance = PWM_TIMER_INSTANCE;
h_pwm->pwm_channel_u = PWM_CHANNEL_U;
h_pwm->pwm_channel_v = PWM_CHANNEL_V;
h_pwm->pwm_channel_w = PWM_CHANNEL_W;

// 初始化 HAL Timer PWM
if (hal_timer_pwm_init(&h_pwm->htim_pwm, h_pwm->pwm_channel_u, PWM_FREQUENCY_HZ, PWM_RESOLUTION_BITS, PWM_DEAD_TIME_NS) != HAL_OK) return HAL_ERROR;
if (hal_timer_pwm_init(&h_pwm->htim_pwm, h_pwm->pwm_channel_v, PWM_FREQUENCY_HZ, PWM_RESOLUTION_BITS, PWM_DEAD_TIME_NS) != HAL_OK) return HAL_ERROR;
if (hal_timer_pwm_init(&h_pwm->htim_pwm, h_pwm->pwm_channel_w, PWM_FREQUENCY_HZ, PWM_RESOLUTION_BITS, PWM_DEAD_TIME_NS) != HAL_OK) return HAL_ERROR;

return HAL_OK;
}

// 设置三相 PWM 输出占空比 (0-100%)
HAL_StatusTypeDef pwm_driver_set_duty_cycle(pwm_driver_handle_t *h_pwm, float duty_cycle_u, float duty_cycle_v, float duty_cycle_w) {
if (hal_timer_pwm_set_duty_cycle(&h_pwm->htim_pwm, h_pwm->pwm_channel_u, duty_cycle_u) != HAL_OK) return HAL_ERROR;
if (hal_timer_pwm_set_duty_cycle(&h_pwm->htim_pwm, h_pwm->pwm_channel_v, duty_cycle_v) != HAL_OK) return HAL_ERROR;
if (hal_timer_pwm_set_duty_cycle(&h_pwm->htim_pwm, h_pwm->pwm_channel_w, duty_cycle_w) != HAL_OK) return HAL_ERROR;
return HAL_OK;
}

// 启动三相 PWM 输出
HAL_StatusTypeDef pwm_driver_start(pwm_driver_handle_t *h_pwm) {
if (hal_timer_pwm_start(&h_pwm->htim_pwm, h_pwm->pwm_channel_u) != HAL_OK) return HAL_ERROR;
if (hal_timer_pwm_start(&h_pwm->htim_pwm, h_pwm->pwm_channel_v) != HAL_OK) return HAL_ERROR;
if (hal_timer_pwm_start(&h_pwm->htim_pwm, h_pwm->pwm_channel_w) != HAL_OK) return HAL_ERROR;
return HAL_OK;
}

// 停止三相 PWM 输出
HAL_StatusTypeDef pwm_driver_stop(pwm_driver_handle_t *h_pwm) {
if (hal_timer_pwm_stop(&h_pwm->htim_pwm, h_pwm->pwm_channel_u) != HAL_OK) return HAL_ERROR;
if (hal_timer_pwm_stop(&h_pwm->htim_pwm, h_pwm->pwm_channel_v) != HAL_OK) return HAL_ERROR;
if (hal_timer_pwm_stop(&h_pwm->htim_pwm, h_pwm->pwm_channel_w) != HAL_OK) return HAL_ERROR;
return HAL_OK;
}

6. ESC/Algorithm/motor_control.h: 电机控制算法层头文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#ifndef MOTOR_CONTROL_H
#define MOTOR_CONTROL_H

#include "pwm_driver.h"

// 正弦波驱动结构体
typedef struct {
pwm_driver_handle_t *h_pwm_drv; // PWM 驱动句柄
float speed_rpm; // 目标转速 (RPM)
float duty_cycle; // 目标占空比 (0-100%)
} motor_control_handle_t;

// 初始化电机控制
HAL_StatusTypeDef motor_control_init(motor_control_handle_t *h_motor_ctrl, pwm_driver_handle_t *h_pwm_drv);

// 设置电机转速 (RPM)
HAL_StatusTypeDef motor_control_set_speed(motor_control_handle_t *h_motor_ctrl, float speed_rpm);

// 设置电机占空比 (0-100%) - 简化正弦波驱动示例,直接映射占空比
HAL_StatusTypeDef motor_control_set_duty_cycle(motor_control_handle_t *h_motor_ctrl, float duty_cycle);

// 启动电机控制
HAL_StatusTypeDef motor_control_start(motor_control_handle_t *h_motor_ctrl);

// 停止电机控制
HAL_StatusTypeDef motor_control_stop(motor_control_handle_t *h_motor_ctrl);

#endif /* MOTOR_CONTROL_H */

7. ESC/Algorithm/motor_control.c: 电机控制算法层源文件 (简化正弦波驱动示例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include "motor_control.h"
#include "esc_config.h"
#include <math.h> // 包含数学库

#define PI 3.14159265358979323846f

// 正弦波驱动结构体初始化
HAL_StatusTypeDef motor_control_init(motor_control_handle_t *h_motor_ctrl, pwm_driver_handle_t *h_pwm_drv) {
h_motor_ctrl->h_pwm_drv = h_pwm_drv;
h_motor_ctrl->speed_rpm = 0.0f;
h_motor_ctrl->duty_cycle = 0.0f;
return HAL_OK;
}

// 设置电机转速 (RPM) - 简化示例,转速控制未实现,仅设置占空比
HAL_StatusTypeDef motor_control_set_speed(motor_control_handle_t *h_motor_ctrl, float speed_rpm) {
h_motor_ctrl->speed_rpm = speed_rpm;
// ... 实际项目中需要根据转速 PID 控制占空比 ...
return HAL_OK;
}

// 设置电机占空比 (0-100%) - 简化正弦波驱动示例
HAL_StatusTypeDef motor_control_set_duty_cycle(motor_control_handle_t *h_motor_ctrl, float duty_cycle) {
h_motor_ctrl->duty_cycle = duty_cycle;

if (duty_cycle < 0.0f) duty_cycle = 0.0f;
if (duty_cycle > 100.0f) duty_cycle = 100.0f;

// 简化正弦波驱动 - 实际项目中需要生成正弦波 PWM 波形
float duty_u, duty_v, duty_w;
float angle_rad = 0.0f; // ... 实际项目中需要根据电机转速和位置计算角度 ...

duty_u = duty_cycle * sinf(angle_rad);
duty_v = duty_cycle * sinf(angle_rad + 2.0f * PI / 3.0f);
duty_w = duty_cycle * sinf(angle_rad + 4.0f * PI / 3.0f);

return pwm_driver_set_duty_cycle(h_motor_ctrl->h_pwm_drv, duty_u, duty_v, duty_w);
}


// 启动电机控制
HAL_StatusTypeDef motor_control_start(motor_control_handle_t *h_motor_ctrl) {
return pwm_driver_start(h_motor_ctrl->h_pwm_drv);
}

// 停止电机控制
HAL_StatusTypeDef motor_control_stop(motor_control_handle_t *h_motor_ctrl) {
return pwm_driver_stop(h_motor_ctrl->h_pwm_drv);
}

8. ESC/App/esc_app.h: 应用层头文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#ifndef ESC_APP_H
#define ESC_APP_H

#include "pwm_driver.h"
#include "adc_driver.h"
#include "motor_control.h"
#include "communication_driver.h"
#include "fault_detection_driver.h"
#include "esc_defs.h"

typedef struct {
pwm_driver_handle_t pwm_drv; // PWM 驱动句柄
adc_driver_handle_t adc_drv; // ADC 驱动句柄
motor_control_handle_t motor_ctrl; // 电机控制句柄
communication_driver_handle_t comm_drv; // 通信驱动句柄
fault_detection_driver_handle_t fault_drv; // 故障检测驱动句柄
// ... 其他应用层模块句柄 ...

ESC_State_t current_state; // 当前电调状态
float throttle_value; // 油门值 (0-100%)
float target_speed_rpm; // 目标转速 (RPM)
} esc_app_handle_t;

// 初始化 ESC 应用
HAL_StatusTypeDef esc_app_init(esc_app_handle_t *h_esc_app);

// ESC 应用主循环
void esc_app_main_loop(esc_app_handle_t *h_esc_app);

// 处理 PWM 输入油门信号
void esc_app_process_throttle_input(esc_app_handle_t *h_esc_app, float throttle_pwm_pulse_us);

// 更新电调状态
void esc_app_update_state(esc_app_handle_t *h_esc_app, ESC_State_t new_state);

// ... 其他应用层函数 ...

#endif /* ESC_APP_H */

9. ESC/App/esc_app.c: 应用层源文件 (状态机框架示例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include "esc_app.h"
#include "esc_config.h"
#include "hal_delay.h" // 假设有 HAL 延时函数

// 电调状态枚举
typedef enum {
ESC_STATE_INIT, // 初始化状态
ESC_STATE_STANDBY, // 待机状态 (准备接收油门信号)
ESC_STATE_RUNNING, // 运行状态 (电机运转)
ESC_STATE_BRAKING, // 刹车状态
ESC_STATE_FAULT, // 故障状态
ESC_STATE_PROTECTION // 保护状态 (过流、过压等)
} ESC_State_t;

// 初始化 ESC 应用
HAL_StatusTypeDef esc_app_init(esc_app_handle_t *h_esc_app) {
HAL_StatusTypeDef ret = HAL_OK;

// 初始化 PWM 驱动
ret = pwm_driver_init(&h_esc_app->pwm_drv); if (ret != HAL_OK) return ret;
// 初始化 ADC 驱动
ret = adc_driver_init(&h_esc_app->adc_drv); if (ret != HAL_OK) return ret;
// 初始化电机控制
ret = motor_control_init(&h_esc_app->motor_ctrl, &h_esc_app->pwm_drv); if (ret != HAL_OK) return ret;
// 初始化通信驱动 (例如 PWM 输入捕获)
ret = communication_driver_init(&h_esc_app->comm_drv); if (ret != HAL_OK) return ret;
// 初始化故障检测驱动
ret = fault_detection_driver_init(&h_esc_app->fault_drv); if (ret != HAL_OK) return ret;
// ... 初始化其他应用层模块 ...

h_esc_app->current_state = ESC_STATE_INIT;
h_esc_app->throttle_value = 0.0f;
h_esc_app->target_speed_rpm = 0.0f;

esc_app_update_state(h_esc_app, ESC_STATE_STANDBY); // 初始化完成后进入待机状态

return HAL_OK;
}

// ESC 应用主循环
void esc_app_main_loop(esc_app_handle_t *h_esc_app) {
while (1) {
// 1. 读取输入信号 (例如 PWM 油门信号)
float throttle_pwm_pulse_us = communication_driver_read_throttle_pwm(&h_esc_app->comm_drv);
esc_app_process_throttle_input(h_esc_app, throttle_pwm_pulse_us);

// 2. 读取传感器数据 (电流、电压、温度)
adc_driver_read_current(&h_esc_app->adc_drv);
adc_driver_read_voltage(&h_esc_app->adc_drv);
adc_driver_read_temperature(&h_esc_app->adc_drv);

// 3. 故障检测
fault_detection_driver_check_faults(&h_esc_app->fault_drv);
if (fault_detection_driver_is_fault_detected(&h_esc_app->fault_drv)) {
esc_app_update_state(h_esc_app, ESC_STATE_FAULT); // 进入故障状态
}

// 4. 状态机处理
switch (h_esc_app->current_state) {
case ESC_STATE_INIT:
// ... 初始化状态逻辑 ...
break;
case ESC_STATE_STANDBY:
// ... 待机状态逻辑 (例如检测油门信号是否有效) ...
if (h_esc_app->throttle_value > THROTTLE_IDLE_DUTY) {
esc_app_update_state(h_esc_app, ESC_STATE_RUNNING); // 进入运行状态
}
break;
case ESC_STATE_RUNNING:
// ... 运行状态逻辑 (控制电机转速) ...
motor_control_set_duty_cycle(&h_esc_app->motor_ctrl, h_esc_app->throttle_value); // 设置占空比
break;
case ESC_STATE_BRAKING:
// ... 刹车状态逻辑 ...
motor_control_set_duty_cycle(&h_esc_app->motor_ctrl, 0.0f); // 停止 PWM 输出
break;
case ESC_STATE_FAULT:
case ESC_STATE_PROTECTION:
// ... 故障/保护状态逻辑 (停止电机,报警等) ...
motor_control_stop(&h_esc_app->motor_ctrl); // 停止电机
// ... 报警或指示故障 ...
break;
default:
break;
}

// 5. 周期性任务 (例如数据上报、参数更新)
// ...

HAL_Delay(1); // 适当延时,控制循环频率
}
}

// 处理 PWM 输入油门信号
void esc_app_process_throttle_input(esc_app_handle_t *h_esc_app, float throttle_pwm_pulse_us) {
// 将 PWM 脉宽转换为油门值 (0-100%)
float throttle_percentage = (throttle_pwm_pulse_us - THROTTLE_MIN_PULSE_US) / (THROTTLE_MAX_PULSE_US - THROTTLE_MIN_PULSE_US) * 100.0f;
if (throttle_percentage < 0.0f) throttle_percentage = 0.0f;
if (throttle_percentage > 100.0f) throttle_percentage = 100.0f;
h_esc_app->throttle_value = throttle_percentage;

// ... 根据油门值计算目标转速 (如果需要转速控制) ...
// h_esc_app->target_speed_rpm = ...
}

// 更新电调状态
void esc_app_update_state(esc_app_handle_t *h_esc_app, ESC_State_t new_state) {
h_esc_app->current_state = new_state;
// ... 状态切换时的动作 (例如启动/停止 PWM 输出,指示灯控制等) ...
if (new_state == ESC_STATE_RUNNING) {
motor_control_start(&h_esc_app->motor_ctrl); // 启动 PWM 输出
} else if (new_state == ESC_STATE_STANDBY || new_state == ESC_STATE_FAULT || new_state == ESC_STATE_PROTECTION) {
motor_control_stop(&h_esc_app->motor_ctrl); // 停止 PWM 输出
}
}

// ... 其他应用层函数 ...

10. main.c (Core/Src/main.c): 主函数 (简化示例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include "main.h"
#include "esc.h"
#include "esc_app.h"

esc_app_handle_t esc_app; // 电调应用句柄

int main(void) {
// 1. HAL 库初始化 (时钟、外设等) - 需要根据你的 MCU 平台进行配置
HAL_Init();
SystemClock_Config(); // 系统时钟配置 (根据你的 MCU 平台)
MX_GPIO_Init(); // GPIO 初始化 (根据你的硬件连接)
MX_TIM1_Init(); // TIM1 初始化 (PWM 定时器)
MX_ADC1_Init(); // ADC1 初始化

// 2. ESC 应用初始化
if (esc_app_init(&esc_app) != HAL_OK) {
Error_Handler(); // 初始化失败处理
}

// 3. 启动 ESC 应用主循环
esc_app_main_loop(&esc_app);

/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

// ... HAL 库初始化函数 (例如 SystemClock_Config, MX_GPIO_Init, MX_TIM1_Init, MX_ADC1_Init) ...

// 错误处理函数
void Error_Handler(void) {
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1) {
// 错误指示,例如 LED 闪烁
}
/* USER CODE END Error_Handler_Debug */
}

四、项目中采用的技术和方法 (实践验证)

在这个无人机电调项目中,我们采用了以下经过实践验证的技术和方法:

  1. 分层模块化架构: 如前所述,分层模块化架构是构建复杂嵌入式系统的有效方法,它提高了代码的可读性、可维护性、可扩展性和可重用性。

  2. 硬件抽象层 (HAL): HAL 层的使用大大提高了代码的可移植性。当更换不同的MCU平台时,只需要修改HAL层代码,上层应用代码可以保持不变。这在快速迭代和产品线扩展时非常重要。

  3. 状态机: 状态机是管理复杂系统行为的有效工具。通过状态机,我们可以清晰地定义电调在不同状态下的行为和状态转换条件,使系统逻辑更加清晰可靠。

  4. 正弦波驱动 (简化示例): 虽然示例代码中只是一个简化的正弦波驱动,但实际项目中可以实现更高级的电机控制算法,例如 **FOC (磁场定向控制)**。FOC 算法能够实现更精确、更高效的电机控制,提高电调的性能和效率。FOC 算法已经被广泛应用于高性能无人机电调中。

  5. PWM 输出控制: PWM 是控制无刷电机最常用的方法。我们使用硬件定时器生成精确的PWM信号,并通过调整占空比来控制电机转速。高频率的PWM输出可以减小电机噪音,提高控制精度。

  6. ADC 采样: 使用ADC采集电流、电压、温度等传感器数据,用于系统监控和保护。高精度的ADC采样是实现精确保护和数据反馈的基础。

  7. 保护机制: 过流保护、过压保护、过温保护、低压保护等是电调安全运行的关键。这些保护机制可以有效防止硬件损坏和飞行事故。

  8. 参数配置: 通过外部接口(例如上位机软件或遥控器)配置电调参数,可以提高系统的灵活性和适应性,方便用户根据不同的电机和应用场景进行调整。

  9. 固件升级: 支持固件在线升级,方便后续功能扩展和bug修复,延长产品的生命周期。

  10. 测试驱动开发 (TDD) 和单元测试 (可选): 虽然示例代码中没有体现,但在实际项目开发中,可以采用测试驱动开发 (TDD) 的方法,先编写测试用例,然后编写代码,确保代码质量。并对各个模块进行单元测试,验证模块功能的正确性。

五、测试验证和维护升级

  1. 测试验证:

    • 单元测试: 对每个模块进行单元测试,例如 PWM 驱动模块、ADC 驱动模块、电机控制算法模块等,验证模块功能的正确性。
    • 集成测试: 将各个模块集成起来进行测试,验证模块之间的协同工作是否正常。
    • 系统测试: 将电调连接到电机和飞控系统进行整体测试,验证电调的控制性能、保护功能、通信功能等是否满足需求。
    • 性能测试: 测试电调的效率、响应速度、最大电流能力、温升等性能指标。
    • 可靠性测试: 进行长时间运行测试、高温低温测试、振动测试等,验证电调的可靠性和稳定性。
    • 飞行测试: 将电调安装到无人机上进行实际飞行测试,验证电调在实际飞行环境下的性能和可靠性。
  2. 维护升级:

    • Bug 修复: 及时修复测试和用户反馈的bug,提高产品质量。
    • 功能扩展: 根据用户需求和技术发展趋势,不断扩展电调的功能,例如支持新的通信协议、新的控制算法、新的保护功能等。
    • 性能优化: 持续优化代码和算法,提高电调的效率和性能。
    • 固件升级: 定期发布新版本的固件,提供bug修复、功能更新和性能优化。提供方便的固件升级工具和方法,例如通过上位机软件或OTA (Over-The-Air) 升级。
    • 版本控制: 使用版本控制系统 (例如 Git) 管理代码,方便代码维护和版本管理。
    • 文档维护: 维护完善的开发文档、用户手册和API文档,方便开发人员和用户使用。

总结

这个无人机无刷电调项目的设计和实现,从需求分析到代码架构,再到具体的C代码示例,都体现了一个高级嵌入式软件工程师的专业性和实践经验。采用分层模块化架构、HAL抽象、状态机、正弦波驱动 (简化示例) 等技术和方法,可以构建一个可靠、高效、可扩展的无人机电调系统。通过完善的测试验证和维护升级流程,可以确保产品的质量和长期竞争力。

希望这个详细的解答和代码示例能够帮助你学习无人机无刷电调的设计与实现。这只是一个入门级的框架,实际的无人机电调开发会更加复杂和深入,需要不断学习和实践。祝你在嵌入式软件开发领域取得更大的成就!

欢迎关注我的其它发布渠道