산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
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 스테인리스 스틸 탱크 수위 센서 플로트 스위치

저의 수위와 일반 수위의 차이가 약 3인치이기 때문에 이것은 저에게 완벽하게 작동했습니다. 마운트하고 올바르게 작동하도록 하는 방법을 찾아야 했습니다.

많은 다른 사람들이 eTape를 사용하여 훌륭한 결과를 얻을 수 있다는 것을 알고 있기 때문에 eTape에 대한 모든 것을 내 프로젝트에 남겨두고 이중 플로트 설정을 수행한 방식으로 추가할 것입니다. 이렇게 하면 사람들이 다양한 옵션을 볼 수 있습니다.

내 Pi가 있는 마당 건너편에 위치할 예정이었기 때문에 보고를 위해 자체 장치에 연결해야 했습니다. 이를 위해 Pi가 필요하지 않았기 때문에 이미 집에 있는 기존 시스템으로 정보를 다시 전송할 수 있는 배터리로 작동되는 저전력 Arduino 무선 클론을 선택했습니다.

Low Power Labs에서 구매한 기기입니다. 결국 내 프로젝트에서 4개를 사용하게 되었습니다. 하나는 수위, 하나는 수온, 두 개는 내부 인클로저 온도, 필터 압력 및 물 사용량의 조합을 모니터링하기 위해 메인 시스템에 사용되었습니다.

플래시 및 RFM69HW 433Mhz 트랜시버가 있는 Moteino R5-USB

이 Arduino 클론은 매우 낮은 전력을 사용합니다. 즉, 깊은 절전 모드에서 ~7uA에 불과하므로 두 개의 AA 배터리로 매우 오래 지속됩니다. 내 수온 센서는 수영장 주변에 떠 있고 수위 센서는 전원 근처에 없기 때문에 배터리로 작동되는 무선 장비를 사용해야 했습니다.

처음에는 수영장에 물을 자동으로 추가하는 것 외에는 다른 작업을 할 생각이 없었지만 이러한 일이 자주 되면서 프로젝트가 저절로 성장했습니다. 결국 다음을 수행할 수 있게 되었습니다.

수영장 채우기

수동 또는 자동으로 수영장 채우기 라우팅을 유발하는 요인에 관계없이 수영장에 물을 공급할 방법이 있어야 했습니다. 관개 시설과 도시 상수도 사이에 이미 진공 차단기가 있어야 하기 때문에 기존 스프링클러 시스템에 연결하여 수영장에 물을 공급하기로 했습니다. 저는 기본적으로 밸브가 있는 스프링클러 시스템을 위한 또 다른 "구역"을 만들고 있었습니다.

이는 스프링클러가 작동 중이고 수영장을 채우기로 결정하면 잔디밭에 물이 흐르고 있는 잔디밭을 강탈하고 잔디밭에 제대로 물을 주지 않는다는 문제가 있었습니다. 그래서 스프링클러가 작동 중인지 확인할 방법을 강구해야 했습니다. 처음에는 "정전" 시간대를 사용했습니다. 즉, 스프링클러가 오전 3시부터 오전 6시까지 작동한다는 것을 알았다면 그 시간 동안 수영장을 채우지 마십시오. 그러나 그것은 약간 비 기술적 인 것처럼 보였습니다. 내 Rachio 스프링클러 시스템을 조사하면서 스프링클러 시스템의 상태를 프로그래밍 방식으로 쿼리할 수 있는 내장 API가 있다는 것을 알게 되었습니다. 제 경우에는 간단한 질문이 있었습니다. 지금 뛰고 있습니까?

제 경우에는 간단한 curl 명령을 사용하여 필요한 것을 얻었습니다.

rachio_url ='curl -s -X GET -H "콘텐츠 유형:애플리케이션/json" -H "승인:베어러 xxxx-xxxxx-xx-xxxx-xxxxx-xxx" https:/ /api.rach.io/1/public/device/00xx00x-00xxx000-xxx0x000-00x0x0x0/current_schedule' 

다음과 같은 get_sprinkler_status 함수에 의해 호출됩니다.

출력 =subprocess.check_output(pooldb.rachio_url, shell=True) 경우 출력 =="{}":스프링클러_on ="아니요" 

내 메인 애플리케이션은 60초마다 실행되므로 스프링클러가 작동 중이면 60초 동안 아무것도 하지 않고 다시 확인합니다. 결국 스프링클러가 작동을 멈추고 수영장이 자동으로 채워지기 시작합니다.

수영장을 실제로 채우기 위해 홈디포에서 구입한 일반 24V AC 스프링클러 밸브를 사용했습니다. 나는 이것을 내 수영장으로 가는 내 수영장 배관에 직접 단방향 밸브로 설치했습니다. 단방향 밸브는 펌프가 작동 중일 때 펌프의 압력이 스프링클러 밸브에 대해 물을 밀어내는 것을 방지합니다.

단방향 밸브가 있는 급수관

내 수영장 전기 패널은 240V이고 패널에 중성선이 없기 때문에 240VAC에서 24VAC로의 변압기를 구입해야 했습니다. 충분히 간단합니다. 하지만 아무 이유 없이 변압기를 24시간 가동하고 싶지 않아 릴레이를 사용하여 1) 변압기를 켠 다음 2) 변압기에서 24VAC 출력을 가져와 스프링클러 밸브에 연결했습니다.

릴레이 설정

저는 Pi에서 5v 또는 3.3v VCC를 사용하는 것과 달리 별도의 전원 입력이 릴레이에 전원을 공급하는 광학 절연 모드에서 Sainsmart 솔리드 스테이트 릴레이(매우 저렴)를 사용했습니다. 이것은 릴레이의 간섭을 돕기 위한 것입니다.

스프링클러 밸브 및 스마트 수량계

또한 실시간으로 읽을 수 있는 스마트 계량기를 추가하여 물이 흐르고 있고 시간이 지남에 따라 내가 사용하는 물의 양을 보여줍니다. 이 정보는 MySQL 데이터베이스에 저장되며 역사적으로 저장됩니다.

우리집 수도 미터용 EmonCMS 시스템의 화면

힘, 힘, 힘

이제 내가 알아내야 할 다음 사항이 생겼습니다. 펌프가 작동하는 동안 수영장을 채우려고 하면 펌프의 압력과 싸워야 했습니다. 나는 물의 흐름을 측정하여 펌프가 작동하는 동안 채우는 흐름의 약 50%를 잃은 것으로 판단했기 때문에 펌프가 작동하는 동안에는 채우지 않는 것이 가장 좋다고 생각했습니다. 그래서 펌프의 전력을 모니터링하고 작동 여부를 파악할 방법이 필요했습니다.

이 경우에는 매우 쉬운 방법이 있었습니다. 우리 집의 모든 단일 회로는 전기 모니터링 시스템에 의해 모니터링됩니다. 이 시스템을 GEM이라고 하며 Brultech에서 판매합니다.


내 수영장 펌프는 우리 집에서 가장 많은 전력을 소비하는 제품입니다.

이 시스템을 사용하면 모니터링의 일환으로 집의 모든 전기 사용량을 모니터링할 수 있습니다. 프로세스에서 이 데이터를 MySQL 데이터베이스에 저장합니다. 따라서 1분에 한 번씩 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가 켜져 있어야 합니다. 이것은 YELLOW LED') if DEBUG :print("PUMP_RUN_LED가 켜져 있어야 합니다. 이것은 YELLOW LED입니다.")else:pool_fill_control.led_control(PUMP_RUN_LED, "OFF") pool_pump_running ="아니오" logger.debug('PUMP_RUN_LED가 꺼져 있어야 합니다. 이것은 YELLOW LED') if DEBUG:print("PUMP_RUN_LED가 꺼져 있어야 합니다. 이것은 YELLOW LED입니다.")

물리적 장치에 다양한 버튼, 스위치 및 LED가 있어 스프링클러가 작동 중인지, 펌프가 작동 중인지, 수영장이 채워지고 있는지 또는 일종의 시스템 오류가 있는지 확인할 수 있습니다. . 위에서 필요할 때 펌프 작동 LED를 켜고 끄는 위치를 확인할 수 있습니다.

시스템 LED 외에도 MightyHat 시스템을 사용하여 Pi에 로그인하지 않고도 지능적으로 Pi를 재부팅하거나 종료할 수 있는 시스템 ON/OFF 버튼(왼쪽 상단)이 있습니다. CLI에서 수행하십시오. 또한 내가 원할 때 수영장을 수동으로 채울 수 있는 순간 스위치(왼쪽에서 두 번째)가 있으며 마지막으로 왼쪽에는 시스템에서 스프링클러 밸브로의 전원을 물리적으로 차단하고 GPIO를 트리거하는 DPDT 스위치가 있습니다. 시스템에 풀 채우기를 수동으로 비활성화했음을 알리는 이벤트입니다. 이 스위치가 트리거되면 아무 것도 작동하지 않으며 프로그래밍 방식으로 무언가가 실패하면 관계없이 변압기에서 스프링클러 밸브로 전원을 공급할 수 없습니다.

풀 컨트롤러 – 외부

펌프 관리

시간이 지남에 따라 수영장 제어 시스템에 다른 부분을 추가했습니다. Pentair 가변 속도 펌프를 관리하는 기능. Russell Goldin(tageyoureit)과 그의 풀 컨트롤러 소프트웨어 프로젝트에 참여하세요. Russell의 소프트웨어를 사용하여 RS485 인터페이스를 통해 수영장 펌프와 직접 통신할 수 있었습니다. 연결되면 RPM, GPM 및 사용 중인 와트와 같은 시스템 정보에 대해 펌프를 직접 쿼리할 수 있습니다.

def get_pump_data(key):verbose_debug("get_pump_data() 시작됨") 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() - 완료됨") log("정보", "get_pump_data() - 완료됨") if key =="gpm":pump_gpm =pump_data update_database("pump_status", " pump_gpm", pump_gpm) log("INFO", "현재 GPM:{}".format(pump_gpm)) log("DEBUG", "get_pump_gpm() 완료됨") debug("현재 GPM:{}".format(pump_gpm) )) verbose_debug("get_pump_gpm() 완료") elif 키 =="rpm":pump_rpm =pump_data update_database("pump_status", "pump_rpm", pump_rpm) log("INFO", "현재 RPM:{}".format(pump_rpm)) log("DEBUG", "get_pump_rpm() 완료됨") debug("현재 RPM:{}".format(pump_rpm)) verbose_debug("get_pump_rpm() 완료됨") else:pump_watts =pump_data update_database("pump_status", "pump_watts", pump_watts) log("INFO", "현재 WATTS:{}".format(pump_watts)) log("DEBUG", "get_pump_watts() 완료됨") debug("현재 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", 오류) debug(type(error)) debug(error) verbose_debug("get_pump_data() - EXCEPTION으로 완료됨") log("DEBUG", "get_pump_data() - EXCEPTION으로 완료됨") return pump_data else:pump_data =0 return pump_data 

이제 펌프를 쿼리하고 이전에 없었던 다른 기능을 추가하여 펌프를 제어할 수 있습니다. 웹 인터페이스를 변경하여 펌프를 시작 또는 중지하고 펌프에 구성한 4가지 다른 펌프 프로그램 중 하나를 실행하는 기능을 추가했습니다.

펌프 제어판

물론 RPM, GPM 및 와트를 실시간으로 확인할 수 있습니다.

웹 인터페이스의 펌프 게이지

필터 압력 모니터링

또한 내가 하고 싶었던 한 가지는 필터 압력을 모니터링하여 필터를 백플러시할 때를 알 수 있도록 하는 것이었습니다. ebay에서 100PSI 압력 센서를 구입하여 이미 필터에 있는 아날로그 압력 게이지 옆에 있는 필터에 연결했습니다.

ebay에서 저렴한 발신 장치를 구입하여(위 링크 참조) 다음과 같이 파일러에 묶었습니다.

100 PSI Sender unitPressure Sending unitSending Unit Wiring..

그런 다음 이것을 Moteino-R5에 연결하고 1분에 한 번씩 압력을 읽은 다음 해당 정보를 MySQL 데이터베이스에 출력한 다음 해당 정보를 사용하여 내 웹사이트에서 게이지 출력을 구동합니다.

// 필터 압력 가져오기 void get_filter_pressure() { sensorVoltage =analogRead(PSI_SENSOR_PIN); // 압력 센서 전압을 읽어봅시다. PSI =((sensorVoltage-146)/204)*25; // 전압을 PSI로 변환하고 영점 조정하기 위한 일부 보정 pool_sensors.PSI =PSI; } 

풀 필터 PSI 게이지

추가 하드웨어 및 소프트웨어

메인 시스템은 모두 Python으로 작성되었지만 시스템 작동을 위해 다른 소프트웨어와 하드웨어를 활용했습니다.

저는 Raspberry Pi에서 Pi에 대한 UPS 전원 백업, LCD 상태 화면 및 Pi에 대한 지능형 전원 제어를 제공하는 Low Power Labs MightyHat을 사용합니다. 시스템에 연결된 작은 배터리로 약 2시간 정도 Pi를 실행할 수 있으며 전원이 제 시간에 다시 켜지지 않으면 MightyHat이 자동으로 Pi를 종료하여 갑작스러운 충돌로 인한 충돌을 방지합니다. 정전.

Overfill Alert를 보여주는 Pi3의 MightyHat 클로즈업

MightyHat은 Arduino 클론이므로 Arduino IDE를 사용하여 프로젝트 요구 사항에 맞게 프로그래밍했습니다.

센싱을 위해 다양한 센서와 정보를 사용 가능한 형식으로 가져오는 방법을 사용합니다. 거의 모든 센서 데이터에 대해 OpenEnergyMonitor.org의 무료 EmonCMS 플랫폼을 활용합니다. 이 플랫폼을 사용하면 집 안 모든 곳에서 모든 센서 데이터를 수집할 수 있습니다. 이 정보를 MySQL 데이터베이스에 저장한 다음 풀 제어 시스템에서 사용할 수 있도록 가져올 수 있습니다.

내 수영장에 대한 일부 센서 추적추가 추적 정보

수영장의 실제 수위를 위해 eTape Resistive Liquid Measuring 테이프(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″ 퀵 커넥트를 사용하여 플로우 셀을 라인에 묶었습니다. 하나는 필터의 압력 측면에, 다른 하나는 펌프의 흡입 측면에 있어 플로우 셀을 통해 물이 계속 흐르도록 했습니다.

Flow Cell(맨 왼쪽)Flow Cell w/SensorsJohn Guest 3/8″ 나사식 Quick ConnectsReturn(흡입) LineOutput(압력) 라인 – 산성 주입기 ​​이전에 설치

pH 읽기:

def get_ph_reading():log("DEBUG", "get_ph_reading() 시작됨") pool_pump_running =read_pool_sensor_status_values("pool_sensor_status", "led_status", "pump_run_led"_"running ==p인 경우) :pooldb.temp_probe =="예"인 경우: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_current get_ph_value =float_ ()) debug("현재 pH:{}".format(ph_value)) influx_data.write_data("pH", ph_value) influx_data.write_data("pool_temp", pool_temp) if pooldb.emoncms_server1 =="예":res =requests.get("http://" + pooldb.server1 + "/" + pooldb.emoncmspath1 + "/input/post?&node=" + str( pooldb.ph_node) + "&csv=" + ph_value + "&apikey =" + pooldb.apikey1) log("DEBUG", "Emoncms Server 1에 {}의 현재 pH 값을 보냈습니다.".format(ph_value)) debug("Emoncms Server 1에 {}의 현재 pH 값을 보냈습니다.".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", "Emoncms Server 2에 {}의 현재 pH 값을 보냈습니다.".format( ph_value)) debug("{}의 현재 pH 값을 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)# [이메일 보호됨 ]# 이것은 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 및 line_buffer[-lsl:] ==list('\r')):break return ''.join(line_buffer)def read_lines():lines =[ ] 시도:동안 True:line =read_line() if not line:break ser.flush_input() lines.append(line) e:"Error, ", e return Nonedef send_cmd(cmd):""로 SerialException을 제외한 줄 반환 " 명령을 Atlas 센서에 보냅니다. 보내기 전에 명령 끝에 Carriage Return을 추가하십시오. :param cmd::return:""" buf =cmd + "\r" # 캐리지 리턴 추가 시도:ser.write(buf) e로 SerialException을 제외하고 True를 리턴: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도 같은 방식으로 수행됩니다.

이 플로우 셀에는 플로우 표시기도 설치되어 있습니다. 물이 세포를 통해 흐르면 링이 올라가 자기 스위치를 닫습니다. 스위치의 배선은 파이의 GPIO 핀에 연결됩니다. 다음은 해당 스위치를 읽는 코드입니다.

def pool_pump_running_chemical():pool_pump_running_chemical =GPIO.input(pool_pump_running_pin) if pool_pump_running_chemical ==False:debug("화학 센서 챔버를 통해 실행되는 수영장 펌프:TRUE - 펌프가 실행 중입니다.") else:debug( "화학 센서 챔버를 통해 작동하는 수영장 펌프:FALSE - PUMP IS OFF")

수위 센서 – 작동시키기

위에서 보았듯이 수위 센서는 LowPowerLab에서 배터리로 구동되는 MoteinoUBS를 사용합니다. 이것은 이 애플리케이션을 위한 완벽한 마이크로컨트롤러입니다. 기본적으로 저는 60초마다 Moteino를 깨우고 eTape에서 저항 판독값을 취하고 송신기를 켜고 이 정보를 EmonCMS 시스템에 보내서 풀 스크립트에서 사용할 수 있도록 합니다. 그런 다음 모든 전원을 다시 끕니다.

{ digitalWrite(ETAPE_POWER, HIGH); // eTape의 전원을 켭니다. pool.resistance =analogRead(ETAPE); // 에타페 저항 읽기 digitalWrite(ETAPE_POWER, LOW); // eTape의 전원을 끕니다. take_battery_reading(); // 배터리 읽기 power_spi_enable(); rf12_sleep(RF12_WAKEUP); rf12_sendNow(0, &풀, 풀 크기); rf12_sendWait(2); rf12_sleep(RF12_SLEEP); power_spi_disable(); if (디버그){ flash_led(50); } // 그럼 - 다음 시간까지 기다리세요 :) sleep_until_next_reading(); } 

또한 배터리 전압을 추적하여 배터리 교체 시기를 알 수 있습니다. 스크립트에는 배터리가 양호한지 확인하는 몇 가지 메커니즘이 있습니다. 먼저 배터리 전압 자체를 적극적으로 추적하고, 두 번째로 센서가 나에게 보고하는 빈도와 해당 보고서의 시간 델타를 추적합니다. 많은 판독값을 놓친 경우 해당 센서에 '무언가'가 잘못되었음을 알고 있으며 무엇이 잘못되었는지 확인하기 위해 푸시불렛 알림을 받을 것입니다. 또한 센서가 손실되면 수영장 채우기 시스템이 대기 상태가 되고 언제 멈출지 모르기 때문에 수영장 채우기를 거부합니다.

2 x AA 리튬 배터리를 사용하고 있으며 지금까지 교체하지 않고 1년 넘게 사용하고 있습니다.

수영장 수준의 MoteinoUSB를 안전하게 유지하려면 일종의 방수 인클로저가 필요했습니다. 투명한 뚜껑이 있는 Adafruit 방수 상자를 선택했습니다.

Adafruit 내후성 케이스

다음으로 Adafruit PG-9 케이블 글랜드를 사용하고 상자 측면에 매우 조심스럽게 구멍을 뚫고 케이블 글랜드를 설치했습니다.

Adafruit PG-9 케이블 글랜드

Adafruit 방수 DC 전원 케이블을 사용하여 eTape를 MoteinoUSB 및 인클로저에 연결했습니다.

Adafruit 방수 DC 전원 케이블수위 센서 인클로저 완성

좀 더 건조함을 위해 인클로저에 들어갈 수 있는 습기와 흡수를 위해 인클로저에 넣을 건조제를 구입했습니다. 내가 어렵게 배웠던 한 가지 주의해야 할 점은(감사하게도 센서는 저렴함) 상단이나 케이블 글랜드를 너무 세게 조이지 않는 것입니다. 이것은 약간의 시행 착오를 겪었습니다. 결국 내 생각이 옳다고 '생각'한 후 실제로 싱크대를 채우고 인클로저를 물 속에 넣고 그 위에 물이 채워진 팬을 올려 놓습니다. 몇 시간 동안 이 상태를 유지하여 내가 정확한지 자주 확인합니다.

이제 수위 센서를 장착할 방법과 장소를 찾아야 했습니다. 내 수영장에는 수영장에 물을 수동으로 추가하는 부유물을 수용하는 데 사용되는 작은 시멘트 분지가 있습니다. 이것은 오래 전에 녹슬어서 시멘트 인클로저를 뜯어내지 않고는 수리할 수 없었습니다. 이것이 처음에 내 프로젝트를 시작한 것입니다!

시멘트 대야

시멘트 대야는 수위를 볼 수 있는 작은 3/4″ 선으로 수영장에 연결되어 있지만 수영장에서 아이들이 튀거나 장난을 쳐도 수위에는 영향을 미치지 않습니다. 대야의 물. 이것은 eTape 센서를 장착하기에 완벽한 장소였습니다. 실제 장착을 위해 PVC 파이프를 반으로 자른 다음 사포질하여 시멘트 대야와 같은 원형이 되도록 했습니다. 그런 다음 이 조각을 대야의 측면에 직접 에폭시로 고정했습니다. 이 작업이 완료되면 몇 개의 마른 벽에서 나온 나사를 사용하고 eTape를 PVC 파이프에 나사로 고정했습니다.

PVC 파이프에 eTape 센서 장착 eTape 센서 설치 완료

업데이트:수위를 읽는 새로운 방법!

위를 읽었다면 eTape 설치에 몇 가지 문제가 있어서 eTape가 작동을 멈추고 잘못된 판독값을 제공하여 사용할 수 없게 되었습니다. 나는 Mileone에서 Chris와 이야기를 나눴고 테이프가 고장난 이유를 생각해낼 수 없었습니다. 결국 다른 테이프를 사서 같은 일이 반복되는 데 80달러를 더 지불할 가치가 없었기 때문에 수위를 읽는 방법을 바꿨습니다.

낮은 수준과 전체 수준의 차이가 3인치밖에 없기 때문에 다양한 수준의 센서를 조사한 결과 이 ​​센서를 선택했습니다.

Elecall 스테인리스 스틸 탱크 수위 센서 플로트 스위치

그래서 새 센서를 장착할 방법을 찾아야 했습니다. 나는 그것을 작동시키기 위해 1/4″ 플렉시 유리를 사용하기로 결정했습니다. 나는 필요한 너비를 측정하고 미세 조정을 할 수 있도록 여분의 고정 나사로 플로트를 장착했습니다. 또한 장착할 때 수평이 되도록 작은 레벨을 테이프로 붙였습니다.

장착하기 위해 에폭시를 사용하고 "내장 레벨:

을 사용하여 수평을 맞추었습니다.

풀의 레벨을 읽으려면 두 float의 위치를 ​​알아야 합니다. 그래서 두 수레의 위치를 ​​읽은 다음 수위에 따라 0, 1 또는 2를 보내도록 코드를 프로그래밍했습니다.

상단 플로트가 열려 있고 하단 플로트가 열려 있으면(둘 다 아래로 플로트) 우리는 낮고 "0"을 보냅니다. 아래쪽 플로트가 닫혀 있고(위쪽) 위쪽 플로트가 열려 있으면(아래쪽) 중간이며 "1"을 보냅니다. 두 수레가 모두 닫히면(위로) 수영장이 가득 차서 물이 필요하지 않습니다. 코드는 다음과 같습니다.

UPPER_Float =digitalRead(17);LOWER_Float =digitalRead(3); if (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. 소화전