• 正文
  • 相关推荐
申请入驻 产业图谱

用统计数据揭示BaseFlight开源飞控代码工程的全貌

03/13 15:03 来源:直观解
1972
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

1、背景

Baseflight是一款开源的飞行控制软件,最初是MultiWii项目的32位分支,旨在为多旋翼、固定翼和直升机等飞行器提供高效的飞行控制解决方案。Baseflight的发展历程可以追溯到MultiWii项目,它在性能和功能上进行了显著的优化和扩展,特别是在移植到更强大的32位处理器(如STM32)后,解决了早期8位单片机的性能瓶颈问题。

1.开源与社区支持

Baseflight是一个完全开源的项目,代码托管在GitHub上(https://github.com/multiwii/baseflight,下载其实几百k,纯c代码的空间都不大),获得了全球众多开发者和爱好者的贡献和支持。

2.兼容多种硬件平台:

Baseflight支持多种流行的飞行控制器硬件,例如NAZE32、SKYLINE32 Mini等,这些硬件具有高性价比和良好的性能表现(http://www.yinyanmodel.com/ch/ProductView.asp?ID=393)。

3.丰富的配置选项:

通过Baseflight Configurator图形用户界面,用户可以方便地调整飞控参数,如PID值、传感器校准等,以满足不同的飞行需求。

所谓调整飞控参数,就是调整源码中类似这种的变量:

float magneticDeclination = 0.0f; ? ? ? // calculated at startup from config

4.命令行CLI(command line)接口:

除了图形界面外,Baseflight还提供了命令行接口(CLI),允许用户直接通过串口进行高级设置和调试操作。

5.家族谱系:

Baseflight是Cleanflight和Betaflight等后续项目的前身。Cleanflight在其基础上增加了更多特性,而Betaflight则进一步提升了性能,成为目前FPV竞速无人机中最常用的固件之一https://oscarliang.com/baseflight-cleanflight-comparison/。

2、代码结构概述

三层架构:驱动-计算-工具

BaseFlight代码通常采用分层架构。最上层是与硬件交互的驱动层,负责采集传感器数据(如加速度计陀螺仪、磁力计等)并将控制信号输出到电机驱动模块。中间层是核心控制算法层,包含姿态估计、导航和控制算法等。最下层是一些基础的工具函数库。

图1 笔者用source insight阅读baseflight全代码

主要文件的统计和解释

整个项目不过1.6w行,78个文件。最大的文件是cli.c超过一千行(包含大量的交互处理,所以代码多一点),其余文件均小于1k行,符合良好的c语言代码设计规范。数量最多的是drv_开头的驱动层程序。

其次是各种计算和控制文件,比如fw_nav,是前向导航的意思,也就是控制无人机往前飞。比如mixer是混合器,混合器是混合操控命令环境感知等等渠道的信息,形成最终的每个旋翼的电动机的控制命令。

最后是各种辅助文件,包含各种辅助函数,比如utils.c.h,比如printf.c.h。

还有一个不属于上面三类的重要文件makefile,是把baseflight编译成固件.bin的核心文件,一般不要去改。

图2 baseflight的简明项目报告

文件名 类型 大小 行数 解释
board.h src 9197 - 包含与硬件板相关的定义和配置信息的头文件
buzzer.c src 6377 113 用于控制蜂鸣器源代码文件
buzzer.h src 1756 - 包含与控制蜂鸣器相关的定义和函数声明的头文件
cli.c src 48960 917 用于处理命令行界面的源代码文件
cli.h src 158 - 包含与命令行界面相关的定义和函数声明的头文件
config.c src 12733 316 用于处理配置信息的源代码文件
drv_adc.c src 3462 63 用于控制ADC模数转换器)的源代码文件
drv_adc.h src 570 - 包含与控制ADC相关的定义和函数声明的头文件
drv_adxl345.c src 3486 60 用于控制ADXL345加速度计的源代码文件
drv_adxl345.h src 189 - 包含与控制ADXL345加速度计相关的定义和函数声明的头文件
drv_ak8975.c src 1546 30 用于控制AK8975磁力计的源代码文件
drv_ak8975.h src 122 - 包含与控制AK8975磁力计相关的定义和函数声明的头文件
drv_bma280.c src 1332 27 用于控制BMA280加速度计的源代码文件
drv_bma280.h src 51 - 包含与控制BMA280加速度计相关的定义和函数声明的头文件
drv_bmp085.c src 9395 149 用于控制BMP085气压计的源代码文件
drv_bmp085.h src 50 - 包含与控制BMP085气压计相关的定义和函数声明的头文件
drv_bmp280.c src 7015 76 用于控制BMP280气压计的源代码文件
drv_bmp280.h src 48 - 包含与控制BMP280气压计相关的定义和函数声明的头文件
drv_gpio.c src 2900 62 用于控制GPIO(通用输入输出)的源代码文件
drv_gpio.h src 1179 - 包含与控制GPIO相关的定义和函数声明的头文件
drv_hcsr04.c src 4049 83 用于控制HCSR04超声波传感器的源代码文件
drv_hcsr04.h src 185 - 包含与控制HCSR04超声波传感器相关的定义和函数声明的头文件
drv_hmc5883l.c src 8102 93 用于控制HMC5883L磁力计的源代码文件
drv_hmc5883l.h src 133 - 包含与控制HMC5883L磁力计相关的定义和函数声明的头文件
drv_i2c.c src 16997 289 用于控制I2C总线的源代码文件
drv_i2c.h src 546 - 包含与控制I2C总线相关的定义和函数声明的头文件
drv_i2c_soft.c src 4692 168 用于软件模拟I2C总线的源代码文件
drv_l3g4200d.c src 2709 48 用于控制L3G4200D陀螺仪的源代码文件
drv_l3g4200d.h src 68 - 包含与控制L3G4200D陀螺仪相关的定义和函数声明的头文件
drv_ledring.c src 1214 40 用于控制LED环的源代码文件
drv_ledring.h src 95 - 包含与控制LED环相关的定义和函数声明的头文件
drv_mma845x.c src 4010 41 用于控制MMA845X加速度计的源代码文件
drv_mma845x.h src 52 - 包含与控制MMA845X加速度计相关的定义和函数声明的头文件
drv_mpu.c src 18305 353 用于控制MPU6050/6500/9250 ?IMU(惯性测量单元)的源代码文件
drv_mpu.h src 605 - 包含与控制MPU6050/6500/9250 ?IMU相关的定义和函数声明的头文件
drv_ms5611.c src 5821 117 用于控制MS5611气压计的源代码文件
drv_ms5611.h src 50 - 包含与控制MS5611气压计相关的定义和函数声明的头文件
drv_pwm.c src 14536 237 用于控制PWM脉冲宽度调制)输出的源代码文件
drv_pwm.h src 2090 - 包含与控制PWM输出相关的定义和函数声明的头文件
drv_serial.c src 1019 27 用于控制串口通信的源代码文件
drv_serial.h src 1644 - 包含与控制串口通信相关的定义和函数声明的头文件
drv_softserial.c src 14155 297 用于软件模拟串口通信的源代码文件
drv_softserial.h src 1619 - 包含与软件模拟串口通信相关的定义和函数声明的头文件
drv_spi.c src 3091 93 用于控制SPI(串行外设接口)的源代码文件
drv_spi.h src 260 - 包含与控制SPI相关的定义和函数声明的头文件
drv_system.c src 5970 79 用于系统级别控制的源代码文件
drv_system.h src 564 - 包含与系统级别控制相关的定义和函数声明的头文件
drv_timer.c src 8105 104 用于控制定时器的源代码文件
drv_timer.h src 856 - 包含与控制定时器相关的定义和函数声明的头文件
drv_uart.c src 14017 329 用于控制UART(通用异步收发器)通信的源代码文件
drv_uart.h src 1231 - 包含与控制UART通信相关的定义和函数声明的头文件
flash.bat support 681 - 用于执行闪存操作的批处理文件
fw_nav.c src 9207 176 包含导航相关功能的源代码文件
gps.c src 57742 812 包含GPS相关功能的源代码文件
ibus.c src 2178 49 用于处理i-Bus(Flysky接收机的信号协议)的源代码文件
imu.c src 15173 294 包含IMU(惯性测量单元)相关功能的源代码文件
JLinkSettings.ini - 573 - J-Link调试器的配置文件
main.c src 9069 202 程序的入口点,包含主要的执行逻辑
Makefile - 6751 - 用于管理项目编译的Makefile文件
mixer.c src 24140 342 用于控制飞行器的混合器的源代码文件
mw.c src 43199 832 主要的飞行控制代码的源代码文件
mw.h src 26858 - 包含与飞行控制相关的定义和函数声明的头文件
printf.c src 6704 167 实现了格式化输出功能的源代码文件
printf.h src 4923 - 包含与格式化输出相关的定义和函数声明的头文件
rxmsp.c src 533 18 用于处理R-XSR接收机的源代码文件
sbus.c src 3398 58 用于处理S.Bus(Futaba接收机的信号协议)的源代码文件
sensors.c src 17656 406 用于处理各种传感器的源代码文件
serial.c src 37714 703 用于控制串口通信的源代码文件
spektrum.c src 5512 116 用于处理Spektrum接收机的源代码文件
sumd.c src 1950 47 用于处理SUMD(Graupner接收机的信号协议)的源代码文件
telemetry_common.c src 3237 90 包含通用遥测功能的源代码文件
telemetry_common.h src 288 - 包含与通用遥测功能相关的定义和函数声明的头文件
telemetry_frsky.c src 7648 172 用于处理FrSky遥测的源代码文件
telemetry_frsky.h src 332 - 包含与FrSky遥测相关的定义和函数声明的头文件
telemetry_hott.c src 9205 126 用于处理HoTT遥测的源代码文件
telemetry_hott.h src 8791 - 包含与HoTT遥测相关的定义和函数声明的头文件
utils.c src 3944 114 包含一些常用功能的实用函数的源代码文件
utils.h src 211 - 包含与实用函数相关的定义和函数声明的头文件

表1 全文件列表

里面的main.c,会把主循环拉起来。就像任何持续执行的嵌入式系统,都是靠一个无限循环来保证器件的无限执行的。

 

?// loopy?while?(1) {?//这里,main启动无限循环? ??loop();?#ifdef?SOFTSERIAL_LOOPBACK? ??if?(loopbackPort1) {? ? ? ??while?(serialTotalBytesWaiting(loopbackPort1)) {? ? ? ? ? ??uint8_t?b =?serialRead(loopbackPort1);? ? ? ? ? ??serialWrite(loopbackPort1, b);? ? ? ? ? ??//serialWrite(core.mainport, 0x01);? ? ? ? ? ??//serialWrite(core.mainport, b);? ? ? ? };? ? }? ??if?(loopbackPort2) {? ? ? ??while?(serialTotalBytesWaiting(loopbackPort2)) {? ? ? ? ? ??serialRead(loopbackPort2);? ? ? ? };? ? }#endif}

区区几行代码,其内容却很丰富:

1. 无限循环 (while (1))

while (1) 创建了一个无限循环,使得代码不断重复执行。后面会说如何终止无限循环。

2. 调用 loop() 函数

这个loop() 就是飞行的主要函数,不在main。c里面,而在mw.c里面。mw的意思就是main work。之所以分开无非是软件工程良好代码规范的需要:不要让单个文件太过庞大。

3. 条件编译 (#ifdef SOFTSERIAL_LOOPBACK)

a. #ifdef SOFTSERIAL_LOOPBACK 是一个预处理器指令,表示只有在定义了 SOFTSERIAL_LOOPBACK 宏的情况下,才会编译下面的代码块。

4. 处理 loopbackPort1

a. 如果 loopbackPort1 存在(即不为 NULL 或假值),则进入一个内部循环。

b. while (serialTotalBytesWaiting(loopbackPort1)):此循环将持续运行,直到 loopbackPort1 上没有任何数据等待读取为止。

c. uint8_t b = serialRead(loopbackPort1);:从 loopbackPort1 读取一个字节的数据并存储在变量 b 中。

d. serialWrite(loopbackPort1, b);:将刚刚读取到的数据再写回到 loopbackPort1,这实际上是在模拟一个回环(loopback)操作。

5. 处理 loopbackPort2

a. 如果 loopbackPort2 存在,则进入另一个内部循环。

b. while (serialTotalBytesWaiting(loopbackPort2)):此循环将持续运行,直到 loopbackPort2 上没有任何数据等待读取为止。

c. serialRead(loopbackPort2);:从 loopbackPort2 读取一个字节的数据,但没有将其存储或重新发送出去,因此这似乎只是简单地丢弃数据。

其中值得注意的几个点:

● 死循环:由于 while (1) 是一个死循环,除非通过外部中断或其他方式终止程序,否则这段代码会一直运行下去。

● 资源消耗:在没有数据可读的情况下,serialTotalBytesWaiting 函数会持续返回 false,导致循环快速结束。然而,如果端口上有大量数据等待读取,这可能会导致 CPU 资源的高占用率。

● 调试和测试:#ifdef SOFTSERIAL_LOOPBACK 指令使得这部分代码可以根据需要启用或禁用。这对于调试和测试不同的功能场景非常有用。

3、如何安装?

假设某一位读者花了很大力气根据自己的设备改写了baseflight的程序,而且这位读者可能就是某个无人机厂商的创始人或者总师,需要把自己的产品(这些改进就是你的产品)变现才能盈利,那么我们怎么把修改后的程序“注入”飞控里面。

Baseflight 主要运行在基于 STM32 系列微控制器 (MCU) 的硬件平台上。STM32 是一种广泛应用于无人机飞行控制器的 32 位 ARM Cortex-M 处理器,具有高性能和丰富的外设接口。具体来说,Baseflight 支持多种常见的飞控板,例如 Naze32、F3、CC3D 等 。

步骤 描述 操作
1 准备工具和环境 下载并安装 Betaflight Configurator 或 Baseflight Configurator。
确保电脑上已安装相应的驱动程序
2 连接飞控板 使用 ?USB 线将飞控板连接到电脑,确保连接稳固,飞控板上的电源指示灯亮起。
3 进入引导模式 某些飞控板需要按下并按住“Boot”按钮,然后插入 USB 线。
具体操作请参考飞控板说明书。
4 刷写固件 1.?打开 Betaflight Configurator 或 Baseflight ?Configurator。
2.?连接成功后,软件会自动检测到飞控板。
3.?选择最新的 ?Baseflight 固件文件(通常为 .bin 文件格式)。
4.?点击“Flash ?Firmware”按钮开始刷写过程。
5.?刷写完成后,确保所有步骤都正确无误,并等待提示确认固件已成功安装。
5 配置和校准 通过配置工具对飞控板进行必要的设置和校准。
包括陀螺仪、加速度计、磁罗盘等传感器校准。
PID 参数调整。

表2 安装 Baseflight 固件到硬件中

那么固件哪来的?baseflight都是源文件啊。

步骤 描述 操作
1 获取源代码,加入你自己的修改 从 Baseflight 的官方 GitHub 仓库获取最新版本的源代码。
确保使用的是最新的稳定版本或开发分支。
2 配置硬件目标 根据使用的具体硬件平台(例如 STM32F103C8),配置 Makefile 或其他构建工具来指定目标硬件。
确保生成的固件与硬件兼容。
3 编译固件 使用 Makefile 或类似的构建工具来编译源代码。
通过命令行运行 make 命令启动编译过程。
Makefile 会调用编译器、链接器等工具,生成 .bin ?文件。
4 生成二进制文件 编译完成后,生成的固件将以二进制文件形式保存,通常是 ?.bin 文件格式。这个文件可以直接烧录到 MCU 的闪存中运行。
5 验证固件(避免把硬件烧成砖) 在烧录之前,建议对生成的 .bin 文件进行验证。
可以通过检查文件大小、校验和等方式进行初步验证。
一些开发者还会在固件中嵌入版本信息,以便在烧录前进行进一步验证。
6 烧录固件 使用适当的工具(如 ST-Link、JTAG 等)将生成的 .bin 文件烧录到飞控板的闪存中。
确保在烧录时选择正确的启动模式(例如,STM32F103C8 ?板有引导模式开关),以便正确加载新固件。

表3 baseflight固件生成

特别注意,除非你改变了源工程的文件结构,否则不要改原先的makefile文件。

相关推荐