#include <BluetoothSerial.h>
BluetoothSerial SerialBT;
//馬達及入水閥電源relay01,使用低壓觸發
int relay01 = 25;
//控制沖洗開關relay02,只沖洗8秒,使用低壓觸發
int relay02 = 33;
//控制前段水排出不飲用relay03,前段水30秒不取用
int relay03 = 32;
//用來計數已製水多少秒
int playRoTime = 0;
int playRoTimeOver = 60 * 20;
//製水開關
int playRO = 0;
//水源偵測器,短路表示有水
int Sensor_RoWater = 21;
//低水位偵測器
int Sensor_lowLine = 22;
//高水位偵測器
int Sensor_highLine = 23;
//水塔抽水偵測器
int Sensor_PumpWater = 18;
//蜂鳴器
int buzzer = 19;
//------------------------- TDS START -------------------------
#define TdsSensorPin 35
#define VREF 3.3 // analog reference voltage(Volt) of the ADC
#define SCOUNT 1 // sum of sample point
int analogBuffer[SCOUNT]; // store the analog value in the array, read from ADC
int analogBufferTemp[SCOUNT];
int analogBufferIndex = 0;
int copyIndex = 0;
float averageVoltage = 0;
float tdsValue = 0;
float tdsValueMax = 0;
float tdsValueAvg = 0;
float tdsValueMin = 0;
String tdsValueStr = "";
float temperature = 25; // current temperature for compensation
// median filtering algorithm
int getMedianNum(int bArray[], int iFilterLen){
int bTab[iFilterLen];
for (byte i = 0; i<iFilterLen; i++)
bTab[i] = bArray[i];
int i, j, bTemp;
for (j = 0; j < iFilterLen - 1; j++) {
for (i = 0; i < iFilterLen - j - 1; i++) {
if (bTab[i] > bTab[i + 1]) {
bTemp = bTab[i];
bTab[i] = bTab[i + 1];
bTab[i + 1] = bTemp;
}
}
}
if ((iFilterLen & 1) > 0){
bTemp = bTab[(iFilterLen - 1) / 2];
}
else {
bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
}
return bTemp;
}
void getTDS()
{
static unsigned long analogSampleTimepoint = millis();
if(millis()-analogSampleTimepoint > 40U){ //every 40 milliseconds,read the analog value from the ADC
analogSampleTimepoint = millis();
analogBuffer[analogBufferIndex] = 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[copyIndex] = analogBuffer[copyIndex];
// read the analog value more stable by the median filtering algorithm, and convert to voltage value
averageVoltage = getMedianNum(analogBufferTemp,SCOUNT) * (float)VREF / 4096.0;
//temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0));
float compensationCoefficient = 1.0+0.02*(temperature-25.0);
//temperature compensation
float compensationVoltage=averageVoltage/compensationCoefficient;
//convert voltage value to tds value
tdsValue=(133.42*compensationVoltage*compensationVoltage*compensationVoltage - 255.86*compensationVoltage*compensationVoltage + 857.39*compensationVoltage)*0.5;
Serial.print("voltage:");
Serial.print(averageVoltage,2);
Serial.print("V ");
Serial.print("TDS Value:");
Serial.print(tdsValue,0);
Serial.println("ppm");
}
}
}
//------------------------- TDS END -------------------------
//------------------------- LINE START -------------------------
#include <WiFi.h>
#include <WiFiClientSecure.h>
WiFiClientSecure client;
void sendLine(String msg, String line_token) {
//debug
line_token = "mOhPIFK2NBPZaxIHn8CXwAb2auU8hYGsqbLkeL2UG1c";
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();
Serial.println("send line:" + msg);
Serial.println("token:"+line_token);
}
//------------------------- LINE END -------------------------
//------------------------- 水塔抽水偵測 START -------------------------
//用來計數已抽水多少秒
int startPumpTime = 0;
//運時超過20分line+警告3短音,且後續每5分line警告
int startPumpTimeOver = 60 * 20;
void check_PumpWater() {
Serial.print("Sensor_PumpWater:");
Serial.println(digitalRead(Sensor_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++;
String l_msg = "startPumpTime:" + String(startPumpTime) + "/" + String(startPumpTimeOver);
Serial.println(l_msg);
//抽水超時警告
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_RoWater) == 1)
{
RoWaterMissTime++;
String l_msg = "RoWaterMissTime:" + String(RoWaterMissTime) + "/" + String(RoWaterMissTimeOver);
Serial.println(l_msg);
//停水超時警告
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;
}
//------------------------- RO水源偵測 START -------------------------
//------------------------- SerialBT START -------------------------
int sendSerialBT_resend_Time = 0;
void sendSerialBT()
{
sendSerialBT_resend_Time++;
if( sendSerialBT_resend_Time >= 5 )
{
SerialBT.println("---------------------------------------");
SerialBT.print("抽水馬達(黃):");
if( startPumpTime > 0)
{
SerialBT.print("運作中--> " + String(startPumpTime) + "/" + String(startPumpTimeOver) );
if( startPumpTime >= startPumpTimeOver)
{
SerialBT.println("❌");
}
else
{
SerialBT.println("⚡");
}
}
else
{
SerialBT.println("停止✔️");
}
SerialBT.print("RO水源(綠):");
if( digitalRead(Sensor_RoWater) == 1 )
{
SerialBT.print("無水--> " + String(RoWaterMissTime) + "/" + String(RoWaterMissTimeOver) );
SerialBT.println("❌");
}
else
{
SerialBT.println("有水💧");
}
SerialBT.print("上水位(紫):");
if( digitalRead(Sensor_highLine) == 1 )
{
if( digitalRead(Sensor_lowLine) == 1 )
{
SerialBT.println("尚有水💧");
}
else
{
SerialBT.println("缺水❌");
}
}
else
{
SerialBT.println("滿水💦");
if( playRoTime > 0)
{
SerialBT.println("滿水還在製水❌");
}
if( digitalRead(Sensor_lowLine) == 0 )
{
SerialBT.println("上水位滿水,下水位缺水⚠️⚠️⚠️");
}
}
SerialBT.print("下水位(藍):");
if( digitalRead(Sensor_lowLine) == 1 )
{
SerialBT.println("有水💧");
}
else
{
SerialBT.println("無水❌");
}
SerialBT.print("TDS: " + String(tdsValue,0) + " PPM");
if( tdsValue > 30 )
{
SerialBT.println("❌");
}
else
{
SerialBT.println("✔️");
}
if( playRoTime > 0 )
{
SerialBT.print("RO製水中--> " + String(playRoTime) + "/" + String(playRoTimeOver) );
if( playRoTime >= playRoTimeOver)
{
SerialBT.println("❌");
}
else
{
SerialBT.println("⚡");
}
if( playRoTime > 10)
{
SerialBT.print(tdsValueStr);
if( tdsValueAvg > 30 )
{
SerialBT.println("❌");
}
else
{
SerialBT.println("✔️");
}
}
}
sendSerialBT_resend_Time = 0;
}
}
//------------------------- SerialBT END -------------------------
void setup() {
Serial.begin(115200);
SerialBT.begin("RO121");
//TDS偵測器
pinMode(TdsSensorPin,INPUT);
WiFi.begin("AP", "PASS");
while(WiFi.status() != WL_CONNECTED)
{
delay(1000);
Serial.print(F("."));
}
Serial.println();
Serial.println(F("WiFi connected"));
// Print the IP address
Serial.println(WiFi.localIP());
//馬達及入水閥電源relay01,使用低壓觸發
pinMode( relay01, OUTPUT);
digitalWrite( relay01, HIGH);//通電時預設關閉
//控制沖洗開關relay02,只沖洗8秒,使用低壓觸發
pinMode( relay02, OUTPUT);
digitalWrite( relay02, HIGH);//通電時預設關閉
//控制前段水排出不飲用relay03,前段水30秒不取用
pinMode( relay03, OUTPUT);
digitalWrite( relay03, HIGH);//通電時預設關閉
//水源開關
pinMode( Sensor_RoWater, INPUT_PULLUP);
//飲水機高水位偵測
pinMode( Sensor_highLine, INPUT_PULLUP);
//飲水機低水位偵測
pinMode( Sensor_lowLine, INPUT_PULLUP);
//水塔抽水偵測器
pinMode( Sensor_PumpWater, INPUT_PULLUP);
//蜂鳴器 - 開機取得網路後嗶一聲
pinMode( buzzer, OUTPUT);
digitalWrite( buzzer, HIGH);
delay(100);
digitalWrite( buzzer, LOW);
}
void loop() {
//1秒執行一次
delay(1000);
sendSerialBT();
Serial.println("**********************************");
check_PumpWater();
Serial.print("Sensor_RoWater:");
Serial.print(digitalRead(Sensor_RoWater));
Serial.print(", Sensor_lowLine:");
Serial.print(digitalRead(Sensor_lowLine));
Serial.print(", Sensor_highLine:");
Serial.println(digitalRead(Sensor_highLine));
//取得TDS
getTDS();
//低水位偵測器,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)
{
String l_msg = "完成 "+TimeFormate(playRoTime);
l_msg += "\n";
l_msg += tdsValueStr;
String l_line_token = "i82ej11WC8Z12j77tmxtRGC6H45NWaE7e7gkuMjjglw";
sendLine( l_msg, l_line_token);
}
playRoTime = 0;
return;
}
//製水計時器
playRoTime++;
//製水超時警告,強制停止
if( playRoTime >= playRoTimeOver)
{
digitalWrite( relay01, HIGH);
digitalWrite( relay02, HIGH);
digitalWrite( relay03, HIGH);
if( playRoTime == playRoTimeOver )
{
String l_msg = "超時警告 "+TimeFormate(playRoTime);
l_msg += "\n";
l_msg += tdsValueStr;
String l_line_token = "i82ej11WC8Z12j77tmxtRGC6H45NWaE7e7gkuMjjglw";
sendLine( l_msg, l_line_token);
}
bb(4);
return;
}
//check tds
//10秒後洗牌tda
if( playRoTime == 10 )
{
tdsValueMax = tdsValue;
tdsValueAvg = tdsValue;
tdsValueMin = tdsValue;
}else if( playRoTime > 10 )
{
if( tdsValue > tdsValueMax ) tdsValueMax = tdsValue;
tdsValueAvg = (tdsValueAvg+tdsValue) / 2;
if( tdsValue < tdsValueMin ) tdsValueMin = tdsValue;
tdsValueStr = "tds:"+String(tdsValueMin,0)+"/"+String(tdsValueAvg,0)+"/"+String(tdsValueMax,0);
Serial.println(tdsValueStr);
}
//馬達及入水閥電源
digitalWrite( relay01, LOW);
//控制前段水排出不飲用
if(playRoTime < 120)
{
digitalWrite( relay02, LOW);
}
else
{
digitalWrite( relay02, HIGH);
}
//控制沖洗開關10(s)
if(playRoTime < 10)
{
digitalWrite( relay03, LOW);
}
else
{
digitalWrite( relay03, HIGH);
}
String l_msg = "playRoTime:" + String(playRoTime) + "/" + String(playRoTimeOver);
Serial.println(l_msg);
}
void bb(int ct)
{
//不影響主線程,10秒來一次
if( (playRoTime+RoWaterMissTime+startPumpTime) % 10 == 0 )
{
//1短聲:缺水
//2短聲:啟動太久
for(int i=0;i<ct;i++)
{
digitalWrite( buzzer, HIGH);
delay(100);
digitalWrite( buzzer, LOW);
delay(100);
}
}
}
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;
}
http版
#include <WebServer.h>
//GET WIFI IP
String g_ip = "";
//run time
unsigned long g_runTime = 0;
//馬達及入水閥電源relay01,使用低壓觸發
int relay01 = 25;
//控制沖洗開關relay02,只沖洗8秒,使用低壓觸發
int relay02 = 33;
//控制前段水排出不飲用relay03,前段水30秒不取用
int relay03 = 32;
//用來計數已製水多少秒
int playRoTime = 0;
int playRoTimeOver = 60 * 30;
//製水開關
int playRO = 0;
//水源偵測器,短路表示有水
int Sensor_RoWater = 21;
//低水位偵測器
int Sensor_lowLine = 22;
//高水位偵測器
int Sensor_highLine = 23;
//水塔抽水偵測器
int Sensor_PumpWater = 18;
//蜂鳴器
int buzzer = 19;
//------------------------- TDS START -------------------------
#define TdsSensorPin 35
#define VREF 3.3 // analog reference voltage(Volt) of the ADC
#define SCOUNT 1 // sum of sample point
int analogBuffer[SCOUNT]; // store the analog value in the array, read from ADC
int analogBufferTemp[SCOUNT];
int analogBufferIndex = 0;
int copyIndex = 0;
float averageVoltage = 0;
float tdsValue = 0;
float tdsValueMax = 0;
float tdsValueAvg = 0;
float tdsValueMin = 0;
String tdsValueStr = "";
float temperature = 20; // current temperature for compensation
// median filtering algorithm
int getMedianNum(int bArray[], int iFilterLen){
int bTab[iFilterLen];
for (byte i = 0; i<iFilterLen; i++)
bTab[i] = bArray[i];
int i, j, bTemp;
for (j = 0; j < iFilterLen - 1; j++) {
for (i = 0; i < iFilterLen - j - 1; i++) {
if (bTab[i] > bTab[i + 1]) {
bTemp = bTab[i];
bTab[i] = bTab[i + 1];
bTab[i + 1] = bTemp;
}
}
}
if ((iFilterLen & 1) > 0){
bTemp = bTab[(iFilterLen - 1) / 2];
}
else {
bTemp = (bTab[iFilterLen / 2] + bTab[iFilterLen / 2 - 1]) / 2;
}
return bTemp;
}
void getTDS()
{
static unsigned long analogSampleTimepoint = millis();
if(millis()-analogSampleTimepoint > 40U){ //every 40 milliseconds,read the analog value from the ADC
analogSampleTimepoint = millis();
analogBuffer[analogBufferIndex] = 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[copyIndex] = analogBuffer[copyIndex];
// read the analog value more stable by the median filtering algorithm, and convert to voltage value
averageVoltage = getMedianNum(analogBufferTemp,SCOUNT) * (float)VREF / 4096.0;
//temperature compensation formula: fFinalResult(25^C) = fFinalResult(current)/(1.0+0.02*(fTP-25.0));
float compensationCoefficient = 1.0+0.02*(temperature-25.0);
//temperature compensation
float compensationVoltage=averageVoltage/compensationCoefficient;
//convert voltage value to tds value
tdsValue=(133.42*compensationVoltage*compensationVoltage*compensationVoltage - 255.86*compensationVoltage*compensationVoltage + 857.39*compensationVoltage)*0.5;
Serial.print("voltage:");
Serial.print(averageVoltage,2);
Serial.print("V ");
Serial.print("TDS Value:");
Serial.print(tdsValue,0);
Serial.println("ppm");
}
}
}
//------------------------- TDS END -------------------------
//------------------------- LINE START -------------------------
#include <WiFi.h>
#include <WiFiClientSecure.h>
WiFiClientSecure client;
void sendLine(String msg, String line_token) {
//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();
Serial.println("send line:" + msg);
Serial.println("token:"+line_token);
}
//------------------------- LINE END -------------------------
//------------------------- 水塔抽水偵測 START -------------------------
//用來計數已抽水多少秒
int startPumpTime = 0;
//運時超過20分line+警告3短音,且後續每5分line警告
int startPumpTimeOver = 60 * 20;
void check_PumpWater() {
Serial.print("Sensor_PumpWater:");
Serial.println(digitalRead(Sensor_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++;
String l_msg = "startPumpTime:" + String(startPumpTime) + "/" + String(startPumpTimeOver);
Serial.println(l_msg);
//抽水超時警告
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_RoWater) == 1)
{
RoWaterMissTime++;
String l_msg = "RoWaterMissTime:" + String(RoWaterMissTime) + "/" + String(RoWaterMissTimeOver);
Serial.println(l_msg);
//停水超時警告
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;
}
//------------------------- WiFiServer END -------------------------
WebServer server(80);
void setup() {
Serial.begin(115200);
//TDS偵測器
pinMode(TdsSensorPin,INPUT);
WiFi.begin("AP168", "n0911661293");
while(WiFi.status() != WL_CONNECTED)
{
delay(1000);
Serial.print(F("."));
}
Serial.println();
Serial.println(F("WiFi connected"));
// Print the IP address
g_ip = WiFi.localIP().toString();
Serial.println(g_ip);
//馬達及入水閥電源relay01,使用低壓觸發
pinMode( relay01, OUTPUT);
digitalWrite( relay01, HIGH);//通電時預設關閉
//控制沖洗開關relay02,只沖洗8秒,使用低壓觸發
pinMode( relay02, OUTPUT);
digitalWrite( relay02, HIGH);//通電時預設關閉
//控制前段水排出不飲用relay03,前段水30秒不取用
pinMode( relay03, OUTPUT);
digitalWrite( relay03, HIGH);//通電時預設關閉
//水源開關
pinMode( Sensor_RoWater, INPUT_PULLUP);
//飲水機高水位偵測
pinMode( Sensor_highLine, INPUT_PULLUP);
//飲水機低水位偵測
pinMode( Sensor_lowLine, INPUT_PULLUP);
//水塔抽水偵測器
pinMode( Sensor_PumpWater, INPUT_PULLUP);
//蜂鳴器 - 開機取得網路後嗶一聲
pinMode( buzzer, OUTPUT);
digitalWrite( buzzer, HIGH);
delay(100);
digitalWrite( buzzer, LOW);
createWebServer();
server.begin();
}
String content;
void createWebServer()
{
server.on("/", []() {
content = "<!DOCTYPE html>";
content += "<html>";
content += "<head>";
content += "<title>ro status</title>";
content += "<script>if (navigator.userAgent.indexOf(\"Line\") > -1) location.href += \"?openExternalBrowser=1\";</script>";
content += "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">";
content += "<meta http-equiv=\"refresh\" content=\"5\">";
content += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">";
content += "</head>";
content += "<body>";
content += "<div>";
content += "開機時間🕛 ";
content += TimeFormate(g_runTime);
content += "</div><br />";
content += "<div>";
content += "抽水馬達(黃):";
if( startPumpTime > 0)
{
content += "運作中--> " + String(startPumpTime) + "/" + String(startPumpTimeOver);
if( startPumpTime >= startPumpTimeOver)
{
content += "❌";
}
else
{
content += "⚡";
}
}
else
{
content += "停止✔️";
}
content += "</div><br />";
content += "<div>";
content += "RO水源(綠):";
if( digitalRead(Sensor_RoWater) == 1 )
{
content += "無水--> " + String(RoWaterMissTime) + "/" + String(RoWaterMissTimeOver);
content += "❌";
}
else
{
content += "有水💧";
}
content += "</div>";
content += "<div>";
content += "上水位(紫):";
if( digitalRead(Sensor_highLine) == 1 )
{
if( digitalRead(Sensor_lowLine) == 1 )
{
content += "尚有水💧";
}
else
{
content += "缺水❌";
}
}
else
{
content += "滿水💦";
if( playRoTime > 0)
{
content += "滿水還在製水❌";
}
if( digitalRead(Sensor_lowLine) == 0 )
{
content += "上水位滿水,下水位缺水⚠️⚠️⚠️";
}
}
content += "</div>";
content += "<div>";
content += "下水位(藍):";
if( digitalRead(Sensor_lowLine) == 1 )
{
content += "有水💧";
}
else
{
content += "無水❌";
}
content += "</div>";
content += "<div>";
content += "TDS: " + String(tdsValue,0) + " PPM (" + String(averageVoltage,2) + "V)";
if( tdsValue > 30 )
{
content += "❌";
}
else
{
content += "✔️";
}
content += "</div>";
if( playRoTime > 0 )
{
content += "<div>";
content += "RO製水中--> " + String(playRoTime) + "/" + String(playRoTimeOver);
if( playRoTime >= playRoTimeOver)
{
content += "❌";
}
else
{
content += "⚡";
}
content += "</div>";
content += "<div>";
if( playRoTime > 10)
{
content += tdsValueStr;
if( tdsValueAvg > 30 )
{
content += "❌";
}
else
{
content += "✔️";
}
}
content += "</div>";
}
content += "<div>";
content += "RO馬達:";
if( digitalRead(relay01) == 0 )
{
content += "運作中:";
content += "⚡";
}
else
{
content += "停止";
}
content += "</div>";
content += "<div>";
content += "前段水(100秒):";
if( digitalRead(relay02) == 0 )
{
content += "運作中:";
content += "⚡";
}
else
{
content += "停止";
}
content += "</div>";
content += "<div>";
content += "沖洗(10秒):";
if( digitalRead(relay03) == 0 )
{
content += "運作中:";
content += "⚡";
}
else
{
content += "停止";
}
content += "</div>";
content += "</body>";
content += "</html>";
server.send(200, "text/html", content);
});
}
void loop() {
//1秒執行一次
delay(1000);
g_runTime++;
server.handleClient();
Serial.println("**********************************");
check_PumpWater();
Serial.print("Sensor_RoWater:");
Serial.print(digitalRead(Sensor_RoWater));
Serial.print(", Sensor_lowLine:");
Serial.print(digitalRead(Sensor_lowLine));
Serial.print(", Sensor_highLine:");
Serial.println(digitalRead(Sensor_highLine));
//取得TDS
getTDS();
//低水位偵測器,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)
{
String l_msg = "完成 "+TimeFormate(playRoTime);
l_msg += "\n";
l_msg += tdsValueStr;
String l_line_token = "i82ej11WC8Z12j77tmxtRGC6H45NWaE7e7gkuMjjglw";
sendLine( l_msg, l_line_token);
}
playRoTime = 0;
return;
}
//製水計時器
playRoTime++;
//製水超時警告,強制停止
if( playRoTime >= playRoTimeOver)
{
digitalWrite( relay01, HIGH);
digitalWrite( relay02, HIGH);
digitalWrite( relay03, HIGH);
if( playRoTime == playRoTimeOver )
{
String l_msg = "超時警告 "+TimeFormate(playRoTime);
l_msg += "\n";
l_msg += tdsValueStr;
String l_line_token = "i82ej11WC8Z12j77tmxtRGC6H45NWaE7e7gkuMjjglw";
sendLine( l_msg, l_line_token);
}
bb(4);
return;
}
//check tds
//10秒後洗牌tda
if( playRoTime == 10 )
{
tdsValueMax = tdsValue;
tdsValueAvg = tdsValue;
tdsValueMin = tdsValue;
}else if( playRoTime > 10 )
{
if( tdsValue > tdsValueMax ) tdsValueMax = tdsValue;
tdsValueAvg = (tdsValueAvg+tdsValue) / 2;
if( tdsValue < tdsValueMin ) tdsValueMin = tdsValue;
tdsValueStr = "tds:"+String(tdsValueMin,0)+"/"+String(tdsValueAvg,0)+"/"+String(tdsValueMax,0);
Serial.println(tdsValueStr);
}
//馬達及入水閥電源
digitalWrite( relay01, LOW);
//控制前段水排出不飲用
if(playRoTime < 100)
{
digitalWrite( relay02, LOW);
}
else
{
digitalWrite( relay02, HIGH);
}
//控制沖洗開關10(s)
if(playRoTime < 10)
{
digitalWrite( relay03, LOW);
}
else
{
digitalWrite( relay03, HIGH);
}
String l_msg = "playRoTime:" + String(playRoTime) + "/" + String(playRoTimeOver);
Serial.println(l_msg);
}
void bb(int ct)
{
//不影響主線程,10秒來一次
if( (playRoTime+RoWaterMissTime+startPumpTime) % 10 == 0 )
{
//1短聲:缺水
//2短聲:啟動太久
for(int i=0;i<ct;i++)
{
digitalWrite( buzzer, HIGH);
delay(100);
digitalWrite( buzzer, LOW);
delay(100);
}
}
}
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;
}