Arduino Mega 2560 短信查询温度:SIM800L + DHT22 远程监测
元器件清单
| 元器件 | 数量 | 备注 |
|---|---|---|
| Arduino Mega 2560 | 1 | 多串口优势明显 |
| DHT22 温湿度传感器 | 1 | 数字输出,单总线 |
| SIM800L GSM/GPRS 模块 | 1 | 短信收发,需 3.7-4.2V 供电 |
| 10kΩ 电阻 | 1 | DHT22 数据线上拉 |
| 面包板 | 1 | |
| 跳线 | 若干 |
项目背景
这是一个大型项目的子模块:发送短信 "InTemp" 给 Arduino,自动回复当前温度。作者在整合 DHT 库与 GPRS 库时遇到困难:库示例只能发送固定字符串,无法发送变量 (float 温度值)。经过数周搜索无果,最终找到解决方案:float → String → char 数组,现分享给社区。
软件库修改
使用 Seeeduino_GPRS 库,需修改 sim800.h 适配 Mega 硬件串口:
// 原库使用 SoftwareSerial (引脚 7/8)
#define SIM800_TX_PIN 8
#define SIM800_RX_PIN 7
// 修改为 Mega 硬件串口 Serial3 (引脚 14/15)
// 但作者因修改库困难,保留 SoftwareSerial 接在 10/11
#define SIM800_TX_PIN 10
#define SIM800_RX_PIN 11
建议:Mega 有 4 个硬件串口 (Serial1-Serial3),直接用 Serial3 更稳定,需修改库源码将 SoftwareSerial 替换为 HardwareSerial。
核心难点解决:float 发送短信
// 关键代码片段
float t = dht.readTemperature(); // 读取温度 (float)
String MyString = String(t, 0); // float → String,保留 0 位小数
MyString = (MyString + " Degrees C"); // 拼接单位
// String → char 数组 (sendSMS 需 char*)
int str_len = MyString.length() + 1;
char char_array[str_len];
MyString.toCharArray(char_array, str_len);
// 发送短信
gprs.sendSMS("04xxxxxxxx", char_array); // 替换为真实手机号
硬件接线
| 模块 | 引脚 | Arduino Mega 引脚 |
|---|---|---|
| DHT22 | DATA | D2 |
| DHT22 | VCC | 5V |
| DHT22 | GND | GND |
| DHT22 | - | 10kΩ 上拉到 VCC |
| SIM800L | TXD | D10 (SoftwareSerial RX) |
| SIM800L | RXD | D11 (SoftwareSerial TX) |
| SIM800L | VCC | 18650 电池 (3.7V) / 稳压模块 |
| SIM800L | GND | GND (共地!) |
供电关键:SIM800L 发射峰值电流达 2A,必须用独立电源 (如 18650 锂电池 + 降压模块),不可直接用 Arduino 5V 供电。后续建议加装 DC-DC 稳压模块 (如 LM2596) 设为 4.0V。
完整代码 (DHT_SIMPosting.ino)
// DHT 测试 + SIM800L 短信回复温度
// Written by ladyada, public domain (DHT 部分)
#include "DHT.h"
#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
#include
#include
#define TIMEOUT 5000
GPRS gprs;
bool ITemp = false;
float temp;
String MyString;
#define LED_PIN 13
bool ledStatus = false;
char currentLine[500] = "";
int currentLineIndex = 0;
bool nextLineIsMessage = false;
void Reply() {
Serial.println("GPRS - Send SMS Test ...");
gprs.preInit();
delay(1000);
while (0 != gprs.init()) {
delay(1000);
Serial.print("init error\r\n");
}
Serial.println("Init success, start to send SMS message...");
if (ITemp == true) {
float t = dht.readTemperature();
temp = t;
ITemp = false;
}
MyString = String(temp, 0);
MyString = (MyString + " Degrees C");
int str_len = MyString.length() + 1;
char char_array[str_len];
MyString.toCharArray(char_array, str_len);
gprs.sendSMS("04xxxxxxxx", char_array); // 修改为目标手机号
}
void setup() {
Serial.begin(9600);
Serial.println("DHTxx test!");
dht.begin();
gprs.preInit();
delay(1000);
while (0 != gprs.init()) {
delay(1000);
Serial.print("init error\r\n");
}
// 设置短信文本模式
if (0 != gprs.sendCmdAndWaitForResp("AT+CMGF=1\r\n", "OK", TIMEOUT)) {
Serial.println("ERROR: CMGF");
return;
}
// 开启新短信指示 (+CMT:)
if (0 != gprs.sendCmdAndWaitForResp("AT+CNMI=1,2,0,0,0\r\n", "OK", TIMEOUT)) {
Serial.println("ERROR: CNMI");
return;
}
Serial.println("Init success");
}
void loop() {
delay(2000);
// 定期读取温湿度 (串口监视器观察)
float h = dht.readHumidity();
float t = dht.readTemperature();
Serial.print("Humidity: "); Serial.print(h); Serial.println(" %");
Serial.print("Temperature: "); Serial.print(t); Serial.println(" *C");
SIM(); // 处理短信
}
void SIM() {
digitalWrite(LED_PIN, ledStatus);
Serial.println("Looking for SMS");
if (gprs.serialSIM800.available()) {
char lastCharRead = gprs.serialSIM800.read();
// 按行读取 (\r 或 \n 结束)
if (lastCharRead == '\r' || lastCharRead == '\n') {
String lastLine = String(currentLine);
// 检测到 +CMT: 新短信指示
if (lastLine.startsWith("+CMT:")) {
Serial.println(lastLine);
nextLineIsMessage = true;
}
// 读取短信内容行
else if (lastLine.length() > 0) {
if (nextLineIsMessage) {
Serial.println(lastLine);
// 解析指令
if (lastLine.indexOf("InTemp") >= 0) {
Serial.println("InTemp command received");
ITemp = true;
Reply();
}
// 可扩展其他指令
// else if (lastLine.indexOf("LED ON") >= 0) { ... }
nextLineIsMessage = false;
}
}
// 清空行缓冲
for (int i = 0; i < sizeof(currentLine); ++i) currentLine[i] = 0;
currentLineIndex = 0;
} else {
currentLine[currentLineIndex++] = lastCharRead;
}
}
}
关键技术点总结
- float 发送短信:
String(val, precision)→toCharArray()是通用模式 - 短信解析:AT+CNMI=1,2,0,0,0 使模块主动上报
+CMT:后跟内容行,按行状态机解析 - Mega 多串口优势:建议用 Serial1/2/3 直连 SIM800L,避免 SoftwareSerial 可靠性问题
- 供电设计:SIM800L 必须独立大电流电源,共地
参考资料
- SIM800L 快速入门
- DHT22 数据手册
- Seeeduino_GPRS 库:GitHub
- DHT 库:GitHub
原理图
制造工艺
- 温控风扇DIY:媒体柜散热的继电器驱动方案
- 树莓派+$5 I²C传感器打造温度记录仪
- 树莓派2上使用DS18B20读取温度完整指南
- 树莓派专业温度监测:基于 DS18B20 传感器的完整指南
- 树莓派结合 Maxim 1-Wire 传感器与 DS2482 I2C 桥接器的多点温度测量
- 树莓派精准监测机柜温度:DS18B20 多点部署实战
- IoT 入门教程:树莓派流式传输温度数据
- 树莓派构建网络化实验室气象站:温湿度气压实时监测
- 树莓派 + MCP9808 + InfluxDB + Grafana:家庭温度监测系统
- 树莓派 2 运行 Windows IoT Core 打造 Rover 机器人:从入门到进阶指南
- AuGe12 金锗软钎焊合金——高强度耐腐蚀密封材料
- 铼:超高密度金属丝与耐火应用的理想材料