利用WIFI模块检测水塔水位高度并将结果上传给点灯APP
本帖最后由 xiongjiaxiao 于 2022-2-6 14:52 编辑最近家里老是停水,还好房顶上备用了一个大水塔,以备不时只需,平时往里面灌水,停水时用就行了,但如果水灌得太满的话水就会溢出造成不必要的麻烦,而且每次用完水后主人需要水塔里还剩多少水,因此我就想,有没有一款可以将水塔当前水位发送给用户,使其能够一目了然的知道水塔里还剩多少水。
那么接下来,就要开始构思了。
主控用的是ESP-01M,这款模块的IO数量正好够用,并且他是直插封装的,所以就选他了!
检测距离的话用超声波就行了,但是超声波有个致命缺点,那就是一旦测量物体太近或者太远,就会导致测量结果不准(讲个笑话,之前我在调试的时候用手挡住了超声波模块,结果测量距离高达十万八千里!:L)。不过我们的项目要求的测量精度并不高,所以说就用它了!
现在,就可以开始编写代码了。
在这里,有一个地方要注意了,超声波检测到的距离不能直接上传给点灯APP,这是因为此时超声波检测的并不是剩余水量,因此,我们要用水位的总高度(比如我的水塔高度是两米,我就用2米减去测得的值)减去测得的值,考虑到后期还可以用在别的地方,我就用一个滑块来设定最高的水位(单位为米)因为超声波模块最大能检测7米,因此要将滑块的最小和最大值设置为1-7米,这样测出的数据才是真正的水位高度,你以为这就完了?不不不,如果直接将这样的数据上传到APP,用户看着并不直观,就好比我告诉你,这杯水还有几厘米,你觉得你看得懂吗?因此,我们可以用百分比这样的书来表示水位,(比如说:还剩50厘米的水,而忙的状态是100厘米,那么就相当于50%),但在这里就牵扯到了一个算法的问题了,楼主也是苦思冥想才想出了这么一个算法:比如说水满时高度是100厘米,那么就用100厘米减去超声波测得的值从而得到当前剩下的水,在用这个值除以1,注意,重点来了,是除以1而不是除100,那么就可以得出了当前剩下的水的百分比了。代码为:((value-cs)/(value/100))其中value为水满时的高度(单位是厘米),cs是超声波测得的值,至于最后为啥要除100,你们用计算器算一下就知道了。
最后是代码:
#define BLINKER_WIFI
#include <Ticker.h>
#include <Blinker.h>
#include<stdio.h>
char auth[] = "4ec1296200ff";
char ssid[] = "XTX";
char pswd[] = "13510531949lc";
Ticker tickerSetHigh;
// 新建组件对象
BlinkerNumber Number1("num-a");
BlinkerNumber Number2("num-cm");
BlinkerButton Button1("btn-if");
BlinkerButton Button2("btn-beep");
BlinkerSlider Slider1("ran-sw");
const int trigPin = D1;//D4
const int echoPin = D2;//D3
// defines variables
unsigned int duration;
unsigned int distance;
unsigned int ion;
unsigned int sw_max=100;
void button1_callback(const String & state)
{
BLINKER_LOG("get button state: ", state);
cs_start();
duration = pulseIn(echoPin, HIGH);
distance = duration * 0.034 / 2;
ion = distance;
if (distance > sw_max)
{
Number1.print(0);
Number2.print(0);
}
else
{
switch (sw_max)
{
case (100): Number1.print((sw_max - distance)/1); break;
case (200): Number1.print((sw_max - distance)/2); break;
case (300): Number1.print((sw_max - distance)/3); break;
case (400): Number1.print((sw_max - distance)/4); break;
case (500): Number1.print((sw_max - distance)/5); break;
case (600): Number1.print((sw_max - distance)/6); break;
case (700): Number1.print((sw_max - distance)/7); break;
}
//Number1.print(distance);
Number2.print(ion);
}
}
void button2_beep(const String & state)
{
BLINKER_LOG("get button state: ", state);
if (state == "on")
{
digitalWrite(D5, 0);
Button2.print("on");
}
else if (state == "off")
{
digitalWrite(D5, 1);
Button2.print("off");
}
}
void slider1_if(int32_t value)
{
BLINKER_LOG("get slider state: ", value);
//sw_max=sw_max*100;
switch (value)
{
case (1): sw_max = 100; break;
case (2): sw_max = 200; break;
case (3): sw_max = 300; break;
case (4): sw_max = 400; break;
case (5): sw_max = 500; break;
case (6): sw_max = 600; break;
case (7): sw_max = 700; break;
}
//sw_max=value;
}
void setup() {
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
pinMode(D5, OUTPUT);
digitalWrite(trigPin, LOW);
digitalWrite(D5, 1);
Serial.begin(115200);
BLINKER_DEBUG.stream(Serial);
BLINKER_DEBUG.debugAll();
Blinker.begin(auth, ssid, pswd);
Button1.attach(button1_callback);
Button2.attach(button2_beep);
Slider1.attach(slider1_if);
tickerSetHigh.attach_ms(1, setpin);//给看门狗喂狗,这个一定要,不然会复位!
}
void loop() {
Blinker.run();
//delay(10000);
//delay(10000);
//delay(10000);
//delay(10000);
}
void cs_start()
{
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
}
void setpin()
{
ESP.wdtFeed();
}这里我懒得注释了,有啥问题直接回复!
效果图:
这个挺实用 如果是让超声波一直处于检测状态,就是不通过按键更新状态,应该怎么搞呀,弄了几次还是不行,大佬求帮助
页:
[1]