一、环境介绍
单片机采用:STM32F103ZET6
上网方式:采用ESP8266,也可以使用其他设备代替,只要支持TCP协议即可。比如:GSM模块、有线网卡等。
与物联网云平台的通信协议: 标准MQTT协议3.1.1(TCP)
开发软件:keil5
物联网平台: 腾讯IOT物联网物联网平台。腾讯的物联网平台比起其他厂家的物联网平台更加有优势,腾讯物联网平台可以将数据推到微信小程序上,用户可以直接使用小程序绑定设备,完成与设备之间交互,现在用户基本都会使用微信,所以使用起来非常方便。
本项目完整代码下载地址: https://download.csdn.net/download/xiaolong1126626497/18973282
二、智慧农业介绍
智慧农业就是将物联网技术运用到传统农业中去,运用传感器和软件通过移动平台或者电脑平台对农业生产进行控制,使传统农业更具有“智慧”。除 了精准感知、控制与决策管理外,从广泛意义上讲,智慧农业还包括农业电子商务、食品溯源防伪、农业休闲旅游、农业信息服务等方面的内容。 所谓“智慧农业”就是充分应用现代信息技术成果,集成应用计算机与网络技术、物联网技术、音视频技术、3S技术、无线通信技术及专家智慧与知识,实现农业可视化远程诊断、远程控制、灾变预警等智能管理。
智慧农业是农业生产的高级阶段,是集新兴的互联网、移动互联网、云计算和物联网技术为一体,依托部署在农业生产现场的各种传感节点(环境温湿度、土壤水分、二氧化碳、图像等)和无线通信网络实现农业生产环境的智能感知、智能预警、智能决策、智能分析、专家在线指导,为农业生产提供精准化种植、可视化管理、智能化决策。 “智慧农业”是云计算、传感网、3S等多种信息技术在农业中综合、全面的应用,实现更完备的信息化基础支撑、更透彻的农业信息感知、更集中的数据资源、更广泛的互联互通、更深入的智能控制、更贴心的公众服务。“智慧农业”与现代生物技术、种植技术等科学技术融合于一体,对建设世界水平农业具有重要意义。
本项目采用STM32F103ZET6 ESP8266 设计一个智慧农业管理系统, 能够获取空气中的温湿度数据,光照度数据等,根据种植区的空气温湿度数据,判断是否进行灌溉;可以通过ESP8266 MQTT 协议将采集的温湿度、光照度上传至腾讯云物联网平台,并推送到微信小程序上实时查看;可以在小程序上直接控制电机抽水灌溉。
硬件详情介绍:
主控MCU: STM32F103ZET6
环境光传感器: BH1750
温湿度传感器: SHT30
本地OLED显示屏: 中景园电子0.96寸 SPI接口 OLED显示屏
电机: 微型直流电机
三、创建腾讯云物联网平台设备并配置微信小程序
如果之前从来没有使用过腾讯云物联网平台,创建的详细步骤请看这里: https://blog.csdn.net/xiaolong1126626497/article/details/116902653
下面就是登录腾讯云物联网平台,创建一个智慧农业的设备的关键步骤,有些细节步骤没写,细节请看上面链接这篇文章。
官网地址: https://console.cloud.tencent.com/iotexplorer
四、生成腾讯物联网平台的设备登录信息
使用MQTT协议登录需要一些参数信息,需要使用官网提供的方式生成。
Python示例代码:
代码语言:javascript复制#!/usr/bin/python
# -*- coding: UTF-8 -*-
import base64
import hashlib
import hmac
import random
import string
import time
import sys
# 生成指定长度的随机字符串
def RandomConnid(length):
return ''.join(random.choice(string.ascii_uppercase string.digits) for _ in range(length))
# 生成接入物联网通信平台需要的各参数
def IotHmac(productID, devicename, devicePsk):
# 1. 生成 connid 为一个随机字符串,方便后台定位问题
connid = RandomConnid(5)
# 2. 生成过期时间,表示签名的过期时间,从纪元1970年1月1日 00:00:00 UTC 时间至今秒数的 UTF8 字符串
expiry = int(time.time()) 30*24*60 * 60
# 3. 生成 MQTT 的 clientid 部分, 格式为 ${productid}${devicename}
clientid = "{}{}".format(productID, devicename)
# 4. 生成 MQTT 的 username 部分, 格式为 ${clientid};${sdkappid};${connid};${expiry}
username = "{};12010126;{};{}".format(clientid, connid, expiry)
# 5. 对 username 进行签名,生成token
secret_key = devicePsk.encode('utf-8') # convert to bytes
data_to_sign = username.encode('utf-8') # convert to bytes
secret_key = base64.b64decode(secret_key) # this is still bytes
token = hmac.new(secret_key, data_to_sign, digestmod=hashlib.sha256).hexdigest()
# 6. 根据物联网通信平台规则生成 password 字段
password = "{};{}".format(token, "hmacsha256")
return {
"clientid" : clientid,
"username" : username,
"password" : password
}
if __name__ == '__main__':
# 参数分别填入: 产品ID,设备名称,设备密匙
print(IotHmac("6142CX41XE", "SmartAgriculture","20Y/aAcmj y6SDDh ANR9g=="))
输出的登录参数,用于MQTT协议填参数:
代码语言:javascript复制{'clientid': '6142CX41XESmartAgriculture', 'username': '6142CX41XESmartAgriculture;12010126;HUA2G;1624271589',
'password': 'a8aadebe9721f70e6f9e14fe56ff1d2b5cac9625fa1f96af2f0e0098597fe78b;hmacsha256'}
五、使用MQTT软件测试
MQTT客户端软件下载地址: https://download.csdn.net/download/xiaolong1126626497/18784012
该软件采用QT开发,源码地址: https://blog.csdn.net/xiaolong1126626497/article/details/116779490
设备主题发布与定义的格式:
设备消息数据上传格式:
代码语言:javascript复制{"method":"report","clientToken":"123","params":{"light":78.4,"temperature":21.4,"humidity":60.8,"motor":1}}
登录成功之后,就可以看到设备在线:
打开微信小程序可以查看到设备上传的数据:
六、编写STM32设备端代码
6.1 main.c代码
代码语言:javascript复制#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "key.h"
#include "usart.h"
#include <string.h>
#include "timer.h"
#include "esp8266.h"
#include "mqtt.h"
#include "oled.h"
#include "fontdata.h"
#include "bh1750.h"
#include "iic.h"
#include "sht3x.h"
/*
硬件连接方式:
ESP8266串口WIFI模块与STM32的串口3相连接。
PB10--RXD 模块接收脚
PB11--TXD 模块发送脚
GND---GND 地
VCC---VCC 电源(3.3V~5.0V)
OLED接线:
D0----SCK-----PB14
D1----MOSI----PB13
RES—复位(低电平有效)—PB12
DC---数据和命令控制管脚—PB1
CS---片选引脚-----PA7
微型直流电机: PB8
紫光灯: PB9
LED硬件连接: PB5 PE5
KEY硬件连接:PE3 PE4
*/
#define ESP8266_WIFI_AP_SSID "CMCC-Cqvn" //将要连接的路由器名称 --不要出现中文、空格等特殊字符
#define ESP8266_AP_PASSWORD "99pu58cb" //将要连接的路由器密码
//腾讯物联网服务器的设备信息
#define MQTT_ClientID "6142CX41XESmartAgriculture"
#define MQTT_UserName "6142CX41XESmartAgriculture;12010126;HUA2G;1624271589"
#define MQTT_PassWord "a8aadebe9721f70e6f9e14fe56ff1d2b5cac9625fa1f96af2f0e0098597fe78b;hmacsha256"
//订阅与发布的主题
#define SET_TOPIC "$thing/down/property/6142CX41XE/SmartAgriculture" //订阅
#define POST_TOPIC "$thing/up/property/6142CX41XE/SmartAgriculture" //发布
char mqtt_message[200];//上报数据缓存区
char OLED_ShowBuff[100];
u8 ESP8266_Stat=0;
/*
函数功能: 温湿度光强度显示
*/
void ShowTemperatureAndHumidity(float temp,float humi,float light)
{
sprintf(OLED_ShowBuff,"T: %.2f",temp);
OLED_ShowString(40,16*0,16,OLED_ShowBuff);
sprintf(OLED_ShowBuff,"H: %.2f%%",humi);
OLED_ShowString(40,16*1,16,OLED_ShowBuff);
sprintf(OLED_ShowBuff,"L: %.2f%%",light);
OLED_ShowString(40,16*2,16,OLED_ShowBuff);
}
/*
函数功能: ESP8266显示页面
*/
void ESP8266_ShowPageTable(void)
{
if(ESP8266_Stat)OLED_ShowString(0,16*0,16,"WIFI STAT:ERROR");
else OLED_ShowString(0,16*0,16,"WIFI STAT:OK");
//显示字符串
sprintf((char*)OLED_ShowBuff,"%s",ESP8266_WIFI_AP_SSID);
OLED_ShowString(0,16*1,16,OLED_ShowBuff);
sprintf((char*)OLED_ShowBuff,"%s",ESP8266_AP_PASSWORD);
OLED_ShowString(0,16*2,16,OLED_ShowBuff);
}
int main()
{
u32 time_cnt=0;
u32 i;
u8 key;
u8 page=0;
float temp=0;
float humi=0;
float light=0;
u8 motor_state=0;
float Humidity;
float Temperature;
delay_ms(1000);
delay_ms(1000);
LED_Init();
KEY_Init();
IIC_Init();
//OLED初始化
OLED_Init(0xc8,0xa1); //OLED显示屏初始化--正常显示;
//清屏
OLED_Clear(0);
USART1_Init(115200);
TIMER1_Init(72,20000); //超时时间20ms
USART3_Init(115200);//串口-WIFI
TIMER3_Init(72,20000); //超时时间20ms
Init_SHT30();
USART1_Printf("正在初始化WIFI请稍等.n");
if(ESP8266_Init())
{
ESP8266_Stat=1;
USART1_Printf("ESP8266硬件检测错误.n");
}
else
{
//非加密端口
USART1_Printf("WIFI:%dn",ESP8266_STA_TCP_Client_Mode(ESP8266_WIFI_AP_SSID,ESP8266_AP_PASSWORD,"106.55.124.154",1883,1));
}
//2. MQTT协议初始化
MQTT_Init();
//3. 连接腾讯云IOT服务器
while(MQTT_Connect(MQTT_ClientID,MQTT_UserName,MQTT_PassWord))
{
USART1_Printf("服务器连接失败,正在重试...n");
delay_ms(500);
}
USART1_Printf("服务器连接成功.n");
//3. 订阅主题
if(MQTT_SubscribeTopic(SET_TOPIC,0,1))
{
USART1_Printf("主题订阅失败.n");
}
else
{
USART1_Printf("主题订阅成功.n");
}
while(1)
{
//按键可以测试开锁和关锁
key=KEY_Scan(0);
if(key==1)
{
//清屏
OLED_Clear(0);
//翻页
if(page>=1)
{
page=0;
}
else
{
page ;
}
LED1=!LED1; //LEd状态灯
}
else if(key==2)
{
LED1=!LED1; //LEd状态灯
time_cnt=0;
//电机状态改变
MOTOR_DEV=!MOTOR_DEV;
//电机状态
motor_state=MOTOR_DEV;
//补光灯
LIGHT_DEV=!LIGHT_DEV;
}
//微信小程序开锁方式: 接收WIFI返回的数据
if(USART3_RX_FLAG)
{
USART3_RX_BUFFER[USART3_RX_CNT]='