二,基于esp32-c3 esp8266 多任务水溢报警器(基于超声波非接触式测距)

sean 编辑于2022-05-20 19:58Arduino

上次用esp8266写的用的是导电方式测试水溢出使用了一段时间以后,发现了三个很明显的缺点:

  1. 水满需要,水溢出才能检测出.有点响应滞后.发现时已晚
  2. 需要接触检测,水接触导电金属很容易被腐蚀电解.表面一层氧化层导致检测灵敏度下降,不适合长期使用.
  3. 单任务处理,警报解除时的互动响应有点迟钝.

第二种液位方式的检测报警.解决了之前暴露的问题.这里用的是超声波模式,当水位达到距离阀值,则报警.

既然都是esp32了,不用freertos就不合理了,虽然esp32-C3是单核,也可以多任务,顺便解决之前的单任务顺序执行的缺陷(只有当蜂鸣器播放完,才能响应后面的动作的同步问题).

这次直接上esp32-c3的代码:

#include <Arduino.h>

#include <WiFi.h>
#include <WiFiMulti.h>

#include <HTTPClient.h>

#include <WiFiClientSecure.h>

#define Tone_Pin 6
#define Echo_Pin 7
#define Trig_Pin 8

#define SERVER_DOMIAN_NAME "alarm.freeloong.top"

#ifndef APSSID
#define APSSID "my_wifi_ssid"
#define PASSWORD  "my_wifi_pass"
#endif


unsigned long Time_Echo_us = 0;
unsigned long Len_mm = 0;

// Set up the rgb led names
uint8_t ledR = 3;
uint8_t ledG = 4;
uint8_t ledB = 5;

const char* rootCACertificate = \
                                "-----BEGIN CERTIFICATE-----\n" \
                                "MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n" \
                                "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" \
                                "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" \
                                "QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n" \
                                "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" \
                                "b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n" \
                                "9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n" \
                                "CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n" \
                                "nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n" \
                                "43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n" \
                                "T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n" \
                                "gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n" \
                                "BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n" \
                                "TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n" \
                                "DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n" \
                                "hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n" \
                                "06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n" \
                                "PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n" \
                                "YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n" \
                                "CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n" \
                                "-----END CERTIFICATE-----\n";

int water_status = 0; //water's status 0 empty, 1 full

void alarm_sound(void * parameter) {
  while (true) {
    if (water_status == 1) {
      for (int i = 0; i < 7; i++) {
        digitalWrite(Tone_Pin, LOW);//输出LOW电平,发声
        delay(70);

        digitalWrite(Tone_Pin, HIGH);//输出HIGH电平,关闭发声
        delay(70);
      }
    }
    else if (water_status == 0) {
      digitalWrite(Tone_Pin, HIGH);//输出HIGH电平,关闭发声
    }
    delay(400);
  }
}


void send_full_or_empty(void * parameter) {
  int previous_signal = 0;
  String water_status_string;
  while (true) {
    if ( water_status == 1) {
      water_status_string = "{\"water\":\"full\"}";
    }
    else if (water_status == 0) {
      water_status_string = "{\"water\":\"empty\"}";
    }





    if ( previous_signal != water_status ) {




      previous_signal = water_status;
      WiFiClientSecure *client = new WiFiClientSecure;


      if (client) {
        client -> setCACert(rootCACertificate);

        {
          // Add a scoping block for HTTPClient https to make sure it is destroyed before WiFiClientSecure *client is
          HTTPClient https;

          Serial.print("[HTTPS] begin...\n");
          if (https.begin(*client, "https://alarm.freeloong.top/listen")) {  // HTTPS
            https.addHeader("Content-Type", "application/json");
            Serial.print("[HTTPS] POST...\n");
            // start connection and send HTTP header
            int httpCode = https.POST(water_status_string);

            // httpCode will be negative on error
            if (httpCode > 0) {
              // HTTP header has been send and Server response header has been handled
              Serial.printf("[HTTPS] POST... code: %d\n", httpCode);

              // file found at server
              // HTTP_CODE_OK 200, HTTP_CODE_MOVED_PERMANENTLY 301
              if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
                String payload = https.getString();
                Serial.println("received payload:\n<<");
                Serial.println(payload);
                Serial.println(">>");

              } else {
                Serial.printf("[HTTPS] POST... failed, error: %d\n", httpCode);
              }

              https.end();
            }
          }

          else {
            Serial.printf("[HTTPS] Unable to connect\n");
          }

          // End extra scoping block
        }



        delete client;
      }



      else {
        Serial.println("Unable to create client");
      }



    }





    delay(400);
  }
}

void detect_water_status( void * parameter ) {
  while (true) {
    digitalWrite(Trig_Pin, HIGH); //begin to send a high pulse, then US-025/US-026 begin to measure the distance
    delayMicroseconds(20); //set this high pulse width as 20us (>10us)
    digitalWrite(Trig_Pin, LOW); //end this high pulse

    Time_Echo_us = pulseIn(Echo_Pin, HIGH);               //calculate the pulse width at EchoPin,

    if ((Time_Echo_us < 60000) && (Time_Echo_us > 1))    //a valid pulse width should be between (1, 60000).
    {
      Len_mm = (Time_Echo_us * 34 / 100) / 2; //calculate the distance by pulse width, Len_mm = (Time_Echo_us * 0.34mm/us) / 2 (mm)
      //Serial.print("Present Distance is: ");  //output result to Serial monitor
      //Serial.print(Len_mm, DEC);            //output result to Serial monitor
      //Serial.println("mm");                 //output result to Serial monitor
    }

    if ( Len_mm < 230) {
      if (water_status == 0) {
        //red led open
        ledcWrite(1, 0);
        ledcWrite(2, 255);
        ledcWrite(3, 255);
        water_status = 1;
        //Serial.println("detect person");
      }
    }
    else { //当前没有检测到水
      if (water_status == 1) {
        //green led open
        //ledcWrite(1, 255);
        //ledcWrite(2, 0);
        //ledcWrite(3, 255);
        //关闭led
        ledcWrite(1, 255);
        ledcWrite(2, 255);
        ledcWrite(3, 255);
        water_status = 0;
        //Serial.println("no person");
      }
    }
    delay(200);
  }
}



WiFiMulti WiFiMulti;

void setup() {

  pinMode(Echo_Pin, INPUT);
  pinMode(Trig_Pin, OUTPUT);
  pinMode(Tone_Pin, OUTPUT);
  digitalWrite(Tone_Pin, HIGH);



  ledcAttachPin(ledR, 1); // assign RGB led pins to channels
  ledcAttachPin(ledG, 2);
  ledcAttachPin(ledB, 3);
  //ledcAttachPin(Tone_Pin, 4);


  //LEDC总共有16个路通道(0 ~ 15),分为高低速两组,高速通道(0 ~ 7)由80MHz时钟驱动,低速通道(8 ~ 15)由1MHz时钟驱动。
  //double ledcSetup(uint8_t channel, double freq, uint8_t resolution_bits)
  //(通道号,频率,计数位数)
  //channel为通道号,取值0 ~ 15;
  //freq,设置频率;
  //resolution_bits计数位数,取值0 ~ 20(该值决定后面ledcWrite方法中占空比的最大值,如该值写10,则占空比最大可写2^10-1=1023 ;
  //通道最终频率 = 时钟频率 / ( 分频系数 * ( 2^计数位数 ) );(分频系数最大为1024)
  //该方法返回值:最终频率;

  // Initialize channels
  // channels 0-15, resolution 1-16 bits, freq limits depend on resolution
  // ledcSetup(uint8_t channel, uint32_t freq, uint8_t resolution_bits);
  ledcSetup(1, 12000, 8); // 12 kHz PWM, 8-bit resolution
  ledcSetup(2, 12000, 8);
  ledcSetup(3, 12000, 8);
  //ledcSetup(4, 12000, 8);

  ledcWrite(1, 255);
  ledcWrite(2, 255);
  ledcWrite(3, 255);
  //ledcWriteTone(4, 0);

  Serial.begin(115200);

  Serial.println();
  Serial.println();
  Serial.println();

  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP(APSSID, PASSWORD);

  // wait for WiFi connection
  //Serial.print("Waiting for WiFi to connect...");
  while ((WiFiMulti.run() != WL_CONNECTED)) {
    Serial.print(".");
  }

  Serial.print("Connected! IP address: ");
  Serial.println(WiFi.localIP());

  xTaskCreate(
    detect_water_status,     /* Task function. */
    "detecter",       /* String with name of task. */
    10000,            /* Stack size in words. */
    NULL,             /* Parameter passed as input of the task */
    10,               /* Priority of the task. */
    NULL);            /* Task handle. */

  xTaskCreate(
    send_full_or_empty,     /* Task function. */
    "recive_water_status_and_send_to_server",       /* String with name of task. */
    10000,            /* Stack size in words. */
    NULL,             /* Parameter passed as input of the task */
    10,               /* Priority of the task. */
    NULL);            /* Task handle. */


  xTaskCreate(
    alarm_sound,     /* Task function. */
    "recive_water_status_and_sound_alarm",       /* String with name of task. */
    10000,            /* Stack size in words. */
    NULL,             /* Parameter passed as input of the task */
    10,               /* Priority of the task. */
    NULL);            /* Task handle. */

}

// the loop function runs over and over again forever
void loop() {
  delay(1000);
}

附,简易版的esp8266的本地超声波水位检测仪器(关闭wifi,总电流24ma左右,整体功耗约120mw):

#include <ESP8266WiFi.h>

#define Tone_Pin D1  //gpio 5

#define Echo_Pin D5  //gpio 14
#define Trig_Pin D6  //gpio 12
                   

unsigned long Time_Echo_us = 0;
unsigned long Len_mm = 0;


int water_status = 0; //water's status 0 empty, 1 full

void alarm_sound() {
    if (water_status == 1) {
      for (int i = 0; i < 3; i++) {
        digitalWrite(Tone_Pin, LOW);//输出电平,发声
        delay(70);

        digitalWrite(Tone_Pin, HIGH);//输出电平,关闭发声
        delay(70);
        //Serial.println("alarm full");
      }
    }
    else if (water_status == 0) {
      digitalWrite(Tone_Pin, HIGH);//关闭发声
      //Serial.println("no alarm");
    }
    //delay(400);
}

void detect_water_status( ) {
  //while(true){
    digitalWrite(Trig_Pin, HIGH); //begin to send a high pulse, then US-025/US-026 begin to measure the distance
    delayMicroseconds(20); //set this high pulse width as 20us (>10us)
    digitalWrite(Trig_Pin, LOW); //end this high pulse

    Time_Echo_us = pulseIn(Echo_Pin, HIGH);               //calculate the pulse width at EchoPin,

    if ((Time_Echo_us < 60000) && (Time_Echo_us > 1))    //a valid pulse width should be between (1, 60000).
    {
      Len_mm = (Time_Echo_us * 34 / 100) / 2; //calculate the distance by pulse width, Len_mm = (Time_Echo_us * 0.34mm/us) / 2 (mm)
      //Serial.print("Present Distance is: ");  //output result to Serial monitor
      //Serial.print(Len_mm, DEC);            //output result to Serial monitor
      //Serial.println("mm");                 //output result to Serial monitor
    }

    if ( Len_mm < 230) {
      if (water_status == 0) {
        water_status = 1;
        //led open
        //digitalWrite(LED_BUILTIN, LOW);
        //Serial.println("detect full");
      }
    }
    else { //当前没有检测到水
      if (water_status == 1) {
        //green led open
        //关闭led
        water_status = 0;
        //Serial.println("not full");
      }
    }
    //delay(200);
  //}
}


void setup() {
  pinMode(Echo_Pin, INPUT);
  pinMode(Trig_Pin, OUTPUT);
  
  pinMode(Tone_Pin, OUTPUT);
  digitalWrite(Tone_Pin, HIGH);
  
  pinMode(LED_BUILTIN, OUTPUT);
  //turn the led off
  digitalWrite(LED_BUILTIN, HIGH);
  

  //Serial.begin(115200);

  //Serial.println();
  //Serial.println();
  //Serial.println();

  WiFi.mode(WIFI_OFF);
  WiFi.forceSleepBegin();
  delay(1);
  //Serial.println("wifi off now !");
  
}

// the loop function runs over and over again forever
void loop() {
  detect_water_status();
  alarm_sound();
  delay(400);
}

关于本站

肥龙软件分享的软件是本站作者开发的免费,无广告,安全可靠,绝不附带任何无关软件,绝不困绑任何插件的实用软件。如果您感觉好用,可以捐赠我们,这样我们可以有更积极的动力去改进升级软件,维持服务器运转,感谢您的捐助,谢谢!

致谢 赞赏/捐助名单

2024-8-13 **军 ¥16.8

更新时间:2024.8.31

联系作者(邮箱)
分类