산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 제조공정

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

부품 및 소모품

Microchip ATmega32U4 1개
Espressif ESP8266 ESP-12E 1개
16MHz 크리스털 1개
파워 MOSFET N-채널 4개
전압 레귤레이터 모듈 (Digilent) 1개
DHT11 온습도 센서 (4핀) 1개
DS18B20 프로그래머블 1-Wire 디지털 온도계 1개
MikroE 워터 디텍트 클릭 1개
Arduino LCD 화면 1개
포토레지스터 (조도 센서) 1개

필요한 도구 및 기계

앱 및 온라인 서비스

프로젝트 소개

소개

MIT 오픈 농업 이니셔티브 디렉터인 Caleb Harper의 TED 강연 '디지털 농업'을 보고 큰 영감을 받았습니다. 주제는 이 컴퓨터가 미래에 당신의 음식을 재배할 것입니다였습니다. 강연에서 제게 가장 큰 영감을 준 질문은 "전 세계 어디에서든 실내에서 맛있고 영양가 높은 음식을 재배할 수 있다면 어떨까?"였습니다. 여기서 아이디어가 탄생했습니다!

이상적인 생육 기후 조건을 만들고, 식물이 필요한 정확한 양의 빛과 영양분을 제공하는 박스나 인큐베이터 같은 것을 만들려고 합니다. 햇빛 에뮬레이터, 관개 시스템, 기후 제어기를 하나의 우아하고 모던한 디자인으로 통합하고 싶습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

다음 기술을 구현해 원하는 결과를 달성할 계획입니다:

불행히도 제가 이 아이디어를 처음 생각한 사람은 아닙니다. 하지만 창의적인 아이디어를 내는 가장 좋은 방법은 기존 것을 개선하는 것입니다!

시중에는 여러 유사 프로젝트가 있지만, 각각의 장점에도 불구하고 공간을 너무 많이 차지하거나 너무 작거나, 너무 비싸거나, 한 번에 한 작물만 재배할 수 있는 등의 단점이 있습니다. 많은 조사를 하고 시중 프로젝트의 장단점을 면밀히 분석했으며, 시장 반응을 고려해 단점은 줄이고 최고의 기능만 구현한 새로운 고급 오픈소스 시스템을 만들고자 합니다.

야심 차지만 한번 해봅시다!

실험

식물 다루기는 시간이 많이 걸립니다! 보통 몇 주에서 몇 달이 걸리니 준비해야 합니다!

최종 프로젝트로 무엇을 만들지 이미 알고 있으므로, 미리 준비하고 마지막 순간에 모든 것을 미루지 않아야 합니다. 그래서 가능한 한 빨리 테스트와 실험을 시작하겠습니다!

먼저 알아보고 싶은 것은 영양분 풍부한 안개와 그로우 LED 라이트로 식물을 키우는 것이 흙과 자연광을 쓰는 기존 시스템보다 나은지입니다. 이론적으로는 그렇다고 하지만, 직접 해보기 전에는 믿지 않습니다!

그래서 직접 실험을 시작했는데, 시간이 좀 걸리며 식물을 여러 그룹으로 나누는 방식입니다:

독일 카우프란트(Kaufland) 매장 식물 코너에서 혼합 허브 씨앗을 샀습니다. 이들이 내 테스트용 아기들입니다 :p

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

생애 처음으로 심어보는 거라 실수가 있을 수 있으니 너그럽게 봐주세요 :D

여러 튜토리얼을 확인해 보니 씨앗을 먼저 발아시켜야 한다고 하더군요. 플라스틱 용기에 씨앗을 놓고 종이 타월로 덮었습니다. 이 단계에서는 거의 100% 습도가 필요해 분무기로 종이 타월에 물을 뿌리고 비닐봉지로 덮어 물이 증발하지 않게 했습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

1.5주 동안 뒀다가 열었는데 정말 놀랐습니다!

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

거의 모든 씨앗이 발아했습니다! 아이처럼 기뻤습니다 :)

가장 좋은 어린 식물들, 줄기가 가장 두껍고 전체적으로 더 크고 좋아 보이는 것들을 골랐습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

따라하던 튜토리얼(유튜버)에서 '두 번째 잎'이 나올 때까지 아무 매질에나 심으라고 추천했습니다. 아마존에서 코코넛 코이어 펠릿을 주문했습니다. 유기농이고 흙과 비슷한 특성이 있으며, 물을 주면 크기가 6배로 커지는 게 장점입니다.

심기용 칸막이가 있는 상자도 샀습니다. 2유로밖에 안 해서 일을 훨씬 체계적으로 만들었습니다. 상자 칸막이 안에 코코넛 펠릿을 놓고 물을 줘 완전히 수화시킨 후, 어린 식물들을 가운데에 심고 상자 키트에 포함된 투명 플라스틱으로 덮었습니다.

내 작은 온실은 이렇게 생겼습니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

상자를 닫고 1주일 뒀습니다!

다시 열었을 때 또 놀랐습니다! 실제로 더 커졌습니다! 제가 식물을 키울 수 있을 줄은 상상도 못 했어요. 제 몸 하나 건사하기도 버거운데 :D

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

1주일 후 차이가 눈에 띕니다!

첫 뿌리가 보여서 흙과 클레이 볼에 심고 안개 실험을 시작했습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

컴퓨터 지원 설계 주간에 네트 컵을 설계해 식물을 배치했습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

지역 매장에서 대략 필요한 치수의 플라스틱 용기를 사고 드릴 구멍을 스케치했습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

여기가 코코넛 펠릿과 클레이 볼, 흙으로 된 식물이 들어있는 조립된 테스트 시스템입니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

솔직히 결과가 더 좋을 수 있었습니다 :D

내 안개 시스템에서 몇 개의 식물만 살아남았습니다. 추측컨대 재배 매질 때문인 것 같습니다! 안개가 클레이 볼을 젖게 유지할 만큼 강하지 않고, 흙도 마찬가지였습니다.

부활절 방학!

부활절 방학 동안 아무것도 안 했고 연구실도 닫혀서 시스템도 모두 꺼져 있었습니다. 그래서 식물들이 다 죽었습니다.

새로운 마음으로 이전 관찰을 바탕으로 다른 재배 매질을 사용해 또 다른 시스템을 만들기로 했습니다.

이번 시스템에 선택한 재배 매질은 락울(Rock Wool)입니다. 지역 이케아 매장에서 샀습니다. 거기서 씨앗도 몇 개 샀습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

새 씨앗을 락울에 넣고 1주일 동안 발아시켰습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

1주일 후 상자를 확인했는데, 한 종류의 씨앗은 성공했고 다른 건 실패했습니다! 시간이 없어서 발아한 씨앗으로 계속 진행했습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

한편 또 다른 안개 시스템을 세팅해 작동 시간을 늘려 오직 안개만으로 씨앗을 발아시킬 수 있는지 시험해 보겠습니다.

여러 매개변수와 설정으로 계속 실험해 얼마나 갈 수 있는지 보겠습니다!

전자 회로 설계 및 제작

최종 보드 설계에 앞서 종이에 보드가 구현해야 할 모든 기능과 요구사항을 적고, 몇 개의 핀이 사용될지 추적해 최종 마이크로프로세서를 더 잘 추정하고 결정했습니다.

보드에 들어갈 것들의 스케치:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

최종 보드 선택은 다니엘레 잉그라시아의 satshakit과 조나단 그린햄의 FABLEO 사이에서 이뤄졌습니다.

satshakit은 100% Arduino IDE 및 라이브러리와 호환되며, 제작 가능하고 오픈소스인 보드이자 Fabkit의 개선판입니다.

Fabkit 대비 주요 개선사항 및 특징:

반면 FabLeo는 매우 유사한 특징에 하드웨어 USB까지 있습니다. ATmega328p를 이미 써봤기에 새로운 걸 시도하고 싶어 FabLeo 설계를 출발점으로 삼았습니다.

이 과제의 바이블이자 1번 가이드는 ATmega32u4 핀아웃이었습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

보드 설계에는 EAGLE(Easily Applicable Graphical Layout Editor)을 사용했습니다. 유연하고 확장 가능한 EDA 회로도 캡처, PCB 레이아웃, 자동 라우팅, CAM 프로그램입니다. 프리웨어 라이선스와 웹상의 풍부한 부품 라이브러리 덕분에 취미가들 사이에서 인기가 많습니다.

Eagle에는 보드 설계를 위해 동시에 사용하는 두 개의 창이 있습니다:

EAGLE을 설치한 후 가장 먼저 새 회로도 만들기를 했습니다. 전자 회로도는 회로를 나타내는 도면으로, 실제 전자 부품을 심볼로 표현합니다. 가장 기본적인 심볼은 간단한 도체(트레이스)로 선으로 표시됩니다. 도면에서 선이 연결되면 교차점에 점으로 표시됩니다.

회로도에 부품을 배치하려면 특수 라이브러리를 다운로드해 사용해야 합니다. Eagle에는 사용할 수 있는 많은 내장 부품 라이브러리가 있습니다. 팹 네트워크도 지속적으로 업데이트되는 라이브러리를 유지합니다: fab.lbr

라이브러리 설치 방법: EAGLE 환경에서 상단 툴바의 Library 메뉴 > Use 선택 > 방금 다운로드한 .lbr 파일 열기.

이제 Add component로 가서 라이브러리 선택 후 배치할 부품을 고릅니다.

모든 부품을 회로도에 배치했으면 각 부품을 마이크로프로세서 핀에 연결해야 합니다. EAGLE 왼쪽 메뉴에서 Net을 클릭해 초록 선을 그리면서 핀들을 연결합니다. 중요한 건 핀의 작은 선에서 연결을 시작하는 것입니다(사진에 표시).

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

여러 연결을 피하기 위해 라벨을 사용합니다. EAGLE 왼쪽 메뉴에서 Add Label을 누르고 연결선 끝에 추가합니다. 우클릭 후 name을 선택하면 마이크로프로세서 핀에 쓴 것과 같은 이름을 라벨에 부여해 이런 식으로 연결할 수 있습니다!

모든 게 잘 됐다면 라벨(N$10)을 GND와 연결하시겠습니까? 같은 메시지가 나타납니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

이 단계에서 회로도의 중요한 건 모든 연결의 논리이지 모양이 아닙니다. 모든 부품을 배치하고 논리적으로 연결한 후 모습입니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

AVRISP 핀헤더를 커넥터 순서대로 배치했습니다. 이 핀들로 보드를 프로그래밍합니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

크리스털과 함께한 USB 회로 회로도입니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

입력 12V를 5V로 변환해 보드 전체에 전원을 공급할 전압 레귤레이터 회로도 추가했습니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

이 보드의 중요한 특징 중 하나는 MOSFET 회로입니다. 4개를 추가했는데, 3개는 입력(12V)에 직접 연결하고 1개는 스텝업 전압 레귤레이터에 연결합니다. 마지막 건 24V로 작동하는 포그용 전원입니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

모든 연결을 다시 확인한 후 다음 단계인 보드 레이아웃으로 진행합니다. 상단 메뉴에서 Generate/Switch to Board를 누릅니다.

가장 먼저 그리드 해상도를 높입니다. View 메뉴 > Grid에서 값을 0.01로 변경합니다. 라우트 라인을 그릴 때 더 정밀해집니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

놀랍게도 지금까지 만든 가장 복잡한 보드 라우팅이 가장 빨랐습니다! 보드 제작 경험이 속도 향상에 좋은 영향을 줬나 봅니다. 라우팅을 마치니 작은 야수 같은 보드가 탄생했습니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

이전에도 배운 트릭을 사용했습니다. 부품 주위에 폴리곤을 그리고, 폴리곤 선에서 우클릭 후 이름을 GND로 변경합니다. 이렇게 하면 폴리곤 안쪽 전체가 채워져 GND가 됩니다.

이렇게 하면 시간, 공간, 노력을 많이 아낄 수 있습니다.

모든 걸 다시 확인한 후 파일을 .png 이미지로 내보내기 합니다.

나타나는 창에서 해상도를 1500 dpi로 높이고, monochrome 클릭, window 모드 선택.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

.png 이미지 편집에는 GIMP를 사용합니다. rectangular select tool로 이미지를 선택하되 모든 면에서 약간 여백을 둡니다. File > Copy로 선택 영역 복사. 계속 작업하려면 File > Create from the Clipboard.

모든 편집 후 얻은 결과:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

이 이미지는 인쇄 준비가 됐으며 Inside_Cut이라 부르겠습니다.

Outside Cut 프로세스를 준비하고 얻은 결과:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

보드가 양면이라 두 조각을 밀링한 후 붙여야 합니다. 주의할 점은 바닥 부분은 수평으로 미러링해야 한다는 것입니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

바닥 부분 Inside_Cut

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

바닥 부분 Outside_Cut

이제 CNC 밀링 머신으로 진행합니다. 다시 FabModules로 .PNG 파일을 롤랜드 머신용 G-code로 변환합니다.

Fab Modules 시작. IP 주소를 브라우저 창에 입력하면 첫 인터페이스가 나타납니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

회색 input format 버튼을 누르면 .PNG 이미지를 로드하는 옵션이 있는 새 메뉴가 나타납니다. 여기에서 첫 번째 이미지(내부 조각)를 업로드합니다. 그러면 이미지 미리보기가 Fab Modules에 나타나고 다른 필드와 매개변수도 나타납니다.

창 오른쪽에는 많은 입력 매개변수가 있습니다. 머신을 움직이려면 다음 매개변수를 입력해야 합니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

각각의 필드에 x, y, z 위치 좌표를 입력해 머신을 움직입니다. 머신을 움직이기 전에 zjog 매개변수가 항상 0으로 설정돼 있는지 확인하세요(자동으로 변경돼도). 머신 이동하려면 move to xyz0 버튼을 누릅니다.

* 작은 인생 팁: 멀티미터로 툴과 표면 간 연결이 있는지 확인하세요. PCB 조각용 툴은 직경 0.2mm 이하, 커팅용은 1mm 툴을 추천합니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

내 최종 설정은 이렇게 생겼습니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

아웃사이드 컷 설정은 Z축 값만 빼고 동일합니다. 0.2mm 툴을 1mm 툴로 교체했기 때문입니다. 이렇게 생겼습니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

바닥 부분도 같은 과정으로 내부와 외부 파트 밀링:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스
ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

윗면 최종 결과:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

아랫면 최종 결과:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

이제 납땜합시다!

모든 부품을 제대로 납땜했는지 확인하기 위해 각 부품 납땜 후 멀티미터로 부품과 트레이스 간 도통을 확인했습니다.

과정 단축 애니메이션:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

PCB 보드를 꽂아 확인해 보니 에러가 있었습니다. 경험상 VCC와 GND를 연결할 때마다 컴퓨터가 아두이노 연결을 끊는 걸 보니 쇼트 회로 때문이었습니다. 멀티미터로 확인해 보니 보드 어딘가에서 VCC와 GND가 연결돼 있었습니다. 맞았습니다.

늦은 시간이라 그 작은 실수 찾느라 현미경 아래서 1시간 동안 진짜 열받았습니다. 여기 있습니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

칼로 긁어내고 절연을 늘려 고쳤습니다!

또 다른 건 보드 뒷면에 스텝업 전압 레귤레이터를 장착하는 것입니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

치수를 미리 재서 보드에 고정할 수 있도록 미리 드릴 구멍을 설계했습니다. 하지만 뒷면에 납땜하기 전에 보정해야 합니다.

아이디어는 보드에 12V를 공급하면 스텝업이 MOSFET 회로에 연결된 초음파 분무기에 필요한 24V를 출력하는 것입니다.

고정 12V의 벤치 전원공급장치를 써서 멀티미터로 출력 전압을 측정했습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

필요한 출력(내 경우 24V)으로 조정한 후 보드 뒷면에 납땜했습니다!

뒷면에는 네트워킹 및 통신 주간에 만든 와이파이 보드도 장착했습니다.

자, 여기 야수가 있습니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

모든 게 쉽고 순조로웠다고 생각하는 분들을 위한 영웅 샷 :D

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

파일 다운로드

배선 및 임베디드 프로그래밍 (I/O 디바이스)

보드 프로그래밍에 Arduino IDE를 사용했습니다. 아두이노 보드를 USB 허브에 연결하고 Tools 메뉴에서 올바른 보드(Arduino Leonardo)와 포트를 선택한 후 File > Examples로 가서 Arduino as ISP 스케치를 엽니다. 코드 업로드.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

Done uploading이 뜨면 코드가 보드에 업로드된 겁니다. 아두이노를 PC에서 분리합니다. 다음 단계는 내 PCB 보드를 몇 가닥 와이어로 아두이노에 연결하는 것입니다. 연결 방식은 다음과 같습니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

아두이노 보드를 USB 허브에 연결합니다. Tools에서 올바른 보드 선택, Arduino as ISP 프로그래머 선택, 매개변수 재확인, 부트로더 굽기 버튼 누르기.

Done Uploading! 좋은 징조입니다 :)

보드 테스트를 위해 기본 Blink 예제 코드 업로드:

오, 그 BLINK 너무 사랑해요 :D 이제 센서로 가봅시다!

첫 번째로 사용할 센서는 DHT11 - 온습도 센서입니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

이 센서들은 매우 기본적이고 느리지만, 기본적인 데이터 로깅을 원하는 취미가들에게 훌륭합니다. DHT 센서는 정전용량식 습도 센서와 서미스터 두 부분으로 구성됩니다. 또한 온도와 습도가 포함된 디지털 신호를 내보내는 아주 기본적인 칩이 안에 있습니다. 디지털 신호는 어떤 마이크로컨트롤러로도 꽤 쉽게 읽을 수 있습니다.

특징:

배선은 매우 쉽습니다. VCC, GND, 아무 디지털 핀만 있으면 됩니다. 제 경우 이 센서 연결을 미리 설계해 뒀습니다.

간단한 스케치를 업로드해 테스트합니다. 스케치에는 DHT.h 라이브러리가 포함됩니다.

// DHT11 온습도 센서 예제
#include "DHT.h"
#define DHTPIN 2     // 센서 연결에 사용한 핀 2를 DHTPIN으로 정의
#define DHTTYPE DHT11 // 사용 센서 정의(DHT11)
DHT dht(DHTPIN, DHTTYPE); // DHT 인스턴스 생성

void setup() {
  Serial.begin(9600);
  dht.begin();
}

void loop() {
  float h = dht.readHumidity(); // 습도 읽기
  float t = dht.readTemperature(); // 섭씨 온도 읽기 (기본값)
  Serial.print("Temperature = ");
  Serial.println(t, 2);
  Serial.print("Humidity = ");
  Serial.println(h, 2);
  delay(2000); // 2초 대기
}

시리얼 모니터를 열면 이렇게 나옵니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

다음으로 사용할 센서는 DS18B20 - 1-Wire 디지털 온도 센서입니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

DS18B20은 Maxim IC의 1-Wire 디지털 온도 센서입니다. -55~125°C 범위에서 9-12비트 정밀도로 섭씨 온도를 보고합니다(±0.5°C). 각 센서마다 고유한 64비트 시리얼 번호가 새겨져 있어 한 데이터 버스에 엄청난 수의 센서를 사용할 수 있습니다.

이건 지금까지 본 가장 단순한 디지털 센서 중 하나입니다. 전원과 그라운드 외에 미리 설계한 디지털 핀에 연결할 단일 디지털 신호 핀만 있습니다. 또한 신호와 전원 핀 사이에 4.7k 풀업 저항이 필요한데, 안타깝게도 PCB에 배치하는 걸 깜빡했습니다. 그래서 센서 케이블에 직접 수동으로 납땜할 예정입니다.

시작하기 전에 라이브러리를 다운로드해야 합니다: OneWire.h와 DallasTemperature.h

다음 스케치 업로드:


// 라이브러리 포함
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 3

// OneWire 인스턴스 설정으로 모든 OneWire 디바이스와 통신 (Maxim/Dallas 온도 IC뿐만 아니라)
OneWire oneWire(ONE_WIRE_BUS);

// oneWire 참조를 Dallas Temperature에 전달
DallasTemperature sensors(&oneWire);

void setup(void) {
  Serial.begin(9600);
  sensors.begin();
}

void loop(void) {
  sensors.requestTemperatures(); // 버스 상의 모든 디바이스에 전역 온도 요청
  Serial.print("Temperature is: ");
  Serial.print(sensors.getTempCByIndex(0)); // 같은 버스에 DS18B20 여러 개 가능. 0은 와이어 상 첫 번째 IC
  delay(1000);
}

재미있는 건 센서 프로그래밍에 성공한 후 모든 센서를 통합하면서 작동을 멈췄다는 겁니다! 왜 안 되는지 꽤 오래 고민했지만 시간 제약으로 우리 팹랩 재고에 있던 다른 DS18B20 센서를 써서 직접 방수 처리하기로 했습니다!

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

데이터시트를 참고해 케이블을 제대로 납땜하고 수축 튜브로 서로 절연시켰습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

어떻게 방수 처리할지 감 오시죠? :D 엄마 아마 엔지니어!

말 나온 김에 끝냈습니다!

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

생김새가 좀 그렇지만 :D 작동하고 물에 담가도 새지 않는다는 게 중요합니다!

다음은 LDR = 조도 의존 저항입니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

LDR은 수동 전자 부품으로, 빛 세기에 따라 저항이 변하는 기본적으로 저항입니다. 어둠에서 저항은 매우 높아 거의 1MΩ에 달하지만, 빛이 LDR에 닿으면 저항이 몇 KΩ(10-20kΩ @ 10 lux, 2-4kΩ @ 100 lux)로 떨어집니다(모델에 따라 다름).

LDR은 Vcc(5V)에 연결하면 아날로그 전압을 출력하는데, 입력 빛 세기에 정비례해 크기가 변합니다. 즉, 빛 세기가 강할수록 LDR에서 나오는 전압도 커집니다. LDR이 아날로그 전압을 출력하므로 아두이노의 아날로그 입력 핀에 연결합니다. 아두이노는 내장 ADC(아날로그-디지털 변환기)로 아날로그 전압(0-5V)을 디지털 값(0-1023) 범위로 변환합니다. 환경이나 표면에 충분한 빛이 있으면 아두이노로 LDR에서 읽는 변환된 디지털 값은 800-1023 범위가 됩니다.

센서 테스트용 스케치 코드:

int sensorPin = A0;  // LDR 입력 핀 선택
int sensorValue = 0; // 센서에서 오는 값 저장 변수

void setup(void) {
  Serial.begin(9600);
}

void loop(void) {
  sensorValue = analogRead(sensorPin); // 센서에서 값 읽기
  // 몇 개의 임계값, 정성적으로 결정
  Serial.print("LDR Value = ");
  Serial.print(sensorValue);
  if (sensorValue < 100) {
    Serial.println(" (Dark)");
  } else if (sensorValue < 200) {
    Serial.println(" (Dim)");
  } else if (sensorValue < 500) {
    Serial.println(" (Light)");
  } else if (sensorValue < 800) {
    Serial.println(" (Bright)");
  } else {
    Serial.println(" (Very bright)");
  }
  delay(3000);
}

다음은 수위 센서입니다.

물 통이 비었을 때 알람을 받아 물을 보충할 시기를 알기 위해 수위 센서가 필요했습니다. 미리 생각하지 못했고 재고에도 수위 센서가 없어 직접 만들기로 했습니다!

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

사용 가능한 재료, 제 경우 토양 수분 센서를 쓰기로 했습니다. 수위 센서의 기본 원리는 전기 전도도 측정인데, 토양 수분 센서도 같습니다. 센서를 내 요구사항에 맞게 보정할 수 있다면 수분 센서를 수위 센서처럼 쓸 수 있겠다고 생각했습니다! 원칙적으로 아날로그 센서라 0-1024 값이 나오고 나머지는 수학입니다!

하지만 현실은 약간 다릅니다. 센서가 물에 닿지 않으면 아날로그 값은 0이고, 팁만 담그면 800으로 올라갑니다. 값 읽기용 스케치:

/* 아날로그 핀 A4 값 시리얼 모니터로 출력 */
void setup() {
  Serial.begin(9600);
}
void loop() {
  Serial.println(analogRead(A4));
  delay(100);
}

값을 읽을 수 있게 된 후 센서를 보정해 세 가지 다른 반응을 내도록 했습니다: 값이 0이면 EMPTY!, 800 정도면 LOW, 900 이상이면 Full!

그래픽 LCD 디스플레이

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

일반적으로 LCD 디스플레이는 많은 핀을 쓰는데, 128x64 화면을 다른 방식으로 연결하는 법을 찾아냈습니다. 보드에서 단 3개의 디지털 핀만 사용하는 방식이라 나머지 핀을 다른 용도로 쓸 수 있고 배선도 깔끔합니다. PCB에 LCD용 핀을 미리 마련해 뒀고 이렇게 연결했습니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

LCD 연결 후 프로그래밍할 차례!

우선 U8glib 라이브러리를 여기서 다운로드해야 합니다. 또 코드에서 선언된 핀도 중요합니다. 제가 쓴 핀은: U8GLIB_ST7920_128X64 u8g(4, 12, 6, U8G_PIN_NONE)

라이브러리의 "HELLO WORLD" 예제를 이용해 테스트 코드를 만들었습니다:


#include "U8glib.h"
U8GLIB_ST7920_128X64 u8g(4, 12, 6, U8G_PIN_NONE);

void draw(void) {
  u8g.setFont(u8g_font_unifont);
  u8g.setPrintPos(0, 20);
  u8g.print("GIY Project v1.0!");
}

void setup(void) {
  // 필요시 화면 뒤집기
  // u8g.setRot180();
}

void loop(void) {
  u8g.firstPage();
  do {
    draw();
  } while( u8g.nextPage() );
  delay(500);
}

결과:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

디스플레이가 켜질 때마다 몇 초 동안 팹랩 로고를 표시하면 멋지겠다는 아이디어가 떠올랐습니다. 꽤 많은 시간을 들여 결국 해냈습니다! 그래픽 LCD에 표시하려면 (.bmp) 포맷 이미지가 필요하고 비트맵으로 표시해야 합니다.

먼저 인터넷에서 팹랩 로고를 (.png) 파일로 다운로드하고 내 작은 LCD 테두리에 맞게 크기를 크게 줄였습니다. 다음 온라인 서비스로: LINK

사용한 설정:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

다음 단계는 작은 이미지를 (.bmp) 포맷으로 변환. 다음 온라인 서비스 사용: LINK

이제 (.bmp) 파일이 생겼으니 코드에 넣으려면 HEX 배열로 변환해야 합니다. LCD Assistant라는 좋은 도구를 썼습니다. LCD Assistant에서 이미지 로드: File > Load Image. 이미지 미리보기가 열리면 크기가 맞는지 확인 – 가로 128픽셀, 세로 64픽셀. Byte orientation은 Horizontal, Size endianness는 Little로 설정. 내 LCD 디스플레이 설정:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

File > Save output으로 임시 텍스트 파일 생성. 그 텍스트 파일을 열어 반짝이는 새 배열을 확인합니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

pH 센서

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

인정하건대 이건 제가 다뤄본 모든 센서 중 가장 까다롭습니다! 제가 쓰는 센서 (logo pH sensor v1.1)에 대한 정보를 찾기가 정말 힘들어서 자세히 설명하기로 했습니다!

프로브는 액체에 담그면 (작은) 배터리처럼 작동합니다. pH에 따라 양전압이나 음전압 몇 밀리볼트를 출력합니다. 이 값은 너무 작고 임피던스 같은 기술적 문제로 아두이노에서 직접 쓸 수 없어서 "오프 앰프"가 필요합니다. 오프 앰프 보드는 프로브의 밀리볼트를 아두이노가 받아들일 수 있는 것(0-5V 양수)으로 변환해 줍니다.

pH 측정에 쓰이는 3가지 일반적인 완충 용액: pH 4.01, pH 6.86, pH 9.18 (7.0과 10.0도 존재). 액체 대신 가루를 추천합니다. 더 싸고 유통기한이 길며 가루는 오염될 수 없습니다(병 대비). 제품 설명서를 읽어보시지만 보통 봉지 내용물을 250ml 물에 넣고 저으면 됩니다. 평균 pH(6-8)의 물이면 아무거나 써도 됩니다. 가루가 물을 정확한 pH 레벨로 포화시키기 때문입니다. 저는 수돗물(pH 7.4)을 쓰는데 증류수, 탈광물수와 차이를 못 느꼈습니다. 완충 용액은 시간이 지나면 불안정해져서 몇 주나 몇 달 보관할 수 없습니다.

이제 제가 쓰는 센서에 대해 더 얘기해 보죠!

이제 센서 보정을 해봅시다! 두 가지 다른 매개변수가 있습니다: "오프셋" 값과 "스텝" 값.

오프셋은 모든 pH 값을 특정 전압 범위로 이동시키는 것입니다. pH 7이 2.2V, pH 8이 2.1V를 출력한다면 +0.3V 이동으로 pH 7을 2.5V, pH 8을 2.4V로 만듭니다. 보드에서 하든 소프트웨어로 하든 가능하지만 보드에서 하는 게 프로브 독립적이고 프로그래밍이 적어 더 쉽습니다.

GND(둘 다)와 Vcc를 아두이노 GND와 5V에 연결. 프로브를 빼고 작은 BNC 구멍과 BNC 외부 부분 사이에 쇼트 시킵니다. 볼트미터(또는 아두이노)로 GND와 Po 사이 전압 측정. 포트(BNC 근처)를 돌려 출력이 2.5V가 되게 조정. 이제 pH 7이 2.5V(아날로그 리드 함수로 511)의 정확한 값을 가집니다. 프로브가 0밀리볼트를 출력하기 때문입니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

스텝 보정에는 범위와 정밀도에 따라 하나 이상의 완충 용액이 필요합니다. 이상적으로는 시스템으로 측정할 범위를 아는 게 좋습니다. 저는 pH 5-7 사이 물을 쓰니 완충 4.01(그리고 6.86으로 검증)을 선택했습니다. 보통 pH 8-10 사이를 측정하면 완충 9.18(어쩌면 6.86도)을 고르세요.

(깨끗한) 프로브를 연결해 완충 용액에 넣고 1분간 안정화시킵니다. 위아래로 오갈 때 안정됐다고 봅니다(3.04, 3.05, 3.03, 3.04...). 볼트미터(또는 아두이노) 값 기록, 제 예에선 3.05V.

이게 다입니다. 이제 아래 코드로 쓸 수 있습니다.


int ph_pin = A7; // Po에 연결된 핀 번호
void setup() {
  Serial.begin(9600);
}
void loop() {
  int measure = analogRead(ph_pin);
  Serial.print("Measure: ");
  Serial.print(measure);
  double voltage = 5 / 1024.0 * measure; // 클래식 디지털-전압 변환
  Serial.print("\tVoltage: ");
  Serial.print(voltage, 3);
  // PH_step = (voltage@PH7 - voltage@PH4) / (PH7 - PH4)
  // PH_probe = PH7 - ((voltage@PH7 - voltage@probe) / PH_step)
  float Po = 7 + ((2.5 - voltage) / 0.18);
  Serial.print("\tPH: ");
  Serial.print(Po, 3);
  Serial.println("");
  delay(2000);
}

PH_step 계산은 꽤 단순합니다. 두 알려진 전압의 차이, 제 예에선 2.5V@pH7과 3.05V@pH4.01로 -0.55V. pH 7에서 4.01까지 범위인 2.99 pH 단위에 해당하는 전압 범위. 전압을 pH 단위로 나누면 볼트당 pH 수치(제 경우 0.1839...).

PH_probe는 알려진 pH 7 전압(2.5V)에서 프로브 전압과 매칭되게 PH_step을 더해 계산. 즉, pH 8은 2.5V(pH 7) + 0.1839(1단위/스텝); pH 9는 2.5V + 0.1839 + 0.1839 = 2.87V.

마법 없음, 그냥 수학 :D

MOSFET 출력:

RGB LED 스트립과 초음파 분무기를 디지털 핀으로 제어되는 MOSFET 회로 출력에 연결했습니다. LED 라이트는 setup에서 digitalWrite(LED, HIGH);로 시스템 전원 켜질 때 항상 켜지게 했습니다. 포그 메이커는 수위 값에 따른 If 함수로 만들었습니다. 물이 있으면 포그 메이커 ON, 물 없으면 EMPTY! 시 포그 OFF!

이제 모든 걸 합쳐봅시다!

최종 코드:


#include "dht.h"
#include "U8glib.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#define DHT11_PIN 2
#define ONE_WIRE_BUS 3
#define WATER_LEVEL A4
#define LDR_PIN A3
#define PH_PIN A5
#define GROW_LIGHT 10
#define FOG_PUMP 13

int waterLevel;
int LightLevel;
int pH;
dht DHT;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature waterTemp(&oneWire);
U8GLIB_ST7920_128X64 u8g(4, 12, 6, U8G_PIN_NONE);

const unsigned char logo [] PROGMEM = {
  0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFE, 0x00, 0x03, 0xC0, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xF8, 0x00, 0x07, 0xE0, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xF0, 0x00, 0x1F, 0xF8, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xE0, 0x00, 0x3F, 0xFE, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xC0, 0x00, 0x18, 0x1F, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0x80, 0x00, 0x00, 0x03, 0xC0, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFE, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFC, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFC, 0x03, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xF8, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFC, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xF0, 0x3F, 0xF0, 0x00, 0x00, 0x1F, 0xFC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xF0, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xE0, 0xFF, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xE0, 0xFF, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xFE, 0x1F, 0xFF, 0xFF, 0xF0, 0x3C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xF8, 0x03, 0xFF, 0xFF, 0xC0, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x80, 0xE0, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xE0, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xE0, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xE0, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xE0, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xE0, 0x00, 0x07, 0xF0, 0x00, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0xF0, 0x00, 0x07, 0xF0, 0x00, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0xF0, 0x00, 0x07, 0xF0, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0xF8, 0x00, 0x07, 0xF0, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0xF8, 0x00, 0x07, 0xF0, 0x00, 0x1F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xE0, 0xFC, 0x00, 0x07, 0xF0, 0x00, 0x1F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xE0, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xF0, 0x3E, 0x00, 0x0F, 0xF0, 0x00, 0x7C, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xF0, 0x1E, 0x00, 0x1F, 0xF8, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xF8, 0x06, 0x00, 0x1F, 0xFC, 0x01, 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFC, 0x00, 0x00, 0x7F, 0xFF, 0x0F, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFC, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFE, 0x00, 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0x80, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xE0, 0x00, 0x7F, 0xFE, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xF0, 0x00, 0x1F, 0xF8, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xF8, 0x00, 0x0F, 0xF0, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFC, 0x00, 0x03, 0xC0, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0xFF, 0xFD, 0x3F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

bool first;
float hum = 0.0;
double T = 0.0;

void dht_test(float * humPerc);

void setup(void) {
  waterTemp.begin();
  pinMode(GROW_LIGHT, OUTPUT);
  pinMode(FOG_PUMP, OUTPUT);
  digitalWrite(GROW_LIGHT, HIGH);
  first = true;
  
  if (u8g.getMode() == U8G_MODE_R3G3B2) {
    u8g.setColorIndex(255);
  } else if (u8g.getMode() == U8G_MODE_GRAY2BIT) {
    u8g.setColorIndex(3);
  } else if (u8g.getMode() == U8G_MODE_BW) {
    u8g.setColorIndex(1);
  } else if (u8g.getMode() == U8G_MODE_HICOLOR) {
    u8g.setHiColorByRGB(255, 255, 255);
  }
  
  u8g.firstPage();
  do {
    u8g.drawBitmapP(32, 0, 16, 64, logo);
  } while (u8g.nextPage());
  
  dht_test(&hum);
}

void RefreshDisplay(float * humPerc, double *T, int *WL, int *LL, int *pH_value) {
  u8g.setFont(u8g_font_fub11);
  u8g.setFontRefHeightExtendedText();
  u8g.setDefaultForegroundColor();
  u8g.setFontPosTop();
  u8g.drawStr(4, 0, "Hum%");
  u8g.setPrintPos(68, 0);
  u8g.print(*humPerc);
  u8g.drawStr(4, 15, "Temp");
  u8g.setPrintPos(68, 15);
  u8g.print(*T);
  u8g.drawStr(4, 30, "Wlvl");
  
  if (*WL == 0) {
    u8g.drawStr(68, 30, "EMPTY!");
    digitalWrite(FOG_PUMP, LOW);
  } else {
    if (*WL < 800)
      u8g.drawStr(68, 30, "LOW");
    else {
      digitalWrite(FOG_PUMP, HIGH);
      u8g.drawStr(68, 30, "HIGH");
    }
  }
  
  if (*LL < 100)
    u8g.drawStr(68, 45, "Dark");
  else if (*LL < 200)
    u8g.drawStr(68, 45, "Dim");
  else if (*LL < 500)
    u8g.drawStr(68, 45, "Light");
  else if (*LL < 800)
    u8g.drawStr(68, 45, "Bright");
  else
    u8g.drawStr(68, 45, "2Bright");
  
  double voltage = 5.0 / 1024.0 * (*pH_value);
  float Po = 7 + ((2.5 - voltage) / 0.18);
  u8g.drawStr(4, 45, "pH");
  u8g.setPrintPos(28, 45);
  u8g.print(Po);
}

void loop(void) {
  waterTemp.requestTemperatures();
  T = waterTemp.getTempCByIndex(0);
  waterLevel = analogRead(WATER_LEVEL);
  LightLevel = analogRead(LDR_PIN);
  pH = analogRead(PH_PIN);
  char status;
  int chk = DHT.read11(DHT11_PIN);
  hum = DHT.humidity;
  dht_test(&hum);
  
  if (first) {
    first = false;
  } else {
    u8g.firstPage();
    do {
      RefreshDisplay(&hum, &T, &waterLevel, &LightLevel, &pH);
    } while (u8g.nextPage());
  }
}

void dht_test(float * humPerc) {
  delay(1000);
}

파일 다운로드

3D 디자인 및 3D 프린팅

최종 시스템에 3D 디자인과 프린팅 기술을 많이 사용했습니다. 두 가지 다른 프린터를 사용하고 설정을 많이 조작해 원하는 결과를 얻었습니다!

3D 디자인에는 앞서 언급한 제가 가장 좋아하는 CAD 소프트웨어인 Fusion 360을 사용했습니다. 간단한 모양 만들기와 객체 돌출 방법은 컴퓨터 지원 설계 주간과 3D 스캐닝 및 프린팅 주간에서 배웠으니 자세히 다루지 않겠습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

주요 과제는 시스템의 물리적 외관을 설계하는 것이었습니다. 도전은 섹시하게 보이게 만드는 것이었습니다!

미학은 기능성만큼 중요한 기준이었습니다. 시스템은 조립 가능해야 해서 더 도전적이었습니다. 3D 프린팅, CNC 밀링, 레이저 커팅 등 배운 기술들도 통합하고 싶었습니다.

디지털 세계에서 설계하기 전 종이에 간단한 스케치를 했습니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

최종 3D 디자인:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

내 섹시한 시스템 :D

가장 먼저 설계한 건 물 컨테이너입니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

여러 기능을 통합했습니다! 첫째, 식물이 자랄 충분한 공간, 가운데에 초음파 분무기를 놓을 구멍을 뚫었습니다. 분무기를 컨테이너 레벨과 맞추고 싶었기 때문입니다. 물 레벨은 분무기보다 2cm 위에 있어야 하니 분무기 높이에 맞춘 물은 사용되지 않습니다(낭비). 분무기를 컨테이너 레벨 아래에 두면 컨테이너의 제로 레벨이 정확히 있어야 할 곳(분무기 위 2cm)이 됩니다. 이렇게 하면 모든 물을 다 쓸 수 있습니다!

컨테이너 높이도 고려했습니다. 사실 컨테이너 모든 치수는 실험 단계에서 측정했습니다.

벽면에 구멍을 뚫어 물속 센서 케이블이 전자 섹션으로 숨게 했습니다. 컨테이너 앞면에는 그래픽 디스플레이 부착용 슬롯을 만들었습니다. 컨테이너를 쉽게 분리할 수 있도록 손잡이도 설계했습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

이 각도에서 전자 섹션이 보입니다. 지금은 열려 있지만 덮개도 설계했습니다. 전자 섹션 내부에 보드 전원 공급과 프로그래밍용 접근 구멍도 만들었습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

바닥면에는 시스템 나머지와 부착될 슬라이더를 설계해 컨테이너 분리 시 편리하고 제자리 고정 역할도 하게 했습니다.

이제 출력합시다!

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

자랑스럽게 발표합니다. 사용할 프린터는 우리 팹랩 캄프-린트포트에만 있는 BigRep 3D 프린터입니다. 1입방미터 용량으로 전문가 및 산업용 최대 FFF 빌드 볼륨을 제공합니다.

슬라이싱 소프트웨어는 제 생각에 가장 진보된 도구 중 하나인 Simplify3D를 사용했습니다. 많은 설정과 옵션이 있습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

뭔가를 프린트하는 데 정답이나 오답은 없다고 생각합니다. 특정 객체에 최적 옵션을 찾을 때까지 설정을 갖고 놀면 됩니다.

이 프린터가 새거라 테스트가 많이 안 돼 있습니다. 그래서 설정을 실험하고 시도하고 또 시도해야 했습니다...

물 컨테이너 프린트에 쓸 설정을 아래에 보이지만 일부는 직관적입니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

레이어:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

추가:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

인필:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

서포트:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

온도:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

냉각:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

기타:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

고급:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

이게 제가 바꾼 설정들입니다. 나머지는 기본값으로 뒀습니다.

Prepare to Print를 누르면 소프트웨어가 경로를 생성합니다. 여기서 .gcode를 머신에 보내기 전 모든 게 괜찮은지 확인할 수 있습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

프린터 설정에 대해 간단히: 노즐 온도 = 205°C, 베드 온도 = 70°C 사용. X, Y, Z 축 위치 잡고 모든 설정 재확인 후 작업 시작!

원시 모델 모습:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

서포트 제거하고 모델 정리하면서 이게 엉덩이에 큰 고통이구나 :D라고 느꼈습니다.

보시다시피 쓴 설정이 완벽하진 않아서 컨테이너 가장자리 근처에 큰 구멍들이 있습니다. 어쨌든 방수 처리할 생각이었으니 몰딩 & 캐스팅 섹션에서 어떻게 했는지 보세요!

다음 3D 프린트 파트는 넷 팟(Net Pot)입니다. 씨앗을 재배 매질에 고정하는 컵입니다. 첫 버전은 컴퓨터 지원 설계 주간에서 자세히 다뤘습니다.

이번엔 실험 단계에서 관찰한 걸 바탕으로 디자인을 좀 개선했습니다. 주요 차이점은 빈 공간 크기를 많이 늘려 안개가 더 쉽게 들어가고 뿌리가 더 잘 통과하게 한 것입니다.

기존 디자인을 수정하고 한 가지 더 추가했습니다!

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

윗부분에 약간의 필렛을 줘 전환을 더 부드럽게 했습니다. 바닥면에 볼을 추가하고 Move 명령으로 좀 안으로 이동시켜 바닥에 2-3mm 구조 두께를 남겼습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

불리언 빼기 또는 Combine 기능을 사용해 바닥에 멋진 곡률을 얻었습니다!

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

이제 프린트!

사용한 3D 프린터는 Ultimaker 2+입니다. 슬라이싱엔 사용하기 쉽고 기능적인 아주 좋은 소프트웨어를 썼습니다. 재료는 PLA 필라멘트

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

.stl 파일 임포트 후 사용한 설정:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

여기 내 작은 군대 :D

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

시스템 최종 디자인에서 바닥 부분도 3D 프린트하기로 했습니다. 큰 조각이라 BigRep로도 프린트합니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

물 컨테이너에 쓴 설정과 똑같이 써서 새로운 건 없습니다.

프린트 미리보기:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

시스템 윗면의 둥근 모서리도 3D 프린트했습니다. Ultimaker로 했고 다음 설정 사용:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

여기서 트릭은 표면 최대 매끄러움을 달성하는 거였고 꽤 좋은 결과가 나온 것 같습니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

파일 다운로드

2D 디자인 및 레이저 커팅

레이저 커팅으로 시스템 내부를 모두 덮고 마무리 룩을 줄 아크릴 파츠를 잘랐습니다.

실제로 파츠를 다시 설계한 건 아니고 Fusion 360에서 이미 만든 스케치를 .dxf 파일로 내보냈습니다. 내보낸 후 레이저 커팅 머신에 임포트하기 전 디자인을 편집했습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

Fusion360에서 스케치 모습:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

큰 난장판처럼 보이지만 좋은 건 모든 게 파라메트릭이라는 겁니다! 나중에 변경해야 할 경우를 대비해 올바른 위치에 정렬하고 파라메트릭을 유지하려다 보니 지저분해 보입니다.

Rhino에서 레이저 커팅 전 최종 스케치 모습:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

녹색 아크릴을 쓰기로 했습니다. 유기적 룩을 주고 녹색 식물과 잘 어울립니다.

앞뒤 커버는 흰색으로 했습니다. 다 취향 문제고 제가 보는 방식이고 제가 좋아하는 방식입니다.

앞뒤 커버는 내부 컷 빼곤 치수가 똑같습니다. 앞 커버에는 LCD 디스플레이용 구멍이 있습니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

뒷 커버에는 보드 전원 공급과 프로그래밍용 접근 구멍을 만들었습니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

또 다른 레이저 커팅 파츠는 윗면입니다. 빛이 통과하게 투명 아크릴을 쓰기로 했습니다. 무게를 줄이고 빛이 더 많이 통과하게 추가 컷도 설계했습니다. RGB LED 스트립 폭을 측정해 자연광과 인공광 모두 충분히 통과할 수 있게 부착했습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

설계 끝났으니 레이저 커팅 갑시다!

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

우리 팹랩에서 쓰는 레이저 커터는 Epilog Fusion 60Watt, 작업 영역 1016 x 711mm의 CO2 레이저 커터입니다. 나무, 판지, 아크릴 등 엔지니어링 플라스틱을 자르고 각인할 수 있습니다.

모든 파츠에 같은 재료 plexiglass 5mm를 써서 같은 설정으로 모두 처리했습니다!

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

파일 다운로드

CNC 밀링

배운 모든 기술과 기법을 시스템에 통합하고 싶어 CNC 밀링할 구조물 파츠도 있습니다. 다시 설계한 건 아니고 Fusion360 스케치에서 .dxf 파일을 내보냈습니다!

디자인 커팅에 큰 CNC 몬스터를 사용합니다.

CNC(컴퓨터 수치 제어)는 매우 높은 속도로 회전하는 커팅 비트를 사용해 파츠에서 재료를 제거하는 기계입니다.

미리 프로그래밍된 컴퓨터 파일(보통 .GCode 파일)을 읽어 어디 어떻게 자를지 알 수 있습니다. 커팅 비트는 스핀들 모터로 매우 높은 RPM으로 회전하며 비트를 위아래로 움직일 수 있습니다. 이 메커니즘은 크로스 암으로 좌우, 전후로 움직입니다. 따라서 X, Y, Z 축으로 움직일 수 있는 3축 라우터로 알려졌습니다. 2D 컷아웃과 에칭, 3D 릴리프 작업도 가능합니다.

팹랩 캄프-린트포트엔 e(sign: Easy Worker MasterPro 2513의 CNC 포털 밀링 머신이 있습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

작업 영역은 2600 x 1400 x 300mm이고 진공 테이블이 있습니다. 주로 나무 밀링에 쓰지만 HSD 스핀들(3.9kW, 24,000RPM)로 금속도 쉽게 밀링 가능합니다.

사용할 재료는 18mm 합판

먼저 나무 시트를 CNC 베드에 놓고 정렬한 후 진공 켭니다. .dxf 파일 내보낸 후 머신 CAM 소프트웨어에 임포트하기 전 디자인 편집.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

먼저 머신을 홈 해야 합니다!

X, Y, Z 제로 위치 설정을 위해 소프트웨어의 홈 버튼(또는 리모컨)으로 머신을 홈시킵니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

처음엔 베드 모서리 중 하나에 대략 X, Y 제로를 맞췄습니다. 레이저로도 시도해 봤지만 시뮬레이션할 때마다 제로가 작업 영역을 벗어나 충돌이 표시돼 매번 실패했습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

이제 머신과 함께 제공되는 특수 도구로 Z축을 찾습니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

중요한 건 머신 베드 위에 놓는 것입니다!

이제 첫 번째 작업인 조각을 시작합니다. 사용한 설정:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

Calculate Toolpath로 작업 시뮬레이션해 충돌 없는지 확인. .GCode 저장 후 작업 시작하면 이 창이 뜹니다:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

이제 아웃사이드 컷 시작:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

작업 완료 후 결과:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

몰딩 & 캐스팅 섹션에서 쓸 또 다른 파츠도 밀링했습니다.

물 컨테이너 방수용 몰드 준비. 설계:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

새로운 건 없습니다. 위와 정확히 같은 설정 사용. 유일한 차이는 재료 두께가 10mm 나무였고, 나중에 붙여서 몰드 만들 7조각을 잘랐습니다.

파일 다운로드

몰딩 & 캐스팅

기존 컨테이너 방수용 물 컨테이너를 준비하려고 이 기법을 썼습니다. 얇은 재료 층(더 작은 컨테이너)으로 쉽게 분리 가능하게 봤습니다.

이전 섹션 CNC 밀링 결과:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

동일한 7조각을 잘라 레퍼런스 구멍으로 정렬! 바닥 5조각 가운데에 큰 구멍을 뚫어 에어 펌프를 넣고 나중에 캐스트를 쉽게 뺄 수 있게 했습니다.

모든 조각을 붙이고 고정한 후 모습:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

접착제 마르는 동안 펌프용 작은 플라스틱 "것"(뭐라 불러야 할지 :D)을 만들었습니다. 내 몰드에 나사로 고정하고 원할 때 빼낼 수 있게 하는 아이디어입니다.

몰드 준비 완료:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

뒷면:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

진공 캐스팅 준비 완료!

우리 팹랩 캄프-린트포트에 있는 Formech - 수동 진공 성형기를 사용했습니다.

여러 번 시도했는데 매번 몰드를 빼내려다 캐스트가 부서졌습니다. 몇 시간 시행착오 끝에 해결책을 찾았습니다! 먼저 얇은 재료 층을 하나 진공 성형하고, 빼지 않은 채로 그 위에 실제 컨테이너를 캐스팅합니다. 첫 번째 얇은 층이 미끄럽고 실리콘 스프레이를 뿌리면 몰드를 훨씬 쉽게 뺄 수 있습니다.

실리콘이 좀 마른 후 실제 레이어를 캐스팅합니다.

자, 여기 있습니다!!!

쉬웠다고 생각하는 분들을 위한 영웅 샷

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

모든 것 조립하기

이제 모든 걸 조립합시다! 구조물 조립부터 시작합니다. 필요한 도구들 옆에 두고:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

과정 단축 애니메이션:

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

라이트 조립을 위해 RGB LED 스트립을 4조각으로 자르고(미리 길이 측정), 납땜했습니다!

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

모든 센서 연결하고 배선 정리 후 보드를 전자 섹션에 고정했습니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

여기가 시스템입니다!!! 모든 게 조립된 멋진 재배 시스템 GIY

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

작동 중 영웅 샷!

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

최종 프레젠테이션 비디오

© 2017 Albot Dima. All rights reserved | Albot.Dumitru@hsrw.org

이 작업은 Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License 하에 라이선스됩니다.

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

프로젝트에 대한 더 자세한 내용은 공식 소스를 방문하세요:

https://archive.fabacademy.org/2017/fablabkamplintfort/students/396/final.html

코드

GIY 보드 - 코드 Arduino

#include "dht.h"
#include "U8glib.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#define DHT11_PIN 2
#define ONE_WIRE_BUS 3
#define WATER_LEVEL A4
#define LDR_PIN A3
#define PH_PIN A5
#define GROW_LIGHT 10
#define FOG_PUMP 13

int waterLevel;
int LightLevel;
int pH;
dht DHT;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature waterTemp(&oneWire);
U8GLIB_ST7920_128X64 u8g(4, 12, 6, U8G_PIN_NONE);

const unsigned char logo [] PROGMEM = {
  0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFE, 0x00, 0x03, 0xC0, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xF8, 0x00, 0x07, 0xE0, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xF0, 0x00, 0x1F, 0xF8, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xE0, 0x00, 0x3F, 0xFE, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xC0, 0x00, 0x18, 0x1F, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0x80, 0x00, 0x00, 0x03, 0xC0, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFE, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFC, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFC, 0x03, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xF8, 0x07, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFC, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xF0, 0x3F, 0xF0, 0x00, 0x00, 0x1F, 0xFC, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xF0, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xE0, 0xFF, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xE0, 0xFF, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xFE, 0x1F, 0xFF, 0xFF, 0xF0, 0x3C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xF8, 0x03, 0xFF, 0xFF, 0xC0, 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x80, 0xE0, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xE0, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xE0, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xE0, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xE0, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x80, 0xE0, 0x00, 0x07, 0xF0, 0x00, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0xF0, 0x00, 0x07, 0xF0, 0x00, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0xF0, 0x00, 0x07, 0xF0, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0xF8, 0x00, 0x07, 0xF0, 0x00, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xC0, 0xF8, 0x00, 0x07, 0xF0, 0x00, 0x1F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xE0, 0xFC, 0x00, 0x07, 0xF0, 0x00, 0x1F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xE0, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xF0, 0x3E, 0x00, 0x0F, 0xF0, 0x00, 0x7C, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xF0, 0x1E, 0x00, 0x1F, 0xF8, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xF8, 0x06, 0x00, 0x1F, 0xFC, 0x01, 0xE0, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFC, 0x00, 0x00, 0x7F, 0xFF, 0x0F, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFC, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFE, 0x00, 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0x80, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xE0, 0x00, 0x7F, 0xFE, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xF0, 0x00, 0x1F, 0xF8, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xF8, 0x00, 0x0F, 0xF0, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFC, 0x00, 0x03, 0xC0, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0xFF, 0xFF, 0xFF, 0xFD, 0x3F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

bool first;
float hum = 0.0;
double T = 0.0;

void dht_test(float * humPerc);

void setup(void) {
  waterTemp.begin();
  pinMode(GROW_LIGHT, OUTPUT);
  pinMode(FOG_PUMP, OUTPUT);
  digitalWrite(GROW_LIGHT, HIGH);
  first = true;
  
  if (u8g.getMode() == U8G_MODE_R3G3B2) {
    u8g.setColorIndex(255);
  } else if (u8g.getMode() == U8G_MODE_GRAY2BIT) {
    u8g.setColorIndex(3);
  } else if (u8g.getMode() == U8G_MODE_BW) {
    u8g.setColorIndex(1);
  } else if (u8g.getMode() == U8G_MODE_HICOLOR) {
    u8g.setHiColorByRGB(255, 255, 255);
  }
  
  u8g.firstPage();
  do {
    u8g.drawBitmapP(32, 0, 16, 64, logo);
  } while (u8g.nextPage());
  
  dht_test(&hum);
}

void RefreshDisplay(float * humPerc, double *T, int *WL, int *LL, int *pH_value) {
  u8g.setFont(u8g_font_fub11);
  u8g.setFontRefHeightExtendedText();
  u8g.setDefaultForegroundColor();
  u8g.setFontPosTop();
  u8g.drawStr(4, 0, "Hum%");
  u8g.setPrintPos(68, 0);
  u8g.print(*humPerc);
  u8g.drawStr(4, 15, "Temp");
  u8g.setPrintPos(68, 15);
  u8g.print(*T);
  u8g.drawStr(4, 30, "Wlvl");
  
  if (*WL == 0) {
    u8g.drawStr(68, 30, "EMPTY!");
    digitalWrite(FOG_PUMP, LOW);
  } else {
    if (*WL < 800)
      u8g.drawStr(68, 30, "LOW");
    else {
      digitalWrite(FOG_PUMP, HIGH);
      u8g.drawStr(68, 30, "HIGH");
    }
  }
  
  if (*LL < 100)
    u8g.drawStr(68, 45, "Dark");
  else if (*LL < 200)
    u8g.drawStr(68, 45, "Dim");
  else if (*LL < 500)
    u8g.drawStr(68, 45, "Light");
  else if (*LL < 800)
    u8g.drawStr(68, 45, "Bright");
  else
    u8g.drawStr(68, 45, "2Bright");
  
  double voltage = 5.0 / 1024.0 * (*pH_value);
  float Po = 7 + ((2.5 - voltage) / 0.18);
  u8g.drawStr(4, 45, "pH");
  u8g.setPrintPos(28, 45);
  u8g.print(Po);
}

void loop(void) {
  waterTemp.requestTemperatures();
  T = waterTemp.getTempCByIndex(0);
  waterLevel = analogRead(WATER_LEVEL);
  LightLevel = analogRead(LDR_PIN);
  pH = analogRead(PH_PIN);
  char status;
  int chk = DHT.read11(DHT11_PIN);
  hum = DHT.humidity;
  dht_test(&hum);
  
  if (first) {
    first = false;
  } else {
    u8g.firstPage();
    do {
      RefreshDisplay(&hum, &T, &waterLevel, &LightLevel, &pH);
    } while (u8g.nextPage());
  }
}

void dht_test(float * humPerc) {
  delay(1000);
}
GIY 보드 - LCD + 라이트 코드 Arduino

#include "U8glib.h"
int led = 10;
U8GLIB_ST7920_128X64 u8g(4, 12, 6, U8G_PIN_NONE);

void draw(void) {
  u8g.setFont(u8g_font_unifont);
  u8g.setPrintPos(0, 20);
  u8g.print("GIY Project v1.0!");
}

void setup(void) {
  pinMode(led, OUTPUT);
  digitalWrite(led, HIGH);
}

void loop(void) {
  u8g.firstPage();
  do {
    draw();
  } while (u8g.nextPage());
  delay(500);
}

회로도

ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스 ATmega32U4, ESP8266, 센서로 만드는 DIY 스마트 IoT 디바이스

제조공정

  1. 커스텀 4×4 틱택토 방문카드 PCB – 설계, 제작, 코드 가이드
  2. 스마트 홈 연동을 위한 다중 위치 온도 센서 시스템
  3. 862D+ 납땜 인두 컨트롤러 DIY: 정밀함과 신뢰성
  4. MotionSense: 아두이노와 ESP8266으로 만드는 스마트 침입 감지 시스템
  5. 3D 프린터 화재 예방: 스마트 센서 안전 시스템
  6. 아두이노, Yaler, IFTTT로 웹 연동 IoT 게이지 만들기
  7. 아두이노 기반 척력 자기 부상: 간단 회로 & DIY 가이드
  8. 정밀 핸들링을 위한 고급 원격 제어 그리퍼 로봇
  9. 고성능 아두이노 기상 관측용 데이터 로거 제작 가이드
  10. CoroFence 열화상 감지기: Panasonic Grid-EYE & PIR 센서 IoT 연동