亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

水池填充控制

监测水位、温度、 pH、ORP、过滤器压力、电力使用和泵操作。必要时补充游泳池。

故事

想法

2015 年夏天,我和儿子们重建了整个泳池系统。一开始是我们买房子时继承的水管和阀门问题、过滤器问题和一家基本上无能的泳池公司,这是我们买房子时遗留下来的。一旦它开始看起来像这样,我就决定是时候做点什么了:

我们自己的私人泻湖

开始使用

首要任务是清理池,然后弄清楚如何保持这种状态。我一直很喜欢自动化,我认为这是一个完美的尝试之地。很快,游泳池又变成了这个样子:

恢复正常

但问题仍然存在,整个系统在能力和智能方面都缺乏,这是我想改变的。所以首先,我们需要更换过滤器、泵和一堆阀门。我花了很多时间在一个名为“Trouble Free Pool”的网站上,它是 DIYer 的救星。

我的劳动力

我们遇到了一些挫折,其中之一是当他们安装围栏时,他们在从过滤系统到游泳池的管线周围浇筑混凝土。

不用说,所有这些混凝土和那些泳池线都必须更换,以便项目向前推进。几乎一切都必须进行。

早先我决定将一些自动化整合到新的泳池系统中。我选择了一个名为 Autopilot 的管理系统。 (我的家人说我选择它是因为我是一名飞行员并且喜欢这个名字! ) 这个系统可以让我把水池改造成盐水池并处理一些管理工作,主要是在必要时运行盐水发生器,并泵送酸来控制 pH 值。除了这些之外,没有其他自动化。

最终我们搞定了一切。我们还拿回了我们的厨房,它最终成为了我的项目工作室。

全部完成:

自动化——开始

既然物理设备已安装并运行,我认为能够在不必一直拔出软管的情况下填充游泳池会很好。我想用一个 Raspberry Pi 和一个普通的喷水阀,我会做生意!我购买了另一个 Pi(我在各种项目中到处使用它们)并布置了我想要它做什么。

Raspberry Pi3

最初我认为我需要能够做两件事:

我开始做研究,遇到了一家制造液体卷尺的公司,该卷尺会随着水位(或其他液体)的上升或下降而改变电阻。 Milone 也很乐意为我创建一个特定尺寸的单元,因为它们的任何尺寸都不适合我想要放置的位置。

Milone 的 eTape

更新 :不幸的是,由于某种原因,我的 Milone eTape 在实际夹克内进水而失败了。在与 Milone 讨论了这个问题后,我决定更换它并可能遭受同样的问题的成本,不值得更换的成本。更糟糕的是,我需要一个他们必须专门为我制作的特殊尺码。

内套管中的水导致 eTape 失败......

Elecall 不锈钢水箱水位传感器浮球开关

由于我的低水位和正常水位之间的差异约为三英寸,这对我来说非常有用。我只需要找到一种方法来安装它并使其正常工作。

因为我认识其他几个人使用 eTape 并取得了很好的效果,所以我将把有关 eTape 的所有内容都留在我的项目中,并按照我进行双浮点设置的方式进行添加。这样人们可以看到几个不同的选项。

由于它将位于我的 Pi 所在的院子对面,因此有必要将其连接到自己的设备以进行报告。由于我不需要为此使用 Pi,我选择了一个电池供电的低功耗 Arduino 无线克隆,它将信息传输回我已经在房子周围安装的现有系统。

这些设备是我从低功耗实验室购买的。我最终在我的项目中使用了其中的四个:一个用于水位,一个用于水温,两个在主系统中用于监控内部外壳温度、过滤器压力和用水量的组合。

带闪存和 RFM69HW 433Mhz 收发器的 Moteino R5-USB

这些 Arduino 克隆使用极低的功耗——在深度睡眠模式下仅为 ~7uA,这意味着它们可以使用两节 AA 电池持续很长时间。我的水温传感器漂浮在我的游泳池周围,而我的水位传感器离电源很远,所以我不得不使用电池供电的无线设备。

一开始,除了自动给水池加水之外,我并没有打算做任何其他事情,但是随着这些事情的发生,这个项目有了自己的想法。最终我将能够做到以下几点:

填满池子

无论是什么触发了池填充路由(手动或自动),我都必须有办法将水注入池中。由于我们已经需要在灌溉和城市供水之间安装真空断路器,因此我选择将其连接到现有的喷水灭火系统中,以便为游泳池供水。我基本上是在为我的喷水灭火系统创建另一个“区域”,并配有阀门。

这带来了一个问题,如果我的洒水器正在运行,而我决定将水池注满,我就会抢走任何草坪区正在流水的地方,而这将无法正确地给草坪浇水。所以我必须想出一种方法来确定洒水器是否正在运行。最初我使用了一个“停电”时区——即,如果我知道我的洒水器从凌晨 3 点运行到早上 6 点,在这段时间内不要填满游泳池。但这似乎有点非技术性。在研究我的 Rachio 喷水灭火系统时,我了解到他们有一个内置的 API,可以让我以编程方式查询喷水灭火系统的状态。就我而言,我只是有一个简单的问题:你在跑步吗?

就我而言,我只是使用了一个简单的 curl 命令来获取所需的内容:

rachio_url ='curl -s -X GET -H "Content-Type:application/json" -H "Authorization:Bearer xxxx-xxxxx-xx-xxxx-xxxxx-xxx" https:// /api.rach.io/1/public/device/00xx00x-00xxx000-xxx0x000-00x0x0x0/current_schedule'

这由我的 get_sprinkler_status 函数调用,如下所示:

output =subprocess.check_output(pooldb.rachio_url, shell=True)if output =="{}":splashrs_on ="No" 

我的主应用程序每 60 秒运行一次,所以如果我的洒水器正在运行,我只需再过 60 秒什么都不做,然后再次检查。最终,洒水器将停止运行,水池将自动开始注水。

为了真正填满游泳池,我使用了一个在 Home Depot 购买的普通 24V 交流喷水阀。我用一个单向阀将它直接安装到我的游泳池管道中,该管道通向我的游泳池。单向阀可防止泵在运行时压力将水推向喷水阀。

带单向阀的水管

由于我的泳池电气面板是 240V,而且面板中没有中性线,所以我不得不使用 240VAC 到 24VAC 的变压器。足够简单。但是,我不想无缘无故地运行变压器 24×7,所以我使用继电器来 1) 打开变压器,然后 2) 从变压器获取 24VAC 输出并将其连接到喷水阀。

继电器设置

我在光隔离模式下使用了 Sainsmart 固态继电器(非常便宜),在这种模式下,我有一个单独的电源输入为继电器供电,而不是使用来自 Pi 的 5v 或 3.3v VCC。这应该有助于消除继电器的干扰。

洒水阀和智能水表

我还添加了一个智能仪表,我可以实时读取它,以显示水正在流动以及随着时间的推移我使用了多少水。此信息存储在 MySQL 数据库中,并在历史记录中存储:

从我的 EmonCMS 系统中筛选出我家的水表

力量,力量,力量

接下来是我需要弄清楚的事情。当我的泵运行时,如果我试图填充游泳池,我将与泵的压力作斗争。我通过测量水流量确定在泵运行时我损失了大约 50% 的注水流量,因此我认为最好在泵运行时不注水。所以我需要一种方法来监控我的泵的功率并确定它是否正在运行。

在这种情况下,我有一个非常简单的方法来做到这一点。我家中的每个电路都由电气监控系统监控。该系统称为 GEM,由 Brultech 出售。


我的泳池泵是我家最大的用电设备

有了这个系统,我可以监控我家的所有用电情况,并作为监控的一部分过程中,我将此数据存储在 MySQL 数据库中。因此,我每分钟只查询一次我的 MySQL 数据库,并计算出我的池面板当前使用了多少瓦特。

 if pool_pump_running_watts> pooldb.max_wattage:pool_fill_control.led_control(PUMP_RUN_LED, "ON") pool_pump_running ="Yes" logger.debug('PUMP_RUN_LED 应该是ON。这是黄色LED') 如果是DEBUG :print("PUMP_RUN_LED 应该是开的。这是黄色 LED")else:pool_fill_control.led_control(PUMP_RUN_LED, "OFF") pool_pump_running ="No" logger.debug('PUMP_RUN_LED 应该是 OFF。这是黄色 LED') if DEBUG:print("PUMP_RUN_LED 应该关闭。这是黄色 LED")

我在物理单元上有各种按钮、开关和 LED,让我可以查看喷头是否正在运行、泵是否正在运行、水池是否正在注水或是否存在某种系统错误.在上方,您可以看到我在必要时打开和关闭泵运行 LED 的位置。

除了系统 LED 之外,我还有一个系统开/关按钮(左上角),它允许我使用 MightyHat 系统智能地重新启动或关闭我的 Pi,而无需登录 Pi从 CLI 执行此操作。我还有一个瞬时开关(左侧第二个),它允许我在需要时手动填充我的水池,最后在左侧我有一个 DPDT 开关,它可以物理中断从我的系统到洒水阀的电源并触发 GPIO事件告诉系统我们已手动禁用填充池。当这个开关被触发时什么都不起作用,如果某些东西以编程方式出现故障,无论如何都无法从变压器到喷水阀。

池控制器 - 外部

管理泵

随着时间的推移,我在泳池控制系统中添加了另一部分。能够管理我的 Pentair 变速泵。输入 Russell Goldin (tageyoureit) 和他的泳池控制器软件项目。 Russell 的软件允许我通过 RS485 接口直接与我的泳池泵通信。连接后,我可以直接查询泵的系统信息,如 RPM、GPM 和使用中的瓦数:

def get_pump_data(key):verbose_debug("get_pump_data() Started") verbose_debug("get_pump_data() 调用了'{}' ".format(key)) log("INFO", " get_pump_data() 用 '{}' ".format(key)) 调用 if pump_control_active:global json try:req =urllib2.Request(pooldb.PUMP_DATA_URL) opener =urllib2.build_opener() f =opener.open(req) data =json.load(f) pump_data =data["pump"]["1"][key]verbose_debug("get_pump_data()返回{}".format(pump_data)) log("INFO","get_pump_data()返回{ }".format(pump_data)) verbose_debug("get_pump_data() - Completed") log("INFO", "get_pump_data() - Completed") if key =="gpm":pump_gpm =pump_data update_database("pump_status", " pump_gpm", pump_gpm) log("INFO", "Current GPM:{}".format(pump_gpm)) log("DEBUG", "get_pump_gpm() Completed") debug("Current GPM:{}".format(pump_gpm) )) verbose_debug("get_pump_gpm() Completed") elif key =="rpm":pump_rpm =pump_data update_database("pump_status", "pump_rpm", pump_rpm) log("INFO", "Current RPM:{}".format(pump_rpm)) log("DEBUG", "get_pump_rpm() Completed") debug("Current RPM:{}".format(pump_rpm)) verbose_debug("get_pump_rpm() Completed") else:pump_watts =pump_data update_database("pump_status", "pump_watts", pump_watts) log("INFO", "Current WATTS:{}".format(pump_watts)) log("DEBUG", "get_pump_watts() Completed") debug("Current WATTS :{}".format(pump_watts))verbose_debug("get_pump_watts() Completed") 返回 pump_data 除了异常作为错误:pump_data =0 debug("EXCEPTION:get_pump_data()") log("WARN", "EXCEPTION:get_pump_data( )") log("WARN", error) debug(type(error)) debug(error) verbose_debug("get_pump_data() - Completed with EXCEPTION") log("DEBUG", "get_pump_data() - Completed with EXCEPTION")返回 pump_data 否则: pump_data =0 返回 pump_data 

现在我可以查询泵并控制我的泵添加另一个我以前没有的功能。通过更改我的 Web 界面,我增加了启动或停止泵以及运行我在泵上配置的四种不同泵程序之一的功能:

泵控制面板

当然,我们可以实时查看 RPM、GPM 和 Watts:

Web 界面上的泵表

监测过滤器压力

我还想做的一件事是监控过滤器压力,以便我知道何时反冲洗我们的过滤器。我在 ebay 上购买了一个 100 PSI 压力传感器,并将其绑在我的过滤器旁边,紧挨着过滤器上已有的模拟压力表。

我从 ebay 上购买了一个便宜的发送器单元(见上面的链接),然后像这样把它绑在我的文件管理器上:

100 PSI Sender unitPressure Sending unit Wiring..

然后我将其连接到 Moteino-R5 中,我每分钟读取一次压力,然后将该信息输出到我的 MySQL 数据库,然后使用该信息在我的网站上驱动仪表输出。

// 获取我们的过滤器压力 void get_filter_pressure() { sensorVoltage =analogRead(PSI_SENSOR_PIN); // 让我们读取压力传感器电压 PSI =((sensorVoltage-146)/204)*25; // 一些校准将电压转换为 PSI 并将其归零 pool_sensors.PSI =PSI; } 

池过滤器 PSI 仪表

其他硬件和软件

主系统完全用Python编写,但我使用了其他软件和硬件来使我的系统工作。

在我的 Raspberry Pi 上,我使用 Low Power Labs MightyHat,它为 Pi 提供 UPS 备用电源、LCD 状态屏幕和 Pi 的智能电源控制。我可以使用连接到系统的小电池运行 Pi 大约两个小时左右,如果电源没有及时恢复,那么 MightyHat 将自动关闭 Pi 以防止它因突然崩溃电源故障。

Pi3 上的 MightyHat 特写显示溢出警报

MightyHat 是 Arduino 克隆,因此我使用 Arduino IDE 对其进行编程以满足我的项目需求。

对于感应,我使用了各种传感器和方法将信息转换为可用格式。对于几乎所有的传感器数据,我使用 OpenEnergyMonitor.org 免费的 EmonCMS 平台。这个平台让我可以从家里的任何地方收集我所有的传感器数据。它将这些信息存储在 MySQL 数据库中,然后我可以在那里获取它以在我的池控制系统中使用。

我游泳池的一些传感器跟踪附加跟踪信息

对于游泳池的实际水位,我使用 eTape 电阻式液体卷尺 (http://www.milonetech.com):

eTape 和 Moteino 模拟一切

我的 IO 控制器板之一

IO 控制器板、LED 控制器、电源接口 IO 控制器板 – 返回

USB pH 和 ORP 传感器板

Atlas Scientific pH 和 ORP 传感器接口板

为了获得准确的 pH 和 ORP 读数,我使用了 Atlas Scientific pH 和 ORP 传感器及其接口板。我将它们安装在流通池中,该流通池还可以监控泵是否正在运行。我使用标准的 John Guest 3/8" 快速接头将流通池连接到管线上,一个在过滤器的压力侧,一个在泵的吸入侧,以保持水流过流通池。

流通池(最左侧)带传感器的流通池 John Guest 3/8" 螺纹快速连接返回(吸入)线输出(压力)线 - 在酸注射器之前安装

读取我们的 pH 值:

def get_ph_reading():log("DEBUG", "get_ph_reading() Started") pool_pump_running =read_pool_sensor_status_values("pool_sensor_status", "led_status", "pump_run_led" ) if pool_True_running :if pooldb.temp_probe =="Yes":pool_temp =float(read_pool_sensor_status_values("pool_sensor_status", "system_status", "pool_current_temp" )) ph_value =float(get_ph.get_current_ph_with_temp(pool_temp)) else:ph_value.get float_current_ph ()) debug("Current pH is:{}".format(ph_value)) influx_data.write_data("pH", ph_value) influx_data.write_data("pool_temp", pool_temp) if pooldb.emoncms_server1 =="Yes":res =requests.get("http://" + pooldb.server1 + "/" + pooldb.emoncmspath1 + "/input/post?&node=" + str( pooldb.ph_node) + "&csv=" + ph_value + "&apikey =" + pooldb.apikey1) log("DEBUG", "Sent current pH Value of {} to Emoncms Server 1".format(ph_value)) debug("Sent current pH Value of {} to Emoncms Server 1".format( ph_value)) 如果 pooldb.emoncms_server2 =="是":res =requests.get("https://" + pooldb.server2 + "/" + pooldb.emoncmspath2 + "/input/post?&node=" + str( pooldb.ph_node) + "&csv =" + ph_value + "&apikey=" + pooldb.apikey2) log("DEBUG", "Sent current pH Value of {} to Emoncms Server 2".format( ph_value)) debug("Sent current pH Value of {} to Emoncms Server 2".format(ph_value)) update_pool_sensor_status_values("pool_sensor_status", "pool_chemicals", "pool_current_ph", ph_value) log("DEBUG", "get_ph_reading() Completed") else:log("INFO", "Pool Pump未运行,无法获得准确的 pH 读数!") debug("池泵未运行,无法获得准确的 pH 读数!") log("DEBUG", "get_ph_reading() Completed")

此代码调用“get_ph.py”模块,如下所示:

#!/usr/bin/python## 用于 pool_control_master.py__author__ ='Richard J. Sears'VERSION ="V3.4 (2018-03-16)"# [email protected ]# 这仅用于 Atlas Scientific pH 板。import serialimport sysimport timefrom serial import SerialExceptionusbport ='/dev/PH'try:ser =serial.Serial(usbport, 38400, timeout=0)except serial.SerialException as e:打印“错误”,e sys.exit(0)def read_line():lsl =len('\r') line_buffer =[] while True:next_char =ser.read(1) if next_char =='':break line_buffer.append(next_char) if (len(line_buffer)>=lsl and line_buffer[-lsl:] ==list('\r')):break return ''.join(line_buffer)def read_lines():lines =[ ] 尝试:while True:line =read_line() 如果不是 line:break ser.flush_input()lines.append(line) 将除 SerialException 之外的行返回为 e:打印“错误”,e 返回 Nonedef send_cmd(cmd):“” " 向 Atlas Sensor 发送命令。发送前,在命令末尾添加回车。:param cmd:::return:""" buf =cmd + "\r" # 添加回车 try:ser.write(buf) return True except SerialException as e:print "Error, ", e return Nonedef get_current_ph_with_temp(current_temp):# send_cmd("RESPONSE,0") send_cmd ("C,0") send_cmd("T,%d" % current_temp) send_cmd("R") time.sleep(1.3) lines =read_line() return linesdef get_current_ph_no_temp():# send_cmd("RESPONSE,0") send_cmd("C,0") send_cmd("R") time.sleep(1.3) lines =read_line() return linesdef main():# send_cmd("RESPONSE,0") send_cmd("C,0") send_cmd( "R") time.sleep(1.3) lines =read_lines() print("No Temperature Calibration Performed:") for i in range(len(lines)):print lines[i]if __name__ =='__main__':main ()

ORP 以同样的方式完成。

该流通池还安装了流量指示器。如果水流过电池,环会上升并关闭磁性开关。开关的接线连接到 pi 上的 GPIO 引脚。这是我读取该开关的代码:

def pool_pump_running_chemistry():pool_pump_running_chemistry =GPIO.input(pool_pump_running_pin) if pool_pump_running_chemical ==False:debug("Pool Pump Running via Chemical Sensor Chamber:TRUE - PUMP IS RUNNING") else:debug( “通过化学传感器室运行的池泵:错误 - 泵关闭”)

水位传感器 - 使其工作

如上所述,水位传感器使用 LowPowerLab 的电池供电的 MoteinoUBS。这是适用于该应用的完美微控制器。基本上,我每 60 秒唤醒一次 Moteino,从 eTape 读取电阻读数,启动我的发射器并将此信息发送到我的 EmonCMS 系统以供我的池脚本使用。然后我再次关闭所有电源:

{ digitalWrite(ETAPE_POWER, HIGH); // 打开 eTape 的电源 pool.resistance =analogRead(ETAPE); // 读取 etape 电阻 digitalWrite(ETAPE_POWER, LOW); // 关闭 eTape 的电源 take_battery_reading(); // 读取电池电量 power_spi_enable(); rf12_sleep(RF12_WAKEUP); rf12_sendNow(0, &pool, sizeof pool); rf12_sendWait(2); rf12_sleep(RF12_SLEEP); power_spi_disable();如果(调试){ flash_led(50); } // 就是这样 - 等到下一次:) sleep_until_next_reading(); } 

我还跟踪我的电池电压,以便我知道什么时候该更换我的电池。该脚本有多种机制来确保电池良好。首先,我主动跟踪电池电压本身,其次我跟踪传感器向我报告的频率以及这些报告的时间增量。对于许多错过的读数,我知道该传感器“出了点问题”,我会收到 Pushbullet 通知以查看问题所在。此外,由于缺少传感器,我的泳池填充系统进入待机状态,并且会拒绝填充泳池,因为它不知道何时停止。

我使用了 2 节 AA 锂电池,到目前为止它们已经运行了一年多没有更换过。

为了保证池级 MoteinoUSB 的安全,我需要某种防水外壳。我选择了带有透明盖子的 Adafruit 防风雨盒。

Adafruit 防风雨外壳

接下来,我使用了 Adafruit PG-9 电缆密封套,并非常小心地从盒子的侧面钻孔并安装了电缆密封套。

Adafruit PG-9 电缆接头

使用 Adafruit 防水直流电源线,我将 eTape 连接到 MoteinoUSB 和外壳。

Adafruit 防水直流电源线完成水位传感器外壳

为了更加干燥,我购买了干燥剂放入外壳中以吸收水分并使其进入外壳。需要注意的一件事是,我通过艰难的方式(幸好传感器很便宜)学到了不要将顶部或电缆密封套拧得太紧。这需要一些试验和错误。最后,在我“认为”我做对了之后,我实际上把我的水槽装满了,把外壳放在水下,用一个装满水的平底锅放在它上面。我保持这种方式几个小时,每隔几个小时检查一次我是否正确。

现在我需要想办法安装水位传感器。在我的游泳池里,我们有一个小的水泥盆,用来放置手动向游泳池加水的浮子。这个很久以前就生锈了,如果不拆掉水泥外壳就无法修复。这就是我最初开始我的项目的原因!

水泥盆

水泥盆通过一条3/4″的小线与水池相连,可以让我看到水位,但孩子们在水池里泼水或乱搞不会影响水位盆里的水。这是安装 eTape 传感器的理想场所。为了进行实际安装,我拿了一根 PVC 管,将其切成两半,然后用砂纸打磨,使其与水泥盆的形状相同。然后我将这块环氧树脂直接固定在盆的侧面。完成后,我使用了几个石膏板螺钉并将 eTape 拧到了 PVC 管上。

eTape 传感器安装到 PVC 管道已完成 eTape 传感器安装

更新:读取水位的新方法!

如果您阅读以上内容,我的 eTape 安装遇到了一些问题,导致我的 eTape 停止工作并给出错误读数,使其无法使用。我在 Mileone 与 Chris 交谈,但由于磁带失败的原因,我们无法提出来。最后,我再拿一盘磁带又发生同样的事情,不值得再花 80 美元,所以我改变了读取水位的方法。

由于我的低电平和全电平之间确实只有 3" 的差异,所以我研究了各种电平传感器并选择了这个:

Elecall 不锈钢水箱水位传感器浮球开关

所以我不得不想办法安装新传感器。我决定使用 1/4 英寸有机玻璃来使它工作。我测量了我需要的宽度,并用一个额外的固定螺丝安装了浮子,这样我就可以进行微调。我还在它上面贴了一个小水平面,所以当我安装它时它会是水平的:

为了安装它,我只使用了一些环氧树脂并使用我的“内置水平仪”将其调平:

要读取水池的高度,我需要知道两个浮标的位置。所以我编写了我的代码来读取两个浮标的位置,然后根据水位发送 0、1 或 2。

如果上浮子打开而下浮子打开(都向下浮动),那么我们是低的,它发送一个“0”。如果下浮子关闭(上)而上浮子打开(下),那么我们就在中间,我们发送一个“1”。如果两个浮标都关闭(向上),则游泳池已满,我们不需要任何水。下面是代码的样子:

UPPER_Float =digitalRead(17);LOWER_Float =digitalRead(3);如果(UPPER_Float ==LOW){ UPPER_Float_Position =“关闭”; } else { UPPER_Float_Position ="开盘"; } if (LOWER_Float ==LOW) { LOWER_Float_Position ="关闭"; } else { LOWER_Float_Position ="开盘"; } if ((UPPER_Float ==LOW) &&(LOWER_Float ==LOW)) { pool_level.level =2; // Both closed =Pool is FULL } else if ((UPPER_Float ==HIGH) &&(LOWER_Float ==LOW)) { pool_level.level =1; // Lower closed, Upper open =Pool MIDWAY } else { pool_level.level =0; // Both floats open =Pool LOW add water }

So the value of 0, 1 or 2 is transmitted to EmonCMS and written to my database. Each minute we query that database to see if we need to add water:

get_pool_level_value =read_emoncms_database("data", pooldb.pool_level_table)

and if it is low, we add water:

if get_pool_level_value ==0:get_pool_level ="LOW" pool_fill_valve("OPEN")

And this is the new way we are reading our pool level and managing filling our pool.

Pool Temperature Sensor – Making it work

Following in the footsteps of my eTape sensor, I build the same configuration for my pool temperature sensor. This time however, I added a temp probe inside the enclosure so I could monitor the temperature in the enclosure. It would also let me know what the temperature was just above the surface of the water in the pool. The second temperature sensor was fed through the PG-9 cable gland and into the pool water. I then just tossed the enclosure into the pool and thought I was done. However, my kids had other ideas. They thought it was fun to grab the temperature sensor hanging down from the enclosure and spin it around like a top and throw it at each other. Needless to say the first one didn’t last long.

So I went down to my local pool store and purchased a chlorine floater and installed the enclosure and temp probe into it. We have not had a problem since doing so. Even if they throw it, it won’t bother it at all. Most people leave it alone since they think it is chlorine even though we have a saltwater pool.

Pool temp sensor floaterPool temp sensor floater

Keeping track of our Acid Level

Part of the pool automation system that is not handled by my project is the dispensing of muriatic acid to keep our pH under control. While the Pool Auto Pilot system handles that, we still need to be able to see if we need acid added to the tank. For this I used a $9.00 DFRobot Liquid Level Sensor:

XKC-Y25-T12V Liquid Level Sensor

This particular sensor is weatherproof and works by sensing when there is no longer liquid behind whatever you have it attached to and then sending a signal to the GPIO that you can read. Once you can read it, you can then do your alerting, etc.

I simply connected this to my Pi (it utilizes the 5v rail and one GPIO pin) and then added in a little bit of code to read the state of the sensor:

def acid_level():acid_level_ok =GPIO.input(acid_level_sensor_pin) if acid_level_ok ==True:

I then epoxied the sensor to our acid tank at the level where I wanted to be notified and hooked it all up:

This tank has a pretty thick wall and this sensor worked great. I tested it before affixing it just to make sure.

Web Interface

V3.5.0 Web Interface

Once I had all of this pretty much working like I wanted it, I decided that I needed to have a nice interface so we could track all of the data, manually add water to the pool without having to go to the pool room, stop an automatic fill that may be in progress and check the status of the batteries in our temperature sensor and our level sensor.

The main capabilities of the web interface as of right now are:

I am very thankful to Russell Goldin ([email protected]) for his amazing work on the Pentair RS-485 control software needed for my system to be able to talk to and control my pump. You can check out his github HERE.

With Russ’s software I am able to directly control my Pentair pump without having to spend several thousand dollars on their proprietary hardware!

I spent a lot of time programming everything in python but I did not have an experience building a web interface so I asked around and eventually decided on Flask as the web framework that I would use to build the web interface.

Learning Flask was not as hard as I had thought it was going to be and it integrates very well with the python code that I had already written to control the pool. Flask is a mix of python-like code and html like templates and did everything that I needed it to do:

Upper Control PanelSystem GaugesLower Panel

The control part of the interface is very easy. If I want to start a manual fill, I simply click on the “Manual Fill” button and as long as there is not a system problem, we are not running the sprinklers and we are not already “automatically” filling the pool, the system starts a manual fill of the pool. The “Pool Filling” led will turn blue, than “Manual Fill” button will toggle on and the “Fill Timer” will start a countup. Click the “Manual Fill” button again and the system stops filling and reverts back to normal.

If we are filling the pool automatically and I want to stop that process, I simply click the “Pool Filling” button (led reverts to button to show that you can push it to stop the automatic fill) and the system stops filling and sends me notifications based on the configuration of the system (debug, logging, email, pushbullet, sms).

Flask has the ability to process things prior to showing you the html output:

{% if system_error_led =="True" %}  {% elif system_run_led =="True" %}  {% else %}  {% endif %}

In this example, if there is a system error I show a red led, otherwise if the system is running I show a green led and if I am not running and there is no error, then I show a grey led. This statement is processed before the html is rendered and is a very powerful way to interact with a python driven system.

Historical Graphing

As I continue to extend the system and learn more about what I can do, I wanted to start to watch historical trends in my pool system along with a lot of other home automation stuff I have been playing around with lately. After looking around I choose Grafana and InfluxDB.

Basically I already had my data being recorded utilizing EmonCMS so I just needed to have a quick way to get it into InfluxDB so Grafana could do it’s magic. Basically within the mail pool program whenever I get a pH, ORP or temp reading, I write it to the influxdb:

def get_ph_reading():log("DEBUG", "get_ph_reading() Started") pool_pump_running =read_pool_sensor_status_values("pool_sensor_status", "led_status", "pump_run_led" ) if pool_pump_running =="True":if pooldb.temp_probe =="Yes":pool_temp =float(read_pool_sensor_status_values("pool_sensor_status", "system_status", "pool_current_temp" )) ph_value =float(get_ph.get_current_ph_with_temp(pool_temp)) else:ph_value =float(get_ph.get_current_ph_no_temp()) debug("Current pH is:{}".format(ph_value)) influx_data.write_data("pH", ph_value) influx_data.write_data("pool_temp", pool_temp) if pooldb.emoncms_server1 =="Yes":res =requests.get("http://" + pooldb.server1 + "/" + pooldb.emoncmspath1 + "/input/post?&node=" + str( pooldb.ph_node) + "&csv=" + ph_value + "&apikey=" + pooldb.apikey1) log("DEBUG", "Sent current pH Value of {} to Emoncms Server 1".format(ph_value)) debug("Sent current pH Value of {} to Emoncms Server 1".format(ph_value)) if pooldb.emoncms_server2 =="Yes":res =requests.get("https://" + pooldb.server2 + "/" + pooldb.emoncmspath2 + "/input/post?&node=" + str( pooldb.ph_node) + "&csv=" + ph_value + "&apikey=" + pooldb.apikey2) log("DEBUG", "Sent current pH Value of {} to Emoncms Server 2".format( ph_value)) debug("Sent current pH Value of {} to Emoncms Server 2".format( ph_value)) update_pool_sensor_status_values("pool_sensor_status", "pool_chemicals", "pool_current_ph", ph_value) log("DEBUG", "get_ph_reading() Completed") else:log("INFO", "Pool Pump is NOT running, cannot get accurate pH reading!") debug("Pool pump is NOT running, cannot get accurate pH reading!") log("DEBUG", "get_ph_reading() Completed") 

and from influx_data.py:

import syssys.path.append('../')from influxdb import InfluxDBClientimport pooldbdef write_data(measurement, value):client =InfluxDBClient(pooldb.influx_host, pooldb.influx_port, pooldb.influx_user, pooldb.influx_password, pooldb.influx_dbname) json_body =[ { "measurement":measurement, "fields":{ "value":value } } ] client.write_points(json_body)

From there it is a simple matter of setting up Grafana to look at the InfluxDB and make the graphs:

Notifications

My system relies heavily on notifications. Currently the system can provide notifications via logging to a log file, debug messages to stdout allowing for the running of the main program from the command line with valuable, immediate feedback, pushbullet, email and SMS via Twillio. Because of all they types of notifications as well as areas where there can be notifications, I created a system which allows me to fine tune my notifications very easily via my web interface.

By setting up the code in this manner, I can very easily and quickly adjust my notification settings as well as different categories that I want to have those notifications applied to at that time. In future versions of the code, I am going to create an entire “Notifications” panel that allows me the ability to set specific notification types by category. For example I might want an SMS message about filling events, but email notifications about system errors and pushbullet notifications about my pump. In this manner I am able to tweak all of my notification settings to be exactly how I want then to notify me…both the how and the when!

Current Notification Settings Panel
root scruffy:www # ./pool_control_master.pyStarted is_database_online()MightyHat Serial setup completedSystem Reset Status =No Reset RequestedStarted get_pool_temp()get_pool_temp returned 67.30Fpool_temp in C is 19.61Started is_pool_pump_running()pool_pump_running_watts returned 563 watts in use by pump.PUMP_RUN_LED should be ON. This is the YELLOW LEDCurrent unix datetime stamp is:1521835161Pool LEVEL sensor last updated at:1521835044Pool LEVEL sensor battery voltage is:3.2Pool LEVEL sensor battery percentage is 100Pool TEMP sensor last updated at:1521835131Pool TEMP sensor battery voltage is:3.2Pool TEMP sensor battery percentage is 100Pool FILTER PSI is:21Time dfference between last pool LEVEL sensor reading is:117 seconds.Time dfference between last pool TEMP sensor reading is:30 seconds.Everything appears to be OK with the pool sensors!pool_sensors:Pool Resistance is:724pool_sensors:Pool Level Percentage is:85pooldb:Static critical pool level resistance set at (740).pooldb:Static normal pool level resistance set at (710).Our Pool Level is MIDWAY.Total Gallons:22462Acid Level OKTotal Current Power Utilization:2039 wattsTotal Current Power Import:415 wattsTotal Current Solar Production:1624 wattsCurrent GPM:15Current RPM:2225Starting get_ph_reading().Current pH is:7.043Sent Emoncms Server 1 current PH Value:7.043Sent Emoncms Server 2 current PH Value:7.043Completed get_ph_reading()Starting get_orp_reading().Sent Emoncms Server 1 current ORP Value:669.8Sent Emoncms Server 2 current ORP Value:669.8Completed get_orp_reading()

Running from the cli

Alexa Skill and Interface

One of the last things I wanted to tackle was to integrate my pool control system with Alexa. We have Echo Dots and Echo Shows and I wanted to use the visual Echo Show when I could. So I spent a bunch of time learning how to do Alexa skills and then I used the Python microframework Flask-Ask to program the interconnection between my pool control system and the Alexa Skill.

It was a very interesting learning curve, but now I can query Alexa and get all of our pool stats and we can fill (or stop filling) our pool via voice commands:

Alexa Show Interface with pool, electrical and solar stats

Conclusion

I am running V3.5.0 of my code now which seriously changes the way I am checking sensors, and handling error checking. I have also started breaking out my code into separate python functions instead of a monolithic block of 4,000+ lines of code. I will put it up and include all of the Flask programming as well.

This project has taught me a lot about programming, the Pi and Arduinos.

Pool Control System – InternalPool Control System – External

To view all of the code, please visit my Github site HERE! Thank you for reading about my project.

Source: Pool Fill Control


制造工艺

  1. 控制电路
  2. 草坪洒水器
  3. 游泳池
  4. 洗碗机
  5. 台球桌
  6. 水枪
  7. 填水坝
  8. 厕所
  9. 避孕药
  10. 消防栓
  11. 洗发水