사람들에게 처음부터 급수 시스템을 만드는 방법을 가르치는 것입니다.
이는 센서와 Arduino Uno와 같은 스마트 미니 컨트롤러를 사용하여 식물의 성장에 영향을 미치는 다양한 요소를 제어하여 수행됩니다. 이 논문이 끝나면 식물을위한 완전한 기능의 급수 시스템을 만들 수 있습니다. 제 특정 사례에서 저는 수경 재배 종류의 급수, 더 구체적으로 심해 문화 수경 시스템에 초점을 맞추기로 결정했습니다. 이 토양이없는 수경 시스템은 양동이, 플라스틱 튜브 및 물과 같은 일반 요소로 만들 수 있습니다.
시스템은 Arduino 보드에 의해 자동화되고 실행됩니다. 쉽게 건설 할 수 있고 저렴한 시스템으로 가정 수경 재배자와 상업용 재배자 모두가 활용합니다.
시스템의 기본 개념은 간단하지만 다양한 재료로 구축 된 물 배양 시스템을 구축하고 사용하는 다양한 상상력이 있습니다.
DWC를 처음부터 만드는 방법에 대한 온라인 자습서가 많이 있지만, 이들 중 어느 것도 DWC를 Arduino에 연결하여 보다 자체 효율적으로 만드는 방법을 탐색하지 않습니다. 여기에 제시된 프로젝트는 Arduino를 사용하여 자동화 시스템에 더 강하게 관심을 갖지만이 프로젝트의 개선 된 향후 릴리스에서 IOT 시스템을 구현하려고합니다. 이전 프로젝트는 두 개의 버튼과 LCD 화면으로 제어되는 Arduino에 의해 단독으로 실행되지만 데이터 로그를 보류하지 않고 화면에 온도 및 습도를 표시 할 수 있지만 후자의 미래는 완전히 다른 수준에 도달 할 것입니다.
사실, 이것은 Arduino와 함께 Rasberrypy에 의해 실행되며, 모든 것이 데이터를 기록하고 메시지를 통해 사용자에게 전송되며 다양한 시드에 대한 사전 예약 계획을 갖는 5 인치 터치 스크린에 표시됩니다.
1단계: 아두이노 센서
Arduino 프로젝트에는 훌륭한 배경 커뮤니티가 있으므로 보드 자체와 함께
다양한 모듈을 구입할 수 있습니다.
각 모듈은 값(예: 온도, 습도 등)의 아날로그 또는 디지털 판독값을 가질 수 있습니다. 모든 모듈은 배선하기 쉽고 대부분은 시스템의 코딩 측면과 관련하여 쉽고 간단하게 읽을 수 있도록 사용할 수 있는 추가 라이브러리와 함께 제공됩니다.
모듈은 디지털 또는 아날로그 신호를 반환할 수 있으며, 이에 따라 Arduino가 핀을 통해 해석합니다. 한편으로 디지털은 디지털 변조에 의해 생성 된 이산 시간 신호인 반면, 다른 한편으로 아날로그 신호는 물리적 측정을 나타내는 연속 신호입니다. 또한 센서 사용과 함께 공기와 물을 모두 교반하는 데 몇 개의 저전압 펌프가 사용됩니다.
2단계: 구성 요소 목록
• 플라스틱 버킷 (50 lt)
• 플라스틱 튜브 (모든 원예 상점에서 구입 가능)
• 네트 냄비 (이 냄비는 DWC 시스템에만 해당)
• x2 워터 펌프 (12V)
• 비료 용기 (5 lt)
• 습도 및 온도 센서
• 수위 센서
• 공기 펌프 (6V, 수족관 상점에서 찾기)
• 수족관 공기 돌
•릴레이 스위치
• 여러 저항기
•전선
•아두이노 보드
•실시간 클록 모듈(DS3231)
•LCD 모듈
• 푸시 버튼 x2
나열된 모든 구성 요소는 다음과 같은 이유로 선택되었습니다.
Arduino 보드: 브랜드는 Arduino 보드와 관련하여 중요하지 않습니다(클론인지 여부). Uno 보드는 핀이 많지 않고 실험 자체에 Arduino 실드 또는 추가 구성 요소가 필요하지 않기 때문에이 DIY 실험에 더 적합한 보드 일 것입니다.
릴레이 스위치 : 이것은 오랜 시간이 걸렸습니다. 전자 분야에 대한 지식이 부족하기 때문에 주로 각 구성 요소의 전압이 다르기 때문에 어떤 스위치를 사용하는 것이 가장 좋은지 파악하는 데 시간이 걸렸습니다. Arduino만으로는 5V의 에너지 만 제공 할 수 있기 때문에 두 개의 추가 전원 (9V 배터리)을 연결해야했습니다. 그러나 12V 전류를 처리하는 것은 올바르게 배선되지 않으면 구성 요소가 융합될 위험이 있거나 보드 자체의 기능에 해를 끼칠 수 있으므로 위험할 수 있습니다. 릴레이 스위치는 간단한 방식으로 작동합니다 : 물리적 스위치가있어 정상적으로 열리고 닫힌 회로 사이를 전환 할 수 있습니다. 전류가 필요하지 않을 때 배터리 (+)와 배터리 (-) 사이의 전류 흐름을 단순히 둘러싸는 회로에 갇히게됩니다. 모스펫도 잘 작동했을 것이지만 릴레이 스위치가 더 안전하고 실용적이라고 생각합니다.
12V 워터 펌프: 이것은 웹에서 엄청나게 저렴한 가격으로 발견되었으며 작동하려면 물에 잠겨 있어야 합니다. 그 외에도 잘 작동합니다.
6V 공기 펌프: 나는 이것을 중국에서 주문했고 내가 해야 할 일을 하는 데 완벽하고 공기를 펌핑하며 고전압 등이 필요하지 않습니다. 배송까지 한 달이 걸렸지 만 그만한 가치가있었습니다.
모든 원예 요소 (플라스틱 튜브, 그물 냄비 등)는 원예 웹 사이트에서 온라인으로 구입했습니다.
DHT22 온도 및 습도 센서: 이 센서는 DHT11보다 훨씬 정확하며 adafruit 라이브러리는 사용이 쉽고 깔끔합니다(라이브러리 페이지 링크).
수위 센서의 경우 다른 모델도 마찬가지이지만이 유형을 사용했습니다. 이 모듈은 모든 컨테이너에 따라 매핑 될 수있는 아날로그 값을 반환하므로 라이브러리가 필요하지 않습니다.
마지막으로 실시간 클록 모듈 (DS3231)은 오랫동안 올바른 모듈을 찾고 있었는데, 훌륭하고 따라하기 쉬운이 지침을 발견했습니다. 그것은 또한이 환상적인 도서관에 나를 연결했습니다 - 모든 크레딧은 매뉴얼이 짧지 만 잘 설명 된 이해하기 매우 쉽게 만든이 사람들에게 돌아갑니다.
4단계: 시작하는 방법...
우선 모든 부품을 조립할 장소를 만들어야합니다.
- 치수가 그물 냄비의 상단 부분과 같아야하는 양동이 뚜껑에 둥근 구멍을 뚫습니다. 제 경우에는 레이저 절단 도구가 없었기 때문에 커터와 나침반만 사용했습니다. 나침반에 마커가 부착 된 모양을 그리고 나중에 자르는 것이 나침반 다리와 커터를 묶는 것이 잘 작동하지 않기 때문에 더 좋습니다.
- 이제 DWC 수경 시스템을 조립할 준비가 모두 완료되었습니다. 공기 라인을 공기 돌에 연결하고 버킷 바닥에 놓습니다. 공기 펌프에 전원을 공급하고 양동이에 뚜껑을 덮고 식물 바구니/화분을 삽입합니다. 바구니/냄비의 바닥이 수중 약 3/4인치가 되도록 충분히 높은 양질의 물로 양동이를 채우십시오. 뚜껑을 다시 열고 내부의 급수관에 영구 마커를 표시하십시오. 이것은 수위 센서의 최대 수위 표시가 됩니다.
- 구성 요소의 모든 배선은 프리츠 다이어그램에 설명되어 있습니다. 지금까지의 코딩이 HIGH 및 LOW이기 때문에 상당히 쉽습니다. 켜고 끄려면 깜박임 스케치를 사용할 수 있습니다. 아두 이노 IDE를 열고 파일 > 예제 > 기본 사항> 깜박임으로 이동하십시오. 핀 번호를 저장하는 변수를 변경하면 됩니다.
이 시점에서 기능 시스템을 성공적으로 완료했어야 합니다. 지금부터 추가 된 모든 구성 요소는 프로젝트를 사용자와보다 상호 작용하게 만드는 측면에서만 필요합니다. 이 단계에 첨부 된 그림의 것과 거의 비슷해야합니다. 그것은 잘 작동해야합니다, 나는 당신이 그렇게 할 적절한시기라고 생각할 때 켜고 꺼야하는 전자 시스템 이상을 갖는 것이 너무 많은 노력을 발견했습니다. arduino를 암시하면 버킷이 자체 효율적으로 만들어지며 필요할 때 물을 붓는 경우 온도나 습도가 너무 높은 경우 사용자에게 조언합니다.
5단계: 자동화 추가
앞서 언급했듯이 이 프로젝트에 대해 두 가지 수준의
자동화를 추가하겠습니다. 이러한 지침이 끝나면 식물 성장에 필요한 값을 LCD 화면에 반환하는 시스템을 구축하는 방법을 명확하게 알게 될 것입니다. 따라서 다음을 수행 할 수 있습니다.
• 모든 것이 정상인지 사용자에게 전달 (온도 및 습도 확인)
• 식물에 물을 필요로하는 하루 횟수와 기간에 대해 자동화하십시오. 그러나 여전히 사용자의 입력이 필요합니다.
• 성장의 시간을 돌보십시오.
• 시스템에 약간의 오류가 발생하면 빨간색 LED와 LCD 화면에 경고 메시지로 사용자에게 알립니다.
그러나 다음 페이지에서는 Raspberry PI를 통해 이미 구축 된 시스템을 인터넷에 연결하는 방법을 설명합니다. 적절한 터치 스크린과 깔끔한 사용자 인터페이스가 있습니다. 또한 메시지 나 이메일을 통해 사용자에게 알리고 결국 특정 종류의 씨앗 (정보 데이터베이스)을 재배하는 방법을 알게됩니다. LCD 화면의 경우 웹에서 찾은 3D 모델을 인쇄했으며이를 사용하여 Arduino와 LCD를 한 블록에 캡슐화합니다. 훌륭하지는 않지만 골판지와 거품으로 크기를 조정했다는 사실 외에도 잘 작동했습니다.
6단계: 계획 및 실습
건물의 마지막 부분에 접근한 방식은 양동이 안에 구성 요소를 넣을 위치에 대한 아이디어를 얻으려고 하는 것입니다. 그래서 버킷 내부에 마커로 구성 요소 위치를 그린 다음 내부에 넣고 접착제로 붙이고 방수 테이프로 전선을 보호합니다.
두 개의 버튼과 LCD가 있는 아두이노의 케이스는 중앙 슬롯으로 버킷 외부에 있을 것입니다.
배선은 fritzing에서 설명하지만 실시간 시계와 LCD 모듈은 다이어그램에서 누락되었으며 다음 단계에서 설명합니다.
올바른 방식으로 연결된 arduino에 업로드하면 첨부 된 스케치는 온도 및 습도의 판독 값을 반환합니다. 라이브러리는 오류 처리를 매우 쉽게 만듭니다.
스케치에는 ReadWaterLevel 함수도 있는데, 이 함수는 물이 너무 많거나 너무 적은 경우 오류를 반환하도록 매핑할 수 있는 수위의 아날로그 판독값을 반환합니다.
7 단계 : 실시간 클럭 추가
실시간 클럭 모듈을 추가하고 사용자에게 경고해야 할 때 일종의
경고를 만드는 것이 이러한 지시 사항의 마지막 단계입니다.
먼저 최종 배선과 프로토 코드를 살펴본 다음 연습을 할 수 있습니다.
배선:
VCC -> 아두 이노 5V
GND -> 아두이노 GND
SCL -> SCL 또는 A5
SDA -> SDA 또는 A4
실시간 시계를 연결하는 데 개인적으로 사용한 지시 대상은 SCL 및 SDA 전용 핀의 존재와 관련하여 몇 가지 의구심을 보여줍니다. 나는 내 연구를했고, 나는 그것이 정확하다고 주장 할 수있다 : 아날로그 핀 5와 아날로그 핀 4는 전용이며, 내가 사용하는 것이 좋습니다. 또한이 특정 실시간 클럭 모듈에서 배터리 슬롯을 올바르게 사용하는 이유는 설명되지 않았습니다.
내가 조사하는 동안, 나는 필요한 반죽이 리튬 20132 배터리 일뿐만 아니라 충전이 필요하기 때문에 모듈의 회로가 배터리에 전력을 충전하도록 설계되었으며 재충전 할 수없는 배터리를 충전하고 싶지 않다고 설명하는이 페이지를 발견했습니다.
첨부된 스케치는 다음 단계에서 코드의 날짜와 시간을 설정합니다. 사용자 입력을 추가하여 최종 부분 인 현재 날짜 및 시간과 급수 프로그래밍을 설정합니다.
8단계 : LCD 화면 추가
LCD 구성 요소와 아름다운 라이브러리에 대한 몇 가지 자습서를 읽은 후 LCD의 배선을 올바르게 완료하고 RTC 모듈을 기반으로 날짜와 시간을 인쇄하는 작은 프로그램을 작성했습니다.
다음 단계는 사용자 입력 및 정보 로그 (습도, 온도 및 물)를 추가하는 것입니다.
참고로 온라인 자습서는 좋지만 어떻게 든 전체 프로세스를 실제보다 더 복잡하게 만듭니다.
우선, 우리가 필요로하는 것은 일부 값과 일부 텍스트 만 인쇄하기 때문에 간단한 작업입니다.
첨부된 이미지에 표시된 것처럼 LCD 핀은 vcc 및 gnd로 가는 핀으로 나뉩니다. 핀은 디지털 읽기로, 다른 하나는 화면 레트로 조명을 위해 VCC로, 일부는 쓰기 및 읽기와 같은 작업을 위해 마지막으로 다른 핀으로 이동합니다.
9단계: 프로토타입
코딩:
코드 구조의 구성을 설명하려고 노력할 것입니다. 포함 된 비디오를 보면 우리 프로그램이 가져야하는 주요 기능을 보여 주려고했습니다 (보시다시피 저는 그래픽 디자이너가 아닙니다). 우선, 사용자가 급수 프로그램을 초기화해야하는지 여부를 프로그램이 확인하기를 원합니다. 사용자는 요일 및 시간을 설정 한 다음 물이 얼마나 자주 필요하고 얼마나 오래 필요한지 결정해야합니다.
두 개의 버튼은 모든 입력을 지시합니다. 각 조각의 최종 와이어는 다음 단계에서 올 것이며, 지금은 설명하고 프로토 코딩하는 것으로 제한하겠습니다.
main(){
If (CheckButtonPress()) { If only one is pressed, activate the pump and stop only at the next click.
If both are pressed à make numbers blink and let the user decide date and time, where one button is to increase and the other to complete). }
if(CheckWaterLevel() ) {alert} //this two functions are bool and return 0
if nothing happens
if(CheckTempAndHuml() ) {alert}
if(IsTimeToWater()) {Start_pumps()} }
10단계: 사용자 입력 추가
누구나 사용할 수 있도록 입력을 가능한 한 간단하게 유지하고 싶습니다.
두 개의 버튼 : 하나는 숫자를 늘리고 다른 하나는 선택 항목을 선택합니다. 함께 누르면 사용자는 시간 프로그램의 설정에 액세스 할 수 있습니다. 아무 것도 설정되지 않은 경우(처음 사용) 사용자에게 날짜 및 시간을 설정하라는 메시지가 표시됩니다. 이 작업이 완료되면 화면에 기본적으로 날짜 및 시간이 표시되어야 합니다. 하나의 버튼을 누르면 화면에 습도 / 온도가 표시되어야합니다. 값이 너무 높으면 사용자에게 경고 메시지가 표시됩니다.
첫 번째 단계 (첫 번째 비디오)에서 입력 작업을 한 다음 온도와 습도 (두 번째 비디오)를 추가했습니다.
11단계: 마무리
이 시점에서 누락된 유일한 단계는 버킷에 모든 구성 요소를 추가하는 것입니다. 납땜이 필요한 접착제/납땜; 식물의 물이 필요한 횟수와 기간에 대한 더 많은 코드를 작성하십시오 (높고 낮은 수위에 대한 경고 메시지 포함).
첫 번째 설정된 요일 기능의 외관을 개선하고 수위 센서의 기능을 추가했습니다.
두 번째 수위를 프로그래밍하는 방법도 보여 드리겠습니다.
첨부 된 코드는 마지막 코드이며 프리츠는 마지막 몇 단계와 동일하게 유지됩니다.
코드에 관한 최종 설명 :
첨부 된 스케치에서이 프로그램을 코딩하는 데보다 절차 적 접근 방식을 선호하는 방법을 알 수 있습니다. 나는 간단한 기능과 while 루프를 가질 때 프로그램을 다루기가 더 쉽다는 것을 안다. 예를 들어, 시간, 날짜 및 프로그램을 설정할 때마다 각각 자체 루프가 있어야합니다. 즉, 설정하는 동안 다른 작업이 발생할 수 있습니다. 이전 급수 시간에 더 가까운 시간을 변경하려는 경우 새 프로그램을 설정하는 동안 물이 시작되지 않도록하는 것이 좋습니다.
부울:
Bool set -> 이것이 거짓 인 동안, 프로그램은 while 루프에 남아 있습니다 (각 while 루프는 하나의 변수에만 해당됩니다. 시간 및 날짜). 설정 버튼을 누르면 'set'을 true로 설정하여 결과적으로 루프에서 벗어나야합니다. 다음 루프 전에 다시 false로 설정해야합니다 (등등). 마지막에는 전체 함수가 true가되고 재설정 된 경우 엉망이되는 기능을 종료하므로 false로 재설정해야합니다.
Bool Pump_ON -> 이것은 수동 급수 전용입니다. 왼쪽 버튼을 눌렀을 때 (그리고 프로그램이 실행 중이거나 다음 부울-) 다음 버튼을 누를 때까지 펌프를 켭니다.
Bool Prog_Run -> 수동 버튼을 눌렀지만 급수 프로그램이 실행 중인 경우 입력을 무시하십시오. 흐르는 물 프로그램을 중지하려면 사용자가 프로그램을 다시 설정해야 합니다(이전 프로그램에 더 이상 만족하지 않는 경우).
12 단계 : 조각 얻기
모든 조각의 설계 및 최종 장착에 접근하는 올바른 방법은 없습니다. 지금은 더 멋진 디자인 (IKEA가 가장 좋아하는 디자인 중 하나입니다)을 선택하는 대신 가장 쉬운 디자인 (버킷)을 고수하기로 결정했습니다.
어쨌든 나는 최종 제품을 얻기 위해 플라스틱 튜브와 원예 용 물을 깡통을 사용했습니다. 나는이 단계를 따랐다.
- 순서가 중요하다는 것을 기억하면서 펌프를 안전한 장소에 붙입니다 (접착하기 전에 항상 물을 확인하고 체크 아웃하십시오).
- 모듈도 붙이고 적어도 케이블이 연결되는 부분에 테이프를 붙입니다.
- 플라스틱의 3 개의 출구 조각을 사용하여 물을 플랜트 또는 밸브로 이어지는 다른 플라스틱 파이프로 구동하십시오.이 경우 시스템을 비우려면 수동으로 버킷을 켜고 두 개의 물통을 닫으면 공장으로 이동하여 다른 하나를 엽니 다 (임베디드 비디오의 첫 번째 단계에서 설명).
- 모든 전선과 모든 파이프를 버킷에 고정하여 움직일 때 구성 요소가 서로 굴러 부딪히지 않도록하십시오 (특히 공기 돌!).
- 전선에 방수 테이프를 붙입니다 (물과 elettricity는 좋은 친구가 아닙니다).
- 플라스틱 90도 각도 조각을 사용하여 파이프를 회전시키는 것을 막으십시오, 그렇지 않으면 모호한 물 흐름이 압력 문제를 일으킬 것입니다.
녹는 접착제를 잘 사용하고 약간의 창의력을 납땜하는 것이 DIY에 대한 나의 작은 경험을 이끌어 냈습니다. 금속 부품 간의 접촉을 피하기 위해 납땜 된 연결을 검은 색 테이프 또는 접착제로 고정하여 가능한 한 모든 것을 안전하게 유지하려고 노력했습니다 (elettrecution의 위험은 없지만 전원이 회로에서 빠져 나가는 즉시 전력 손실로 인해 arduino가 재설정됩니다. 예를 들어 금속 조각 접촉).
13 단계 : 납땜
공기 펌프를 납땜 한 후 버킷 내부의 모든 구성 요소를 장착 할 수 있습니다 (한 그림 참조).
이제 납땜하고 LCD와 그 위치, 케이스 및 보관 위치에 대해 생각할 때입니다.
LCD를 납땜하는 것은 각 핀이 다른 핀에 닿지 않도록해야하고 문제를 피하기 위해 납땜을 올바르게 수행해야하기 때문에 약간의 고통이었습니다. LCD 오류를 디버깅하는 것은 가장 고통스러운 일입니다. 어떤 핀이 어떤 오류를 일으키는지 파악하는 데 며칠을 보냈고 여러 번 수정하려고했습니다. 결국 테이프로 금속을 분리해야했습니다.
여기에서 간단한 프로그램을 업로드하여 납땜 된 LCD를 볼 수 있으며 "Hello world"+ 초 경과를 인쇄 할 수 있습니다.
케이스는 전선 아웃 용 구멍이 있도록 설계되었습니다 (마지막 그림 참조).
14단계: 최종 제품에 RTC 추가
그것이 거기에 남아 있는지 확인하기 위해 RTC에는 납땜 (암) 용으로 만들어진 핀이 있기 때문에 케이블을 납땜했습니다. 모든 것을 테스트하기 위해 날짜와 시간 (기본값)을 인쇄하는 간단한 프로그램을 작성했습니다.
연결이 너무 지저분하지 않고 Arduino의 핀이 부족하지 않도록 케이스 뒷면에 브레드 보드를 부착했으며 추가 단계에서 케이스 레이아웃을 개선하고 더 깔끔하게 만들 것입니다.
15 단계 : 버튼 추가
푸시 버튼은 어디에 붙여야하는지, 케이스의 구멍에 맞추는 방법을 몰랐기 때문에 추가하기가 까다 롭습니다.
그래서 나는 약간의 거품을 자르고 그 안에 버튼을 누른 다음 (회로를 만드는 데 필요한 두 다리를 납땜 한 후) 구멍과 같은 지점에 폼 (버튼 포함)을 붙였습니다.
16 단계 : 다른 모든 항목 추가
모든 전선을 버킷에 매달아 놓으면 연결이 상당히 쉬워졌습니다.
II는 방금 전선을 브레드 보드로 몰고 뒷면의 올바른 위치에 고정했습니다.
모든 판독 값을 하나씩 가져 와서 테스트하는 데 약간의 시간이 걸립니다.
뒷면에는 브레드 보드의 수평을 맞추고 전체 케이스를 평평하게 만들기 위해 거품을 부착했습니다 (마지막 단계는 버킷에 부착하는 것입니다)..
17단계: 서비스 케이스 위치 안정화
첨부 된 오류 로그 및 최종 제품
<p> /*mind the <> !!!!*/</p><p>#include Time.h<br>#include TimeLib.h</p><p>#include LiquidCrystal.h
#include DS3231.h
#include dht.h</p><p>// Initialize LCD with following connections
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
DS3231 rtc(SDA, SCL);
dht DHT;
Time t;</p><p>#define DHT22_PIN 13</p><p>const int PIN_BUTTON1 = 7; // digital
const int PIN_BUTTON2 = 8; // digital
const int PUMP_1 = 6; // digital
const int PUMP_2 = 10;
const int read = A0; //Sensor AO pin to Arduino pin A0
int value; //Variable to store the incomming data</p><p>void ReadWaterLvl();
void SetProgram();
void SetDate();</p><p>int Day , Month ;
int Year = 2000;
int h, m, s;
int DayOfTheWeek;</p><p>int Time_Water_h ;
int Interval ;
int Water_howlong;</p><p>int Current_m;</p><p>bool set;
bool Pump_ON;
bool Prog_Run;</p><p>void setup() {</p><p> Serial.begin(9600);
rtc.begin();</p><p>
pinMode(PUMP_1, OUTPUT);
pinMode(PUMP_2, OUTPUT);
lcd.begin(16, 2);</p><p>}</p><p>void InitialiseClock()
{
// rtc.setDOW(DayOfTheWeek);
rtc.setTime(h, m, s);
rtc.setDate(Day, Month, Year); //
}</p><p>void loop() {
lcd.clear();
lcd.noBlink();</p><p> if(HIGH == digitalRead(PIN_BUTTON1) && HIGH == digitalRead(PIN_BUTTON2))
{
delay(500);
SetDate();</p><p> }</p><p> if (!Time_Water_h == NULL || !Interval == NULL || !Water_howlong == NULL )
{
if(Time_Water_h == hour()|| Time_Water_h + Interval == hour())
{
if (!(minute() > Water_howlong))
{ digitalWrite(PUMP_1, HIGH);
digitalWrite(PUMP_2, HIGH);
Prog_Run = true;
}
else{
digitalWrite(PUMP_1, LOW);
digitalWrite(PUMP_2, LOW);
Prog_Run = false;
}
}</p><p> }</p><p>
if(HIGH == digitalRead(PIN_BUTTON1))
{
int chk = DHT.read22(DHT22_PIN);
switch (chk)
{
case DHTLIB_OK:
Serial.println("OK,\t");
break;
case DHTLIB_ERROR_CHECKSUM:
Serial.println("Checksum error,\t");
break;
case DHTLIB_ERROR_TIMEOUT:
Serial.println("Time out error,\t");
break;
default:
Serial.println("Unknown error,\t");
break;
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Celsius: ");
lcd.setCursor(11, 0);
lcd.print(DHT.temperature);
lcd.setCursor(0, 1);
lcd.print("Humidity: ");
lcd.setCursor(11, 1);
lcd.print(DHT.humidity);</p><p> delay(250);</p><p> }</p><p> else{ lcd.setCursor(0, 0);
lcd.print(rtc.getTimeStr());</p><p> lcd.setCursor(0, 1);
lcd.print(rtc.getDateStr());</p><p> if(Pump_ON == true || Prog_Run == true)
{
lcd.setCursor(13, 0);
lcd.print("ON");
}
else if (Pump_ON == false && Prog_Run == false) {
lcd.setCursor(13, 0);
lcd.print("OFF");
}
}
</p><p> ReadWaterLvl();
if ( value>415 && Pump_ON == false && Prog_Run == false)
{
lcd.clear();
while(value>415)
{
lcd.setCursor(0, 0);
lcd.print("**TOO MUCH WATER!!**");
lcd.scrollDisplayLeft();
// digitalWrite(ALERT_LED, HIGH);
ReadWaterLvl();
}
}
else{
// digitalWrite(ALERT_LED, LOW);
}
if (value<=350 && Pump_ON == false && Prog_Run == false )
{
lcd.clear();
while(value<=350)
{
lcd.setCursor(0, 0);
lcd.print("**TOO LITTLE WATER!!**");
lcd.scrollDisplayLeft();
// digitalWrite(ALERT_LED, HIGH);
ReadWaterLvl();
}
}
else{
// digitalWrite(ALERT_LED, LOW);
}</p><p> if(HIGH == digitalRead(PIN_BUTTON2) && Pump_ON == false && Prog_Run == false)
{digitalWrite(PUMP_1, HIGH);
digitalWrite(PUMP_2, HIGH);
Pump_ON = true;
}
else if (HIGH == digitalRead(PIN_BUTTON2) && Pump_ON == true && Prog_Run == false)
{digitalWrite(PUMP_1, LOW);
digitalWrite(PUMP_2, LOW);
Pump_ON = false;}
delay (500); ///Dont under estimate the delay, LCD needs it to correctly print
}</p><p>void SetDate()
{
Month = Day = 1;
Year = 2000;
rtc.setDate(Day, Month, Year);
while (set == false) ///set day
{
lcd.clear();
lcd.print("ENTER DAY: ");
lcd.setCursor(0,1);
lcd.print(rtc.getDateStr(FORMAT_SHORT));
lcd.setCursor(1,1);
lcd.blink();
if (HIGH == digitalRead(PIN_BUTTON1))
{
lcd.noBlink();
Day += 1;
}
if (HIGH == digitalRead(PIN_BUTTON2))
{
set = true;
}</p><p> if (Day > 31)
{
Day = 1;
}
rtc.setDate(Day, Month, Year);
delay (250);
}</p><p>/*************************************************/
set = false;
while (set == false) //set month
{
lcd.clear();
lcd.print("ENTER MONTH: ");
lcd.setCursor(0,1);
lcd.print(rtc.getDateStr(FORMAT_SHORT));
lcd.setCursor(4,1);
lcd.blink();
if (HIGH == digitalRead(PIN_BUTTON1))
{
lcd.noBlink();
Month += 1;
}
if (HIGH == digitalRead(PIN_BUTTON2))
{
set = true;
}
if (Month > 12)
{
Month = 1;
}
rtc.setDate(Day, Month, Year);
delay (250);
}</p><p>
/********************************************************/
set = false;
while (set == false) //set year
{
lcd.clear();
lcd.print("ENTER YEAR: ");
lcd.setCursor(0,1);
lcd.print(rtc.getDateStr(FORMAT_SHORT));</p><p> lcd.setCursor(7,1);
lcd.blink();</p><p>
if (HIGH == digitalRead(PIN_BUTTON1))
{
lcd.noBlink();
Year += 1;
}
if (HIGH == digitalRead(PIN_BUTTON2))
{
set = true;
}
rtc.setDate(Day, Month, Year);
delay (250);
}
/******************************************/
set = false;
while (set == false) //set h
{
lcd.clear();
lcd.print("ENTER TIME: h");
lcd.setCursor(0,1);
lcd.print(rtc.getTimeStr());</p><p> lcd.setCursor(1,1);
lcd.blink();</p><p>
if (HIGH == digitalRead(PIN_BUTTON1))
{
lcd.noBlink();
h += 1;
}
if (HIGH == digitalRead(PIN_BUTTON2))
{
set = true;
}</p><p> if (h > 23)
{
h = 0;
}
InitialiseClock();
delay (250);
}</p><p>/*************************************************/
set = false;
while (set == false) //set m
{
lcd.clear();
lcd.print("ENTER TIME: m");
lcd.setCursor(0,1);
lcd.print(rtc.getTimeStr());
lcd.setCursor(4,1);
lcd.blink();
if (HIGH == digitalRead(PIN_BUTTON1))
{
lcd.noBlink();
m += 1;
}
if (HIGH == digitalRead(PIN_BUTTON2))
{
set = true;
}
if (m > 59)
{
m = 0;
}
InitialiseClock();
delay (250);
}
setTime(h, m, 0, Day, Month, Year);
SetProgram();
set = false;
}</p><p>void SetProgram()
{
/********************************************************** SET Hour*/
set = false;
while(set == false)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Water starts at:");
lcd.setCursor(0, 1);
lcd.print(Time_Water_h);
if (HIGH == digitalRead(PIN_BUTTON1))
{
lcd.noBlink();
Time_Water_h += 1;
}
if (HIGH == digitalRead(PIN_BUTTON2))
{
set = true;
}
if (Time_Water_h > 23)
{
Time_Water_h = 0;
}
delay (250);
}</p><p>/********************************************************** SET Interval*/</p><p> set = false;
while(set == false)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("How often:");
lcd.setCursor(0, 1);
lcd.print("Every ");
lcd.setCursor(6, 1);
lcd.print(Interval);
lcd.setCursor(8, 1);
lcd.print("hours");
if (HIGH == digitalRead(PIN_BUTTON1))
{
lcd.noBlink();
Interval += 1;
}
if (HIGH == digitalRead(PIN_BUTTON2))
{
set = true;
}
if (Interval > 24)
{
Time_Water_h = 0;
}
delay (250);
}</p><p>/********************************************************** SET Length*/</p><p> set = false;
while(set == false)
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("For how long:");
lcd.setCursor(0, 1);
lcd.print(Water_howlong);
lcd.setCursor(3, 1);
lcd.print("minutes");
if (HIGH == digitalRead(PIN_BUTTON1))
{
lcd.noBlink();
Water_howlong += 1;
}
if (HIGH == digitalRead(PIN_BUTTON2))
{
set = true;
}
if (Water_howlong > 30)
{
Water_howlong = 0;
}
delay (250);
}</p><p> lcd.clear();</p><p>}</p><p>void ReadWaterLvl()
{
value = analogRead(A0); //Read data from analog pin and store it to value variable
Serial.println(value);
}</p>
댓글