• 学习太极创客 — ESP8226 (十二)ESP8266 多任务处理


    视频链接:https://www.bilibili.com/video/BV1L7411c7jw?p=22&spm_id_from=333.851.header_right.history_list.click&vd_source=b91967c499b23106586d7aa35af46413

    资料链接:http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-tips/ticker/

    ESP8266 在运行过程中,只能一条线式的依次执行任务。但是我们在开发物联网项目时,可能需要 ESP8266 在执行某一任务的过程中,还能处理其它任务。比如,我们使用 ESP8266 来控制电机运行的同时,还需要定时检查某一个引脚上连接按钮有没有被用户按下。

    为了解决以上问题,我们可以使用 Ticker 库来解决这一问题。

    ESP8266 多任务处理 – Ticker 库使用说明

    Ticker 库并不是 Arduino 的第三方库,无需安装。

    1、Ticker 库基本操作

    程序功能:开发板通过 PWM 控制 LED 灯产生呼吸灯效果的同时,通过串口发送信息。

    /**********************************************************************
    项目名称/Project          : 零基础入门学用物联网
    程序名称/Program name     : a_basic_tinker
    团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
    作者/Author              : CYNO朔
    日期/Date(YYYYMMDD)     : 20200703
    程序目的/Purpose          : 
    本程序旨在演示如何使用Ticker库来定时执行操作。
    如需了解本程序的详细说明,请参考以下函数:
    http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-tips/ticker/
    -----------------------------------------------------------------------
    其它说明 / Other Description:
    本程序为太极创客团队制作的免费视频教程《零基础入门学用物联网 》中一部分。该教程系统的
    向您讲述ESP8266的物联网应用相关的软件和硬件知识。以下是该教程目录页:
    http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/                    
    ***********************************************************************/
    #include <Ticker.h>
     
    Ticker ticker;// 建立Ticker用于实现定时功能
    int count;    // 计数用变量
     
    void setup() {
      Serial.begin(9600);
      pinMode(LED_BUILTIN, OUTPUT);
     
      // 每隔一秒钟调用sayHi函数一次,attach函数的第一个参数
      // 是控制定时间隔的变量。该参数的单位为秒。第二个参数是
      // 定时执行的函数名称。
      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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    程序说明:

    利用 Ticker 库,我们可以让 ESP8266 定时调用某一个函数。

    通过示例程序,我们可以看到,ESP8266 将会每隔一秒钟通过串口监视器输出一次信息。我们是通过语句ticker.attach(1, sayHi) 来实现这一操作的。

    该语句中的 attach 函数有两个参数。第一个参数可控制调用函数的时间间隔,单位是秒。这里的数字 1 说明 ESP8266 将会每隔一秒钟调用一次函数。那么具体调用哪一个函数呢?这个函数名称正是通过第二个参数来限定的。也就是名称为 sayHi 的函数。该函数将会让 ESP8266 定时通过串口监视器输出一次信息。信息内容是“Hi”后面跟一个数值。这个数值是为了标注 sayHi 函数被调用了多少次。

    2、停止定时执行函数

    假设,我们只想让 sayHi 这个函数执行有限的次数,又应该如何处理呢?

    当 Ticker 定时调用某一函数执行到一定次数后,我们可以使用detach 函数来停止定时调用函数。在操作上,只需要在 sayHi 这个函数中添加 if 语句即可,示例如下。

    // 在Tinker对象控制下,此函数将会定时执行。
    void sayHi(){
      count++;
      Serial.print("Hi ");
      Serial.println(count);
      if(count >= 10){
        ticker.detach();// 当定时调用了10次后,停止定时调用函数
        Serial.print("ticker.detach()");
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行结果如下,
    在这里插入图片描述

    3、向定时调用函数传递参数

    我们可以向 Ticker 库定时调用的函数来传递参数。不过要注意的是,传递参数的数量只能是一个。

    请注意:attach函数所能传递的参数最多只有一个。另外该参数仅能是以下类型中的一种:char, short, int, float, void *, char *。

    如下面示例程序所示,语句 ticker.attach(1, sayHi, 8) 有 3 个参数。其中第三个参数就是向定时调用的sayHi函数所传递的参数。

    /**********************************************************************
    项目名称/Project          : 零基础入门学用物联网
    程序名称/Program name     : a_basic_tinker
    团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
    作者/Author              : CYNO朔
    日期/Date(YYYYMMDD)     : 20200703
    程序目的/Purpose          : 
    本程序旨在演示如何使用Ticker库来定时执行操作。
    如需了解本程序的详细说明,请参考以下函数:
    http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-tips/ticker/
    -----------------------------------------------------------------------
    其它说明 / Other Description:
    本程序为太极创客团队制作的免费视频教程《零基础入门学用物联网 》中一部分。该教程系统的
    向您讲述ESP8266的物联网应用相关的软件和硬件知识。以下是该教程目录页:
    http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/                    
    ***********************************************************************/
    #include <Ticker.h>
     
    Ticker ticker;// 建立Ticker用于实现定时功能
    int count;    // 计数用变量
     
    void setup() {
      Serial.begin(9600);
      pinMode(LED_BUILTIN, OUTPUT);
      analogWriteRange(1023);
     
      // 每隔一秒钟调用sayHi函数一次,attach函数的第一个参数
      // 是控制定时间隔的变量。该参数的单位为秒。第二个参数是
      // 定时执行的函数名称。
      ticker.attach(1, sayHi, 10);
    }
     
    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(int hiTimes){
      count++;
      Serial.print("Hi ");
      Serial.println(count);
      
      if(count >= hiTimes){
        ticker.detach();// 当定时调用了10次后,停止定时调用函数
        Serial.print("ticker.detach()");
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    运行结果如下,
    在这里插入图片描述

    示例4. 利用多个Ticker对象让ESP8266处理多任务

    我们可以建立多个 Ticker 对象,让多个 Ticker 对象来实现 ESP8266 的多任务处理。

    如下实例程序所示,我们通过语句 Ticker buttonTicker;来建立第二个 Ticker 对象。

    然后再使用 buttonTicker.attach_ms(100, buttonCheck) 来实现第二个 Ticker 对象的任务处理。

    这里我们使用了 attach_ms 函数,该函数与 attach 函数功能相似,唯一区别是 attach 函数的时间单位是秒,而 attach_ms 的时间单位是毫秒。也就是说,这条语句将会让 ESP8266 每隔 100 毫秒执行一次 buttonCheck 函数。

    /**********************************************************************
    项目名称/Project          : 零基础入门学用物联网
    程序名称/Program name     : a_basic_tinker
    团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
    作者/Author              : CYNO朔
    日期/Date(YYYYMMDD)     : 20200703
    程序目的/Purpose          : 
    本程序旨在演示如何使用Ticker库来定时执行操作。
    如需了解本程序的详细说明,请参考以下函数:
    http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-tips/ticker/
    -----------------------------------------------------------------------
    其它说明 / Other Description:
    本程序为太极创客团队制作的免费视频教程《零基础入门学用物联网 》中一部分。该教程系统的
    向您讲述ESP8266的物联网应用相关的软件和硬件知识。以下是该教程目录页:
    http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/                    
    ***********************************************************************/
    #include <Ticker.h>
     
    Ticker ticker;// 建立Ticker用于实现定时功能
    Ticker buttonTicker;
    int count;    // 计数用变量
     
    void setup() {
      Serial.begin(9600);
      pinMode(LED_BUILTIN, OUTPUT);
      analogWriteRange(1023);
      pinMode(D3, INPUT_PULLUP);
     
      // 每隔一秒钟调用sayHi函数一次,attach函数的第一个参数
      // 是控制定时间隔的变量。该参数的单位为秒。第二个参数是
      // 定时执行的函数名称。
      ticker.attach(1, sayHi, 60);
      buttonTicker.attach_ms(100, buttonCheck);
    }
     
    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(int hiTimes){
      count++;
      Serial.print("Hi ");
      Serial.println(count);
      
      if(count >= hiTimes){
        ticker.detach();// 当定时调用了10次后,停止定时调用函数
        Serial.print("ticker.detach()");
      }
    }
    
    void buttonCheck(){
      if (digitalRead(D3) == LOW){
        Serial.println("D3 Button Pushed...");
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    示例5. 使用”计数器”来控制 ESP8266 定时执行较复杂的函数

    Ticker 定时调用的函数必须要“短小精悍”。比如以上一系列的示例程序中,我们仅仅让 Ticker 定时调用函数执行简单的串口数据输出,以及很基本的运算。事实上,在使用 Ticker 库时,定时调用函数必须要很快的执行完毕。否则会产生难以预料的问题。

    这就产生了一个问题。假如我们需要 ESP8266 定时执行的操作较为复杂,这该如何是好呢?
    在这里插入图片描述

    /**********************************************************************
    项目名称/Project          : 零基础入门学用物联网
    程序名称/Program name     : e_timer_http
    团队/Team                : 太极创客团队 / Taichi-Maker (www.taichi-maker.com)
    作者/Author              : CYNO朔
    日期/Date(YYYYMMDD)     : 20200703
    程序目的/Purpose          : 
    本程序旨在演示如何使用计数器来控制ESP8266定时执行较复杂的函数。Ticker定时调用的函数必须要“短小精悍”。
    而不能是复杂且占用时间较长的函数。对于较为复杂的函数,我们可以使用计数器的方法来实现。
     
    本程序将会定时让ESP8266向example网络服务器发送请求,并且将服务器响应信息显示在屏幕中。
     
    如需了解本程序的详细说明,请参考以下函数:
    http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/iot-c/esp8266-tips/tinker/
    -----------------------------------------------------------------------
    其它说明 / Other Description:
    本程序为太极创客团队制作的免费视频教程《零基础入门学用物联网 》中一部分。该教程系统的
    向您讲述ESP8266的物联网应用相关的软件和硬件知识。以下是该教程目录页:
    http://www.taichi-maker.com/homepage/esp8266-nodemcu-iot/                    
    ***********************************************************************/
    #include <Ticker.h>
    #include <ESP8266WiFi.h>
    #include <ESP8266HTTPClient.h>
     
    #define URL "http://www.example.com"
     
    // 设置wifi接入信息(请根据您的WiFi信息进行修改)
    const char* ssid = "FAST_153C80";
    const char* password = "123456798";
     
    Ticker ticker;
     
    int count;
     
    void setup() {
      Serial.begin(9600);
     
      //设置ESP8266工作模式为无线终端模式
      WiFi.mode(WIFI_STA);
      
      //连接WiFi
      connectWifi();
     
      ticker.attach(1, tickerCount);
    }
     
    void loop() {  
      if (count >= 5){   
        httpRequest();
        count = 0;
      }
    }
     
    void tickerCount(){
      count++;
      Serial.print("count = ");
      Serial.println(count);
    }
     
    // 发送HTTP请求并且将服务器响应通过串口输出
    void httpRequest(){
      WiFiClient client; 
      HTTPClient httpClient;
    
      httpClient.begin(client, 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) {
        // 使用getString函数获取服务器响应体内容
        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
      WiFi.begin(ssid, password);
     
      //等待WiFi连接,连接成功打印IP
      while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.print(".");
      }
      Serial.println("");
      Serial.print("WiFi Connected!");   
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

    这个程序运行有问题,总是会导致异常而自动重启。
    在这里插入图片描述
    报 Exception (9) ,(查相关手册说导致的原因有两个,一个是野指针,一个是读/写 Cache 地址不对齐)。
    在这里插入图片描述
    查了半天也没有查出个所以然。

    这个程序与视频中所使用的库的版本不一样,我这里使用的版本是3.0.2,
    在这里插入图片描述
    视频中所使用的是 2.6.3 版本,
    在这里插入图片描述
    3.0.0版本是一个分水岭。因为多了这句代码

    HTTPClient httpClient;
    WiFiClient client; 
     
    httpClient.begin(client, URL); 
    
    • 1
    • 2
    • 3
    • 4

    所以要想让程序正常运行,其中一个的解决方法就是重新安装 2.6.3 版本的库,然后不加上 WiFiClient client; 这个对象。

    后来,经过尝试,发现将 WiFiClient client; 定义在 HTTPClient httpClient; 的前面,程序运行就不会出现任何问题了,所以不用重新安装库了(上面程序已改正过来)。

  • 相关阅读:
    java计算机毕业设计汇美食电子商城MyBatis+系统+LW文档+源码+调试部署
    Spring Boot(七十八):实现API 多版本控制
    【VS Code 与 Qt6】运用事件过滤器批量操作子级组件
    vue3中安装并使用CSS预处理器Sass的方法介绍
    Jenkins详解(三)
    [Python] 集合操作及方法总结
    Hadoop 启动!
    多元统计分析-----例8.1:今有14名学生的身高和体重数据,做相关图以显示相关变量间的关系。
    施耐德电气携中国信通院和中国联通共同发布白皮书,共探5G+PLC深度融合应用
    【KD】2022 ECCV Factorizing Knowledge in Neural Networks
  • 原文地址:https://blog.csdn.net/xuechanba/article/details/125418090