目标
制作一个ESP8266串口和MQTT相互透传的小WIFI,可用手机修改其连接的路由器,由此该模块可以任意加载到各种串口传输的单片机上,完成硬件到云端的传输。
1 实物图
2 MQTT网页测试客户端
链接:https://pan.baidu.com/s/1th4U0_nC3FOnvusPokYSGQ
提取码:j7fm
3 ESP8266硬件程序烧录代码
//----------------------------------------------------------------------------------------// //-----------------------------------程序功能-----------------------------------------// /* 总功能: 制作一个MQTT服务器和ESP8266串口互相传输消息的模块 如何使用: 1修改每个芯片的信息 1-1 修改每一个产品的ID 1-2 修改对应MQTT服务器配置信息 1-3 修改默认登陆WIFI的消息 2使用步骤 2-1 连接WIFI 上电前5S内 如果检测到超过2S的按键长按,进入配网模式,LED慢闪。配网成功后,自动记录WIFI的账号和密码。 如果没有检测到超过2S的按键动作,5s后自动进入连接WIFi模式,,LED快闪,连接上次记录的WIFI。 2-2 连接MQTT服务器 连接不成功,5S后重连。 连接成功,等待服务器发送过来消息,或者将自己的串口收到的消息发送给MQTT服务器 2-3 按键功能预留 按下按键,led亮 离开按键,led灭 */ //----------------------------------------------------------------------------------------// #include <ESP8266WiFi.h> #include <PubSubClient.h> #include <math.h> #include <EEPROM.h> WiFiClient espClient; PubSubClient client(espClient); //----------------------------------------------------------------------------------------// //-----------------------------------配置信息开始-----------------------------------------// //----------------------------------------------------------------------------------------// // 产品唯一ID 微信分配 #define PRODUCT_ID "gh_e93c1b3098b9_cc8c4f4cd693972f" // 默认连接WIFI账号密码 #define DEFAULT_STASSID "dongdong"//默认连接的路由器的名字 HUAWEI-H3VBKZ #define DEFAULT_STAPSW "dongdong"//默认连接的路由器的名字 13991320168 //通信服务器消息 #define MQTT_SEVER "www.dongvdong.top" #define MQTT_PORT 1883 #define MQTT_USER "dongdong" #define MQTT_PASS "dongdong" #define MQTT_ID PRODUCT_ID // 使用产品ID充当服务器识别ID #define MQTT_PUB_TOPIC PRODUCT_ID"/s" // 发布话题 产品ID+/s #define MQTT_REC_TOPIC PRODUCT_ID"/r" // 接受话题 产品ID+/r // led状态反转 bool ledState=0; // 配网 #define Smart_KEY D2 //配网按键 #define Smart_LED D4 //配网LED指示灯 //led控制按键中断 #define Use_LED D4 //控制LED #define Use_KEY D2 //控制LED的按键 //-----------------------------------配置信息结束-----------------------------------------// #define MAGIC_NUMBER 0xAA struct config_type { char stassid[32]; char stapsw[64]; uint8_t magic; }; config_type config; char sendmsg[100];// 发送话题 /***************************(1.1)按键LED函数()*****************************/ // LED管脚口初始化 void LED_begin(){ pinMode(Use_LED,OUTPUT); digitalWrite(Use_LED, LOW); pinMode(Use_KEY, INPUT); detachInterrupt(Use_KEY); attachInterrupt(Use_KEY, highInterrupt, RISING); } // 高电平触发 void highInterrupt(){ digitalWrite(Use_LED, LOW); detachInterrupt(Use_KEY); attachInterrupt(Use_KEY, lowInterrupt,FALLING); } // 低电平触发 void lowInterrupt(){ digitalWrite(Use_LED, HIGH); detachInterrupt(Use_KEY); attachInterrupt(Use_KEY, highInterrupt, RISING); } /**************************************************************/ /*************************(2) WIFI连接设置 *************************************/ /* 1连接WIFI 自动连WIFI接入网络*/ void setup_wifi() { WiFi.begin(config.stassid, config.stapsw); while (WiFi.status() != WL_CONNECTED) { ESP.wdtFeed(); delay(200); ledState = !ledState; digitalWrite(Smart_LED, ledState); Serial.print("..."); } Serial.println("\r\n--------------WIFi CONNECT!-------------\r\n"); Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str()); Serial.printf("PSW:%s\r\n", WiFi.psk().c_str()); } /**************************************************************************/ /*************************(3) 服务器连接设置 *************************************/ /* 2连接服务器 等待,直到连接上服务器*/ void reconnect() {//等待,直到连接上服务器 while (!client.connected()) {//如果没有连接上 Serial.println("Connect lost!");//连接失败 if (client.connect(MQTT_ID+random(999999999),MQTT_USER,MQTT_PASS)) {//接入时的用户名,尽量取一个很不常用的用户名 client.subscribe(MQTT_REC_TOPIC);//接收外来的数据时的intopic client.publish(MQTT_PUB_TOPIC,"hello world "); Serial.println("Connect sever succes!");//连接失败 } else { Serial.println("failed, rc=");//连接失败 Serial.print(client.state());//重新连接 Serial.println(" try again in 5 seconds");//延时5秒后重新连接 delay(5000); } } } void callback(char* topic, byte* payload, unsigned int length) {//用于接收数据 char recmsg[length+1]; for (int i = length-1; i >=0; i--) { recmsg[i]=(char)payload[i]; } recmsg[length]='\0'; Serial.println(recmsg); // String str(recmsg); // char 转换String } /**************************************************************************/ /*************************(4) smartConfig配置 *************************************/ void smartConfig() { Serial.println("Start smartConfig module"); pinMode(Smart_LED, OUTPUT); digitalWrite(Smart_LED, 0); WiFi.mode(WIFI_STA); Serial.println("\r\nWait for Smartconfig"); WiFi.stopSmartConfig(); WiFi.beginSmartConfig(); while (1) { Serial.print("."); digitalWrite(Smart_LED, 0); delay(500); digitalWrite(Smart_LED, 1); delay(500); if (WiFi.smartConfigDone()) { Serial.println("SmartConfig Success"); strcpy(config.stassid, WiFi.SSID().c_str()); strcpy(config.stapsw, WiFi.psk().c_str()); Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str()); Serial.printf("PSW:%s\r\n", WiFi.psk().c_str()); saveConfig(); break; } } } /**************************************************************************/ /*******************************5 保存信息**************************************/ /* * 保存参数到EEPROM */ void saveConfig() { Serial.println("Save config!"); Serial.print("stassid:"); Serial.println(config.stassid); Serial.print("stapsw:"); Serial.println(config.stapsw); EEPROM.begin(1024); uint8_t *p = (uint8_t*)(&config); for (int i = 0; i < sizeof(config); i++) { EEPROM.write(i, *(p + i)); } EEPROM.commit(); } /* * 从EEPROM加载参数 */ void loadConfig() { EEPROM.begin(1024); uint8_t *p = (uint8_t*)(&config); for (int i = 0; i < sizeof(config); i++) { *(p + i) = EEPROM.read(i); } EEPROM.commit(); //出厂自带 if (config.magic != MAGIC_NUMBER) { strcpy(config.stassid, DEFAULT_STASSID); strcpy(config.stapsw, DEFAULT_STAPSW); config.magic = MAGIC_NUMBER; saveConfig(); Serial.println("Restore config!"); } Serial.println(" "); Serial.println("-----Read config-----"); Serial.print("stassid:"); Serial.println(config.stassid); Serial.print("stapsw:"); Serial.println(config.stapsw); Serial.println("-------------------"); } void waitKey() { pinMode (Smart_LED, OUTPUT); pinMode (Smart_KEY, INPUT); digitalWrite(Smart_LED, 0); Serial.println(" press key 2s: smartconfig mode! \r\n press key <2s: connect wifi!"); char keyCnt = 0; unsigned long preTick = millis(); unsigned long preTick2 = millis(); int num = 0; while (1) { ESP.wdtFeed(); if (millis() - preTick < 10 ) continue;//等待10ms preTick = millis(); num++; if (num % 20 == 0) //50*10=500ms=0.5s 反转一次 { ledState = !ledState; digitalWrite(Smart_LED, ledState); // delay(1); Serial.print("."); } if (keyCnt >= 200 && digitalRead(Smart_KEY) == 1) { //按2S 进入一键配置 keyCnt = 0; Serial.println("\r\n try to begin smartConfig! \r\n"); smartConfig();// 手机灵活设置WIFI break; } // 不按按键,自动连接上传WIFI if (millis() - preTick2 > 5 * 1000) { Serial.println("\r\n try to connect wifi! \r\n"); setup_wifi(); break; } if (digitalRead(Smart_KEY) == 1){ keyCnt++;} else{keyCnt = 0;} } digitalWrite(Smart_LED, 0); pinMode (Smart_KEY, OUTPUT); } /**************************************************************************/ void serial_mqtt_sendmsg(){ //-------------------Begin----------------------// //功能: 通过串口给MQTT服务器发送数据 if(Serial.available()>0){ delay(100); String comdata = Serial.readString(); Serial.print("Serial.readString:"); //从串口缓存区中读取的整个字符串,直至检测到终止字符。 // char terminator = ','; // String comdata =Serial.readStringUntil(terminator); // Serial.print("Serial.readStringUntil: "); Serial.println(comdata); while(Serial.read()>= 0){} char charBuf[100]; comdata.toCharArray(charBuf, 100) ; client.publish(MQTT_PUB_TOPIC,charBuf); comdata = ""; } //-------------------End----------------------// } //初始化函数 void setup() {//初始化程序,只运行一遍 Serial.begin(9600);//设置串口波特率(与烧写用波特率不是一个概念) loadConfig();// 读取信息 waitKey(); delay(5000); client.setServer(MQTT_SEVER, MQTT_PORT);//端口号 client.setCallback(callback); //用于接收服务器接收的数据 LED_begin();//设置LED模式 } // 循环主函数 void loop() {//主循环 if(WiFi.status() == WL_CONNECTED){ // 初始化连接 reconnect();//确保连上服务器,否则一直等待。 // 订阅话题等待 client.loop();//MUC接收数据的主循环函数。 // 将串口数据发送给服务器 serial_mqtt_sendmsg(); } else { Serial.println("wifi fail!"); setup_wifi() ; } }