零基础入门学用物联网(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!"); } ```

相关推荐
Deitymoon8 小时前
STM32F103——超声波模块
stm32·单片机·嵌入式硬件
你怎么知道我是队长11 小时前
计算机系统基础22---计算机的基本组成---IO控制方式
单片机·嵌入式硬件
風清掦11 小时前
【STM32学习笔记-12】Unix 时间戳、BKP 备份寄存器与 RTC 实时时钟
笔记·stm32·单片机·嵌入式硬件·学习·实时音视频·unix
hoiii18712 小时前
基于STM32的扫地机器人源码工程
stm32·单片机·机器人
济61712 小时前
ARM Linux 驱动开发篇---Linux字符设备驱动代码阅读指南---附设备树LED驱动实战案例
linux·嵌入式·嵌入式linux驱动开发
担水老头12 小时前
蓝桥杯嵌入式赛道解决LCD和LED引脚冲突的问题
嵌入式
振南的单片机世界14 小时前
EXTI边沿检测:上升沿、下降沿、双边沿,硬件自动捕捉
stm32·单片机·嵌入式硬件
数字化顾问14 小时前
(97页PPT)麦肯锡战略规划制定方法及模板制品(附下载方式)
人工智能·物联网
Max_uuc15 小时前
【感知心法】别相信你的传感器!撕碎“所读即所得”的 API 幻觉,论物理世界的“全员撒谎”与状态观测器的绝对凝视
单片机
踏着七彩祥云的小丑16 小时前
嵌入式——认识电子元器件——符号
单片机·嵌入式硬件