【Arduino和高中通用技术】——十、一个简单的环境监测

本文详细介绍了一个基于Arduino Uno、多种传感器及ESP8266模块的环境监测系统搭建过程。系统可检测温湿度、火焰和可燃气体,并通过ESP8266将数据上传至乐为网。文章提供了传感器连接指导、程序代码解析及AT命令控制ESP8266的具体实现。

        有几天没写了,这次写一个完整的例子——环境监测。它包含温湿度、火焰、可燃气体检测,并发送数据到乐为网。乐为网用起来比OneNet(中国移动物联网平台)要简单很多,只是很多功能是收费的,但是不用自己开发APP只需关注公众号就可以接收到消息,图简单玩玩体验一下可以尝试。

一、硬件

1、Arduino Uno(如果你要连接很多传感器或者以后还会扩展那么应该选择Mega2560)

2、DHT11(DHT22要准确一些,价格也能接受,两者使用完全一样)

3、火焰传感器

4、可燃气体传感器(我的是MQ9)

5、Esp8266模块(这里用的是AT命令操作比较麻烦)

6、杜邦线、面包板

二、编写程序

       这些传感器使用都非常简单,基本都是一根线就可以了。DHT11使用的是DHT库,关于单总线通讯原理可以自行百度一下。火焰和可燃气体传感器都是读取模拟电压——analogRead即可。

       简单的解释一下程序中的一些代码:

void upDate() {
	ehPost.infos[0].Value =0;
	ehPost.infos[1].Value = 0;
	ehPost.infos[2].Value = 0;
	ehPost.infos[3].Value = 0;
	for (int i = 0; i < buffLen;i++) {
		ehPost.infos[0].Value += dtBuff[i];
		ehPost.infos[1].Value += dhBuff[i];
		ehPost.infos[2].Value += flBuff[i];
		ehPost.infos[3].Value += mqBuff[i];
	}
	ehPost.infos[0].Value /= buffLen;
	ehPost.infos[1].Value /= buffLen;
	ehPost.infos[2].Value /= buffLen;
	ehPost.infos[3].Value /= buffLen;
}

该函数用于更新传感器数据,我们知道传感器的数据是有一定的波动的,有时候可能瞬间变为不平滑的曲线,这主要来源于传感器自身、连接线的稳固、供电是否稳定以及是否有强电磁扰动等一些原因。哪怕对于这样简单的工程也要仔细考虑电路的排布,供电的稳定性。消除这些扰动的方法有很多,这里进行了简单的取平均。可以用其他的一些平滑方法,例如缓存数组保存前10秒和后5秒的内容(程序10秒上传一次)——当缓存数组指针达到数组末尾时回到第一个元素。

        代码中使用的其他方法都没有太多需要解释的地方,EEPROM部分之前介绍过,所以就不重复。接下来关注一下使用AT命令来控制ESP8266上传数据到乐为物联:

// 
// 
// 

#include "ESP8266SoftwareSerialHTTPPOST.h"
SoftwareSerial wifi_SoftSerial(rxPin, txPin);

ESP8266SoftwareSerialHTTPPOST::ESP8266SoftwareSerialHTTPPOST()
{
		wifi_SoftSerial.begin(9600);
}

int ESP8266SoftwareSerialHTTPPOST::initESP8266()
{
	int errcnt = 0;
	if (!doATCommand(F("AT+CIPMODE=1"), deftStr, deffStr, 10)) { errcnt++; }
	if (!doATCommand(F("AT+RST"), deftStr, deffStr, 100)) { errcnt++; }
	if (!doATCommand(F("AT+CIPMUX=0"), deftStr, deffStr, 10)) { errcnt++; }
	if (!doATCommand(F("AT+CWMODE=1"), deftStr, deffStr, 10)) { errcnt++; }
	return errcnt;
}

bool ESP8266SoftwareSerialHTTPPOST::initWifi()
{
	//测试Wifi连接
	if (!doATCommand(F("AT+CWJAP?"),wifi_ssid, F("No AP"),100)) {
		//连接到WIFI
		if (!doATCommand("AT+CWJAP=\"" + wifi_ssid + "\",\"" + wifi_password + "\"", deftStr,deffStr,10000)) {
			Serial.println(F("AT+CWJAP:ERROR:"));
			Serial.println(resultLine);
			return false;
		}
	}
	return true;
}

bool ESP8266SoftwareSerialHTTPPOST::httpPost()
{
	bool result = true;
	//连接服务器
	result = doATCommand("AT+CIPSTART=\"TCP\",\"" + HostAddress + "\"," + HostPort, deftStr, deffStr, 1000);
	if (!result) {
		Serial.println(F("AT+CIPSTART:ERROR:"));
		Serial.println(resultLine);
		return false;
	}
	/*
	POST /api/V1/gateway/Updatesensors/01 HTTP/1.1
	userkey:000009999778878979789
	Host:www.lewei50.com
	Content-Length:30

	[{"Name":"H1","Value":"22"}]
	*/
	String curData = mathData();
	//Post数据
	result = postString("POST " + HostApiPath + " HTTP/1.1" );

	if (result) {
		result = postString("userkey:" + UserKey );
	}
	if (result) {
		result = postString("Host: " + HostAddress );
	}
	if (result) {
		result = postString("Content-Length:" + (String)curData.length());
	}
	if (result) {
		result = postString("");
	}
	if (result ) {
		result = postString(curData);
	}
	curData = "";
	//退出透传
	doATCommand(F("+++"), deftStr, deffStr, 20);

	//关闭TCP/UDP连接
	doATCommand(F("AT+CIPCLOSE"), deftStr, deffStr, 20);

	return result;
}

bool ESP8266SoftwareSerialHTTPPOST::doATCommand(String cmd, String tStr, String fStr, unsigned long outTime)
{
	unsigned long LastTime = 0UL;			//过去的时间
	unsigned long StartTime;				//开始时间
	int result = -1;
	//发送命令
	wifi_SoftSerial.println(cmd);
	//等待数据返回
	while (result==-1)
	{
		StartTime = micros();
		if (wifi_SoftSerial.available()>0) {
			while (wifi_SoftSerial.available()>0)
			{
				resultLine = wifi_SoftSerial.readStringUntil('\n') + '\n';
				//Serial.print(resultLine);
				if (resultLine.lastIndexOf(tStr)>-1) {
					result = 0;
				}
				if (resultLine.lastIndexOf(fStr)>-1) {
					result = 1;
				}
			}
		}
		LastTime += micros()-StartTime;				//增加经过的时间
		if (LastTime > outTime*1000) {
			break;
		}
	}
	delay(100);
	return result == 0;
}

String ESP8266SoftwareSerialHTTPPOST::mathData()
{
	String curData = "[";
	int count = sizeof(infos) / sizeof(infos[0]);
	for (int i = 0; i<count; i++)
	{
		curData += "{\"Name\":\"" + (String)infos[i].Name + "\",\"Value\":\"" + (String)infos[i].Value + "\"},";
	}
	curData[curData.length()-1]= ']';
	return curData;
}

bool ESP8266SoftwareSerialHTTPPOST::postString(String line)
{
	if (doATCommand("AT+CIPSEND=" + (String)(line.length()+2), ">", deffStr, 1000)) {
		if (doATCommand(line, F("SEND OK"), F("FAIL"), 1000)) {
			return true;
		}
		else {
			Serial.println(F("Send:err"));
			Serial.println(resultLine);
		}
	}
	else {
		Serial.println("Post:ERROR" + Crlf + line + Crlf + line.length());
		Serial.println(resultLine);
	}
	return false;
}

这部分代码相对长一些,最好对照AT命令表来进行查看。首先,我们进入透传模式,所谓的透传就是我们发送给ESP8266什么内容,ESP8266就发送什么内容给服务器。而后进行身份验证、上传数据、等待返回、退出透传并关闭连接。整个过程中会遇到非常多的问题,例如数据包走丢了、服务器睡着了、ESP8266帕金森了……所以我们需要处理超时,这非常重要在DoCommand函数中我们进行计时,如果超时那么就返回失败,否则很可能程序不知道跑了几分钟就翘辫子。

 

下面附上完整的程序代码,传感器和ESP8266连接都非常简单,自行百度教程很多。

https://download.youkuaiyun.com/download/zcsor/11014886

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清晨曦月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值