二,基于esp32-c3 esp8266 多任务水溢报警器(基于超声波非接触式测距)
sean 编辑于2022-05-20 19:58Arduino
上次用esp8266写的用的是导电方式测试水溢出使用了一段时间以后,发现了三个很明显的缺点:
- 水满需要,水溢出才能检测出.有点响应滞后.发现时已晚
- 需要接触检测,水接触导电金属很容易被腐蚀电解.表面一层氧化层导致检测灵敏度下降,不适合长期使用.
- 单任务处理,警报解除时的互动响应有点迟钝.
第二种液位方式的检测报警.解决了之前暴露的问题.这里用的是超声波模式,当水位达到距离阀值,则报警.
既然都是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.31
联系作者(邮箱)
软件