arduino / esp8266

NodeMcu ESP8266

因為不裝壓力桶,所以一般市場上的微電腦控制不能滿足我的需求(前段水問題)
也趁著假日把家裡的RO飲水機給物聯網化
透過ESP8266的HTTP CLIENT把製水狀況發送到LINE

//D1=5接腳,水源開關,通電0表示有水才可製水
int switch01 = 5;

//D2=4接腳,高壓開關,通電0表示缺水,且要有水源時即可開始製水
int switch02 =  4;

//D5=14接腳,馬達及入水閥電源relay01,使用低壓觸發
int relay01 = 14;

//D6=12接腳,控制沖洗開關relay02,只沖洗8秒
int relay02 = 12;

//D7=13接腳,控制前段水排出不飲用relay03,前段水120秒不取用
int relay03 = 13;

//D8=15接腳,異常蜂鳴器
int buzzer = 15;

//用來計數已製水多少秒
int startTime01 = 0;

//用來計數已停水多少秒
int startTime02 = 0;

//警告時間
int errorTime01 =3600;

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

void setup() {
  // put your setup code here, to run once:

  Serial.begin(115200);

  //板子上的LED,當製水時給LOW亮燈
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);//通電時預設關閉

  //水源開關,通電0表示有水才可製水
  pinMode( switch01, INPUT_PULLUP);

  //高壓開關,通電0表示缺水,且要有水源時即可開始製水
  pinMode( switch02, INPUT_PULLUP);

  //馬達及入水閥電源relay01,使用低壓觸發
  pinMode( relay01, OUTPUT);
  digitalWrite( relay01, HIGH);//通電時預設關閉

  //控制沖洗開關relay02,只沖洗8秒,使用低壓觸發
  pinMode( relay02, OUTPUT);
  digitalWrite( relay02, HIGH);//通電時預設關閉

  //控制前段水排出不飲用relay03,前段水120秒不取用
  pinMode( relay03, OUTPUT);
  digitalWrite( relay03, HIGH);//通電時預設關閉

  //異常蜂鳴器
  pinMode( buzzer, OUTPUT);
  digitalWrite( buzzer, LOW);//通電時預設關閉


  WiFi.begin("SSID", "PASSWORD");

  while(WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(F("."));
  }
  Serial.println();
  Serial.println(F("WiFi connected"));

  // Print the IP address
  Serial.println(WiFi.localIP());

}

void loop() {
  // put your main code here, to run repeatedly:

  //1秒執行一次
  delay(1000);

  //水源開關:當水源缺水時=1進入且最後需停止, 1開路缺水 0閉路有水
  if ( digitalRead(switch01) == 1)
  {

    startTime01 = 0;
    digitalWrite( relay01, HIGH);
    digitalWrite( relay02, HIGH);
    digitalWrite( relay03, HIGH);
    digitalWrite(LED_BUILTIN, HIGH);

    startTime02++;
    //如果停水太久,響叫鳴蜂器
    if(startTime02 > errorTime01)
    {
      digitalWrite( buzzer, HIGH);
    }
    else
    {
      digitalWrite( buzzer, LOW);
    }


    Serial.print("switch01=");
    Serial.println(startTime02);
    return;
  }

  //不缺水歸0
  startTime02 = 0;

/*
 * 先使用多壓1秒
  //第一次偵測缺水時,先等2秒,因有可能觸碰到管路,一下下即可恢復,是不用製水的
  if( digitalRead(switch02) == 0 && startTime01==0 )
  {
    Serial.println("wait 2S...");
    delay(2000);
  }
*/

  //高壓開關:當滿水時=1進入且最後需停止
  if ( digitalRead(switch02) == 1)
  {

    //如果startTime01不等於0,那表示剛製水完成,發送通知
    if (startTime01 != 0)
    {

      //剛滿水時多加壓避免微誤動
      delay(1500);
      digitalWrite( relay01, HIGH);
      digitalWrite( relay02, HIGH);
      digitalWrite( relay03, HIGH);
      digitalWrite( buzzer, LOW);
      digitalWrite(LED_BUILTIN, HIGH);

      String l_url = "http://192.168.123.2/ro.php?startTime01="+String(startTime01);
      //String l_time = String(startTime01);
      //String l_url01 = l_url+l_time;
      
      Serial.println(l_url);
      //WiFi.disconnect();

      
      WiFiClient client;
      HTTPClient http;

      if (http.begin(client, l_url))
      {
        int httpCode = http.GET();
        Serial.printf("[HTTP] GET... code: %d\n", httpCode);
        /*
          String payload = http.getString();
          Serial.println(payload);
        */
      }
      
      Serial.println("send mail");
      startTime01 = 0;
      return;
    }

    startTime01 = 0;
    digitalWrite( relay01, HIGH);
    digitalWrite( relay02, HIGH);
    digitalWrite( relay03, HIGH);
    digitalWrite( buzzer, LOW);
    digitalWrite(LED_BUILTIN, HIGH);
    
    Serial.println("switch02=0");
    return;
  }

  startTime01++;

  digitalWrite(LED_BUILTIN, LOW);
  digitalWrite( relay01, LOW);
  //控制沖洗開關,只沖洗10秒
  if(startTime01 < 11)
  {
    digitalWrite(relay02, LOW);
  }
  else
  {
    digitalWrite(relay02, HIGH);
  }

  //控制前段水排出不飲用relay03,前段水120秒不取用
  if(startTime01 < 120)
  {
    digitalWrite(relay03, LOW);
  }
  else
  {
    digitalWrite(relay03, HIGH);
  }

  //如果製水太久,響叫鳴蜂器
  if(startTime01 > errorTime01)
  {
    digitalWrite( buzzer, HIGH);
  }
  else
  {
    digitalWrite( buzzer, LOW);
  }
  Serial.print("startTime01:");
  Serial.println(startTime01);
}

php Line Notify
http://192.168.31.1:81/ro_line.php?startTime01=1238

<?php
        $headers = array(
                'Content-Type: multipart/form-data',
                'Authorization: Bearer mOhPIFK2NBPZaxIHn8CXwAb2auU8hYGsqbLkeL2UG1c'
                //wzn8UXvyTvzcdPVeVoyM2MPkOyGl84AnbEzuCEADvoZ
                //'Authorization: Bearer wzn8UXvyTvzcdPVeVoyM2MPkOyGl84AnbEzuCEADvoZ'
        );
        $message = array(
                'message' => 'time:'.$_GET["startTime01"]
        );
        $ch = curl_init();
        curl_setopt($ch , CURLOPT_URL , "https://notify-api.line.me/api/notify");
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $message);
        $result = curl_exec($ch);
        echo $result;
        curl_close($ch);
?>

水塔

#include <ESP8266WiFi.h>

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  Serial.begin(9600);

  WiFi.begin("apssid", "pass");
  while(WiFi.status() != WL_CONNECTED)
  {
    delay(1000);
    Serial.print(F("."));
  }
  Serial.println(WiFi.localIP());

  line("time:1");
}

int startTime01 = 0;

void loop() {
  delay(1000);
  startTime01++;
  if(startTime01 > 541)
  {
    if( startTime01 % 540 == 0 )
    {
      String line_msg = "超時:"+String(startTime01);
      line(line_msg);
    }
  }

}

WiFiClientSecure client;
void line(String msg) {
  client.setInsecure();
  if (client.connect("notify-api.line.me",443)) {
    String data = "message="+msg;
    client.println("POST /api/notify HTTP/1.1");
    client.println("Host: notify-api.line.me");
    client.println("Authorization: Bearer 5oF8K44hd45iw8dLBw789YBpgMU3DHOqi2LDiGwjm0C");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.println(data);
  }
  client.stop();
}

超音波

#include <Ultrasonic.h>

#define TRIGGER 5  // NodeMCU D1 腳
#define ECHO    4  // NodeMCU D2 腳
Ultrasonic ultrasonic(TRIGGER, ECHO);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
    
}

int startTime01 = 0;

void loop() {
  // put your main code here, to run repeatedly:
  Serial.print("Distance: ");
  Serial.print(ultrasonic.distanceRead());  //讀取距離
  Serial.println(" CM");
  delay(2000);
}

溫度DHT11

#include "DHT.h"        // including the library of DHT11 temperature and humidity sensor
#define DHTTYPE DHT11   // DHT 11

#define dht_dpin D6
DHT dht(dht_dpin, DHTTYPE); 

void setup() {
  // put your setup code here, to run once:
  dht.begin();
  Serial.begin(9600);
  Serial.println("Humidity and temperature \n\n");
  Serial.println("==========================================");
  delay(700);
}


void loop() {

    Serial.print(D6);
    float h = dht.readHumidity();
    float t = dht.readTemperature();         
    Serial.print("Current humidity = ");
    Serial.print(h);
    Serial.print("%  ");
    Serial.print("temperature = ");
    Serial.print(t); 
    Serial.println("C  ");
    delay(3000);
}

LINE Notify

#include <ESP8266WiFi.h>

void setup() {
  Serial.begin(9600);

  WiFi.begin("apssid", "pass");
  while(WiFi.status() != WL_CONNECTED)
  {
    delay(1000);
    Serial.print(F("."));
  }
  Serial.println(WiFi.localIP());
  
  line("許尊測試aa");
}
void loop() {
  delay(2000);
}

WiFiClientSecure client;
void line(String msg) {
  client.setInsecure();
  if (client.connect("notify-api.line.me",443)) {
    String data = "message="+msg;
    client.println("POST /api/notify HTTP/1.1");
    client.println("Host: notify-api.line.me");
    client.println("Authorization: Bearer 5oF8K44hd45iw8dLBw789YBpgMU3DHOqi2LDiGwjm0C");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.println(data);
  }
  client.stop();
}

讀取網頁

void getHtml() {
  WiFiClient client;
  //WiFiClientSecure client;
  //client.setInsecure();
  HTTPClient http;
  Serial.println("a");
  if (http.begin(client, "http://192.168.31.1:81/audio.php"))
  {
    Serial.println("b");
    int httpCode = http.GET();
    Serial.printf("[HTTP] GET... code: %d\n", httpCode);
    String payload = http.getString();
    Serial.println(payload);
  }
}

網頁控制led

#include <ESP8266WiFi.h>

WiFiServer server(80);
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  WiFi.begin("AP168", "pass");
  while(WiFi.status() != WL_CONNECTED)
  {
    delay(1000);
    Serial.print(F("."));
  }
  Serial.println(WiFi.localIP());

  server.begin();
}


void loop() {
  // put your main code here, to run repeatedly:
  delay(2000);
  WiFiClient client = server.available();
  if (client) {
    if (client.available()) {
      String req = client.readStringUntil('\r');
      client.println("HTTP/1.1 200 OK");
      client.println("Content-type:text/html; charset=utf-8");
      client.println("Connection: close");
      client.println();

      if (req.indexOf("/led/off") != -1) {
        digitalWrite(LED_BUILTIN, HIGH);
        client.println("OFF");
      }else if (req.indexOf("/led/on") != -1) {
        digitalWrite(LED_BUILTIN, LOW);
        client.println("ON");
      }else{
        client.println("fuck168");
      }
    }
  }
  Serial.println("end123");
}

#深度睡眠作業流程
1.借助深度睡眠,應用程序範例如下所示:
2.ESP8266連接到Wi-Fi
3.ESP8266執行任務(讀取感測器,發布MQTT消息等)
4.睡眠一段預定的時間
5.ESP8266喚醒
6.一遍又一遍地重複該過程
喚醒方法
#1定時器喚醒: ESP8266在預定義的時間段後自行喚醒
2外部喚醒:按RST按鈕時ESP8266喚醒(ESP8266重新啟動)
要使用ESP8266的定時器喚醒功能,您需要在NodeMCU板中將RST引腳連接到標有D0的GPIO 16 。

void setup() {
  Serial.begin(115200);
  Serial.setTimeout(2000);

  // 等待序列初始化。
  while(!Serial) { }
  
  // 深度睡眠模式設定60秒,ESP8266自身喚醒,當GPIO 16(在Nodemcu板D0)連接到復位引腳時
  Serial.println("我醒了, 但我將進入深度睡眠模式60秒");
  ESP.deepSleep(60e6); 
  
  // 深睡眠模式直到復位引腳連接到LOW信號(例如按鈕或磁性簧片開關)
  //Serial.println("我醒了, 但我將進入深度睡眠模式直到RESET引腳收到LOW信號");
  //ESP.deepSleep(0); 
}

void loop() {
}

賀眾版

//D1=5接腳,水源開關,通電0表示有水才可製水
int switch01 = 5;

//D2=4接腳(藍),高水位偵測器,1滿水,需立即停止
int switch02 =  4;

//D3=0接腳(橙),低水位偵測器,1缺水,可開始製水
int switch03 =  3;

//D5=14接腳,馬達及入水閥電源relay01,使用低壓觸發
int relay01 = 14;

//D6=12接腳,控制沖洗開關relay02,只沖洗8秒
int relay02 = 12;

//D7=13接腳,控制前段水排出不飲用relay03,前段水120秒不取用
int relay03 = 13;

//D8=15接腳,異常蜂鳴器
int buzzer = 15;

//用來計數已製水多少秒
int startTime01 = 0;

//用來計數已停水多少秒
int startTime02 = 0;

//製水開關
int playRO = 0;

//警告時間
int errorTime01 =3600;

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

void setup() {
  // put your setup code here, to run once:

  Serial.begin(115200);

  //板子上的LED,當製水時給LOW亮燈
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);//通電時預設關閉

  //水源開關,通電0表示有水才可製水
  pinMode( switch01, INPUT_PULLUP);

  //D2=4接腳(藍),高水位偵測器,1滿水,需立即停止
  pinMode( switch02, INPUT_PULLUP);

  //D3=0接腳(橙),低水位偵測器,1缺水,可開始製水
  pinMode( switch03, INPUT_PULLUP);

  //馬達及入水閥電源relay01,使用低壓觸發
  pinMode( relay01, OUTPUT);
  digitalWrite( relay01, HIGH);//通電時預設關閉

  //控制沖洗開關relay02,只沖洗8秒,使用低壓觸發
  pinMode( relay02, OUTPUT);
  digitalWrite( relay02, HIGH);//通電時預設關閉

  //控制前段水排出不飲用relay03,前段水120秒不取用
  pinMode( relay03, OUTPUT);
  digitalWrite( relay03, HIGH);//通電時預設關閉

  //異常蜂鳴器
  pinMode( buzzer, OUTPUT);
  digitalWrite( buzzer, LOW);//通電時預設關閉


  WiFi.begin("AP168", "pass");

  while(WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(F("."));
  }
  Serial.println();
  Serial.println(F("WiFi connected"));

  // Print the IP address
  Serial.println(WiFi.localIP());

}

void loop() {
  // put your main code here, to run repeatedly:

  //1秒執行一次
  delay(1000);

  //水源開關:當水源缺水時=1進入且最後需停止, 1開路缺水 0閉路有水
  if ( digitalRead(switch01) == 1)
  {

    startTime01 = 0;
    digitalWrite( relay01, HIGH);
    digitalWrite( relay02, HIGH);
    digitalWrite( relay03, HIGH);
    digitalWrite(LED_BUILTIN, HIGH);

    startTime02++;
    //如果停水太久,響叫鳴蜂器
    if(startTime02 > errorTime01)
    {
      digitalWrite( buzzer, HIGH);
    }
    else
    {
      digitalWrite( buzzer, LOW);
    }


    Serial.print("switch01=");
    Serial.println(startTime02);
    return;
  }

  //不缺水歸0
  startTime02 = 0;


  Serial.print("switch02:");
  Serial.println(digitalRead(switch02));
    Serial.print("switch03:");
  Serial.println(digitalRead(switch03));


  //低水位偵測器,1缺水,可開始製水
  if ( digitalRead(switch03) == 0)
  {
    playRO = 1;
  }

  //高水位偵測器,1滿水,需立即停止
  if ( digitalRead(switch02) == 0)
  {
    playRO = 0;
  }


  //playRO=0,表示尚有水
  if ( playRO == 0)
  {

    //如果startTime01不等於0,那表示剛製水完成,發送通知
    if (startTime01 != 0)
    {

      digitalWrite( relay01, HIGH);
      digitalWrite( relay02, HIGH);
      digitalWrite( relay03, HIGH);
      digitalWrite( buzzer, LOW);
      digitalWrite(LED_BUILTIN, HIGH);

      String l_url = "http://192.168.31.1:81/ro_line.php?startTime01="+String(startTime01);
      //String l_time = String(startTime01);
      //String l_url01 = l_url+l_time;
      
      Serial.println(l_url);
      //WiFi.disconnect();

      
      WiFiClient client;
      HTTPClient http;

      if (http.begin(client, l_url))
      {
        int httpCode = http.GET();
        Serial.printf("[HTTP] GET... code: %d\n", httpCode);
      }
      
      Serial.println("send mail");
      startTime01 = 0;
      return;
    }

    startTime01 = 0;
    digitalWrite( relay01, HIGH);
    digitalWrite( relay02, HIGH);
    digitalWrite( relay03, HIGH);
    digitalWrite( buzzer, LOW);
    digitalWrite(LED_BUILTIN, HIGH);
    
    Serial.println("switch02=0");
    return;
  }

  startTime01++;

  digitalWrite(LED_BUILTIN, LOW);
  digitalWrite( relay01, LOW);
  //控制沖洗開關,只沖洗10秒
  if(startTime01 < 11)
  {
    digitalWrite(relay02, LOW);
  }
  else
  {
    digitalWrite(relay02, HIGH);
  }

  //控制前段水排出不飲用relay03,前段水120秒不取用
  if(startTime01 < 120)
  {
    digitalWrite(relay03, LOW);
  }
  else
  {
    digitalWrite(relay03, HIGH);
  }

  //如果製水太久,響叫鳴蜂器
  if(startTime01 > errorTime01)
  {
    digitalWrite( buzzer, HIGH);
  }
  else
  {
    digitalWrite( buzzer, LOW);
  }
  Serial.print("startTime01:");
  Serial.println(startTime01);
}

彰草家水塔抽水記錄

#include <ESP8266WiFi.h>


void setup() {
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  Serial.begin(9600);

  WiFi.begin("apssid", "pass");
  while(WiFi.status() != WL_CONNECTED)
  {
    delay(1000);
    Serial.print(F("."));
  }
  Serial.println(WiFi.localIP());

  line("開始...");

}

int startTime01 = 0;

void loop() {

  delay(1000);
  startTime01++;

  //Serial.println(startTime01);
  if( startTime01 % 2 == 0 )
  {
    digitalWrite(LED_BUILTIN, HIGH);
    //Serial.println("LOW");
  }
  else
  {
    digitalWrite(LED_BUILTIN, LOW);
    //Serial.println("HIGH");
  }

  if(startTime01 > 541)
  {
    if( startTime01 % 540 == 0 )
    {
      String line_msg = "超時:"+String(startTime01);
      line(line_msg);
    }
  }

}


WiFiClientSecure client;
void line(String msg) {
  client.setInsecure();
  if (client.connect("notify-api.line.me",443)) {
    String data = "message="+msg;
    client.println("POST /api/notify HTTP/1.1");
    client.println("Host: notify-api.line.me");
    client.println("Authorization: Bearer XxvczpI3sKY9rDu9azlMX5rF1wuxVbD8KoIG3k6vhWh");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.println(data);
  }
  client.stop();
}

ESP8266 HTTP版 抽水加RO 20140127備份

#include <ESP8266WiFi.h>

String g_ip = "";
int g_playRoCnt = 0;

//run time
unsigned long g_runTime = 0;
WiFiServer server(80);

//馬達及入水閥電源relay01,使用低壓觸發
int relay01 = D0;
//控制沖洗開關relay02,只沖洗8秒,使用低壓觸發
int relay02 = D1;
//控制前段水排出不飲用relay03,前段水60秒不取用
int relay03 = D2;

//水源偵測器,短路表示有水
int Sensor_water = D5;
//高水位偵測器
int Sensor_highLine = D6;
//低水位偵測器
int Sensor_lowLine = D7;

//蜂鳴器
int buzzer = D8;

//水塔偵測器
int Sensor_PumpWater = D9;



//-------------------------  水塔抽水偵測 START  -------------------------
//用來計數已抽水多少秒
int startPumpTime = 0;
//運時超過20分line+警告3短音,且後續每5分line警告
int startPumpTimeOver = 60 * 20;

void check_PumpWater() {

  //1=馬達沒有在抽水
  if ( digitalRead(Sensor_PumpWater) == 1)
  {

    //如果startPumpTime不等於0,那表示剛製水完成,發送通知
    if (startPumpTime != 0)
    {
      String l_msg = "完成 "+TimeFormate(startPumpTime);
      String l_line_token = "5oF8K44hd45iw8dLBw789YBpgMU3DHOqi2LDiGwjm0C";
      sendLine( l_msg, l_line_token);
    }
    startPumpTime = 0;
    return;
  }

  startPumpTime++;

  //抽水超時警告
  if( startPumpTime >= startPumpTimeOver)
  {
    //每超過5分鐘發line通知警告一次
    if( startPumpTime % 300 == 0 )
    {
      String l_msg = "超時 "+TimeFormate(startPumpTime);
      String l_line_token = "5oF8K44hd45iw8dLBw789YBpgMU3DHOqi2LDiGwjm0C";
      sendLine( l_msg, l_line_token);
    }
    bb(3);
  }
}
//-------------------------  水塔抽水偵測 END  -------------------------

//-------------------------  RO水源偵測 START  -------------------------
//用來計數已停水多少秒
int RoWaterMissTime = 0;
//超過30分鐘沒有水源,警告
int RoWaterMissTimeOver = 60 * 30;

bool ckeck_RoWaterMiss() {

  //水源開關:當水源缺水時=1進入停止
  if ( digitalRead(Sensor_water) == 1)
  {
    RoWaterMissTime++;

    //停水超時警告
    if( RoWaterMissTime >= RoWaterMissTimeOver)
    {
      if( RoWaterMissTime % RoWaterMissTimeOver == 0 )
      {
        String l_msg = "無水源 "+TimeFormate(RoWaterMissTime);
        String l_line_token = "i82ej11WC8Z12j77tmxtRGC6H45NWaE7e7gkuMjjglw";
        sendLine( l_msg, l_line_token);
      }
      bb(1);
    }
    
    return true;
  }
  //不缺水歸0
  RoWaterMissTime = 0;
  return false;
}














void setup() {
  Serial.begin(115200);
  WiFi.begin("AP168", "n0911661293");

  //蜂鳴器
  pinMode( buzzer, OUTPUT);

  //馬達及入水閥電源relay01,使用低壓觸發
  pinMode( relay01, OUTPUT);
  digitalWrite( relay01, HIGH);//通電時預設關閉
  //控制沖洗開關relay02,只沖洗8秒,使用低壓觸發
  pinMode( relay02, OUTPUT);
  digitalWrite( relay02, HIGH);//通電時預設關閉
  //控制前段水排出不飲用relay03,前段水30秒不取用
  pinMode( relay03, OUTPUT);
  digitalWrite( relay03, HIGH);//通電時預設關閉

  while(WiFi.status() != WL_CONNECTED)
  {
    delay(1000);
    Serial.print(F("."));
  }
  Serial.println();
  g_ip = WiFi.localIP().toString();
  Serial.println(g_ip);


  //板子上的LED,當製水時給LOW亮燈
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);//通電時預設關閉

  pinMode( Sensor_water,     INPUT_PULLUP);
  pinMode( Sensor_lowLine,   INPUT_PULLUP);
  pinMode( Sensor_highLine,  INPUT_PULLUP);
  //水塔抽水偵測器
  pinMode( Sensor_PumpWater, INPUT_PULLUP);


  //蜂鳴器
  digitalWrite( buzzer, HIGH);
  delay(300);
  digitalWrite( buzzer, LOW);

  server.begin();
}


//用來計數已製水多少秒
int startTime01 = 0;
//製水開關
int playRO = 0;
//用來計數已製水多少秒
int playRoTime = 0;
int playRoTimeOver = 60 * 20;

void loop() {
  delay(1000);
  g_runTime++;
  //呼吸燈 5秒閃1秒
  if( g_runTime % 6 == 1 ) digitalWrite(LED_BUILTIN, HIGH);
  if( g_runTime % 6 == 0 ) digitalWrite(LED_BUILTIN, LOW);

  webServer();
  check_PumpWater();

  //製水計時器
  startTime01++;

  //低水位偵測器,0=缺水,可開始製水
  if ( digitalRead(Sensor_lowLine) == 0) playRO = 1;

  //高水位偵測器,0=滿水,需立即停止
  if ( digitalRead(Sensor_highLine) == 0) playRO = 0;

//如果RO水源缺水就必須立即停止
  if( ckeck_RoWaterMiss() ) playRO = 0;

  //playRO=0,表示尚有水
  if ( playRO == 0)
  {
    digitalWrite( relay01, HIGH);
    digitalWrite( relay02, HIGH);
    digitalWrite( relay03, HIGH);

    //如果playRoTime不等於0,那表示剛製水完成,發送通知
    if (playRoTime != 0)
    {
      g_playRoCnt++;
      String l_msg = "完成 "+TimeFormate(playRoTime);
      String l_line_token = "i82ej11WC8Z12j77tmxtRGC6H45NWaE7e7gkuMjjglw";
      sendLine( l_msg, l_line_token);
    }

    playRoTime = 0;
    return;
  }

  //製水計時器
  playRoTime++;

  //RO製水超時警告,強制停止
  if( playRoTime >= playRoTimeOver)
  {
    digitalWrite( relay01, HIGH);
    digitalWrite( relay02, HIGH);
    digitalWrite( relay03, HIGH);

    if( playRoTime == playRoTimeOver )
    {
      String l_msg = "RO製水超時警告,已經強制停止 "+TimeFormate(playRoTime);
      String l_line_token = "i82ej11WC8Z12j77tmxtRGC6H45NWaE7e7gkuMjjglw";
      sendLine( l_msg, l_line_token);
    }
    bb(4);
    return;
  }



  //製水呼吸燈
  if( g_runTime % 2 == 0 ) digitalWrite(LED_BUILTIN, LOW);

  //馬達及入水閥電源
  digitalWrite( relay01, LOW);

  //控制前段水排出不飲用
  if(playRoTime <= 60)
  {
    digitalWrite( relay02, LOW);
    //控制沖洗開關10(s)
    if(playRoTime <= 10)
    {
      digitalWrite( relay03, LOW);
    }
    else
    {
      digitalWrite( relay03, HIGH);
    }
  }
  else
  {
    digitalWrite( relay02, HIGH);
  }
}

void webServer()
{
  WiFiClient client = server.available();
  if (!client) return;

  client.print("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");


  client.print("<html><head>");
    client.print("<title>NodeMCU ESP8266 Status</title>");
    client.print("<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />");
    client.print("<meta http-equiv=\"refresh\" content=\"3\" />");
    client.print("<link rel=\"icon\" href=\"data:,\">");
    client.print("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />");
    client.print("<script>if (navigator.userAgent.indexOf(\"Line\") > -1) location.href  += \"?openExternalBrowser=1\";</script>");
  client.print("</head><body>");

    client.print("🕛開機時間:");
    client.print(TimeFormate(g_runTime));
    client.print("<hr />");
    //g_playRoCnt
    client.print("🏃製水次數:");
    client.print(g_playRoCnt);
    //RO製水超時警告,強制停止
    if( playRoTime >= playRoTimeOver) client.print("<br />RO製水超時,❌❌❌已經強制停止,需拔電重開!!!");
    client.print("<br />");
    client.print("• 大馬達(D0):");
    if( digitalRead(relay01) == 0 )
    {
      client.print("⚡運作中 ⏳");
      client.print( String(playRoTime) + "/" + String(playRoTimeOver) );
    }
    else
    {
      client.print("💤停止");
    }
    client.print("<br />");

    client.print("• 前段水(D1):");
    if( digitalRead(relay02) == 0 )
    {
      client.print("⚡運作中");
    }
    else
    {
      client.print("💤停止");
    }
    client.print("<br />");

    client.print("• 前沖洗(D2):");
    if( digitalRead(relay03) == 0 )
    {
      client.print("⚡運作中");
    }
    else
    {
      client.print("💤停止");
    }
    client.print("<div style='border-top: 1px dashed #c5c5c5;'></div>");
    

    client.print("• 水 源(D5):");
    if( digitalRead(Sensor_water) == 1 )
    {
      client.print("❌缺水《開路》");
      client.print(String(RoWaterMissTime) + "/" + String(RoWaterMissTimeOver));

    }
    else
    {
      client.print("✔️正常《閉路》");
    }
    client.print("<br />");

    client.print("• 上水位(D6):");
    if( digitalRead(Sensor_highLine) == 0 )
    {
      if( digitalRead(Sensor_lowLine) == 0 )
      {
        client.print("⚠️⚠️⚠️異常上水位滿水,下水位缺水");
      }
      else
      {
        client.print("💦滿水《閉路》");
        if( playRoTime > 10) client.print(",確還在製水❌❌❌❌");
      }
    }
    else
    {
      if( digitalRead(Sensor_lowLine) == 0 )
      {
        client.print("❌缺水《開路》");
      }
      else
      {
        client.print("💧中間《開路》");
      }
    }
    client.print("<br />");

    client.print("• 下水位(D7):");
    if( digitalRead(Sensor_lowLine) == 0 )
    {
      client.print("❌缺水《閉路》");
    }
    else
    {
      client.print("💧有水《開路》");
    }

    client.print("<hr />");
    client.print("📣📣📣(警示聲說明)<br />");
    client.print("• 蜂鳴器(D8):");
    client.print(digitalRead(buzzer));
    client.print("<br />");
    client.print("• 1短嗶:RO缺水源<br />");
    client.print("• 3短嗶:抽水超時警告<br />");
    client.print("• 4短嗶:RO製水超時警告,強制停止");

    client.print("<hr />");
    client.print("• 抽水馬達(RX):");
    if( digitalRead(Sensor_PumpWater) == 0 )
    {
      client.print("⚡運作中 ⏳" + String(startPumpTime) + "/" + String(startPumpTimeOver));
      if( startPumpTime >= startPumpTimeOver) client.print("❌");
    }
    else
    {
      client.print("💤停止");
    }
    client.print("<br />👨‍💻注意:抽水時無法上傳固件!");

  client.print("</body></html>\r\n");

}

String TimeFormate(int seconds)
{
  unsigned int minutes = seconds / 60;
  unsigned int hours = minutes / 60;
  unsigned int days = hours / 24;
  seconds %= 60;
  minutes %= 60;
  hours %= 24;

  String l_time = "";

  if( days > 0 ) l_time = String(days)+"D ";

  if (hours > 0)
  {
    if (hours < 10)
    {
      l_time += "0";
    }
    l_time += String(hours) + ":";
  }

  if (minutes < 10)
  {
    l_time += "0";
  }
  l_time += String(minutes) + ":";

  if (seconds < 10)
  {
    l_time += "0";
  }
  l_time += String(seconds);
  return l_time;
}



void sendLine(String msg, String line_token) {

  WiFiClientSecure client;
  //debug
  //line_token = "mOhPIFK2NBPZaxIHn8CXwAb2auU8hYGsqbLkeL2UG1c";

  msg += "\nhttp://";
  msg += g_ip;

  client.setInsecure();
  if (client.connect("notify-api.line.me",443)) {
    String data = "message="+msg;
    client.println("POST /api/notify HTTP/1.1");
    client.println("Host: notify-api.line.me");
    client.println("Authorization: Bearer " + line_token);
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.println(data);
  }
  client.stop();
}


void bb(int ct)
{
  //不影響主線程,10秒來一次
  if( g_runTime % 10 == 0 )
  {
    //1短聲:缺水
    //2短聲:啟動太久
    for(int i=0;i<ct;i++)
    {
      digitalWrite( buzzer, HIGH);
      delay(100);
      digitalWrite( buzzer, LOW);
      delay(100);
    }
  }
}

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。