最近几年物联网技术越来越火,身边不少朋友都在玩智能家居。作为一个嵌入式开发老鸟,我觉得用STC89c51和ESP8266搭建环境监测系统是个不错的入门项目。这个组合成本低、上手快,特别适合刚接触物联网的新手。
STC89c51是经典的51单片机,价格只要几块钱一片,开发环境简单,资料丰富。我十年前学单片机就是从它开始的。ESP8266则是性价比超高的WiFi模块,自带TCP/IP协议栈,能直接连接路由器上网。这两个加起来成本不超过30元,比买现成的物联网开发板划算多了。
传感器方面,DHT11温湿度传感器是最常见的选择,价格便宜精度够用。如果想测空气质量,可以加个MQ-135气体传感器。光照强度可以用光敏电阻,土壤湿度用土壤湿度传感器。这些传感器在淘宝都能轻松买到,单价基本都在10元以内。
STC89c51和ESP8266的连接很简单,主要注意三点:第一,电平匹配。ESP8266是3.3V器件,而STC89c51是5V的,直接连接可能会烧坏模块。我建议在TX、RX线上加个电平转换电路,用两个1k电阻分压就行。第二,供电要稳。ESP8266工作时电流可能达到200mA,最好单独用AMS1117稳压芯片给它供电。第三,记得把ESP8266的EN脚接高电平。
具体接线如下:
DHT11温湿度传感器只需要一个IO口,我一般接在P2.0。MQ-135气体传感器是模拟输出的,接在P1.0(ADC0)。光敏电阻可以用电阻分压电路接到P1.1。如果还要接其他传感器,建议先画个接线图,避免后面搞混。
这里有个小技巧:所有传感器的电源最好都通过MOS管控制,需要采集数据时才通电。这样可以降低整体功耗,对电池供电的系统特别有用。我用的是SI2302 MOS管,用P2.7控制通断。
开发STC89c51程序推荐用Keil C51,虽然界面老了点但很稳定。安装完记得去STC官网下载最新的器件支持包,不然可能找不到STC89c51的型号。我用的版本是Keil uVision5,配合STC-ISP下载程序。
新建工程时要注意几点:
ESP8266出厂一般自带AT固件,但最好刷个新版本。我推荐用安信可的一键烧录工具,刷他们优化过的AT固件。刷完后先用串口助手测试下基本功能:
bash复制AT
AT+CWMODE=1
AT+CWJAP="你的WiFi名","密码"
如果返回OK说明模块工作正常。记得把波特率设为9600,和程序里保持一致。有些模块默认是115200,需要先发AT+UART=9600,8,1,0,0命令修改。
DHT11的时序要求比较严格,我写了个稳定的读取函数:
c复制void DHT11_Read() {
unsigned char i, j;
P2_0 = 0; // 拉低总线
delay_ms(18); // 保持至少18ms
P2_0 = 1; // 释放总线
delay_us(30); // 等待20-40us
if(!P2_0) { // DHT11响应
while(!P2_0); // 等待80us低电平
while(P2_0); // 等待80us高电平
for(j=0; j<5; j++) {
for(i=0; i<8; i++) {
while(!P2_0); // 等待50us低电平
delay_us(30); // 判断高电平持续时间
if(P2_0) {
dat[j] |= (1<<(7-i));
while(P2_0);
}
}
}
}
}
这个函数会把温湿度数据保存在dat数组里。注意DHT11每次读取间隔要大于1秒,不然可能出错。
对于MQ-135这类模拟传感器,需要用ADC读取电压值。STC89c51没有内置ADC,我用了PCF8591模块。读取代码很简单:
c复制unsigned char Read_ADC(unsigned char ch) {
I2C_Start();
I2C_Write(0x90); // PCF8591地址
I2C_Write(0x40|ch); // 控制字
I2C_Start();
I2C_Write(0x91); // 读模式
dat = I2C_Read(0); // 读取数据
I2C_Stop();
return dat;
}
读回来的值需要根据传感器特性做线性化处理。比如MQ-135的空气质量检测,通常要查表换算成ppm值。
通过串口发送AT指令控制ESP8266连接服务器。我封装了几个常用函数:
c复制void ESP8266_SendCmd(char *cmd) {
UART_SendString(cmd);
delay_ms(500);
}
void Connect_Server() {
ESP8266_SendCmd("AT+CIPSTART=\"TCP\",\"api.bemfa.com\",80\r\n");
ESP8266_SendCmd("AT+CIPSEND\r\n");
}
实际项目中要做好错误处理,比如WiFi断开重连、服务器连接超时等。我一般会设置3次重试机制。
数据上传采用HTTP POST方式,格式要符合规范。关键代码如下:
c复制void Post_Data() {
char post[150];
sprintf(post,"uid=你的UID&topic=你的主题&msg=#%d#%d#%d#\r\n",
temperature,humidity,air_quality);
ESP8266_SendCmd("POST /api/device/v1/data/1/ HTTP/1.1\r\n");
ESP8266_SendCmd("Host: api.bemfa.com\r\n");
ESP8266_SendCmd("Content-Type: application/x-www-form-urlencoded\r\n");
ESP8266_SendCmd("Connection:close\r\n");
ESP8266_SendCmd("Content-Length:");
sprintf(post,"%d\r\n\r\n",strlen(post));
ESP8266_SendCmd(post);
}
数据中的#号是分隔符,后面做APP解析时会用到。建议上传频率不要太高,5-10秒一次就够了,避免服务器压力过大。
APP Inventor是MIT开发的图形化编程工具,特别适合做物联网展示端。我建议先在电脑上装个AI伴侣APP,这样调试起来更方便。
新建项目时要注意:
收到服务器推送的数据后,需要按#号分割字符串:
blocks复制when Web1.GotText
set temp to split(Web1.ResponseText,"#")
set Label1.Text to join(list item 1 of temp,"℃")
set Label2.Text to join(list item 2 of temp,"%")
界面设计可以自由发挥,我通常会把实时数据放在上半部分,下半部分加个折线图显示历史趋势。APP Inventor的图表组件功能有限,如果要做复杂展示可以考虑用第三方库。
如果想用电池供电,有几个省电方法:
实测下来,优化后平均电流可以从50mA降到5mA左右,两节18650能用一个月。
最常遇到的问题是ESP8266连接不稳定,我的经验是:
另一个常见问题是数据上传失败,通常是服务器响应超时。可以增加以下处理: