鱼缸毕设 esp8266 arduino 点灯·blinker 小爱同学-Arduino中文社区 - Powered by Discuz! Archiver

mzl 发表于 2022-9-29 01:26

鱼缸毕设 esp8266 arduino 点灯·blinker 小爱同学


esp8266引脚图






界面配置



#define BLINKER_WIFI               //支持wifi
//#define BLINKER_ESP_SMARTCONFIG    //Smartconfig或者手机微信扫码自动配网,代码配网请注释此条
#define BLINKER_MIOT_MULTI_OUTLET//支持多路插座,最多4个插孔
#define BLINKER_PRINT Serial       //串口协议库
#define BLINKER_WITHOUT_SSL      //blinker默认使用加密方式进行远程通信,但通信加密会消耗大量的RAM,如果您对通信安全性无要求
                     //可以添加宏BLINKER_WITHOUT_SSL用以获得更多可用RAM,BLINKER_WITHOUT_SSL目前仅可用于ESP8266,其他设备的RAM足以进行加密通信

#include <Blinker.h>               //使用第三方Blinker库
#include <Servo.h>               //舵机库

#include <OneWire.h>               //使用温度的库
#include <DallasTemperature.h>   //使用温度的库



char auth[] = "128679da61a7";//ed9c736dca2f
char ssid[] = "TP-LINK_鲁";
char pswd[] = "13198852106";
/*char ssid[] = "l";
char pswd[] = "12345678";*/

#define Servo_pin 13//定义舵机连接引脚D7

//定义温度传感器信号
#define ONE_WIRE_BUS 2                // DS18B20 DQ接ESP8266引脚D4(GPIO2)
#define hot 14                        //控制加热棒继电器接ESP8266引脚D5(GPIO14)和   void setup()中的pinMode(hot,OUTPUT);配合
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

//定义水质传感器信号
#define TdsSensorPin A0               //TDS水质传感器A接ESP8266引脚A0
#define VREF 5.0      // analog reference voltage(Volt) of the ADC
#define SCOUNT30             // sum of sample point
int analogBuffer;    // store the analog value in the array, read from ADC
int analogBufferTemp;
int analogBufferIndex = 0, copyIndex = 0;
            
float averageVoltage = 0, tdsValue = 0, tdsValue_MAX= 300 , tempe = 25 ,tempe_MAX = 28;//
//int lock = 0;
double temp,data;

//定义继电器信号
#define Relay_1 0         //定义继电器1信号接入GPIO5,D3
#define Relay_2 4         //定义继电器2信号接入GPIO4,D2
#define Relay_3 16         //定义继电器3信号接入GPIO0,D0
#define Relay_4 12         //定义继电器4信号接入GPIO12,D6

//定义水位传感器信号
#define Grove_Water_Sensor 5         // S接ESP8266引脚D1(GPIO5)
#define Water 15                        //继电器IN接ESP8266引脚D8(GPIO15)控制水泵开关

// 新建Blinker软件组件对象
BlinkerButton Button("MainSwitch");   //组件对象,要和APP组件中的“数据键名”一致,总开关
BlinkerButton Button1("btn-1");       //组件对象,要和APP组件中的“数据键名”一致,开关1
BlinkerButton Button2("btn-2");       //组件对象,要和APP组件中的“数据键名”一致,开关2
BlinkerButton Button3("btn-3");       //组件对象,要和APP组件中的“数据键名”一致,开关3
BlinkerButton Button4("btn-4");       //组件对象,要和APP组件中的“数据键名”一致,开关4
BlinkerButton Button5("Refresh");       //APP端按钮状态刷新

BlinkerNumber TEMP("tempe");         //定义温度数据键名
BlinkerNumber DEMP("data");         //定义水位数据键名
BlinkerNumber WATER("tdsValue");    //定义水质数据键名
BlinkerText WATERSTATUS("waterStatus");//定义水位 文本键名
BlinkerText HOT("hot");                //定义加热棒 文本键名
BlinkerText TDS("tds");                //定义水质 文本键名
//定义插座状态,用于小爱同学状态反馈
bool oState = { false };
#define OUTLET_ALL   0//所有插孔
#define OUTLET_NO_11//插座插孔一
#define OUTLET_NO_22//插座插孔二
#define OUTLET_NO_33//插座插孔三
#define OUTLET_NO_44//插座插孔四


//喂食量
Servo servo;
int feedamount = 300;
int feed_EA = 1;
BlinkerSlider Slider1("ran-feedamount"); //喂食量滑块(通过延时时间控制出食量)
void   Slider1_feedamount(int32_t amount)
{
feedamount = amount >= 1000 ? 1000 : amount <= 1 ? 1
               : amount;
Slider1.print(feedamount);
BLINKER_LOG("feedamount:", feedamount);
}

BlinkerButton Button6("btn-handfeed"); //喂食
void   Button6_callback(const String &state)
{
BLINKER_LOG("get button state: ", state);
if (state == BLINKER_CMD_BUTTON_TAP && feed_EA)
{
    feed_EA = 1;
    BLINKER_LOG("get feedamount: ", feedamount);
    feed_cat();
    Blinker.vibrate(1000);    //震动1s
    Button6.color("#0000FF");
    Button6.text("出料完成");
    Button6.print();
    feed_EA = 1;
}
}
void feed_cat() //喂食出料
{

//playmusic();
servo.write(0);
Button6.color("#FFA500");
Button6.text("出料中");
Button6.print();
Blinker.delay(50);

Blinker.delay(feedamount * 10);
servo.write(90);
}


//反馈继电器状态函数
void RelayState(int num)
{
switch(num)
{
    case 1:   //插座插孔一状态
      if(digitalRead(Relay_1)==LOW)
      {
          Button1.color("#808080");   //设置app按键是灰色,16进制颜色码
          Button1.text("关灯");          //设置app按键注释“关”
          Button1.print("off");
          oState = false;
      }
      else if(digitalRead(Relay_1==HIGH))
      {
          Button1.color("#FFA500");   //设置app按键是橙色,16进制颜色码https://www.w3school.com.cn/tags/html_ref_colornames.asp
          Button1.text("开灯");          //设置app按键注释“开”
          Button1.print("on");
          oState = true;
      }
      break;
    case2:
      if(digitalRead(Relay_2)==LOW /*|| digitalRead(Water) == HIGH*/)
      {
          //lock = 1;
          Button2.color("#808080");   //设置app按键是灰色,16进制颜色码
          Button2.text("注水关");          //设置app按键注释“关”
          Button2.print("off");
          oState = false;
      }
      else if(digitalRead(Relay_2==HIGH) /*|| digitalRead(Water) == LOW*/)
      {
          //lock = 0;
          Button2.color("#FFA500");   //设置app按键是橙色,16进制颜色码
          Button2.text("注水开");          //设置app按键注释“开”
          Button2.print("on");
          oState = true;
      }
      break;
    case3:
      if(digitalRead(Relay_3)==LOW)
      {
          Button3.color("#808080");   //设置app按键是灰色,16进制颜色码
          Button3.text("排水关");          //设置app按键注释“关”
          Button3.print("off");
          oState = false;
      }
      else if(digitalRead(Relay_3==HIGH))
      {
          Button3.color("#FFA500");   //设置app按键是橙色,16进制颜色码
          Button3.text("排水开");          //设置app按键注释“开”
          Button3.print("on");
          oState = true;
      }
      break;
    case4:
      if(digitalRead(Relay_4)==LOW)
      {
          Button4.color("#808080");   //设置app按键是灰色,16进制颜色码
          Button4.text("加热棒关");          //设置app按键注释“关”
          Button4.print("off");
          oState = false;
      }
      else if(digitalRead(Relay_4==HIGH))
      {
          Button4.color("#FFA500");   //设置app按键是橙色,16进制颜色码
          Button4.text("加热棒开");          //设置app按键注释“开”
          Button4.print("on");
          oState = true;
      }
      break;
      default:
            break;
}
}
// 在APP控制,按下MainSwitch按键即会执行该函数
void button_callback(const String & state)
{
    BLINKER_LOG("操作了MainSwitch: ", state);//APP中的Monitor控件打印的信息
    if (state=="on")
    {
      ctrl_multi_outlet(OUTLET_ALL, LOW);//打开继电器--所有
      // 反馈继电器状态
      Button.color("#FFA500");   //设置app按键是橙色,16进制颜色码
      Button.text("开");          //设置app按键注释“开”
      Button.icon("fal fa-power-on");
      Button.print("on");
      Blinker.vibrate();//开启继电器时反馈,让手机震动
    } else if(state=="off")
    {
      ctrl_multi_outlet(OUTLET_ALL, HIGH);//关闭继电器--所有
      // 反馈继电器状态
      Button.color("#808080");   //设置app按键是橙色,16进制颜色码
      Button.text("关");          //设置app按键注释“开”
      Button.icon("fal fa-power-off");
      Button.print("off");
    }
}

// 在APP控制,按下Switch1按键即会执行该函数--第1路开关
void button1_callback(const String & state)
{
    BLINKER_LOG("get button state: ", state);//APP中的Monitor控件打印的信息
    if (state=="on")
    {
      ctrl_multi_outlet(OUTLET_NO_1,HIGH );//打开继电器--第1路
      // 反馈继电器状态
      RelayState(1);    //调用继电器反馈程序
    } else if(state=="off")
    {
      ctrl_multi_outlet(OUTLET_NO_1, LOW);//关闭继电器--第1路
      // 反馈继电器状态
      RelayState(1);    //调用继电器反馈程序
    }
}

// 在APP控制,按下Switch2按键即会执行该函数--第2路开关
void button2_callback(const String & state)
{
    BLINKER_LOG("get button state: ", state);//APP中的Monitor控件打印的信息
    if (state=="on")
    {
      ctrl_multi_outlet(OUTLET_NO_2,HIGH );//打开继电器--第2路
      // 反馈继电器状态
      RelayState(2);    //调用继电器反馈程序
    } else if(state=="off")
    {
      ctrl_multi_outlet(OUTLET_NO_2,LOW );//关闭继电器--第2路
      // 反馈继电器状态
      RelayState(2);    //调用继电器反馈程序
    }
}

// 在APP控制,按下Switch3按键即会执行该函数--第3路开关
void button3_callback(const String & state)
{
    BLINKER_LOG("get button state: ", state);//APP中的Monitor控件打印的信息
    if (state=="on")
    {
      ctrl_multi_outlet(OUTLET_NO_3, HIGH);//打开继电器--第3路
      // 反馈继电器状态
      RelayState(3);    //调用继电器反馈程序
    } else if(state=="off")
    {
      ctrl_multi_outlet(OUTLET_NO_3, LOW);//关闭继电器--第3路
      // 反馈继电器状态
      RelayState(3);    //调用继电器反馈程序
    }
}

// 在APP控制,按下Switch4按键即会执行该函数--第4路开关
void button4_callback(const String & state)
{
    BLINKER_LOG("get button state: ", state);//APP中的Monitor控件打印的信息
    if (state=="on")
    {
      ctrl_multi_outlet(OUTLET_NO_4, HIGH);//打开继电器--第4路
      // 反馈继电器状态
      RelayState(4);    //调用继电器反馈程序
    } else if(state=="off")
    {
      ctrl_multi_outlet(OUTLET_NO_4, LOW);//关闭继电器--第4路
      // 反馈继电器状态
      RelayState(4);    //调用继电器反馈程序
    }
}

//APP端状态手动刷新按钮
void button5_callback(const String & state)
{
for(int i=0;i<5;i++)
{
    RelayState(i);
}
}
//小爱同学控制插座多个插孔
void ctrl_multi_outlet(uint8_t num, uint8_t io_level)
{
    switch (num)
      {
            case 0://所有插孔
                digitalWrite(Relay_1, io_level);//控制继电器1
                digitalWrite(Relay_2, io_level);//控制继电器2
                digitalWrite(Relay_3, io_level);//控制继电器3
                digitalWrite(Relay_4, io_level);//控制继电器4
                break;
            case 1://插座插孔一
                digitalWrite(Relay_1, io_level);//控制继电器1
                break;
            case 2://插座插孔二
                digitalWrite(Relay_2, io_level);//控制继电器2
                break;
            case 3://插座插孔三
                digitalWrite(Relay_3, io_level);//控制继电器3
                break;
            case 4://插座插孔四
                digitalWrite(Relay_4, io_level);//控制继电器4
                break;
            default:
                break;
      }
}

//小爱电源类回调,例如:“打开插座”、“打开插座插孔一”、“打开插座插孔二”
void miotPowerState(const String & state, uint8_t num)
{
    BLINKER_LOG("need set outlet: ", num, ", power state: ", state);

    if (state == BLINKER_CMD_ON)
    {
      ctrl_multi_outlet(num, LOW);//打开继电器,num表示是多少路(继电器低电平出发)
      BlinkerMIOT.powerState("on", num);
      BlinkerMIOT.print();
      RelayState(num);

      oState = true;
    }
   else if (state == BLINKER_CMD_OFF)
    {
      ctrl_multi_outlet(num, HIGH);//关闭继电器,num表示是多少路

      BlinkerMIOT.powerState("off", num);
      BlinkerMIOT.print();
      RelayState(num);

      oState = false;
    }
}

//小爱设备查询的回调函数,查询设备状态,例如:“插座插孔一状态”
void miotQuery(int32_t queryCode,uint8_t num)
{
    BLINKER_LOG("插孔",num,"状态",",codes:", queryCode);

    switch (num)
    {
         case 0 :
            BLINKER_LOG("状态:");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
         case 1 :
            BLINKER_LOG("插孔1状态:");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
         case 2 :
            BLINKER_LOG("插孔2状态:");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
         case 3 :
            BLINKER_LOG("插孔3状态:");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
         case 4 :
            BLINKER_LOG("插孔4状态:");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
         default :
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
    }
}



//心跳包刷新状态
void heartbeat()
{
for(int i=0;i<5;i++)
{
    RelayState(i);
}
   TEMP.print(tempe);      //给blinkerapp回传温度数据
   WATER.print(tdsValue);      //给blinkerapp回传水质数据
   DEMP.print(data);         //给blinkerapp回传水位数据
}
//显示图表
void dataRead(const String & data)
{
    BLINKER_LOG("Blinker readString: ", data);

    uint32_t BlinkerTime = millis();

    Blinker.vibrate();      
    Blinker.print("millis", BlinkerTime);

    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
void dataStorage()
{
Blinker.dataStorage("tempe",tempe);      //app显示图表温度
Blinker.dataStorage("tdsValue",tdsValue);   //app显示图表水质
Blinker.dataStorage("data",data);         //app显示图表水位
}//图表 https://blog.csdn.net/weixin_64583141/article/details/125903980

void setup()
{
    // 初始化串口,用于调试,后期可删除
    Serial.begin(115200);
    BLINKER_DEBUG.stream(Serial);
    BLINKER_DEBUG.debugAll();

    servo.attach(13);//舵机接口D7
    servo.write(90);//360度舵机静止
    Slider1.attach(Slider1_feedamount);

    Button6.attach(Button6_callback);
   
    // 初始化有继电器的IO
    pinMode(Relay_1, OUTPUT);
    pinMode(Relay_2, OUTPUT);
    pinMode(Relay_3, OUTPUT);
    pinMode(Relay_4, OUTPUT);
    //初始化继电器初始状态
    digitalWrite(Relay_1, HIGH);       //继电器为低电平触发,初始化为HIGH
    digitalWrite(Relay_2, HIGH);
    digitalWrite(Relay_3, HIGH);
    digitalWrite(Relay_4, HIGH);
   
    //初始化blinker
   // Blinker.begin(auth);            //手机配网用这段
   
    Blinker.attachData(dataRead);            //图表数据获取
    Blinker.attachDataStorage(dataStorage);
   
    Blinker.begin(auth, ssid, pswd);//代码配网用这段
    Button.attach(button_callback);   //绑定按键回调
    Button1.attach(button1_callback); //绑定按键回调
    Button2.attach(button2_callback); //绑定按键回调
    Button3.attach(button3_callback); //绑定按键回调
    Button4.attach(button4_callback); //绑定按键回调
    Button5.attach(button5_callback);
   
    //小爱同学注册回调
    BlinkerMIOT.attachPowerState(miotPowerState); //注册小爱电源回调
    BlinkerMIOT.attachQuery(miotQuery);         //小爱设备查询的回调函数
   
    //心跳包,初始化
    Blinker.attachHeartbeat(heartbeat);         //app定时向设备发送心跳包, 设备收到心跳包后会返回设备当前状态

sensors.begin();
pinMode(TdsSensorPin, INPUT);
pinMode(hot,OUTPUT);
pinMode(Grove_Water_Sensor, INPUT); // The Water Sensor is an Input
pinMode(Water, OUTPUT); // The LED is an Output加热棒继电器打开
}

void loop()
{

Blinker.run();

   //获取水位cm
temp=(long)analogRead(5);//传感器连接引脚gpio5,D1
//根据最大值时候的模拟值计算出当前实际值
//data=(temp/650)*4;//最高4cm
//data=(temp/650)*20;//最高31.48cm
data=(temp/650)*10;//最高15.74cm
Serial.print("the depth is:");
Serial.print(data);
Serial.println("cm");
DEMP.print(data);
//获取水质
static unsigned long analogSampleTimepoint = millis();
if (millis() - analogSampleTimepoint > 40U)//every 40 milliseconds,read the analog value from the ADC
{
    analogSampleTimepoint = millis();
    analogBuffer = analogRead(TdsSensorPin);    //read the analog value and store into the buffer
    analogBufferIndex++;
    if (analogBufferIndex == SCOUNT)
      analogBufferIndex = 0;
}
static unsigned long printTimepoint = millis();
if (millis() - printTimepoint > 800U)
{
    printTimepoint = millis();
    for (copyIndex = 0; copyIndex < SCOUNT; copyIndex++)
      analogBufferTemp = analogBuffer;
    averageVoltage = getMedianNum(analogBufferTemp, SCOUNT) * (float)VREF / 1024.0; // read the analog value more stable by the median filtering algorithm, and convert to voltage value
    float compensationCoefficient = 1.0 + 0.02 * (tempe - 25.0); //temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0));
    float compensationVolatge = averageVoltage / compensationCoefficient; //temperature compensation
    tdsValue = (133.42 * compensationVolatge * compensationVolatge * compensationVolatge - 255.86 * compensationVolatge * compensationVolatge + 857.39 * compensationVolatge) * 0.5; //convert voltage value to tds value
    if(tdsValue < tdsValue_MAX){
    //digitalWrite(hot,HIGH);
    TDS.print("鱼缸水质硬度正常");
}else{
    //digitalWrite(hot,LOW);
    TDS.color("#FF0000");   //设置app按键是纯红色,16进制颜色码
    TDS.print("鱼缸水质偏高");
    Blinker.vibrate(1000);//鱼缸水质偏高时反馈,让手机震动
}
    Serial.print("voltage:");
    Serial.print(averageVoltage,2);
    Serial.print("V   ");
    Serial.print("TDS Value:");
    Serial.print(tdsValue, 0);
    Serial.println("ppm");
    WATER.print(tdsValue);
}
getTemperature();
//Blinker.delay(500);
getWaterHight();

}
//获取水位
void getWaterHight(){
/*   if(lock == 0){
      Serial.println("按钮已经关闭了");
      if( digitalRead(Grove_Water_Sensor) == HIGH) {
          digitalWrite(Water,LOW);
          WATERSTATUS.print("鱼缸水位正常,注水泵已关闭");
       }else {
          WATERSTATUS.color("#FF0000");   //设置app按键是纯红色,16进制颜色码
          digitalWrite(Water,HIGH);
          WATERSTATUS.print("鱼缸水位低,注水泵已打开");
       }
   }else{
      Serial.println("按钮已经开启 自动模式失效");
    }*/

      if( digitalRead(Grove_Water_Sensor) == HIGH) {
          digitalWrite(Water,LOW);
          WATERSTATUS.print("鱼缸水位正常,注水泵已关闭");
       }else {
          WATERSTATUS.color("#FF0000");   //设置app按键是纯红色,16进制颜色码
          digitalWrite(Water,HIGH);
          WATERSTATUS.print("鱼缸水位低,注水泵已打开");
       }

}
//获取温度并赋值
void getTemperature(){
sensors.requestTemperatures(); // 发送命令获取温度
//Serial.print("temperature: ");
tempe= (float)sensors.getTempCByIndex(0);
if(tempe < tempe_MAX){
    HOT.color("#FF0000");   //设置app按键是纯红色,16进制颜色码
    digitalWrite(hot,HIGH);
    HOT.print("鱼缸水温低于28℃,加热棒已打开");
}else{
    digitalWrite(hot,LOW);
    HOT.print("鱼缸水温正常,加热棒已关闭");
}
Serial.print("the temperature is:");
Serial.print(tempe);
Serial.println(" ℃");
TEMP.print(tempe);
}

int getMedianNum(int bArray[], int iFilterLen)
{
int bTab;
for (byte i = 0; i < iFilterLen; i++)
    bTab = bArray;
int i, j, bTemp;
for (j = 0; j < iFilterLen - 1; j++)
{
    for (i = 0; i < iFilterLen - j - 1; i++)
    {
      if (bTab > bTab)
      {
      bTemp = bTab;
      bTab = bTab;
      bTab = bTemp;
      }
    }
}
if ((iFilterLen & 1) > 0)
    bTemp = bTab[(iFilterLen - 1) / 2];
else
    bTemp = (bTab + bTab) / 2;
return bTemp;
}




shili 发表于 2022-9-30 16:04

楼主,app页面上的配置代码有教程码?

mzl 发表于 2022-9-30 16:06

shili 发表于 2022-9-30 16:04
楼主,app页面上的配置代码有教程码?

点灯app直接可以拖组件

shili 发表于 2022-9-30 16:06

感谢 楼主无私奉献,

Delay_mx 发表于 2022-10-10 15:15

你好,我也在做这个。不过没你那么多传感器。水位我原来用的是浮子开关,不知道这用的是哪个型号的水位传感器跟TDS?

mzl 发表于 2022-10-12 16:39

Delay_mx 发表于 2022-10-10 15:15
你好,我也在做这个。不过没你那么多传感器。水位我原来用的是浮子开关,不知道这用的是哪个型号的水位传感 ...

水位传感器就是1块钱一个那个 容易腐蚀 可以买一个非接触式的液体传感器
水质是模拟TDS水质传感器
页: [1]
查看完整版本: 鱼缸毕设 esp8266 arduino 点灯·blinker 小爱同学