站内搜索
发作品签到
鸭式布局制导探空火箭
专业版

鸭式布局制导探空火箭

简介

基于STM32的塔式火箭飞控,搭载ICM42688六轴传感器,SPL06气压计,通过控制鸭翼舵面偏转,进而实现火箭制导,支持GPS定位,数据回传,定高开伞回收等功能.

简介:基于STM32的塔式火箭飞控,搭载ICM42688六轴传感器,SPL06气压计,通过控制鸭翼舵面偏转,进而实现火箭制导,支持GPS定位,数据回传,定高开伞回收等功能.
星火计划2025
复刻成本:999

开源协议

CC BY-NC-ND 3.0

(未经作者授权,禁止转载)
创建时间:2025-08-13 01:33:09更新时间:2025-09-16 13:46:52

描述

视频链接:

[B站视频--功能演示及介绍] (https://b23.tv/oJUeSUk)
[抖音视频--火箭发射测试] (https://v.douyin.com/mNeh_hm-i_Y/b@n.dN)
[抖音视频--火箭项目视频介绍] (https://v.douyin.com/crXb9vUJCHw/Q@X.MJ)
欢迎关注我的B站UID:2028030889 抖音号:43167085679。

项目简介

一枚鸭式布局制导火箭,基于STM32的自研塔式火箭飞控,搭载ICM42688六轴传感器,SPL06气压计,通过控制鸭翼舵面偏转,进而实现火箭制导,支持GPS定位,数据回传,定高开伞回收等功能。本项目软件,硬件,机械设计资料在CC-BY-NC-ND 3.0协议下发布,仅供爱好者DIY学习交流使用,未经本人许可严禁任何形式的商业使用及贩卖。火箭研发具有危险性,禁止在无安全防护的情况下进行试验。本设计不提供任何形式的工作保障/售后保修,不对任何因产品设计、操作不当以及违反当地法律法规所造成的制作人、第三方人身财产资源损坏/损害的后果及连带责任负责。

火箭在2025年7月7日进行了首次发射测试
ba5d8cf58796aacecff429cb23f567a9.jpg

项目功能

火箭由分布于箭体的四路鸭翼舵面控制姿态。飞控实时感知火箭当前飞行姿态,飞行高度,垂直速度,经纬度等,进而控制鸭翼舵面偏转,实现基本的火箭制导功能。飞控通过卡尔曼滤波融合六轴传感器与气压计高度数据,估测垂直速度,当火箭到达最高点时,垂直速度为0,此时火箭开伞。搭配VOFA+地面站,火箭使用Lora实时回传飞行数据,位置信息,用于火箭回收与后期分析研究。

8ea5527a768f106b5b7354f845fc103c.png

项目参数

火箭飞控由功能明确的三块PCB堆叠而成:
电源层:由12V锂电池或Type-C接口供电,经DCDC芯片和LDO芯片转换为5V与3.3V后,分别给舵机与主控层,信号层供电。电源板有四路舵机接口,通过XH2.54-4P的排线连接主控板,接收PWM信号后用来控制舵机。

5331f979561d8daf57c256e73d105601.png

主控层:使用STM32F103C8T6作为主控芯片,板上集成ICM42688-P六轴传感器,SPL06-001气压计,通过姿态解算与卡尔曼滤波估测垂直速度后,用于控制火箭姿态与定高开伞功能。同时支持GNSS定位报文解析,获得经纬度与对地速度等位置信息,并一同发送至信号层。

2693b8cb3cade5c29da61afeed665ca8.png
信号层:集成大夏龙雀DX-GP10 GNSS定位芯片,使用泽耀A39C系列(可选)Lora模块,通过串口接收来自主控层的数据并转发至地面站。

33777756b32622ed8860ea3e5d6cea19.png

连接VOFA+上位机

火箭飞控可通过Lora或数传连接上位机,波特率默认115200,使用FireWater数据协议。
代码内默认传输欧拉角,经纬度,垂直速度,对地速度,高度,加速度等信息。
VOFA+上位机下载地址 https://www.vofa.plus/

726759ff429f8bf53b1da8a9e2142a86.png

3D打印与组装

  1. 火箭的每个功能舱段使用M36mm + M312mm 十字螺丝固定,鸭翼舵面使用银燕舵机摇臂+1mm螺丝+502胶水固定,火箭摔过几次,依旧能用,当然有更好的方式欢迎讨论。

7425a5e3298e1cb05e756b0de50ce1cb.jpg
2. 塔式飞控使用四根M2.5螺纹棒+六角螺母固定,外壳使用长100mm,外径63内径57的亚克力管,需要对其进行钻孔,以便使用螺丝固定亚克力管。舵机依次排列在舵机舱内。舵机型号:银燕ES08MA金属模拟12g
8d239dee518d99bfb0c887c7de2c7e4d.png
3. 组装舵机舱时,将四组舵机依次放置在舵机舱内,再盖好舵机舱顶盖,舱内上下均有卡扣固定,安装时需要对准卡扣,注意调整。

c82d355c8de0c3e090d213c024518e63.jpg
4. 使用火箭连接件(图中黑色部分)连接各舱段,这样的连接件你一共需要打印四个,整理好舵机的线缆。

d3b35b18388eb047084c5dd7715e6829.jpg
5. 组装好降落伞舱还有整流罩,降落伞舱预留了一个M2.5的小孔,用于固定整流罩或者安装挂件,降落伞舱内也预留了小孔,可以安装电子点火头,触发开伞。

b3cb10fbcdd6aee9d272824cad5d107a.jpg
e0333490c6f673487d3d992166fed1a2.jpg
6. 火箭底座可以用来安装20mm外径的火箭发动机,例如四凯模型火箭发动机或者自制发动机。你可以使用Soildworks对其尺寸进行修改,以适配其他型号的火箭发动机,将发动机塞进底座圆孔之后,使用螺丝和强力胶水固定即可。火箭发射需在有安全保护的条件下进行。
59ea8d1b2d8ab74a077f406549b466e8.jpg
7. 靠近发动机舱的舱段(图中白色部分是电池舱,可以存放一个三角形的12V锂电池组,购买时注意尺寸),安装螺丝时将电池垫高一点,注意螺丝不要贯穿电池,以免发生危险。我的发动机舱是红色的,3D打印的时候适当提高热床温度,以免发动机舱脱离热床。

6c882a25774e85f8ca3375467931ce0c.jpg
8. 打螺丝(hh),建议使用电动螺丝刀。如果把握不了螺丝长度,建议都使用 M3*6mm 的十字螺丝

实物展示

使用加热台焊接飞控各元器件,注意焊接温度不要长时间超过180度,以免损坏气压计和惯性传感器。主控层有两个按键,分别是复位和屏幕信息切换,GPS经纬度,气压高度,欧拉角等重要信息,可以通过此按键切换。飞控组装完成后,建议在飞控与电池之间再外接一个开关,给火箭底部的舱段开一个口 , 就可以在不拆解火箭的情况下开启/关闭电源.

512d41f7e370f7f1daa242a4b2e5b753.jpg
火箭飞控启动后,在火箭朝相应方向倾倒时,鸭翼应保持竖直,以提供相反方向的力矩,从而修正火箭姿态.

c9d946ae9376a71e2d35d815f14f41d1.png
使用一个频率在1575.42/1561mhz的GPS有源陶瓷天线,通过SMA接口连接到信号板,在窗台或者室外可以搜索到GPS信号。通过主控板上的按键切换到GPS数据显示模式,可以观察此时的经纬度,对地速度等数据。搜索到GPS卫星并且定位有效时,信号板上会有LED闪烁。

3890c06e319bbc9ba2e34a2698d2e364.png

ICM42688P与SPL06驱动(完整代码请参考附件)

ICM42688P

typedef struct{
	int16_t AccX;
	int16_t AccY;
	int16_t AccZ;
	
}ICM42688AccData;  
typedef struct{
	float gx;
	float gy;
	float gz;
}AccG;
typedef struct{
	int16_t GyroX;
	int16_t GyroY;
	int16_t GyroZ;
	
}ICM42688GyroData;
ICM42688AccData *DataAcc;ICM42688GyroData *DataGyro;
void ICM42688_Read_Reg(uint8_t reg,uint8_t *Data)
{
	*Data = 0;
	MySPI_ICM42688_Start();
	
	reg |= 0x80;//高1位是读写位
	MySPI_ICM42688_SwapByte(reg);
	
	*Data = MySPI_ICM42688_SwapByte(0xFF);//将需要的数据交换过来,0xFF没有意义
	MySPI_ICM42688_Stop();

}
void ICM42688_Write_Reg(uint8_t reg,uint8_t Data)
{
	MySPI_ICM42688_Start();
	MySPI_ICM42688_SwapByte(reg);
	
	MySPI_ICM42688_SwapByte(Data);
	MySPI_ICM42688_Stop();
}

void ICM42688_Init(uint8_t *State)
{

	MySPI_ICM42688_Init();
	
	uint8_t Time=100,ID = 0;    
	ICM42688_Read_Reg(ICM42688_WHO_AM_I,&ID);
	if(ID != 0x47&&Time>0){
		ICM42688_Read_Reg(ICM42688_WHO_AM_I,&ID);
		Time--;	*State = 0;
	}
	else {*State = 1;}  /*判断ICM42688P是否正确连接*/
	
	
	if(*State == 1)
	{
		ICM42688_Write_Reg(0x11,0x01);//设备配置.SPI0,软复位
		Delay_ms(100);//软复位后等待响应
		ICM42688_Write_Reg(ICM42688_PWR_MGMT0,0x0F);		//电源配置
		
//		ICM42688_Write_Reg(ICM42688_ACCEL_CONFIG0,0x46);	//1KHz,4G	
		ICM42688_Write_Reg(ICM42688_ACCEL_CONFIG0,0x01);	//32KHz,16G			
		ICM42688_Write_Reg(ICM42688_ACCEL_CONFIG1,0x14);    //3级滤波
		
		//ICM42688_Write_Reg(ICM42688_GYRO_CONFIG0,0x66);  	//1KHz,250度/s
		ICM42688_Write_Reg(ICM42688_GYRO_CONFIG0,0x01);     //32KHz,2000度/s
		ICM42688_Write_Reg(ICM42688_GYRO_CONFIG1,0x0A);		//3级滤波	

	}
	
}

void ICM42688_Data(ICM42688AccData *DataAcc,ICM42688GyroData *DataGyro)
{
	uint8_t buffer[12];
    
    // 读取加速度+陀螺仪数据(共12字节)
    MySPI_ICM42688_Start();
    MySPI_ICM42688_SwapByte(ICM42688_ACCEL_DATA_X1 | 0x80);  // 设置读标志位[4](@ref)
    for(int i=0; i<12; i++) {
        buffer[i] = MySPI_ICM42688_SwapByte(0xFF);  // 连续读取12字节[4](@ref)
    }
    MySPI_ICM42688_Stop();

    // 解析加速度数据(前6字节)
    DataAcc->AccX = (buffer[0] << 8) | buffer[1];
    DataAcc->AccY = (buffer[2] << 8) | buffer[3];
    DataAcc->AccZ = (buffer[4] << 8) | buffer[5];
    
    // 解析陀螺仪数据(后6字节)
    DataGyro->GyroX = (buffer[6] << 8) | buffer[7];
    DataGyro->GyroY = (buffer[8] << 8) | buffer[9];
    DataGyro->GyroZ = (buffer[10] << 8) | buffer[11];

}

SPl06_001

typedef struct{
	float Pressure;
	float Tempreture;
	float Height;
}SPL06_Data;

void SPL06_Read_Reg(uint8_t reg, uint8_t *Data) {
    *Data = 0;
    MySPI_SPL06_Start();
    reg |= 0x80; // 设置读标志位
    MySPI_SPL06_SwapByte(reg);
    *Data = MySPI_SPL06_SwapByte(0xFF);
    MySPI_SPL06_Stop();
}

void SPL06_Write_Reg(uint8_t reg, uint8_t Data) {
    MySPI_SPL06_Start();
    MySPI_SPL06_SwapByte(reg); // 写标志位
    MySPI_SPL06_SwapByte(Data);
    MySPI_SPL06_Stop();
}

uint8_t SPL06_Init(uint8_t *State) {
    uint8_t ID;
    MySPI_SPL06_Init();
	SPL06_Write_Reg(0x0C, 0x09);
	Delay_ms(200);
    SPL06_Read_Reg(0x0D, &ID);
    if (ID != 0x10) {
        *State = 0;
    }
	else
		*State = 1;
 
    // 配置传感器
    SPL06_Write_Reg(0x08, 0x07); // 连续测量模式
	SPL06_Write_Reg(0x06, 0x76); // 压力配置
    SPL06_Write_Reg(0x07, 0xF6); // 温度配置,改完还要改下面的系数
    SPL06_Write_Reg(0x09, 0x0C); // FIFO禁用,压力移位

    return ID;
}

void SPL06_GetData(SPL06_Data *Data) {
    uint8_t  buffer[6];
	int32_t Ori_Pressure,Ori_Tempreture;
    MySPI_SPL06_Start();
    MySPI_SPL06_SwapByte(0x00 | 0x80); // 读数据寄存器,地址自增
    //依次读取数据寄存器
    for (int i = 0; i < 6; i++) {
        buffer[i] = MySPI_SPL06_SwapByte(0xFF);
    }
    MySPI_SPL06_Stop();
    
	
	//组合原始数据
	Ori_Pressure   = (int32_t)((buffer[0] << 16) | (buffer[1] << 8) | buffer[2]); 
	Ori_Tempreture = (int32_t)((buffer[3] << 16) | (buffer[4] << 8) | buffer[5]);
	Ori_Pressure = (Ori_Pressure << 8) >> 8;   // 保留符
	Ori_Tempreture = (Ori_Tempreture << 8) >> 8;	
	//读取校准系数
	int16_t Temp_Config0,Temp_Config1;
	int32_t Pressure_Config00,Pressure_Config10;int16_t Pressure_Config20,
			Pressure_Config30,Pressure_Config01,Pressure_Config11,Pressure_Config21;	
	uint8_t data[18];
	
	MySPI_SPL06_Start();
	MySPI_SPL06_SwapByte(0x10 | 0x80);
	for(int j = 0;j < 18;j++)
	{
		data[j]= MySPI_SPL06_SwapByte(0xFF);
	}
	MySPI_SPL06_Stop();
	
	//温度校准
	Temp_Config0 = (int16_t)((data[0] << 4) | ((data[1] & 0xF0) >> 4));
	Temp_Config0 = (Temp_Config0&0x0800)?(0xF000|Temp_Config0):Temp_Config0;   //补码转换
	Temp_Config1 = (int16_t)((data[2])      | ((data[1] & 0x0F) << 8));	
	Temp_Config1 = (Temp_Config1&0x0800)?(0xF000|Temp_Config1):Temp_Config1;
	
	float Traw_sc = Ori_Tempreture / 1040384.0f;
	Data->Tempreture = Temp_Config0 * 0.5 + Temp_Config1 * Traw_sc;
	
	//压力校准
	
	Pressure_Config00 =  (int32_t)((data[3] <<  12) | ((data[4] << 4) | ((data[5] & 0xF0) >> 4 )));
		Pressure_Config00 = (Pressure_Config00&0x080000)?(0xFFF00000|Pressure_Config00):Pressure_Config00;   //补码转换(C00,C10是16位,在16-20位判断负数)
	Pressure_Config10 =  (int32_t)((data[7]       ) | ((data[6] << 8) | ((data[5] & 0x0F) << 16)));
		Pressure_Config10 = (Pressure_Config10&0x080000)?(0xFFF00000|Pressure_Config10):Pressure_Config10;   //补码转换
	Pressure_Config01 =  (int16_t)((data[8]  << 8 ) | ((data[9])));
		Pressure_Config01 = (Pressure_Config01&0x08000)?(0xFFF00000|Pressure_Config01):Pressure_Config01;   //补码转换
	Pressure_Config11 =  (int16_t)((data[10] << 8 ) | ((data[11])));
		Pressure_Config11 = (Pressure_Config11&0x08000)?(0xFFF00000|Pressure_Config11):Pressure_Config11;   //补码转换	
	Pressure_Config20 =  (int16_t)((data[12] << 8 ) | ((data[13])));
		Pressure_Config20 = (Pressure_Config20&0x08000)?(0xFFF00000|Pressure_Config20):Pressure_Config20;   //补码转换
	Pressure_Config21 =  (int16_t)((data[14] << 8 ) | ((data[15])));
		Pressure_Config21 = (Pressure_Config21&0x08000)?(0xFFF00000|Pressure_Config21):Pressure_Config21;   //补码转换	
	Pressure_Config30 =  (int16_t)((data[16] << 8 ) | ((data[17])));
		Pressure_Config30 = (Pressure_Config30&0x08000)?(0xFFF00000|Pressure_Config30):Pressure_Config30;   //补码转换
	

	float Praw_sc =  Ori_Pressure / 1040384.0f;//改这里的系数
	Data->Pressure = Pressure_Config00 + Praw_sc*(Pressure_Config10 + Praw_sc*(Pressure_Config20 + Praw_sc * Pressure_Config30))+ Traw_sc * Pressure_Config01 + Traw_sc *Praw_sc*(Pressure_Config11+Praw_sc*Pressure_Config21);	
	

	Data->Height = 43300*(1-pow((Data->Pressure/101325),1/5.255));
	
}

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

3D模型

序号文件名称下载次数
暂无数据

附件

序号文件名称下载次数
1
火箭(星火计划2025).zip
824
克隆工程
添加到专辑
0
0
分享
侵权投诉
知识产权声明&复刻说明

本项目为开源硬件项目,其相关的知识产权归创作者所有。创作者在本平台上传该硬件项目仅供平台用户用于学习交流及研究,不包括任何商业性使用,请勿用于商业售卖或其他盈利性的用途;如您认为本项目涉嫌侵犯了您的相关权益,请点击上方“侵权投诉”按钮,我们将按照嘉立创《侵权投诉与申诉规则》进行处理。

请在进行项目复刻时自行验证电路的可行性,并自行辨别该项目是否对您适用。您对复刻项目的任何后果负责,无论何种情况,本平台将不对您在复刻项目时,遇到的任何因开源项目电路设计问题所导致的直接、间接等损害负责。

底部导航