超灵敏音频升降仪:飞行员专用精密气压计
组件与物料
![]() |
SparkFun Arduino Pro Mini 328 - 3.3V/8MHz | × | 1 |
项目介绍
简介
本仪器供飞行员在飞行中使用(滑翔伞、三角翼、热气球等),帮助寻找热气流核心,更好地利用上升气流爬升。
简要说明
这是一个极其灵敏的气压计,通过声音指示上升与下沉。上升时发出简单的“滴-滴”声,每秒一声或更快(上升速率越快,蜂鸣频率越高);灵敏度高到仅几厘米/秒的上升速度就能触发蜂鸣——你可以试着慢慢抬起手臂,手持仪器即可听到声音。下沉速率达到 -1 m/s 或更大时,会发出长连续的“滴———”声报警。
组件清单
- Arduino Pro Mini 3.3V 8MHz 作为主控单元
- GY-63 (MS5611) 气压传感器 3.3V
- 8位拨码开关
- 蜂鸣器(带内部振荡器的有源类型)
- 8选1多路复用器 4051 3.3V
- 1S 3.7V 350mAh 锂聚合物电池 + 10cm 红/黑导线及公母连接器
- 升压模块 + USB 锂电充电器,TP5400(来自 AZDelivery)
- 若干电阻:8×4.7k 电阻网络、220Ω、2×10k,电容 47μF、470μF
- 自恢复保险丝 0.5A
- 小型黑色 ABS 塑料盒,尺寸 78×39×22 mm
- 滑动开关
- 6针母排针(用于 FTDI)
- 17针公排针(多组)
- 4针 90° 公排针(用于气压传感器电路)
- 30cm 硬质绝缘导线(用于跳线和连接)
- 绿色挂绳
请注意原理图中黑色开关下方的棕色“陶瓷电容”实际上是自恢复保险丝(Fritzing 中未找到对应符号)。8个电阻用单个电阻网络替代,内含 8×4.7kΩ,共 9 引脚(1 个公共端 + 8 个电阻端),位于蓝色拨码开关上方的黑色元件。Fritzing 原理图文件可在下方下载。
拨码开关功能详解
使用蓝色 8 位拨码开关选择和更改升降仪参数,参数表及说明如下:
- 引脚 1:未使用,任意位置无影响
- 引脚 2:音量高/低切换;接通时短路蜂鸣器串联电阻,增大电流以提高音量
- 引脚 3 和 4:下沉报警阈值(m/s),二进制编码:00=-999(无报警),01=-1,10=-2,11=-3
- 引脚 5 和 6:蜂鸣频率(Hz),二进制编码:00=+1,01=+1.5,10=+2,11=+3
- 引脚 7 和 8:灵敏度(m/s),二进制编码:00=+0.0(最大灵敏度,<10cm/s 即触发),01=+0.1,10=+0.2,11=+0.5
从电路角度看,引脚 1 和 3-8 通过 4051 多路复用器模拟读取,软件判断值 >512 为接通。Arduino 通过 3 个输出位(000 到 111)选择读取 8 个通道中的哪一个。详见代码中的 readDIPswitch() 函数。
电池管理
两个 10k 电阻与 47μF 电容组成分压电路监测电池电压。锂聚合物电池放电至 3.3V 以下会损坏,因此每 10 秒(BATTinterval)调用 checkBATT(),电压过低时蜂鸣器每秒发出 6 短促蜂鸣提醒。请勿拖延,及时关机充电!
重要:必须在盒子上至少打一个孔供空气流通,否则气压传感器无法工作。图中打了两个孔:一个用于听蜂鸣声,一个用于观察充电指示灯;Micro USB 接口也需要一个孔。打孔后仪器不再防水。
绿色挂绳用于安全固定在机上,防止丢失。
PCB 设计
采用单面 PCB,因此需用几根跳线(虚线)解决布线。下方提供元件面和焊盘面镜像文件,可用激光打印机打印在“黄纸”或“蓝纸”上(蓝纸效果更好但价格稍高)。打印时关闭节墨模式,使用 1200 dpi 分辨率确保深黑效果。用烫斗将碳粉从转印纸转移到铜板上。双面打印使项目更“专业”。
使用十余个 Arduino 引脚。未使用的引脚无需焊接,保持空置。将 6 针母排焊在 Mini Pro 顶面,以便日后通过 FTDI 接口更新固件。
USB 升压电源电路倒置安装。在 USB 接口旁“Power USB”标识处用两根粗公排针(去掉塑料座)配合焊锡固定。三根导线分别连接 GND-、BATT+ 和 OUT+ 到该电路。
气压传感器
GY-63 (MS5611) 气压传感器(PCB 上标记为 P-Sensor)封装在小型电路板上,通过 I2C 总线与 Arduino 通信,内含温度传感器(本项目未使用)。
程序核心是 readPSensor() 函数。我们需要的是相对高度变化:函数每秒多次读取并累加到 PrexTotal;每半秒(PrexInterval)计算平均高度变化,并根据拨码开关设置发出蜂鸣或长鸣。这种简单滤波已足够;曾尝试卡尔曼滤波、Madgwick 和 Mahony 算法,但对本项目无显著提升。
更新与提示
以上就是全部内容。我非常享受这个项目的制作过程!你也试试吧!:-)
—— Marco Zonca
代码
升降仪代码 Arduino
/* This sketch act as Variometer for paragliding, by Marco Zonca, 2020
Arduino MiniPro 3.3 as CPU, GY-63 (MS5611) barometric pressure sensor,
8 x dipswitch, buzzer, Mux 4051, lipo 1s 3.7v 350mA,
3.7v -> 5v voltage stepup + lipo usb charger;
DipSwitch:
1= not used
2= hw low/high buzzer volume
3= \ sink alarm: OFF -1.0 -2.0 -3.0 m/sec
4= /
5= \ frequency beeps: +1.0 +1.5 +2.0 +3.0 Hz
6= /
7= \ sensibility: +0.0 +0.1 +0.2 +0.5 m/sec
8= /
*/
#include <MS5611.h>
#include <NewTone.h>
const int muxIOpin = 15;
const int vbattPin = 14;
const int muxbit0 = 4;
const int muxbit1 = 5;
const int muxbit2 = 6;
const int buzzerPin = 7;
const int DIPSWinterval = 5000;
const int BATTinterval = 10000;
const int PrexInterval = 500;
const boolean isDebug = false;
float sensibility[5];
float frequency[5];
float sinkalarm[5];
long n=0;
boolean dipswitch[9];
String dips;
unsigned long prevDIPSWmillis = 0;
unsigned long prevBATTmillis = 0;
float n1=0;
float n2=0;
float SensorVBatt=0;
double referencePressure = 0;
unsigned long prevPrexMillis = 0;
unsigned long currPrexMillis = 0;
double realPressure = 0;
float absoluteAltitude = 0;
float relativeAltitude = 0;
float avgAltitude = 0;
float avgPrevAltitude = 0;
long PrexCounter = 0;
float PrexTotal = 0;
float PrexVario = 0;
boolean isFirstCalc = true;
MS5611 psensor; // pressure sensor
void setup() {
Serial.begin(9600);
pinMode(muxbit0, OUTPUT);
pinMode(muxbit1, OUTPUT);
pinMode(muxbit2, OUTPUT);
pinMode(buzzerPin, OUTPUT);
sensibility[4]=0; sensibility[3]=0.5; sensibility[2]=0.2; sensibility[1]=0.1; sensibility[0]=0.0;
frequency[4]=0; frequency[3]=3.0; frequency[2]=2.0; frequency[1]=1.5; frequency[0]=1.0;
sinkalarm[4]=0; sinkalarm[3]=-3.0; sinkalarm[2]=-2.0; sinkalarm[1]=-1.0; sinkalarm[0]=-999.9;
readDIPswitch();
psensor.begin();
referencePressure = psensor.readPressure();
if (isDebug == true) Serial.println("Vario is on");
NewTone (buzzerPin,4);
delay(750);
noNewTone();
}
void loop() {
readPSensor();
if ((prevDIPSWmillis+DIPSWinterval) < millis()) {
readDIPswitch();
prevDIPSWmillis=millis();
}
if ((prevBATTmillis+BATTinterval) < millis()) {
checkBATT();
prevBATTmillis=millis();
}
}
void readPSensor() {
realPressure = psensor.readPressure();
absoluteAltitude = psensor.getAltitude(realPressure);
relativeAltitude = psensor.getAltitude(realPressure, referencePressure);
PrexCounter = PrexCounter + 1;
PrexTotal = PrexTotal + relativeAltitude;
currPrexMillis = millis();
if (currPrexMillis - prevPrexMillis >= PrexInterval) {
avgAltitude = PrexTotal / PrexCounter;
if (isFirstCalc == true) {
avgPrevAltitude=avgAltitude;
isFirstCalc=false;
}
PrexVario=(avgAltitude-avgPrevAltitude) * (1000/PrexInterval); // vario mSec
if ((PrexVario <= sensibility[4]) && (PrexVario >= sinkalarm[4])) {
noNewTone();
}
if ((PrexVario > sensibility[4])) {
NewTone (buzzerPin,((int)(PrexVario+frequency[4])));
}
if ((PrexVario < sinkalarm[4])) {
NewTone (buzzerPin,0.1);
}
avgPrevAltitude=avgAltitude;
prevPrexMillis = currPrexMillis;
PrexTotal=0;
PrexCounter=0;
if (isDebug == true) {
Serial.print("Vario=");
Serial.println(PrexVario);
}
}
}
void readDIPswitch() {
int s=0;
for (n=1; n<9; n++) {
dips="0000"+String(n-1, BIN);
dips=(dips.substring(dips.length()-3,dips.length()));
if (dips.substring(2,3) == "0") digitalWrite(muxbit0, LOW);
else digitalWrite(muxbit0, HIGH);
if (dips.substring(1,2) == "0") digitalWrite(muxbit1, LOW);
else digitalWrite(muxbit1, HIGH);
if (dips.substring(0,1) == "0") digitalWrite(muxbit2, LOW);
else digitalWrite(muxbit2, HIGH);
if (analogRead(muxIOpin) > 512) dipswitch[n]=false;
else dipswitch[n]=true;
if (isDebug == true) {
if (dipswitch[n]==false) Serial.print("0");
else Serial.print("1");
}
}
if (isDebug == true) Serial.println("");
s=0;
if (dipswitch[7]==true) s = s + 2;
if (dipswitch[8]==true) s = s + 1;
sensibility[4]=sensibility[s];
if (isDebug == true) {
Serial.print("Sensibility=");
Serial.println(sensibility[4]);
}
s=0;
if (dipswitch[5]==true) s = s + 2;
if (dipswitch[6]==true) s = s + 1;
frequency[4]=frequency[s];
if (isDebug == true) {
Serial.print("Frequency=");
Serial.println(frequency[4]);
}
s=0;
if (dipswitch[3]==true) s = s + 2;
if (dipswitch[4]==true) s = s + 1;
sinkalarm[4]=sinkalarm[s];
if (isDebug == true) {
Serial.print("SinkAlarm=");
Serial.println(sinkalarm[4]);
}
}
void checkBATT() {
n1 = analogRead(vbattPin);
n2=(((6.60 * n1) / 1023.00));
SensorVBatt=(n2 + ((n2 * 0.0) /100));
if (SensorVBatt <= 3.4) {
NewTone (buzzerPin,6,1000);
}
if (isDebug == true) {
Serial.print("VBatt=");
Serial.println(SensorVBatt);
}
}
自定义零件与外壳
原理图
vario_R1XzPifiX4.fzz制造工艺
- 无液气压计:设计、历史与压力测量未来
- 高灵敏电压检测器:构建音频信号探测器
- 高灵敏度音频检测器:捕捉超微弱电信号
- 先进检测技术以极高灵敏度定位晶体管缺陷
- 革命性超薄MXene应变传感器提升机械臂精度与安全
- 先进光学接收器用于空间通信
- Google Cloud Secret Manager:敏感数据全生命周期安全管理实战
- Amstrong® Ultra 650MC – 高强度、低碳、优异焊接性能的热轧钢
- Amstrong® Ultra 650MCT – 高强度、低碳、优异低温韧性的热轧钢
- Amstrong® Ultra 700MC — 高强度细晶粒钢,卓越焊接性能
- Amstrong® Ultra 700MCT — 超高屈服强度、低碳细晶粒、卓越焊接性能
- 超高纯铬 (UHP Cr) – 纯度 ≥99.95%,关键应用首选
