高性能 Arduino 气象气球数据记录器
元器件与物料清单
| 元器件 | 数量 |
|---|---|
| Maxim Integrated DS18B20 可编程分辨率 1-Wire 数字温度计 | 2 |
| DHT22 温湿度传感器 | 1 |
| SparkFun 三轴加速度计模块 - ADXL335 | 1 |
| 公头排针 36 位单排长针 (0.1") | 2 |
| Arduino Mega 2560 | 1 |
| 5050 SMD LED | 1 |
| 电阻 4.75kΩ | 2 |
| 电阻 100Ω | 3 |
| 电阻 10kΩ | 1 |
| Flash 存储卡, MicroSD 卡 | 1 |
| Micro SD 卡模块 | 1 |
所需工具与设备
- 电烙铁 (通用)
- 无铅焊锡丝
应用与在线服务
- Arduino IDE
项目简介
大家好!你可能会想:Arduino 真的能送入太空吗?几乎可以。利用气象气球,你可以将 Arduino、相机、蒜香面包或任何你想要的东西送到距离太空三分之一的高度!尽管只到达了太空边缘,但那里已没有 99% 的大气层,因此我们称之为“近空间”。
本指南内容详尽,除非你只是浏览,否则请务必阅读完“路径 1”部分。现在让我们开始探索如何实现这个项目。
三大实施路径
根据你的需求和技能水平,提供三条路径供选择。所有路径都需要一定的焊接技能,因为平流层中存在强风。每条路径各有优劣,取决于你的兴趣点:
- 路径 1: 使用万能板、多种传感器构建简单数据记录器,所需焊接技能较少。
- 路径 2: 使用预设计的 PCB 扩展板,外观整洁美观,由我们设计测试。
- 路径 3: 自行设计 PCB。本指南不深入讲解 PCB 设计,但会提供关键设计指南和学习资源链接。
路径选择建议
- 路径 1 最简单,灵活性最高,可自行选择传感器、开发板和功能,但需确保焊接牢固以应对飞行环境。
- 路径 2 限制较多,必须使用指定传感器和 Arduino Mega,但无需担心焊接和编程,是学习 PCB 的良好起点。我们提供 Gerber 文件、导出设置和代码。PCB 成本低廉(5 片约 $2),价格因供应商而异。
- 路径 3 难度最大,需掌握 PCB 设计、编程和焊接技能。若你已具备这些能力,本指南仍能提供重要限制条件和细节参考。
重要法规与安全提示
在开始前,必须了解相关法规,气象气球发射可能受地区限制。本指南不涵盖气球选择、载荷舱制作、充气等内容,但会提供相关指南链接。以下是关键限制(以美国 FAA 规定为例):
- 载荷舱不得包含手机信号设备;如携带手机必须设为飞行模式。
- 使用 GPS 追踪需取得 HAM 无线电执照(需考试和费用)。
- 载荷重量与尺寸比超过 3.0 盎司/平方英寸时,总重量必须小于 4 磅。
- 单个载荷/包裹重量不得超过 6 磅。
- 双载荷总重量不得超过 12 磅。
路径 1 - 万能板方案
设计考量
开始设计前需考虑:所需传感器类型、飞行剖面、供电方案、回收方式等。原理图包含温湿度传感器、气压传感器、IMU 和 SD 卡模块。如需 GPS 定位载荷舱,需额外添加 GPS 模块。
回收方案对比
- SPOT GPS 模块: 易用、无限范围(卫星通讯)、电池寿命长,但价格昂贵、倒置时失效、信号易被厚物体阻挡。我们使用 SPOT 3 卫星信使并设计 3D 打印云台保持直立。
- APRS 无线电: 最可靠,可传回数据、坐标、高度,但需 HAM 执照,本指南不含接线图。
- 手机: 不推荐。需解决飞行后退出飞行模式问题,成本高于 SPOT,仅作备用。
飞行剖面规划
- 考虑是否需要远程开伞
- 温度可达 -40°C,传感器需耐低温
- 低温降低电池性能,建议大容量电源 + 泡沫保温箱,同时满足重量限制
- 制作清单:数据类型、是否搭载相机、载荷舱内部布局
原理图与接线图
Arduino Mega 对这些传感器属于过配,但使用我们提供的代码必须用 Mega。若改用 Nano,需将 MicroSD 模块引脚改为对应板子的 SPI 引脚。
核心代码
// DHT22 设置
#include "DHT.h"
#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// SD 卡设置
#include
#include
File sdcard_file;
int CS_pin = 10;
// DS18B20 温度传感器
#include
#include
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
int scale = 3; // ADXL337 用 3(±3g), ADXL377 用 200(±200g)
boolean micro_is_5V = true; // 5V 单片机设为 true
void setup() {
Serial.begin(9600);
sensors.begin();
dht.begin();
pinMode(CS_pin, OUTPUT);
if (SD.begin()) {
Serial.print("SD Card found!");
} else {
Serial.print("Error finding SD Card");
return;
}
sdcard_file = SD.open("data.csv", FILE_WRITE);
if (sdcard_file) {
// 写入 CSV 表头
sdcard_file.print("DS18B20");
sdcard_file.print(",");
sdcard_file.print("DHT22 Temp");
sdcard_file.print(",");
sdcard_file.print("Hum");
sdcard_file.print(",");
sdcard_file.print("H.InX");
sdcard_file.print(",");
sdcard_file.print("rawX");
sdcard_file.print(",");
sdcard_file.print("rawY");
sdcard_file.print(",");
sdcard_file.print("rawZ");
sdcard_file.print(",");
sdcard_file.print("scaledX");
sdcard_file.print(",");
sdcard_file.print("scaledY");
sdcard_file.print(",");
sdcard_file.print("scaledZ");
sdcard_file.print(",");
sdcard_file.println(" ");
}
}
void loop() {
delay(222);
// 加速度计读取
int rawX = analogRead(A0);
int rawY = analogRead(A1);
int rawZ = analogRead(A2);
float scaledX, scaledY, scaledZ;
if (micro_is_5V) {
scaledX = mapf(rawX, 0, 675, -scale, scale);
scaledY = mapf(rawY, 0, 675, -scale, scale);
scaledZ = mapf(rawZ, 0, 675, -scale, scale);
} else {
scaledX = mapf(rawX, 0, 1023, -scale, scale);
scaledY = mapf(rawY, 0, 1023, -scale, scale);
scaledZ = mapf(rawZ, 0, 1023, -scale, scale);
}
// DS18B20 温度
sensors.requestTemperatures();
int etemp = sensors.getTempCByIndex(0);
// DHT22 温湿度
float h = dht.readHumidity();
float t = dht.readTemperature();
float f = dht.readTemperature(true);
if (isnan(h) || isnan(t) || isnan(f)) return;
float hif = dht.computeHeatIndex(f, h);
float hic = dht.computeHeatIndex(t, h, false);
// 写入 SD 卡
sdcard_file.print(etemp); sdcard_file.print(",");
sdcard_file.print(t); sdcard_file.print(",");
sdcard_file.print(h); sdcard_file.print(",");
sdcard_file.print(hic); sdcard_file.print(",");
sdcard_file.print(rawX); sdcard_file.print(",");
sdcard_file.print(rawY); sdcard_file.print(",");
sdcard_file.print(rawZ); sdcard_file.print(",");
sdcard_file.print(scaledX); sdcard_file.print(",");
sdcard_file.print(scaledY); sdcard_file.print(",");
sdcard_file.print(scaledZ); sdcard_file.print(",");
sdcard_file.print(" "); sdcard_file.println(" ");
sdcard_file.close();
delay(223);
}
float mapf(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
关键注意事项
- 排查问题时逐个测试传感器代码隔离故障
- SD 卡必须格式化为 FAT16 或 FAT32,容量 ≤ 16GB
- 建议加装状态指示 LED,发射前三次确认记录器正常运行
- SD 卡模块供电敏感,遇问题尝试更换电源
数据记录器可记录温度、湿度、加速度数据。高度测量需用 GPS,90% 气压计在 30,000 英尺以上失效。更多指南请查阅链接,欢迎联系我们提问。
路径 2 - 预设计 PCB 方案
使用预设计的 Eclipse PCB,可获取内部温度、外部温度、湿度、加速度数据。所需元件:
- 5050 SMD LED
- SparkFun ADXL337
- 大量排针
- Micro SD 卡模块
- DHT22 湿度传感器
- 2× DS18B20 温度传感器
- Arduino Mega
- Eclipse PCB
Gerber 文件托管于 GitHub 仓库。我们已在实际飞行中测试并改进。
PCB 订购设置
- 层数和尺寸保持默认
- 单片 PCB
- 1.6mm 厚度
- 任意颜色(绿色出货最快)
- 表面处理:HASL(含铅),无铅焊锡需改为无铅工艺
- 1oz 铜厚
- 无金手指、确认生产文件
- 飞针测试:全测
- 无镀孔半孔
- 数量任意
推荐 JLCPCB 等中国制造商性价比高,美资厂商质量更稳定,但服务商不影响最终质量。
PCB 组装指南
所有排针焊接在 PCB 两侧,直接插入 Arduino Mega 即可完成所有接线。PCB 内部走线宽 0.35mm,连接各传感器至对应排针,比万能板/面包板更可靠。
代码烧录与测试
将 PCB 插上 Mega,连接电脑,打开 Arduino IDE 烧录 GitHub 仓库中的 1.6 版代码。MicroSD 卡格式化为 FAT16/FAT32,容量 ≤ 16GB(2GB 足够 2 小时飞行)。插入 SD 卡上传代码,串口监视器应显示 SD 卡初始化成功并开始记录。等待 10 秒取出卡读取 CSV 文件验证数据。
完整代码(含 MPL3115A2 气压计与 LED 状态指示)
// DHT22 设置
#include "DHT.h"
#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// SD 卡设置
#include
#include
File sdcard_file;
int CS_pin = 10;
// DS18B20 温度传感器
#include
#include
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
// MPL3115A2 气压计设置
#include
#include
Adafruit_MPL3115A2 baro = Adafruit_MPL3115A2();
int scale = 3;
boolean micro_is_5V = true;
// LED 指示灯
int Blue = 7;
int Red = 6;
int Green = 5;
void setup() {
pinMode(23, INPUT); // 检测开关停止写入保存数据
sensors.begin();
pinMode(Blue, OUTPUT);
pinMode(Red, OUTPUT);
pinMode(Green, OUTPUT);
digitalWrite(Green, HIGH);
dht.begin();
pinMode(CS_pin, OUTPUT);
if (SD.begin()) {
// 绿灯闪烁 3 次表示成功
for(int i=0;i<3;i++) {
digitalWrite(Green, LOW); digitalWrite(Green, HIGH);
}
} else {
digitalWrite(Green, LOW); digitalWrite(Red, HIGH); delay(5000); return;
}
sdcard_file = SD.open("data.csv", FILE_WRITE);
if (sdcard_file) {
digitalWrite(Red, LOW); digitalWrite(Blue, LOW); digitalWrite(Green, HIGH);
} else {
// 红/蓝灯交替闪烁报错
digitalWrite(Green, LOW); digitalWrite(Red, HIGH); delay(1000);
digitalWrite(Red, LOW); digitalWrite(Blue, HIGH); delay(1000);
digitalWrite(Green, LOW); digitalWrite(Red, HIGH); delay(1000);
digitalWrite(Red, LOW); digitalWrite(Blue, HIGH); delay(1000);
digitalWrite(Red, HIGH); digitalWrite(Blue, LOW);
}
// 写入 CSV 表头
sdcard_file.print(","); sdcard_file.print("DS18B20"); sdcard_file.print(",");
sdcard_file.print("DHT22 Temp"); sdcard_file.print(","); sdcard_file.print("Hum"); sdcard_file.print(",");
sdcard_file.print("H.InX"); sdcard_file.print(","); sdcard_file.print("Int. Temp"); sdcard_file.print(",");
sdcard_file.print("Pres. Pasc."); sdcard_file.print(","); sdcard_file.print("alt."); sdcard_file.print(",");
sdcard_file.print("rawX"); sdcard_file.print(","); sdcard_file.print("rawY"); sdcard_file.print(","); sdcard_file.print("rawZ"); sdcard_file.print(",");
sdcard_file.print("scaledX"); sdcard_file.print(","); sdcard_file.print("scaledY"); sdcard_file.print(","); sdcard_file.print("scaledZ");
}
void loop() {
delay(222);
digitalWrite(Green, LOW); digitalWrite(Blue, HIGH);
if(!baro.begin()) { }
float pascals = baro.getPressure();
float altm = baro.getAltitude();
float tempC = baro.getTemperature();
// 加速度计
int rawX = analogRead(A0);
int rawY = analogRead(A1);
int rawZ = analogRead(A2);
float scaledX, scaledY, scaledZ;
if (micro_is_5V) {
scaledX = mapf(rawX, 0, 675, -scale, scale);
scaledY = mapf(rawY, 0, 675, -scale, scale);
scaledZ = mapf(rawZ, 0, 675, -scale, scale);
} else {
scaledX = mapf(rawX, 0, 1023, -scale, scale);
scaledY = mapf(rawY, 0, 1023, -scale, scale);
scaledZ = mapf(rawZ, 0, 1023, -scale, scale);
}
// DS18B20
sensors.requestTemperatures();
// DHT22
float h = dht.readHumidity();
float t = dht.readTemperature();
float f = dht.readTemperature(true);
if (isnan(h) || isnan(t) || isnan(f)) return;
float hif = dht.computeHeatIndex(f, h);
float hic = dht.computeHeatIndex(t, h, false);
// 写入数据
sdcard_file.println(sensors.getTempCByIndex(0));
sdcard_file.print(","); sdcard_file.print(t); sdcard_file.print(","); sdcard_file.print(h); sdcard_file.print(",");
sdcard_file.print(hic); sdcard_file.print(","); sdcard_file.print(tempC); sdcard_file.print(",");
sdcard_file.print(pascals); sdcard_file.print(","); sdcard_file.print(altm); sdcard_file.print(",");
sdcard_file.print(rawX); sdcard_file.print(","); sdcard_file.print(rawY); sdcard_file.print(","); sdcard_file.print(rawZ); sdcard_file.print(",");
sdcard_file.print(scaledX); sdcard_file.print(","); sdcard_file.print(scaledY); sdcard_file.print(","); sdcard_file.print(scaledZ); sdcard_file.print(",");
delay(223);
sdcard_file.close();
}
float mapf(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
路径 3 - 自制 PCB 方案
本指南不教授 PCB 设计,请先掌握相关技能。此处仅提供设计指南(基于美国法规):
核心设计考量
- 传感器选择: 温度、湿度、高度、空气质量、辐射、GPS 等
- 温度传感器需测至 -50°C,精度越高越好。注意:高空太阳辐射会导致温度读数偏高
- 回收方案: 同路径 1(SPOT GPS、APRS 无线电、手机备用)
- 重量限制: 同前文 FAA 规定
- 供电难题: 平流层极低温导致电池失效,Arduino 也可能故障。最佳策略:泡沫箱保温维持室温,辅以太阳能板或暖宝宝
- 无法使用气压计测高(30,000 英尺以上失效),需 GPS
PCB 设计建议
可设计为扩展板或完整 PCB。完成后全面测试并确认合规。
结语
气象气球是将设备送入平流层的酷炫方式,可搭载相机(我们用 360 相机)获取精彩画面和数据,法规相对宽松。但必须遵守所有规则:
- 加装雷达反射器
- 飞行前申报 NOTAM (Notice to Airmen)
- 确保结构牢固防止脱落
- 尽一切可能降低撞击风险
FAA 限制不多,请遵守规则,别让监管收紧毁了大家的乐趣。希望本指南对你有帮助!欢迎订阅我们的 YouTube 频道支持团队,有任何问题随时留言或联系。
祝 Arduino 之旅愉快!
NM Rocketry Reviews
自定义零件与外壳
用于保持 SPOT 个人追踪器直立的云台 3D 打印模型 (.stl)
原理图
路径 1 参考原理图
GitHub 仓库 (PCB 文件与代码)
https://github.com/nmrocketryreviews/HADLdatalogger
制造工艺
- Arduino 数字骰子:LCD 显示随机点数的电子骰子
- 多位置温度传感器系统,助力智能家居集成
- DIY Arduino USB 游戏手柄 — 自制高性能游戏手柄
- MotionSense:基于 Arduino 与 ESP8266 的智能入侵检测系统
- 3D 打印机防火卫士:智能传感器安全系统
- Pixel Chaser:Arduino Nano 单键 NeoPixel 追逐小游戏
- 基于 Arduino、Yaler 与 IFTTT 构建 Web 化 IoT 仪表盘
- Arduino 简易排斥式磁悬浮:电路与 DIY 指南
- Arduino 8×8 LED 矩阵翻页时钟 - DIY 实时时钟项目
- 自制 10 美元便携 Arduino 气象站 - Nano + DHT22 + BMP180 + LCD
- 进阶微控制器实验平台:ESP32、Arduino、PIC 与多传感器模块集成
- CoroFence 热成像检测器:Panasonic GridEye + PIR + IoT 集成