본문 바로가기
생활 취미 만들기

수직 수경 농장 (수경식물재배)

by 굿뜨클랑 2022. 12. 11.
728x90

   오늘은 수경 재배에 대해 알아보겠습니다.

아파트에서 생활하면서 베란다에서 쉽게 제작하여 제작할 수 있는 프로젝트를 설명하도록 하겠습니다.

  

프로젝트를 RUFS라고 부르며, Robotic Urban Farm System에 대해

  • 수직 수경 정원
    • 고밀도 수율 및 더 짧은 성장 주기 허용
    • 자원 소비 감소 - 물, 비료 및 공간
    • 노동력 절약 - 경작할 잡초나 토양 없음
    • 훌륭한 맛 결과로 작물의 더 높은 일관성
  • 마이크로 컨트롤러에 의해 유지 관리 (Raspberry Pi & Arduino)
    • 급수 주기 - 모니터 및 자동 리필 레벨
    • 식물 영양소 및 pH - 모니터링 및 수정
    • 온도 모니터링
    • 공기 순환 및 조명 제어 (실내 작동용)
  • 스마트하고 연결됨
    • 농장 컨트롤러 앱 스마트 폰, 태블릿 및 PC
    • 시스템에 리필이 필요할 때 알림 받기
    • 무언가가 예상대로 실행되지 않을 때 경고
  • 일년 내내 재배 - 일년 중 매월 신선한 농산물
  • 제한된 공간의 도시 환경에 적합
  • 자동화를 통한 운영 시간 및 유지보수 단축
  • 영양소 및 급수 주기에 대한 추측 제거

 

수경법은 수중 재배의 하위 집합이며 토양이없는 물에서 미네랄 영양 용액을 사용하여 식물을 재배하는 방법입니다.

수경법이라는 단어는 기술적으로 물을 의미하는 라틴어 "hydro"와 노동을 의미하는 "ponos"에서 유래 한 작동 수를 의미합니다. 태초부터 많은 다른 문명은 초기 멕시코와 이집트 문명과 같은 식물 재배를 위해 수경법에 의존해 왔습니다. 그러나 최근 수경법으로 성장하는 것은 다양한 시장에서 인기와 사용이 증가하고 있습니다.

(위키피디아 http://en.wikipedia.org/wiki/Hydroponics 에서 발췌)

 

친환경적이고 효율적

물은 재순환되어 효율성을 높이며 종종 물 소비에 대해 90 % 이상 효율적입니다.

우리의 수직 디자인은 훨씬 더 작은 설치 공간에서 더 높은 밀도의 식물을 허용합니다. 5' x 5' 미만의 공간으로 160개의 식물을 재배하고 있습니다.

 

자동화

시스템은 일련의 Arduino 컨트롤러로 유지 관리됩니다. 급수 주기, pH 수준, 영양소 수준, 조명 주기 및 환기 팬은 모두 Arduino를 통해 유지됩니다.

Arduino는 I2C를 사용하여 라즈베리 파이에 네트워크로 연결하여 모든 시스템 매개 변수를 실시간으로 모니터링하고 업데이트 할 수 있습니다. Raspberry Pi는 데이터를 실행하는 모든 시스템의 기록 로그를 유지 관리하고 웹 서비스 경우 집합을 통해 사용할 수 있도록 하는 데 추가로 사용됩니다.

컴패니언 스마트폰/태블릿 앱은 Raspberry Pi와 인터페이스하여 전 세계 어디에서나 전체 시스템을 구성하고 모니터링할 수 있습니다. 라즈베리 파이는 JSON 웹 서비스를 통해 앱과 통신합니다.

단계는 여기에 설명되어 있으며 플랜트 제안 및 업데이트를 포함한 추가 프로젝트 정보는 당사 웹 사이트에서 확인할 수 http://www.bltrobotics.com/

 

우리는 무엇을 키우고 있습니까?

수직 수경법은 잎이 많은 녹색 채소에 아주 잘 어울립니다. 나는 현재 양상추 (로메인, 보스턴 턱받이, 스프링 믹스), 양배추 (빨간색과 녹색), 허브 (바질, 실란트로, 민트, 딜, 향신료), 시금치, 케일 (난쟁이 곱슬 품종), 브로콜리 및 피튜니아를 성공적으로 재배하고 있습니다.

 

 

1 단계 : 구매할 제품

위 사진의 모델 건설을 위해 10 개의 타워로 구성된 2 개의 뱅크

부품 및 부품(구매 대상)

 

지원 프레임

(5) 10' - 2" PVC 관

(1) 10' - 3" PVC 관

(4) 2" PVC 90° 팔꿈치

(8) 2 "PVC 티

(4) 3 내지 2 PVC 티

(4) 3" PVC 엔드캡

참고 : 모든 PVC 파이프 및 피팅은 스케줄 40-셀룰러 PVC입니다.

 

타워/리턴

(10) 10' - 2" x 3" PVC 다운스파우트

(1) 10' PVC 압출 거터 4"

(4) PVC 거터 엔드 캡 (왼쪽 2 개와 오른쪽 2 개)

(2) 1" 나사산 3/4" 가시 어댑터

(2) 3/4" PVC 암나사산 커넥터

(20) 2" PVC 파이프 행거("J" 후크)

(20) #6 스테인리스 1 1/2" 기계 나사 및 너트

 

물 공급/반환

(1) 10' - 1" ID 음료수 배관

(3) 1" 나사산 3/4" 가시 어댑터

(1) 1" 가시 티

(5) 3/4" PEX 90° 엘보 - 가시

(1) 3/4" PEX 티 - 가시

(1) 1" 내지 3/4" PEX 감속기 - 가시

(2) PEX 크림프 링 10팩

(1) 10 팩 1 1/2" 호스 클램프

(1) 25' - 3/4" PEX

(20) 조정 가능한 0-10GPH 드립 이미 터

(1) 14 갤런 부드러운 플라스틱 버킷

 

2단계: 지원 프레임 구축

지원 프레임

지지 프레임은 2" 및 3" OD(외경)의 표준 Schedule 40 PVC로 구성됩니다. 프레임은 모듈식 특성(서로 맞추기 쉬움)과 크기 조정을 위한 사용 용이성(기본 도구로 직선 절단하기 쉬움)을 위해 이 재료로 구성되었습니다. 이것은 프레임이 구조적이고 물을 운반하지 않기 때문에 목재, 플라스틱 및 금속과 같은 다른 구조 재료의 사용을 배제하지 않습니다.

 

공구 노트:

이 프로젝트의 PVC 파이프는 연귀 톱을 사용하여 절단하는 것이 가장 좋습니다. 이들은 저렴한 수공구 또는 전기/전동 공구로 쉽게 구할 수 있습니다. 마이터 톱은 프레임의 안정성을 추가하는 데 도움이 되는 우수한 90° 절단을 제공합니다.

PVC는 두 부분으로 된 접착제 시스템을 사용하는 접착제입니다.

진동 다기능 전동 공구는 수직 타워의 주머니를 자르는 데 사용되었습니다.

전기 히트 건은 수직 타워의 주머니를 형성하는 데 사용되었습니다.

지지 프레임은 (2) (2) "상단 바" 구성 요소와 (2) "교차 지지대"로 연결된 메인 다리 구성 요소입니다.

"상단 막대"와 "십자 지지대"의 길이는 시스템이 지원할 타워의 용량을 결정합니다.

3" PVC로 만든 두 개의 추가 다리 확장이 있어 외부에서 사용할 때 요소에 대한 추가 지지를 제공할 수 있습니다. 실내 사용을 위해 생략 할 수 있습니다.

4 '에서 우리는 중앙 간격으로 4.5 인치 간격으로 (10) 성장 타워를 지원하고 있습니다.

 

3 단계 : 메인 다리

프레임 구조의 핵심은 (2) 동일하게 구성된 다리 유닛입니다.

우리는 안정성을 위해 개별 다리 구성 요소를 함께 접착했지만 장치를 실내로 이동할 때 쉽게 분해할 수 있도록 크로스 피스에 접착하지 않았습니다.

다리의 대부분은 2" PVC이며 조각 #4 및 #8은 3"입니다.

 

메인 레그 컷 리스트

  1. 2" PVC의 10' 섹션에서
    1. 32"에서 (2) 섹션 자르기 - (파트 #1 - 첫 번째 세트)
    2. 2"에서 (28) 섹션 자르기 - (파트 #3 - 첫 번째 세트)
  2. 2" PVC의 10' 섹션에서
    1. 32"에서 (2) 섹션 자르기 - (파트 #1 - 두 번째 세트)
    2. 2"에서 (28) 섹션 자르기 - (파트 #3 - 두 번째 세트)
  3. 10" PVC의 2' 섹션에서
    1. 24 "에서 (2) 섹션 자르기 - (파트 # 2 - 첫 번째 및 두 번째 세트)
    2. 3 "에서 (4) 섹션 자르기 - (파트 # 7 - 첫 번째 및 두 번째 세트)
    3. 크로스 피스를 위해 남은 60인치 예약
  4. 3" PVC의 10' 섹션에서
    1. 24 "에서 (2) 섹션 자르기 - (파트 # 4 - 첫 번째 및 두 번째 세트)

메인 레그 조립 지침

파트 #5 및 파트 #6은 2인치 90° PVC 티입니다. 두 다리를 모두 완료하려면 모두 (8)이 필요합니다. 부품 #8은 3"에서 2"90° PVC 티입니다. 두 다리를 모두 완료하려면 모두 (4)가 필요합니다.

 

드라이 핏 :

  1. 3" 파이프 부품 #4를 (2) 상단에 2" 개구부가 있는 부품 #8 90° 티에 맞춥니다.
  2. 작은 2" 파이프 부품 #7을 부품 #8 90° 티 상단에 장착
  3. 2" 90° 티 파트 #6을 티 7°로 열어 파트 #90에 맞춥니다.
  4. 2" 파이프 부품 #3을 부품 #6 90° 티에 끼웁니다.
  5. 2" 90° 티 파트 #5를 파트 #3에 맞추고 티 입구가 90°가 다리의 다른 쪽을 향하도록 합니다.
  6. 2" 파이프 부품 #1을 부품 #5 90° 티에 끼웁니다.
  7. 2" 파이프 파트 #2를 (2) 파트 #5 다리에 지지대 추가 90° 티에 끼웁니다.

4단계: 지원 상단

상단 지지대는 성장 시스템의 크기와 시스템이 지원할 수 있는 타워 수를 나타냅니다.

우리의 현재 계획에는 중앙에 4.5" 간격의 타워가 있는 4' 길이의 2" PVC가 포함됩니다. 타워의 중심 사이의 간격을 늘려 더 큰 성장 영역을 지원하도록 간격을 수정할 수 있습니다.

또한 더 적은 수의 성장 타워를 지원하기 위해 파이프 길이를 줄일 수 있습니다.

지지대 상단 구조는 (2) 동일하게 구성된 단위입니다.

 

상단 컷 목록 지원

  1. 2" PVC의 10' 섹션에서
    1. 48 "에서 (2) 섹션 자르기 - (파트 # 1 - 첫 번째 및 두 번째 세트)

상단 조립 지침 지원

드라이 핏 :

  1. 2" 파이프 부품 #1을 (2) 부품 #2 90° 엘보에 맞춥니다.

5 단계 : 하단 지원

상단 지지대와 마찬가지로 하단 십자 표시는 시스템 크기를 나타내며 조각은 지지 프레임 상단과 너비가 같아야 합니다.

현재 계획에는 4 '길이가 포함됩니다.

지지대 하단 조각은 (2) 동일하게 4' 섹션입니다.

또한 프레임 하단에는 바람에 대한 추가 지지를 제공하기 위해 장치를 외부에 설치할 때 좋은 (2) 옵션 확장 다리가 포함되어 있습니다.

하단 컷 리스트 지원

  1. 10" PVC의 2' 섹션에서
    1. 48 "에서 (2) 섹션 자르기 - (파트 # 1 - 첫 번째 및 두 번째 세트)
  2. 3" PVC의 나머지 부분에서
    1. 12"에서 (4) 섹션 자르기 - (파트 #2)

 

상단 하단 지침 지원

드라이 핏 :

  1. 2" 파이프 파트 #1을 메인 다리 구성 요소의 파트 #6 90° 티에 끼웁니다.
    1. 참고: 하단 크로스 피스를 설치할 때 다리를 지탱하는 데 도움이 되는 추가 사람이 필요합니다.
  2. 옵션: 3" 파이프 파트 #2를 메인 다리 구성 요소의 파트 #9 90° 티에 맞춥니다.
  3. 옵션: 캡 부품 #3을 3" 파이프 부품 #2에 설치

6단계: 타워 성장/물 반환

타워는이 시스템의 식물에 대한 재배 영역을 제공합니다.

또는 현재 설계는 3" 수직 성장 타워를 중앙에 4.5" 간격으로 배치하여(타워 중심에서 이웃 타워까지의 거리) 타워 사이에 약 1.5인치를 제공하여 매우 높은 밀도의 식물을 지원합니다.

현재 4' 길이는 타워당 (8) 슬롯이 있는 (10) 타워를 지원합니다. 양면으로 우리는 전체 시스템에 대해 (160) 개의 식물을 얻습니다.

이러한 고밀도 및 수직 재배 시스템에는 성장할 수 있는 식물의 종류에 대한 몇 가지 한계가 있다. 우리는 우리가 성장할 수 있는 것의 한계를 계속 테스트하고 있으며 위키  사용자 포럼의 What to Grow 섹션에서 성공과 실패를 공유할 것입니다.

 

타워/반환 개요


타워는 2" x 3" PVC 수정 다운스파우트입니다. 다운스파우트는 일반적으로 10' 섹션에서 사용할 수 있습니다.

10 '섹션의 가용성은 우리 디자인의 5 '높이를 결정했습니다.

물 반환은 4인치 PVC 빗물 받이입니다. 10' 섹션으로도 제공됩니다. 그들은 거터 캡으로 끝을 자르고 덮습니다. 엔드 캡의 왼쪽 버전과 오른쪽 버전이 다르기 때문에 모두 선택하십시오.

 

타워/반환 건설 단계

1 부 : 타워

 

타워 컷 리스트

  1. 2" x 3" PVC 다운스파우트의 10' 섹션에서
    1. (10) 섹션을 60"에서 반으로 자릅니다.

타워 형성 지침

우리는 식물 주머니를 형성하는 데 도움이되는 나무 템플릿 도구를 만들었습니다.

  1. (20) 타워를 (10)의 (2) 세트로 나눕니다.
    1. 성장 공간을 개선하기 위해 성장 타워의 식물 슬롯을 오프셋/엇갈리게 합니다.
  2. (10) 라인의 경우 하단에서 6"부터 시작하여 6"마다 첫 번째 (8) 타워 세트의 전면에 수평선을 표시하십시오.
    1. 속도 사각형이 도움이 되며 다운 스파우트 재료를 가로질러 직선을 얻습니다.
  3. (10) 라인의 경우 하단에서 6"부터 시작하여 9"마다 첫 번째 (8) 타워 세트의 전면에 수평선을 표시하십시오.
  4. 직선 절단 비트가 있는 진동 다기능 전동 공구를 사용하여 그려진 선에서 2인치 슬라이스를 자릅니다.
  5. Electric Heat Gun을 사용하여 플라스틱을 몇 초 동안 부드럽게합니다 (히트 건의 와트에 따라 약 15-30 초) 컷 위 3 인치, 아래 3 인치. PVC가 움푹 패이거나 가라 앉기 시작하고 젖은 처진 종이처럼 보입니다.
  6. 나무 템플릿을 사용하여 절단시 연화 된 PVC에 밀어 넣으십시오. 약 30초 동안 제자리에 고정합니다.
  7. 타워의 나머지 슬롯에 대해 반복합니다.
  8. 타워 뒷면 상단에 3/16" 구멍을 뚫어 타워 행거용 나사를 끼웁니다.

파트 2 : 물 반환

 

물 반환 컷 목록

  1. 4" PVC 거터의 10' 섹션에서
    1. 46"에서 (4) 섹션 자르기

물 반환 조립 지침

  1. 오른쪽 및 왼쪽 거터 엔드 캡을 식별합니다.
  2. 거터 섹션의 엔드 캡을 테스트합니다.
    1. 우리는 더 나은 접착력을 위해 캡이 거터와 겹치는 약 150그릿 사포(약 5/8")로 거터 플라스틱을 거칠게 만들었습니다.
  3. 엔드 캡의 안쪽 겹치는 가장자리에 실리콘 PVC 접착제의 자유로운 비드를 펼칩니다.
  4. 거터의 엔드 캡을 조심스럽게 끼워 접착제가 거터 재료 주위에 닿도록 합니다.
    1. 우리는 손가락을 사용하여 거터와 캡의 가장자리 주위에 과도한 접착제를 밀어 넣어 좋은 접촉을 보장했습니다.
  5. 권장 건조 시간까지 마스킹 테이프 또는 기타 쉽게 제거할 수 있는 테이프를 캡에 놓습니다.
  6. 다른 3면에 대해 반복하고 마를 때까지 따로 보관하십시오.
  7. 1" 거터의 후면 벽에 4" 구멍을 뚫어 1"에서 3/4" 가시 어댑터를 삽입합니다. 이것은 14갤런 버킷으로 물을 되돌리기 위한 커넥터 역할을 합니다.
  8. 어댑터의 1" 나사산 쪽을 끼우고 거터 안쪽의 암 1" 커넥터에 끼웁니다.
  9. 물 반환의 양쪽에 대해 부드러운 2" 비닐 호스의 (12) - 1" 섹션을 자릅니다.
  10. 1인치 가시 티로 중앙에서 합류하세요.
  11. 비닐 튜브의 한 부분을 14갤런 물 탱크를 놓을 위치까지 자릅니다.

7 단계 : 물 공급

우리는 PEX 크림프 설치 도구가 있었기 때문에 음용수 안전 특성과 설치 용이성을 위해 주요 급수 라인으로 3/4" PEX를 선택합니다. 압착 도구를 사용할 수없는 경우에도 CPVC가 탁월한 선택이 될 것이며, CPVC는 음용수에 대해서도 인증을 받았지만 조립을 위해 접착제와 조인트 커넥터가 필요합니다.

물 공급/반환 개요

물 공급은 메인 다리의 중앙 크로스 피스에서 분기되는 단일 상승이 있도록 배치됩니다. 이 설계는 워터 펌프의 전체 높이 부하를 줄이기 위해 구현되었습니다. (2) 6' 상승이 전체 물 흐름을 감소시키는 대신, 상승은 펌프에 약간 더 효율적입니다.

 

물 공급/반환 건설 단계

  1. 부품 #1 - #6은 메인 레그 치수를 반영하도록 절단된 3/4" PEX입니다.
    1. 이들은 다리를 측정하여 가장 좋은 크기입니다.
  2. 크림프 파트 #1, 파트 #2 및 파트 #3과 파트 #7 - 3/4" 가시 PEX 티.
  3. 크림프 파트 #3 및 파트 #4와 파트 #8 - 3/4" PEX 90° 엘보.
  4. 크림프 파트 #4 및 파트 #5와 파트 #9 - 3/4" PEX 90° 엘보.
  5. 압착 파트 #2 및 파트 #6과 파트 #10 - 3/4" PEX 90° 엘보.
  6. 파트 #5 및 파트 #6에 구멍을 뚫고 파트 #11 - 드립 이미터를 만듭니다.
    1. 파트 #5/파트 #6의 팔꿈치 끝에서 시작하여 끝 4"부터 측정하고 PEX 파이프 하단의 첫 번째 구멍을 표시합니다.
      1. PEX 파이프의 바닥을 따라 선을 그려 나머지 표시의 바닥을 표시하는 것이 도움이됩니다.
    2. 첫 번째 표시에서 4.5인치를 측정하고 두 번째 표시를 합니다.
    3. 4.5인치마다 반복하면 마지막 표시는 팔꿈치에서 반대쪽 다리에서 4인치여야 합니다.
    4. 마크에 3/16 드릴 비트 드릴 사용.
  7. 드립 이미 터에 맞추기 - 파트 # 11
    1. 구멍은 드립 이미 터가 원치 않는 물방울을 방지하기 위해 약간 꼭 맞고 히트 건으로 PEX를 잠깐 (30 초) 부드럽게하여 드립 이미 터를 PEX에 쉽게 삽입 할 수 있습니다.
  8. 1갤런 물통에 14인치 구멍을 뚫습니다.
  9. 1"에서 3/4" 가시 어댑터를 물통의 벽을 통해 끼웁니다.
  10. 리턴 홈통 티의 부드러운 비닐 호스를 물통에 연결합니다.

8단계: 자동화: 인텔 에디슨 및 인텔 IoT 클라우드 사용

목표는 인텔 에디슨을 사용하여 자동화를 추가하는 것입니다.

  • 물 순환
    • 타이머별
    • 타이머별
    • 자연광을 측정하고 처리량을 최대화하기 위해 보강
    • weatherunderground.com 에서 현재 관측된 날씨를 가져오고 보강하여
  • 온도
    • 팬과 루버를 통한 측정 및 시정 조치
  • 영양
    • 영양소 투여 펌프를 통한 측정 및 시정 조치
  • 수질 (pH)
    • 영양소 투여 펌프를 통한 측정 및 시정 조치
  • IoT 통합
    • 데이터 수집
      • 분석을 위해 클라우드에 기록된 모든 측정 및 작업
    • 경고
      • 모든 측정 데이터를 클라우드에서 경고 규칙을 만드는 데 사용할 수 있습니다.
    • 시정 조치
      • 모든 측정 데이터를 사용하여 장치별 시정 조치에서 규칙을 만들 수 있습니다.

우리는 Grove 스타터 키트 플러스 - 인텔® IoT 에디션을 사용하여 많은 센서를 제공했습니다.

Grove 스타터 키트 플러스 내부 내용 - 인텔® IoT 에디션:

환경 키트 - 인텔 로드쇼 제공

추가 센서/부품

  • 로보메시 아날로그 pH 센서
  • 전도도 센서(EC)
  • 12V DC 연동 도징 펌프

9단계: 자동화 계속: 인텔 XDK IoT 에디션

인텔의 XDK IoT 에디션을 활용했습니다. 그것은 당신이 노드 .js 라이브러리를 사용하여 자바 스크립트로 코드를 작성할 수 있습니다.

이 소프트웨어는 인텔 XDK IoT 에디션에서 찾을 수 있으며 IDE를 시작하는 방법에 관한 많은 문서가 있습니다.

코드:

/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
/*global *

*
A simple node.js application intended to blink the onboard LED on the Intel based development boards such as the Intel(R) Galileo and Edison with Arduino breakout board.

MRAA - Low Level Skeleton Library for Communication on GNU/Linux platforms
Library in C/C++ to interface with Galileo & other Intel platforms, in a structured and sane API with port nanmes/numbering that match boards & with bindings to javascript & python.

Steps for installing MRAA & UPM Library on Intel IoT Platform with IoTDevKit Linux* image
Using a ssh client: 
1. echo "src maa-upm http://iotdk.intel.com/repos/1.1/intelgalactic" > /etc/opkg/intel-iotdk.conf
2. opkg update
3. opkg upgrade

Article: https://software.intel.com/en-us/html5/articles/intel-xdk-iot-edition-nodejs-templates
*/

var mraa = require('mraa'); //require mraa
// UDP Options
var options = {
    host : '127.0.0.1',
    port : 41234
};

console.log('MRAA Version: ' + mraa.getVersion()); //write the mraa version to the Intel XDK console
var dgram = require('dgram');
var client = dgram.createSocket('udp4');
var request = require('request');

var lcdDisplayTimer = 0;
var lights = new mraa.Gpio(3); //LED hooked up to digital pin 13 (or built in pin on Galileo Gen2)
lights.dir(mraa.DIR_OUT); //set the gpio direction to output
var ledState = true; //Boolean to hold the state of Led
var groveSensor = require('jsupm_grove');
var LCD = require('jsupm_i2clcd');
var myLcd = new LCD.Jhd1313m1 (0, 0x3E, 0x62);
var rotarySensor = new mraa.Aio(1);
var myButton = new mraa.Gpio(6);
var servoModule = require("jsupm_servo");

//var digitalLightSensor = require("jsupm_tsl2561");
//var lightSensor = new digitalLightSensor.TSL2561();

var lightSensor = require('jsupm_grove');
var light = new groveSensor.GroveLight(0);
var lightLevel = 0;
var lightLowCnt = 0;
var lightTimeRemaining = 960; // minutes in 16 hours
var lightDay = 1440; // minutes in 24 hour day
var lightsState = 0;

var waterSensor = require('jsupm_grovewater');
var waterLevel = new waterSensor.GroveWater(2);
var waterLeverTimer = 0;
var waterLevelValue = 0;

var tempSensor = new groveSensor.GroveTemp(3);
var tempBase = 23; // goal temperature
var tempTheshold = 25; // try to cool down
var tempAlarm = 27; // too hot sound alarm
var louverOpened = 160;
var louverClosed = 0;
var tempValue = 0;

var circulationPump = new mraa.Gpio(4); 
circulationPump.dir(mraa.DIR_OUT); //set the gpio direction to output
var circulationPumpState = 0;
var circulationPumpTimer = 0;
var CIRCULATION_PUMP_TIME_ON = 1;  // pump time on
var CIRCULATION_PUMP_TIME_OFF = 1;  // pump time off

//Instantiate Servo module on digital port 5
var servo = new servoModule.Servo(5);
servo.setMinPulseWidth(600);
servo.setMaxPulseWidth(2200) 

var ecSensor = new mraa.Aio(1);
var EC_reading = 0;
var ecDoser = new mraa.Gpio(6); 
ecDoser.dir(mraa.DIR_OUT); //set the gpio direction to output
var ecDoserState = 0;
var ecDoserTimer = 0;
var ecDoserActivate = false;
var ecSampleTimer = 0;
var EC_DOSER_INTERVAL = 2; // seconds to run doser
var EC_SAMPLE_INTERVAL = 1;  // minutes to wait before using EC reading to determine to dose
var EC_LIMIT = 1500;        // dose when below this value minus EC_Band until it reaches this level
var EC_BAND = 200;
var EC_MS = 0;    // EC micro/S

var fanCooling = new mraa.Gpio(7); 
fanCooling.dir(mraa.DIR_OUT); //set the gpio direction to output
var fanCoolingState = 0;

var alarm = new mraa.Gpio(8); 
alarm.dir(mraa.DIR_OUT); //set the gpio direction to output
var alarmState = 0;

var logTimer = 1;

var localWeather = 'Cloudy';
var url = 'http://api.wunderground.com/api/df5bd75178df2c09/conditions/q/RI/Providence.json';
var weatherTimer = 1;  // wait 1 minute before first call
 
var data = [{
    sensorName : "light",
    sensorType: "light.v1.0"
},{
    sensorName : "temperature",     // air temp
    sensorType: "temperature.v1.0"
}];

/*
data.forEach(function(item) {
    registerNewSensor(item.sensorName, item.sensorType, function () {  
    });
});
*/

periodicActivity(); //call the periodicActivity function

function periodicActivity()
{
    if (checkTimer(weatherTimer)) {getWeather(); weatherTimer = setMinutesTimer(240);} // every 4 hours
    growLights();
    tempControl();
    checkECDoser();
    waterEC();
    if (checkTimer(waterLeverTimer)) {waterCirculation();  waterLeverTimer = setSecondsTimer(1);}
    if (checkTimer(lcdDisplayTimer)) {lcdDisplay(); lcdDisplayTimer = setSecondsTimer(1);}
    if (checkTimer(logTimer)) {sendToCloud(); logTimer = setMinutesTimer(1);}
    setTimeout(periodicActivity,500); //call the indicated function after 1 second (1000 milliseconds)
}

function lcdDisplay()
{
    var lums = 0;
    myLcd.clear();
    myLcd.setCursor(0,0);
    myLcd.write('Cond: ' + localWeather);
    
    myLcd.setCursor(1,0);
    myLcd.write('EC:' + EC_MS);
    
    myLcd.setCursor(1,8);
    if (lightLevel < 100) {lums = 'L';} else if (lightLevel < 130) {lums = 'M';} else {lums = 'H';}
    myLcd.write('L:' + lums);
    
    myLcd.setCursor(1,12); 
    myLcd.write('T:' + tempSensor.value());
} // lcdDisplay

function getWeather()
{
    request({
    url: url,
    json: false
    }, function (error, response, body) {
        if (!error && response.statusCode === 200) {
 //           console.log(response.body);
            var foo = response.body;

   //         console.log(foo.substr(foo.indexOf('"weather":"') + 11,10));
            localWeather = foo.substr(foo.indexOf('"weather":"') + 11,10);
        }
    });
} // getWeather

function waterEC()
{
    EC_reading = ecSensor.read();    // read the analog input voltage
    // 0 to 1024 = 0 to 5v
    //  204 micro/S per volt
    EC_MS = (EC_reading * 4.88).toFixed();    //   5000 micro/S / 1024 = 4.88
    if (EC_MS < (EC_LIMIT - EC_BAND)) {         // outside of acceptible range
        if (checkTimer(ecSampleTimer)) {        // time to re-dose
            ecSampleTimer = 0;
 //           console.log('--ecDoserState ' + ecDoserState);
            if (ecDoserState != 1) {     // if doser not ON then turn it ON
                ecDoserActivate = true;  
                ecSampleTimer = setMinutesTimer(EC_SAMPLE_INTERVAL);  // reset time until next sample - dose
                console.log('dose for EC');
            }
        }
//        console.log('lower than ' + (EC_LIMIT - EC_BAND));
    }
//    console.log('ecSampleTimer ' + ecSampleTimer);
//    console.log('EC = ' + EC_MS);

} // waterEC()

function waterCirculation()
{
    waterLevelValue = waterLevel.isWet();
    if (waterLevelValue == true)
    {
        if (checkTimer(circulationPumpTimer)) {
            if (circulationPumpState == 1) {
                circulationPumpState = 0;
                circulationPumpTimer = setMinutesTimer(CIRCULATION_PUMP_TIME_OFF);
            } else {
                circulationPumpState = 1;
                circulationPumpTimer = setMinutesTimer(CIRCULATION_PUMP_TIME_ON);
            }
            circulationPump.write(circulationPumpState);
        }
    } else {
        console.log('low water');
        circulationPumpTimer = 0;
        circulationPumpState = 0;
        circulationPump.write(circulationPumpState);
    }
//    console.log('pump = ' + circulationPumpState);

} // waterCirculation

function checkECDoser()
{  
    if (ecDoserState == 0 && ecDoserActivate == true)  // if not already on and needs to be on
    {
        ecDoserTimer = setSecondsTimer(EC_DOSER_INTERVAL);  
        ecDoserState = 1;
        ecDoser.write(ecDoserState);  
        console.log('EC Doser is ' + ecDoserState + ' for ' + EC_DOSER_INTERVAL + ' seconds');
    }
    if (checkTimer(ecDoserTimer)) {          // timer went off
        ecDoserActivate = false;
        ecDoserState = 0;                            // turn doser off    
        ecDoser.write(ecDoserState);  
//        console.log('EC Doser Timer Fired');
    }
//    console.log('ecDoserTimer ' + ecDoserTimer);
} // checkECDoser

function tempControl()
{
    // when temp to high; turn on fans, open louvers
    // if temp above theshold, stay on until lowered to base temp
    // turn on buzzer at alarm temp
   tempValue = tempSensor.value();
//    console.log('temp is=' + tempValue);
    if (tempValue > tempTheshold) {
        fanCoolingState = 1;
        servo.setAngle(louverOpened);
 //       console.log('temp hot');
    } else if (tempValue <= tempBase) {
        fanCoolingState = 0;
        servo.setAngle(louverClosed);
 //       console.log('temp normal');
    }
    fanCooling.write(fanCoolingState);
    
    
    if (tempValue >= tempAlarm) {
        alarmState = alarmState ? 0:1;
        alarm.write(alarmState);
    } else {
        alarm.write(0);
        alarmState = 0;
    }
  //  console.log('alarm is=' + alarmState);

} // tempControl()

function growLights() // called every minute
{ 
    //lightLevel = lightSensor.getLux();
    lightLevel = light.value();
    if (lightLevel < 100 && lightTimeRemaining > 0) {
        if (lightLowCnt < 2) {lightLowCnt++;} else {lightsState = 1; lightLowCnt = 0;}
    } else {
        lightsState = 0;
        lightLowCnt = 0;
    }
    lights.write(lightsState);
    lightTimeRemaining--; 
    lightDay--;
    if (lightDay < 1) {lightDay = 1440; lightRemaining = 640;} // new day 24 hr day with 16 hours of light
    if (lightLowCnt > 0) console.log('lightLow: ' + lightLowCnt);    
    console.log('LightLevel: ' + lightLevel);
} // end growLights

function setSecondsTimer(waitTime)
{
    var endTime;
    var d = new Date();

   endTime = d.getTime() + (waitTime * 1000);  // convert back to milliseconds from seconds
   return endTime;
  
} // setSecondsTimer

function setMinutesTimer(waitTime)
{
    var endTime = 0;
    var d = new Date();

    endTime = d.getTime() + (waitTime * 60000);  // convert back to milliseconds from minutes
    return endTime;
  
} // setMinutesTimer

function checkTimer(timer) {
    var d = new Date();
//    console.log('current time ' + d.getTime() + ' timer =' + timer);
    if (d.getTime() > timer) {return true;} 
    else {return false;}

} // checkTimer

function registerNewSensor(name, type, callback){
    var msg = JSON.stringify({
        n: name,
        t: type
    });

    var sentMsg = new Buffer(msg);
    console.log("Registering sensor: " + sentMsg);
    client.send(sentMsg, 0, sentMsg.length, options.port, options.host, callback);
};

function sendObservation(name, value, on){
    var msg = JSON.stringify({
        n: name,
        v: value,
        on: on
    });

    var sentMsg = new Buffer(msg);
    console.log("Sending observation: " + sentMsg);
    client.send(sentMsg, 0, sentMsg.length, options.port, options.host);
    
};

function sendToCloud(){
    //sendObservation("light", lightLevel, new Date().getTime());
    //sendObservation("temperature", tempValue, new Date().getTime());
    //sendObservation("waterPump", circulationPumpState, new Date().getTime());
    //sendObservation("ecSensor", EC_MS, new Date().getTime());
   // sendObservation("ecDoser", ecDoserState, new Date().getTime());
    //sendObservation("coolingFan", fanCoolingState, new Date().getTime());
    //sendObservation("waterLevel", waterLevelValue, new Date().getTime());
    //sendObservation("growLights", lightsState, new Date().getTime());
    //sendObservation("louvers", fanCoolingState, new Date().getTime());

    
} //sendToCloud

10단계: 자동화 계속: 인텔 IoT 분석 대시보드

인텔의 IoT 분석 대시보드 사용

여기 instructables에 대한 대시 보드에 설정하는 방법에 대한 몇 가지 훌륭한 자습서가 있습니다. 10DotMatrix의 Intel-IoT-Analytics-Dashboard가 매우 유용하다는 것을 알았습니다. 여기에 나와 있는 단계에 따라 계정을 설정합니다.

10DotMatrix에서 지시 할 수있는 설명 된대로 계정을 설정하면 알림 및 컨트롤에 대한 규칙을 정의 할 수 있습니다.

인텔의 IoT 분석 대시보드에서 규칙 구축

  1. 왼쪽 탐색의 "규칙"메뉴 항목으로 이동하십시오.
  2. 내 규칙 페이지
    1. "규칙 추가"버튼을 클릭하십시오.
  3. 내 규칙 - 세부 정보 페이지
    1. 규칙에 이름을 지정하고, 우선 순위를 선택하고, 수행할 작업 유형을 선택합니다.
      • 이메일 - 이메일을 보냅니다.
      • HTTP 엔드포인트 - 선택한 웹 서비스 호출
      • 작동 - 이것은 Edison과 통합되어 코딩 할 수있는 작업을 트리거합니다.
  4. 내 규칙 - 장치 페이지
    1.  모니터링 할 장치를 선택하십시오.
  5. 내 규칙 - 조건 페이지
    1. 측정된 모니터링 - 등록된 컨트롤 목록에서 규칙을 생성할 컨트롤을 선택합니다.
    2. 트리거 시기 - 트리거 유형 선택
    3. 작업 유형을 선택하십시오 : 같음, 보다 큼 등 ...
    4. 테스트 값 입력

 

11 단계 : 자동화 옵션 # 2 : Arduino 및 Raspberry Pi Edition 사용

또는 Arduinos와 Raspberry Pi를 사용하여 자동화를 구현할 수 있습니다.

우리는 컨트롤러의 기능을 별도의 구성 요소로 나누었습니다.

기후봇

역할: 실내 작동을 위한 환경 제어


켜기/끄기 간격의 일정과 순환 팬의 자동 온도 조절 및/또는 일정 기반 제어에 따라 조명 주기를 유지하는 데 사용됩니다.

 

하드웨어 구성 요소

(1) 아두이노

(1) Arduino용 2채널 릴레이 모듈 보드 및 실드(출처: eBay)

(1) 공간에 맞는 크기의 순환 팬

(1) 15 미터 - LED 기반 - 12v 유연한 5050 5 : 1 레드 / 블루 (출처 : 이베이)

(1) 아두이노용 방수 DS18B20 디지털 온도 센서 프로브(출처: 이베이)

 

피함봇

역할: 수질 관리

pH 수준 유지 및 영양소 수준 유지를 유지하는 데 사용됩니다.

 

하드웨어 구성 요소

(1) 아두이노

(1) Arduino용 2채널 릴레이 모듈 보드 및 실드

(1) 아날로그 pH 측정기 키트(출처: RobotMesh.com)

(1) 아두이노 전도도 센서(출처: 이베이)

(1) 아두이노용 방수 DS18B20 디지털 온도 센서 프로브(출처: 이베이)

(2) 12V DC 연동 도징 펌프(출처: 아마존)

 

하이드로봇

역할:온/오프 간격 일정에 따른 급수 주기 및 저수지 수위 유지 관리

(1) 아두이노

(1) Arduino용 2채널 릴레이 모듈 보드 및 실드

(2) 측면 장착 수위 제어 플로트 스위치 정상 폐쇄 (출처 : eBay)

(1) 1 "물 유량계 카운터 1-60L / min (출처 : 아마존)

(1) 1/2 "DC 12V 전기 솔레노이드 밸브 물 입구 흐름 스위치 일반적으로 닫힘 (출처 : eBay)

(1) 620 GPH 수중 펌프 (출처 : 항만화물)

 

아두이노 리소스(스케치 및 링크):

DS18B20 디지털 온도 센서 프로브 - 첨부 문서 참조(원와이어.txt)

http://playground.arduino.cc/Learning/OneWire

Arduino 전도도 센서 - 첨부 문서 참조(EC_Sensor.txt)

아날로그 pH 측정기 - 첨부 문서 참조(ph_Meter.txt)

아날로그-pH-미터-키트

 

EC_Sensor.txt
0.00MB
OneWire.h
0.00MB
ph_Meter.txt
0.00MB
popbot.h
0.00MB
FEH7UDYI7LQL9CZ.ino
0.02MB
F0P8REXI7LQL9CT.ino
0.01MB
FKOXFNXI7LQL9CR.ino
0.01MB
FVAZYK0I2BR4JUV.rtf
0.02MB
FACI9V0I2BR4JU7.rtf
0.01MB

12 단계 : 웹 서버 / 데이터베이스 및 스마트 폰 앱

관리 인터페이스

관리 인터페이스는 컨트롤러 구성 요소의 일정과 수준을 업데이트할 수 있는 선택적 구성 요소입니다. 또한 즉각적인 전자 알림 및 기록 데이터 분석을 위해 센서 데이터와 시정 조치를 기록합니다.

참고: 이러한 작업은 아두이노 SDK를 사용하여 아두이노와 직접 통신하여 수행할 수도 있습니다.

라즈베리 파이는 간단한 통신 버스에서 I2C를 통해 아두이노 컨트롤러와 통신합니다.

하드웨어 구성 요소

(1) 라즈베리 파이

 

소프트웨어 설정

라즈베리 파이

아파치2 웹 서버

MySQL 데이터베이스 서브

파이썬

Raspberry Pi는 센서 ID 및 현재 보고된 값을 포함하는 JSON 인코딩 문자열을 사용하여 스마트폰/웹 앱과 인터페이스되는 일련의 웹 서비스를 지원하도록 코딩됩니다.

현재 공기 온도 예:

{ "id": 1, "이름": "공기 온도", "전류 값": 78.2 }

 

13 단계 : 겨울 / 내부 작업

이 시스템은 외부 계절 재배에서 실내 또는 겨울 성장으로 쉽게 전환됩니다.

"J"후크에 장착 된 성장 타워는 상단 2 "PVC 파이프에서 제거됩니다.

타워를 180도 돌려 식물이 프레임의 반대쪽을 향하도록 얼굴을 중앙을 향하도록 합니다.

5/1 구성(빨간색 5개/파란색 1개)에서 5050개의 빨간색/파란색 LED를 사용합니다. 녹색 식물은 녹색 빛을 반사하고 적색/청색광을 흡수하기 때문에, 그 스펙트럼만 제공함으로써, 빛 파장이 낭비되지 않습니다., 효율성을 더욱 높입니다.

LED 스트립은 재배 식물의 2면 사이에 매달려있는 샤워 커튼처럼 성장 프레임의 중앙에 매달려 있습니다. LED는 프레임이 약 12피트 간격으로 구성되기 때문에 공장에서 약 2인치 떨어진 곳에 매달려 있습니다.

조명은 12볼트이며 미터당 약 0.6암페어를 사용합니다.

나는 (8) - 5피트 섹션을 사용하고 6인치 간격으로 방향을 번갈아 가며 한 스트립이 한쪽을 향하고 다른 쪽을 향하도록 합니다.

728x90

댓글