其实这个开伞系统我几个星期前就应该发布了,不过由于我发现有一些地方需要改进以及测试不是很严谨,再加上蛋疼的期中考试,所以就推到现在了。。。
对了,感谢下@彩虹之巅,因为看了他的帖子后我学习了很多,这个系统中有些代码也是他的。
下面引用他的声明:
--------------------------
此版程序作为自己发射火箭测试用,将一些保险验证代码都去掉了,所以一开始定义的一些变量常量没用到,最简单的才是最可靠的。经实际发射,证实此程序识别开伞点可靠。用这个程序请让火箭在发射架上(一定要用发射架,防止火箭在打开电源后发射前倾倒导致意外开伞)就位后再打开系统供电电池电源(9V电池盒自带开关,火箭上掏个小洞对着电池盒上开关,发射前用牙签拨开开关就行),电源打开后由于系统要加载以及要识别SD卡,所以过五秒后再点火。
另外,这个小程序开源,大家想用就用,不反对将此程序用于利润低于30%的商业行为,同时欢迎有兴趣的朋友对这个程序进行改良。另外用此程序发射火箭的朋友请遵守国家的相关法律,本人对用此程序发射火箭所带来的后果不承担任何法律责任。
--------------------
*/
另外本人接触arduino及编程也就几个星期,如有问题,求轻拍!
先说说这个系统的优点吧:
1.气压定高开伞,高度,气压,温度,三轴角度及加速度数据采集(这些都是必须的)。
2.造价便宜,也就5,60来块。
3.发射完火箭后还可以把模块拆下来弄别的玩(前提是你用得扩展版)。
4。。。
再说说这个系统不完美的地方:
1.体积有点大,重量有点重,接线比较乱。
2.不适于新手,需要有一定的电子编程基础。
3.地面气压高度的问题还在,虽然不影响系统的功能,但是每次发射前都要重新写入高度,比较麻烦。
4。。。
/*
注意!
1.一定要保证线路牢固不松,可以用洞洞板弄一个扩展板插上去,这样既牢固又可以方便取下原件干别的。
2.开伞高度设置在下面的代码里,可以自己去修改,气压高度量程-500~9000m。
3.弄好设备测试时,可以去坐电梯上下模拟,很方便,因为是测气压所以不用担心什么。
4.开伞高度是海平面高度,而不是相对你所在地面的高度,在发射之前一定要用arduino测好高度重新写入(测到的高度加上你要开伞的高度,比如我现在测的地面气压高度是-38m,想23m时开伞,那就输入-15m!)
5.火箭准备发射打开设备时,一定要观察arduino的“LED”灯是否在闪烁,没有的话是有故障!
*/
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面正文
一.理论
其实气压开伞的原理,用我的这一张图来说明吧:
大家应该会很容易明白的。
现在说说接线吧
/*
使用设备:
arduino Nano
mpu6050
bmp085或bmp180
sd卡模块
9v电池
线路连接:
sd卡:
5v=5v
sdcs/cs/dat2=d4
mosi/di/dat3=d11
sck/clk/=d13
miso/dat0/d0=d12
gnd=gnd
mpu6050:
int=d2
vcc=3v3
gnd=gnd
scl=a5
sda=a4
bmp085/180:
gnd=gnd
3.3=3v3
scl=a5
sda=a4
继电器:
in=d3
vcc=5v
gnd=gnd
供电:
gnd=gnd
vin=9v(6~12v)
*/
尽量使用扩展板
下面代码,大家不要直接复制。
#include "Wire.h"
#include "I2Cdev.h"
#include "BMP085.h"
#include "MPU6050_6Axis_MotionApps20.h"
#include "SD.h"
//导入库文件
BMP085 barometer;
float temperature;
float pressure;
float altitude;
int a;
int b;
int high=-15;//在这把数字改成你想要开伞的海平面高度(m)
const int chipSelect = 4; //设定SD_CS接口
int32_t lastMicros;bool blinkState = false;
int OPEN;
#define LED_PIN 13//设定led数据灯
//mpu6050设置----------------------
#define Vertical_acceleration_judgment_value 15 //设置加速度为多少时判断火箭为已发射的值,经验值为15.
#define Launched 1 //用来描述火箭状态为已发射.
#define Not_launched 0 //用来描述火箭状态为尚未发射.
#define The_correct_flight_angle_limit_of_rocket 30 //设置火箭正常发射的角度极值
unsigned long time;
int16_t ax, ay, az;//三轴加速度
int rocket_status; //该变量代表火箭当前的状态,分别为未发射或已发射。
float inclination[3]; //箭体三轴倾角,是一个数组,inclination[0] inclination[1] inclination[2] 分别代表三个轴的倾角
int zz,yy,Current_rocket_inclination; //该变量代表火箭与地平线的倾角.zz和yy是后加上去了,三个轴都采集了,可以再现火箭整个飞行过程中的箭体三维姿态。
int16_t Vertical_acceleration; //火箭垂直加速度,用来判断火箭是否已发射.
int last_rocket_inclination=0; //上一次通过传感器获得的火箭倾角.
//下面为计算三轴角度的一些中间变量
MPU6050 mpu;
uint8_t a1;
uint16_t a2;
uint16_t a3;
uint8_t a4[64];
Quaternion a5;
VectorFloat a6;
//上面为计算三轴角度的一些中间变量
void setup()
{
OPEN=0;
XXXXXXXgin();
XXXXXXXXXgin(115200);
Init_MPU_6050(); //初始化MPU6050.
rocket_status=Not_launched; //将火箭状态初始化为未发射.
XXXXXXXXXXXXitialize();
pinMode(3,OUTPUT); //设定继电器为d3口
digitalWrite(3,LOW);//继电器初始化
pinMode(LED_PIN, OUTPUT);//LED初始化
XXXXXgin(chipSelect);
int a=0;
int b=0;
}
void loop() {
zz=Get_Current_Rocket_Inclination(0);
yy=Get_Current_Rocket_Inclination(2);
Current_rocket_inclination=Filter_Current_Rocket_Inclination(1);//取得火箭当前的倾角,参数这里取值为1,代表X轴.
Vertical_acceleration=XXXXXXtAccelerationX()/2048;//还是因为传感器安装位置的关系,火箭垂直轴为X轴。这里表示的是当前火箭的垂直加速度,程序里用作判断火箭是否已经发射。其实就是表示X轴的当前加速度
XXXXXXXXXXXXtControl(BMP085_MODE_TEMPERATURE);
lastMicros = micros();
while (micros() - lastMicros < XXXXXXXXXXXXtMeasureDelayMicroseconds());
temperature = XXXXXXXXXXXXtTemperatureC();
XXXXXXXXXXXXtControl(BMP085_MODE_PRESSURE_3);
while (micros() - lastMicros < XXXXXXXXXXXXtMeasureDelayMicroseconds());
pressure = XXXXXXXXXXXXtPressure();
altitude = XXXXXXXXXXXXtAltitude(pressure);
File dataFile = SD.open("data.txt",FILE_WRITE);
if (dataFile)
{ XXXXXXXXXXXint("X.Y.Z.A.C.P.H");//写入x,y,z轴数据,以及加速度,温度,气压,高度
XXXXXXXXXXXint(",");
XXXXXXXXXXXint(int(Current_rocket_inclination),DEC); //将箭体倾角数据写入文件
XXXXXXXXXXXint(",");
XXXXXXXXXXXint(int(yy),DEC);
XXXXXXXXXXXint(",");
XXXXXXXXXXXint(int(zz),DEC); //箭体姿态的另外两个轴数据写入文件
XXXXXXXXXXXint(",");
XXXXXXXXXXXint(float(Vertical_acceleration),DEC); //将火箭垂直加速度写入文件
XXXXXXXXXXXint(",");
XXXXXXXXXXXint(float(temperature),DEC); //温度
XXXXXXXXXXXint(",");
XXXXXXXXXXXint(float(pressure),DEC); //气压
XXXXXXXXXXXint(",");
XXXXXXXXXXXintln(float(altitude),DEC); //高度
XXXXXXXXXXXose();
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
}
if(altitude>=high+2)//防止上升阶段误开伞
{ a=1;}
if (a==1)//判断是否在下降阶段
{ if(altitude<=high)
b=1;}
if (a+b==2 )//判断高度开伞
{ digitalWrite(3,HIGH);//继电器打开
if(OPEN==0)
{ File dataFile = SD.open("data.txt",FILE_WRITE);
if (dataFile)
{XXXXXXXXXXXintln("Opened"); //在数据文件中写入开伞的标记点
XXXXXXXXXXXose();}
OPEN=1;}
}
}
int Filter_Current_Rocket_Inclination(int b)
{
int temp;
temp=Get_Current_Rocket_Inclination(b);
if(temp==0)
{
return last_rocket_inclination;
}
else
{
last_rocket_inclination=temp;
return last_rocket_inclination;
}
}
/*上面的函数是过滤传感器传回的无效值,参数b可以为0,1,2,分别代表传感器的Z,X,Y三个轴,本程序中取X轴,如果用其它轴来判断,则部分程序需要相应的修改*/
float Get_Current_Rocket_Inclination(int c)
{
float rocket_inclination=0;
a1=XXXXXXtIntStatus();
a3=XXXXXXtFIFOCount();
if (a1&0x02)
{
while (a3<a2) a3=XXXXXXtFIFOCount();
XXXXXXtFIFOBytes(a4, a2);
a3-=a2;
XXXXXXsetFIFO();
XXXXXXpGetQuaternion(&a5, a4);
XXXXXXpGetGravity(&a6, &a5);
XXXXXXpGetYawPitchRoll(inclination, &a5, &a6);
rocket_inclination=inclination[c]*180/M_PI;
return rocket_inclination;
}
}
/*上面的函数是通过传感器来获得当前X轴与地平线的倾角数据,由于不可知的原因,获得的数据可能有噪点,不能拿来直接使用,需要进行适当的过滤.参数c可以为0,1,2,分别代表传感器的Z,X,Y三个轴,本程序中取X轴,如果用其它轴来判断,则部分程序需要相应的修改*/
void Init_MPU_6050()
{
XXXXXXitialize();
XXXXXXtFullScaleGyroRange(3);
XXXXXXtFullScaleAccelRange(3);
XXXXXXtDLPFMode(6);
XXXXXXtDHPFMode(1);
XXXXXXpInitialize();
XXXXXXtDMPEnabled(true);
a2 = XXXXXXpGetFIFOPacketSize();
}
/*上面的函数是对MPU6050进行初始化和一些必要的设置*/
二.实践
其实我原计划是准备用火箭测试的,不过由于考试和广州这多变的天气只好取消,变成电梯测试了。。。
视频地址
XXXXXXXXXXXXXXXXXX/v_show/id_XXXXXXXXXXXXXXXXml
回去导入数据
感觉挺不错的。
三.下载
库文件
库文件.zip
152.94KB
ZIP
157次下载
代码
arduino_bmp085_mpu6050.txt
9.03KB
TXT
176次下载
200字以内,仅用于支线交流,主线讨论请采用回复功能。