零基础入门学用物联网(ESP8266) 第一部分 基础知识篇(六)

参考教程:https://www.bilibili.com/video/BV1L7411c7jw/?spm_id_from=333.1387.favlist.content.click

十、ESP8266应用技巧

1、ESP8266自动配网------WiFiManager库使用说明

(1)在开发物联网项目时,经常需要为ESP8266设置Wi-Fi,在以往的章节例程里,设置Wi-Fi的方法是通过修改程序中的内容来实现的,但是假如这是一个面向用户的产品,用户拿到产品后不可能通过修改程序设置Wi-Fi,因此需要有一个Wi-Fi配置流程,即使是不懂编程的用户,也能为产品设置Wi-Fi。

(2)以下是理想的Wi-Fi配置流程,为了实现该流程,可借助ESP8266的一个第三方库------WiFiManager库。

(3)Wi-Fi配置示例程序:

①预备程序:清理ESP8266储存的Wi-Fi连接信息。

ESP8266的Wi-Fi设置是储存在它的闪存系统中的,因此在启动ESP8266并连接Wi-Fi时,它都会尝试使用闪存系统中储存的信息来进行Wi-Fi连接

在开始介绍如何使用WiFiManager库来配置ESP8266的Wi-Fi设置前,首先需要清除ESP8266的Wi-Fi连接信息,这样才能看到WiFiManager库的工作效果,而WiFiManager类的resetSettings函数即可实现清除功能

运行以下示例程序,可以清除ESP8266的闪存中存储的Wi-Fi连接信息

cpp 复制代码
#include <ESP8266WiFi.h>          
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>         
void setup() {
  Serial.begin(9600);       
  WiFiManager wifiManager;  // 建立WiFiManager对象
  wifiManager.resetSettings(); // 清除ESP8266所存储的WiFi连接信息
  Serial.println("ESP8266 WiFi Settings Cleared");
}
void loop() {}

②示例程序:

创建WiFiManager类后,直接调用其成员函数autoConnect,就能实现ESP8266理想的Wi-Fi配置流程

autoConnect函数有两种重载形式:如果希望启动AP模式构建的Wi-Fi网络无密码,则函数参数只有一个,为Wi-Fi网络名字符串;如果希望启动AP模式构建的Wi-Fi网络有密码,则函数参数有两个,依次为Wi-Fi网络名字符串、Wi-Fi网络密码字符串

cpp 复制代码
#include <ESP8266WiFi.h>          
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>         
void setup() {
    Serial.begin(9600);       
    WiFiManager wifiManager;  // 建立WiFiManager对象
    // 自动连接Wi-Fi,如果连接不上,启动AP模式,Wi-Fi网络名为"AutoConnectAP"
    wifiManager.autoConnect("AutoConnectAP");
    // 如果希望启动AP模式构建的Wi-Fi网络带有密码,则可使用以下语句
    // wifiManager.autoConnect("AutoConnectAP", "00114514");
    
    // WiFi连接成功后将通过串口监视器输出连接成功信息 
    Serial.println(""); 
    Serial.print("ESP8266 Connected to "); Serial.println(WiFi.SSID());
    Serial.print("IP address:\t"); Serial.println(WiFi.localIP());
}
void loop() {}

2、ESP8266多任务处理------Ticker库使用说明

(1)ESP8266在运行过程中,只能一条线式的依次执行任务,但是在开发物联网项目时,可能需要ESP8266在执行某一任务的过程中,还能处理其它任务,比如使用ESP8266来控制电机运行的同时,还需要定时检查某一个引脚上连接按钮有没有被用户按下。为了解决以上问题,可以使用Ticker库(如果有《操作系统》的前置知识储备,以下介绍会更容易理解)。

(2)Ticker类提供了以下几个成员函数:

①attach函数:该函数用于创建任务,并设置其运行周期,需要注意一个Ticker对象只能对应创建一个任务,要想创建多个任务,需要先创建多个Ticker对象。

第一种重载形式有两个函数参数,第一个参数指定调用函数的时间间隔,单位为秒,第二个参数指定调用函数(无参函数)的函数名

第二种重载形式有三个函数参数,第一个参数指定调用函数的时间间隔,单位为秒,第二个参数指定调用函数的函数名,第三个参数是传递给调用函数的参数值(最多有一个,且数据类型局限于char、short、int、float、void*、char*)

②attach_ms函数:该函数用于创建任务,并设置其运行周期,需要注意一个Ticker对象只能对应创建一个任务,要想创建多个任务,需要先创建多个Ticker对象。

第一种重载形式有两个函数参数,第一个参数指定调用函数的时间间隔,单位为毫秒,第二个参数指定调用函数(无参函数)的函数名

第二种重载形式有三个函数参数,第一个参数指定调用函数的时间间隔,单位为毫秒,第二个参数指定调用函数的函数名,第三个参数是传递给调用函数的参数值(最多有一个,且数据类型局限于char、short、int、float、void*、char*)

③detach函数:该函数用于停止其对应的任务被调度运行,该函数无参数。

(3)基本操作示例:

①示例1:

1\]任务调度示意图: ![](https://i-blog.csdnimg.cn/direct/9f3d8acecdc246189fa77d8e791b67e0.png) \[2\]程序代码: ```cpp #include Ticker ticker;// 建立Ticker用于实现定时功能 int count; // 计数用变量 void setup() { Serial.begin(9600); pinMode(LED_BUILTIN, OUTPUT); ticker.attach(1, sayHi); } void loop() { // 用LED呼吸灯效果来演示,在Tinker对象控制下,ESP8266可以定时执行其它任务 for (int fadeValue = 0 ; fadeValue <= 1023; fadeValue += 5) { analogWrite(LED_BUILTIN, fadeValue); delay(10); } for (int fadeValue = 1023 ; fadeValue >= 0; fadeValue -= 5) { analogWrite(LED_BUILTIN, fadeValue); delay(10); } delay(3000); } // 在Tinker对象控制下,此函数将会定时执行 void sayHi(){ count++; Serial.print("Hi "); Serial.println(count); } ``` ②示例2: \[1\]任务调度示意图: ![](https://i-blog.csdnimg.cn/direct/3b7bb38aaea44a6c94b9fc3c94f07e45.png) \[2\]程序代码: ```cpp #include Ticker ticker;// 建立Ticker用于实现定时功能 int count; // 计数用变量 void setup() { Serial.begin(9600); pinMode(LED_BUILTIN, OUTPUT); ticker.attach(1, sayHi); } void loop() { // 用LED呼吸灯效果来演示,在Tinker对象控制下,ESP8266可以定时执行其它任务 for (int fadeValue = 0 ; fadeValue <= 1023; fadeValue += 5) { analogWrite(LED_BUILTIN, fadeValue); delay(10); } for (int fadeValue = 1023 ; fadeValue >= 0; fadeValue -= 5) { analogWrite(LED_BUILTIN, fadeValue); delay(10); } delay(3000); } // 在Tinker对象控制下,此函数将会定时执行 void sayHi(){ count++; Serial.print("Hi "); Serial.println(count); // 当定时调用了6次后,停止定时调用函数 if (count >= 6) { ticker.detach(); // 使用detach来停止ticker对象定时调用函数 Serial.print("ticker.detach()"); } } ``` ③示例3: \[1\]任务调度示意图: ![](https://i-blog.csdnimg.cn/direct/06e7fa3ae91c474498ececc841c9dec4.png) \[2\]程序代码: ```cpp #include Ticker ticker; int count; void setup() { Serial.begin(9600); pinMode(LED_BUILTIN, OUTPUT); ticker.attach(1, sayHi, 8); } void loop() { for (int fadeValue = 0 ; fadeValue <= 1023; fadeValue += 5) { analogWrite(LED_BUILTIN, fadeValue); delay(10); } for (int fadeValue = 1023 ; fadeValue >= 0; fadeValue -= 5) { analogWrite(LED_BUILTIN, fadeValue); delay(10); } delay(3000); } void sayHi(int hiTimes){ count++; Serial.print("Hi "); Serial.println(count); if (count >= hiTimes) { ticker.detach(); Serial.print("ticker.detach();"); } } ``` ④示例4: \[1\]任务调度示意图: ![](https://i-blog.csdnimg.cn/direct/ff28a3c4091d48baa5b23b98dec5828f.png) \[2\]程序代码: ```cpp #include Ticker ticker; Ticker buttonTicker; int count; void setup() { Serial.begin(9600); pinMode(LED_BUILTIN, OUTPUT); pinMode(D3, INPUT_PULLUP); ticker.attach(1, sayHi, 60); buttonTicker.attach_ms(100, buttonCheck); } void loop() { for (int fadeValue = 0 ; fadeValue <= 1023; fadeValue += 5) { analogWrite(LED_BUILTIN, fadeValue); delay(10); } for (int fadeValue = 1023 ; fadeValue >= 0; fadeValue -= 5) { analogWrite(LED_BUILTIN, fadeValue); delay(10); } delay(3000); } void sayHi(int hiTimes){ count++; Serial.print("Hi "); Serial.println(count); if (count >= hiTimes) { ticker.detach(); Serial.print("ticker.detach();"); } } void buttonCheck(){ if (digitalRead(D3) == LOW){ Serial.println("D3 Button Pushed..."); } } ``` (3)Ticker定时调用的函数必须要"短小精悍",简单来说就是不能消耗过多CPU资源,执行时间不能太长,否则可能引发难以预料的问题,那么假如需要ESP8266定时执行的操作较为复杂,就不能直接将该操作封装为Ticker定时调用的函数了,而是应该"另辟蹊径",可以在Ticker类定时调用的函数中增加计数逻辑,当计数值达到一定值时,意味着间隔时间到达一定值,主程序可以根据这个计数值调用需要定时执行的复杂操作,如下所示的示例程序正是运用了这种思想。 ```cpp #include #include #include #define URL "http://www.example.com" const char* ssid = "Zevalin_Computer"; const char* password = "00114514"; Ticker ticker; int count; void setup() { Serial.begin(9600); WiFi.mode(WIFI_STA); connectWifi(); ticker.attach(1, tickerCount); //每隔1s执行一次tickerCount函数 } void loop() { if (count >= 5){ //计数值达到5,说明已经间隔5s httpRequest(); //执行复杂的操作 count = 0; //计数值清零,准备下一次计时 } } void tickerCount(){ count++; //执行一次tickerCount函数,计数值加1 Serial.print("count = "); Serial.println(count); } void httpRequest(){ HTTPClient httpClient; httpClient.begin(URL); Serial.print("URL: "); Serial.println(URL); int httpCode = httpClient.GET(); Serial.print("Send GET request to URL: "); Serial.println(URL); if (httpCode == HTTP_CODE_OK) { String responsePayload = httpClient.getString(); Serial.println("Server Response Payload: "); Serial.println(responsePayload); } else { Serial.println("Server Respose Code:"); Serial.println(httpCode); } httpClient.end(); } void connectWifi(){ WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println(""); Serial.print("WiFi Connected!"); } ```

相关推荐
咸鱼不用加盐11 小时前
HC32F460 USB CDC通信异常:非对齐访问异常排查
单片机·arm·c·cm4
EVERSPIN14 小时前
低功耗MCU对TWS充电仓的驱动控制
单片机·嵌入式硬件·mcu·低功耗mcu
没 名 字15 小时前
电源--辅助电源电路
单片机·嵌入式硬件
北京耐用通信16 小时前
耐达讯自动化CAN转EtherCAT网关:3步配置,赋能电机启动器智能化升级
人工智能·物联网·网络协议·自动化·信息与通信
CinzWS18 小时前
I2C协议 - 优雅的代价:深入开漏总线、时钟延展与多主仲裁的脆弱平衡
嵌入式·i2c
西城微科方案开发18 小时前
高速低功耗增强型8位单片机——HC89F0531 SSOP24
单片机·嵌入式硬件
电商API&Tina19 小时前
1688 拍立淘接口(item_search_img)测试与接入实战心得
java·大数据·前端·物联网·oracle·json
EdmundXjs19 小时前
flashrom v1.5.1 Windows
windows·stm32·单片机
河南博为智能科技有限公司19 小时前
边缘计算物联网关丨配电站房区域集中边缘计算解决方案!
人工智能·物联网·边缘计算
搞物联网的木子19 小时前
LORA扩频技术详解,适合应用到那些产品和行业?
物联网·信息与通信·射频工程