
본문 계속 1/2
STEP 10. ESP32 프로그래밍

전자 장치를 조립했으므로 다음 단계는 XIAO ESP32-C6를 프로그래밍하는 것이었습니다.
펌웨어에는 네 가지 주요 작업이 있습니다:
- Modbus RTU를 통해 토양 매개변수 7가지를 모두 읽습니다.
- 장치를 Wi-Fi에 연결합니다.
- 로컬 웹 서버를 통해 판독값을 JSON으로 제공합니다.
- WS2812 LED를 사용해 Wi-Fi 상태를 표시합니다.
완성된 펌웨어는 프로젝트 파일과 함께 첨부되어 있지만, 아래에서 중요한 부분을 나누어 설명하겠습니다.
1. 필요한 라이브러리 설치
코드를 컴파일하기 전에 Arduino IDE의 라이브러리 관리자에서 다음 라이브러리를 설치하세요:
- ModbusMaster (Doc Walker 제작)
- Adafruit NeoPixel (Adafruit 제작)
Wi-Fi, WebServer 및 mDNS 라이브러리는 ESP32 보드 패키지에 포함되어 있습니다.
다음과 같은 include를 사용했습니다:
Arduino IDE에서 다음을 선택하세요:
Serial Monitor는 115200 baud(보드레이트)로 사용했습니다.
2. Wi-Fi 및 핀 구성
Wi-Fi 자격 증명은 스케치 앞부분에 저장되어 있습니다.
여기에는 제 자격 증명 대신 자리 표시자를 넣었으므로, 사용하려는 네트워크의 자격 증명을 입력하세요:
하드웨어 연결에는 D6과 D7을 UART 핀으로, D3을 MAX485 방향 제어용으로, D2를 WS2812용으로 사용했습니다.
MAX485의 DE 핀과 /RE 핀은 서로 연결하고 D3으로 제어합니다.
3. Modbus 구성
제 센서는 Modbus RTU를 사용해 7가지 판독값을 모두 전송합니다.
구성은 한곳에 모아 두었으므로, 다른 센서가 다른 baud rate, 슬레이브 주소 또는 레지스터 레이아웃을 사용하는 경우 쉽게 변경할 수 있습니다.
USE_INPUT_REGISTERS를 false로 설정하면 펌웨어는 Modbus 기능 0x03을 사용하며, 이 기능은 홀딩 레지스터를 읽습니다.
센서 설명서에 기능 0x04가 지정되어 있다면 다음과 같이 변경하세요:
4. 주요 객체 생성
다음으로 UART 통신, Modbus, 웹 서버 및 WS2812용 객체를 각각 생성했습니다.
웹 서버는 포트 80에서 실행되므로 별도의 포트 번호를 추가하지 않고 ESP32의 IP 주소로 판독값에 액세스할 수 있습니다.
5. 센서 판독값 저장
서로 관련 없는 전역 변수 7개를 두는 대신 모든 값을 하나의 구조체에 저장했습니다.
valid 값은 센서가 응답하는지 웹 대시보드에 알려 주고, modbusResult는 통신 오류를 디버깅하는 데 도움이 됩니다.
6. Wi-Fi 상태 LED
Serial Monitor를 열지 않아도 장치 상태를 알 수 있게 하고 싶었습니다.
ESP32의 연결이 끊겨 있는 동안 RGB LED는 빨간색으로 켜져 있고, Wi-Fi에 연결되면 녹색으로 바뀝니다.
LED는 표시기로만 사용하면 되므로 밝기는 상당히 낮게 설정했습니다.
7. MAX485 제어
RS485는 반이중 방식이므로 MAX485는 동시에 송신하고 수신할 수 없습니다.
Modbus 요청을 보내기 전에 펌웨어가 송신을 활성화합니다. 요청을 보내자마자 모듈을 다시 수신 모드로 전환합니다.
이 함수들은 설정 중에 Modbus 라이브러리에 등록됩니다:
이 방향 제어가 없으면 ESP32는 요청을 올바르게 보낼 수는 있어도 센서의 응답을 전혀 받지 못할 수 있습니다.
8. 7가지 토양 매개변수 읽기
펌웨어는 주소 0x0000에서 시작하는 연속 레지스터 7개를 요청합니다.
요청이 실패하면 데이터를 유효하지 않은 것으로 표시하고 Serial Monitor에 Modbus 결과를 출력합니다.
요청이 성공하면 응답 버퍼에 7가지 측정값이 모두 들어 있습니다.
그런 다음 원시 값을 실제 단위로 변환해야 합니다.
여기서 사용하는 레지스터 순서는 다음과 같습니다:
마지막으로 값을 Serial Monitor에 출력합니다. 덕분에 웹사이트를 사용하기 전에 전자 장치를 더 쉽게 테스트할 수 있었습니다.
이 센서의 버전이 다르면 서로 다른 레지스터나 스케일링을 사용하는 경우가 있습니다. 센서가 응답하지만 판독값이 잘못된 순서로 표시된다면 Modbus 설명서에 따라 조정해야 할 부분은 바로 여기입니다.
9. 판독값을 JSON으로 변환
웹사이트에는 예측 가능한 형식이 필요하므로 판독값을 JSON 객체로 변환합니다.
정상적인 응답은 다음과 같습니다:
웹사이트는 주로 처음 7개 값을 사용합니다. 나머지 필드는 장치를 확인하고 연결 문제를 진단하는 데 유용합니다.
10. 웹사이트의 데이터 요청 허용
웹사이트는 컴퓨터에서 실행되고 API는 ESP32에서 실행되므로 브라우저는 두 대상을 서로 다른 출처로 취급합니다.
localhost 대시보드가 센서 데이터를 요청할 수 있도록 CORS 헤더를 추가했습니다.
no-store 헤더는 브라우저가 이전에 캐시된 판독값을 표시하지 않도록 합니다.
11. /data 엔드포인트 생성
Dirt Nerd에서 사용하는 주요 엔드포인트는 /data입니다.
ESP32와 센서가 응답하는지 확인하기 위한 더 간단한 /health 엔드포인트도 추가했습니다.
서버가 시작될 때 엔드포인트가 등록됩니다:
또한 /에 간단한 진단 페이지를 포함했습니다. 이를 통해 브라우저에서 ESP32의 IP 주소를 직접 열어 전체 Dirt Nerd 대시보드를 시작하지 않고도 센서를 확인할 수 있습니다.
12. Wi-Fi 연결
시작 중에는 ESP32가 연결을 시도하는 동안 RGB LED가 빨간색으로 켜져 있습니다.
연결되면 LED가 녹색으로 바뀌고 IP 주소가 Serial Monitor에 출력됩니다.
숫자로 표시된 IP 주소를 Dirt Nerd 웹사이트에 입력합니다.
13. 자동 Wi-Fi 재연결
라우터나 핫스팟의 연결이 일시적으로 끊길 때마다 장치를 재설정해야 하는 상황은 피하고 싶었습니다.
이 함수는 시작 후에도 RGB 상태가 정확하게 유지되도록 합니다.
14. 설정
setup() 함수는 상태 LED, MAX485, UART, Modbus 연결, Wi-Fi 및 웹 서버를 초기화합니다.
15. 메인 루프
메인 루프는 상당히 간단합니다.
ESP32는 브라우저 요청에 응답하고 Wi-Fi 연결을 모니터링하면서 2초마다 센서를 읽습니다.
펌웨어를 업로드한 후 115200 baud(보드레이트)로 Serial Monitor를 엽니다. RGB LED가 녹색으로 바뀌면 터미널에 표시된 IP 주소를 복사합니다.
그러면 센서 데이터를 다음 주소에서 이용할 수 있습니다:
이제 하드웨어가 로컬 네트워크를 통해 구조화된 데이터를 생성합니다. 웹사이트 단계에서는 Dirt Nerd가 이 엔드포인트에 요청을 보내 원시 판독값을 대시보드, 작물 비교 및 권장 사항으로 변환하는 방법을 보여드리겠습니다.

본문 계속 2/2
STEP 11. 웹페이지 만들기



Next.js, React, TypeScript 및 CSS를 사용하여 Dirt Nerd 웹사이트를 만들었습니다. 주요 목표는 식물 옆에서 사용할 수 있을 만큼 인터페이스를 간단하게 유지하면서도 센서가 수집한 모든 정보를 표시하는 것이었습니다.
웹사이트는 두 가지 작동 모드를 지원합니다:
- 데모 모드에서는 편집 가능한 샘플 측정값을 사용합니다.
- 라이브 모드에서는 ESP32에 실제 측정값을 요청합니다.
주요 프로젝트 파일은 다음과 같습니다:
전체 웹사이트는 이 단계에 ZIP 파일로 첨부되어 있습니다. 다음 섹션에서는 코드의 가장 중요한 부분을 설명합니다.
센서 데이터 저장
센서 측정값은 별도의 sensor-data.ts 파일에 저장했습니다. 이렇게 하면 동일한 대시보드 구성 요소를 샘플 값과 ESP32에서 수신한 데이터 모두에 사용할 수 있습니다.
웹사이트가 라이브 데이터를 수신하면 이 객체 내부의 값만 교체합니다. 나머지 인터페이스는 측정값이 데모 모드에서 왔는지 실제 센서에서 왔는지 알 필요가 없습니다.
웹사이트 상태 관리
메인 페이지에서는 현재 화면, 선택한 작물, 작동 모드, ESP32 주소 및 센서 측정값을 추적합니다.
화면 값에 따라 인터페이스가 랜딩 페이지, 분석 애니메이션 및 최종 대시보드 사이에서 전환됩니다.
장치 설정 저장
선택한 작동 모드와 ESP32 주소는 브라우저에 저장됩니다. 따라서 사용자는 새로 고침할 때마다 주소를 다시 입력할 필요가 없습니다.
설정은 다음을 사용하여 저장합니다:
사용자 지정 데모 측정값 추가
데모 모드에는 7가지 토양 매개변수 모두에 대한 입력 필드가 포함되어 있습니다. 대시보드를 설계할 때 실제 센서를 매번 연결하지 않고도 다양한 값을 테스트할 수 있어 특히 유용했습니다.
다음 함수는 나머지 데이터는 그대로 유지하면서 하나의 측정값을 업데이트합니다:
이러한 사용자 지정 필드는 데모 모드에서만 표시됩니다. 라이브 모드에서는 ESP32에서 값이 직접 전달됩니다.
ESP32 주소 준비
사용자는 Serial Monitor에 표시된 숫자 주소만 입력하면 됩니다.
예:
웹사이트는 이를 자동으로 다음과 같이 변환합니다:
이는 다음 함수를 사용하여 처리됩니다:
또한 완전한 엔드포인트가 이미 입력된 경우 /data가 두 번 추가되는 것도 방지합니다.
ESP32에서 데이터 수신
라이브 모드에서는 웹사이트가 ESP32에 HTTP 요청을 보내고 JSON 응답을 기다립니다.
ESP32는 다음 형식으로 데이터를 반환합니다:
웹사이트는 대시보드에 처음 7개 필드를 사용합니다. 연결 필드는 주로 장치를 테스트하고 진단할 때 유용합니다.
분석 시작
두 모드 모두에서 동일한 분석 버튼이 작동합니다.
데모 모드에서는 웹사이트가 사용자 지정 값을 사용하여 즉시 애니메이션을 시작합니다. 라이브 모드에서는 먼저 ESP32 연결을 확인한 다음 새로운 측정값을 다운로드합니다.
측정 애니메이션 만들기
애니메이션은 토양 센서가 실제로 수행한 측정 과정을 따릅니다.
타이머가 목록을 순서대로 진행한 후 대시보드를 엽니다:
이 애니메이션은 실제 센서 통신을 지연시키지 않습니다. 라이브 모드에서는 먼저 데이터를 요청하고, 보고서가 준비되는 동안 애니메이션이 명확한 피드백을 제공합니다.
작물 보고서 업데이트
선택한 작물은 상태 변수에 저장됩니다:
작물 버튼을 누르면 웹사이트가 해당 값을 변경합니다:
호환성 백분율, 적정 범위, 상태 메시지 및 권장 사항은 모두 선택한 작물 객체에서 값을 읽습니다. 그러면 React가 페이지를 새로 고치지 않고 보고서를 자동으로 업데이트합니다.
현재 프로토타입에서는 작물 프로필을 로컬에 저장합니다. 따라서 외부 식물 데이터베이스나 인터넷 연결 없이도 웹사이트를 사용할 수 있습니다.
데이터 내보내기
데이터 내보내기 버튼은 작동 모드, 측정값 및 선택한 작물을 포함하는 JSON 파일을 생성합니다.
PDF 버튼에는 브라우저의 인쇄 대화 상자를 사용했습니다:
사용자는 인쇄 창에서 Save as PDF 를 선택할 수 있습니다. 별도의 인쇄 스타일시트는 내비게이션 버튼과 기타 불필요한 컨트롤을 숨깁니다.
모바일 최적화
데스크톱 버전에서는 페이지 전체에 7개의 측정값이 표시됩니다. 태블릿에서는 레이아웃이 4열로 변경됩니다.
휴대폰에서는 각 측정값이 작고 가로로 긴 카드가 됩니다:
작물 선택기는 가로로 스크롤할 수 있게 됩니다:
설정 패널도 하단 시트로 바뀌어 한 손으로 사용하기 더 편리해집니다:
웹사이트 실행
첨부된 웹사이트 ZIP 파일의 압축을 푼 후 프로젝트 폴더에서 터미널을 열고 종속 항목을 설치합니다:
로컬 개발 서버를 시작합니다:
웹사이트는 일반적으로 다음 주소에서 열립니다:
라이브 모드를 사용하려면 컴퓨터와 ESP32가 동일한 Wi-Fi 네트워크에 연결되어 있어야 합니다. 설정을 열고 Live mode를 선택한 다음 숫자로 된 ESP32 주소를 입력하고 Test를 누릅니다.
현재 분석기에 직접 연결할 때는 localhost를 통해 인터페이스를 실행합니다. Vercel 배포는 HTTPS를 사용하는 반면 ESP32는 로컬 HTTP 엔드포인트를 제공하므로 일부 브라우저에서는 이 조합을 차단합니다. Localhost를 사용하면 이 문제를 피할 수 있으며 현재 버전에서 가장 안정적인 설정입니다.
STEP 12. 직면한 문제들
센서 레지스터 이해하기
가장 큰 전자기기 문제는 7-in-1 RS485 센서들이 모두 정확히 동일한 레지스터 순서나 스케일링을 사용하지 않는다는 점이었습니다.
센서는 유효한 Modbus 응답을 반환할 수 있지만, pH, EC 또는 NPK 값을 코드에서 사용된 레이아웃과 다른 레지스터에 배치할 수 있습니다.
해결책은 레지스터 주소와 스케일링을 하나의 함수에 유지하여 센서 매뉴얼을 확인한 후 변경할 수 있도록 하는 것이었습니다.
RS485 A 및 B 라벨링
RS485 A 및 B 라벨은 제조업체 간에 항상 일관되지 않습니다.
배선과 설정이 올바른 것처럼 보이지만 센서가 응답하지 않는 경우, A와 B를 한 번 바꾸는 것이 유용한 테스트입니다.
로직 레벨 차이
XIAO는 3.3V GPIO를 사용하는 반면, 전통적인 MAX485 모듈은 일반적으로 5V에서 작동합니다.
RO 출력을 ESP32에 직접 연결하면 입력이 손상될 수 있습니다. 모듈이 전기적으로 호환된다고 가정하는 대신 레벨 시프팅으로 이를 고려했습니다.
IP 주소 변경
ESP32의 로컬 IP는 라우터가 재연결될 때 변경될 수 있습니다.
이는 웹사이트에 저장된 주소가 장치가 연결되어 있음에도 불구하고 결국 작동을 멈출 수 있음을 의미합니다.
테스트 버튼은 이를 빠르게 식별하는 데 도움이 됩니다. 라우터에서 DHCP 예약을 설정하면 주소를 고정할 수도 있습니다.
로컬 HTTP 및 Vercel HTTPS
웹사이트는 Vercel에서 데모로 잘 작동하지만, ESP32와의 직접 통신은 더 복잡합니다.
Vercel은 HTTPS를 사용하는 반면, ESP32는 로컬 네트워크 내에서 HTTP 주소를 제공합니다. 브라우저는 HTTPS 페이지가 그 불안전한 로컬 엔드포인트에 요청하는 것을 차단할 수 있습니다.
현재 빌드에서는 로컬호스트에서 웹사이트를 실행하는 것이 가장 신뢰할 수 있는 솔루션입니다.
모바일 대시보드 레이아웃
원래의 데스크탑 스타일 카드가 휴대폰에서 너무 좁아졌습니다.
글꼴 크기를 줄이는 것만으로는 부족하여, 센서 카드를 컴팩트한 수평 행으로 변경하고 크롭 선택기를 수평으로 스크롤 가능하게 만들었습니다.
이렇게 하여 가독성을 유지하고 야외에서 조작하기 쉽게 만들었습니다.
인클로저 여유 공간
곡선형 인클로저는 예상보다 가장자리 근처에 여유 공간이 적었습니다.
전자기기를 배치할 때 나사 기둥, USB 커넥터 및 케이블 굴곡에 주의해야 했습니다.
삼색 PLA 마감
삼색 필라멘트는 제가 예상한 외관을 생성하지 않았습니다.
출력을 버리는 대신, 샌딩하고 페인팅했습니다. 초록색 마감이 프로젝트와 훨씬 더 잘 어울리게 되었습니다.
STEP 13. 장치 테스트


테스트를 통신, 센서 응답 및 웹사이트 테스트로 나누었습니다.
먼저 대시보드를 열지 않은 상태에서 장치에 전원을 공급했습니다.
WS2812는 처음에 빨간색으로 켜졌고, ESP32가 Wi-Fi에 연결된 후 녹색으로 바뀌었습니다.
보드레이트 115200으로 시리얼 모니터를 열고, 보드가 로컬 IP 주소를 출력하는지 확인했습니다.
그런 다음 브라우저에서 다음 주소를 열었습니다:
이를 통해 ESP32가 JSON을 반환하고 7개의 측정 필드가 모두 존재하는 것을 확인했습니다.
다음으로 프로브를 토양에 넣고 토양 상태가 변할 때 측정값이 합리적인 방향으로 변하는지 관찰했습니다.
이 단계의 주요 목적은 실험실 수준의 정확성을 주장하는 것이 아니라, 명백히 잘못된 레지스터 매핑, 스케일링 또는 통신 오류를 찾는 것이었습니다.
그런 다음 localhost에서 웹사이트를 시작하고 Live 모드를 선택한 후 동일한 IP 주소를 입력했습니다.
Test 버튼으로 연결을 확인했고, 분석을 시작하자 측정값이 대시보드 카드로 전송되었습니다.
페이지를 새로 고치지 않아도 호환성 메시지, 비교표 및 권장 사항이 업데이트되는지 확인하기 위해 사용 가능한 작물 사이를 전환했습니다.
또한 데스크톱 및 휴대폰 화면 너비에서 인터페이스를 테스트했습니다.
센서 카드는 모바일 행으로 바뀌었고, 작물 옵션은 가로로 스크롤할 수 있게 되었으며, Settings 창은 하단 시트로 열렸습니다.
마지막으로 Export Data, Share Report 및 Download PDF 컨트롤을 테스트했습니다.
토양 센서의 측정값을 농업적으로 정확한 것으로 간주하려면 먼저 제조업체의 절차에 따라 센서를 보정해야 합니다.
보다 공식적인 비교를 위해 다음 단계에서는 문서화된 토양 샘플 여러 개를 테스트하고 Dirt Nerd의 측정값을 보정된 기준 기기의 측정값 또는 실험실 결과와 비교해야 합니다.
STEP 14. 최종 생각




Dirt Nerd는 ESP32에 연결된 센서 이상의 의미를 갖게 되었습니다.
제가 가장 즐겼던 부분은 전자기기, 펌웨어, 인터페이스 및 인클로저를 하나의 제품 같은 프로토타입으로 통합하는 것이었습니다.
이 프로젝트는 측정값을 표시하는 것이 작업의 절반에 불과하다는 것을 가르쳐 주었습니다. 사용자가 자신이 기르고자 하는 식물에 대한 의미를 이해할 수 있을 때 정보는 훨씬 더 유용해집니다.
저는 RS485 통신, Modbus 레지스터, 전압 레벨 차이, 로컬 HTTP API 및 반응형 인터페이스 디자인에 대해 많은 것을 배웠습니다.
인클로저 또한 예상치 못한 디자인 여정을 겪었습니다. 처음 상상했던 깨끗한 물방울 모양을 유지하지 않았지만, 약간 오징어 같은 최종 형태가 프로젝트를 더 인식 가능하게 만들었습니다.
미래 버전에서 개선하고 싶은 몇 가지 사항이 있습니다.
신뢰할 수 있는 기준 측정값에 대해 센서를 보정하고, 작물 데이터베이스를 확장하며, 모든 비교를 실시간 읽기에서 직접 계산하고, 펌웨어에 자격 증명을 저장하지 않고 Wi-Fi 설정을 위한 더 나은 방법을 추가하고 싶습니다.
원격 액세스를 위해서는 직접 로컬 HTTP 연결을 안전한 MQTT 또는 클라우드 기반 데이터 경로로 교체하고 싶습니다.
내부 전자기기 장착을 더 정리하고, 분석기가 별도의 전원 케이블 없이 사용될 수 있도록 충전식 배터리를 추가하고 싶습니다.
현재로서는 Dirt Nerd가 토양을 측정하고 결과를 표시하며 이를 더 이해하기 쉬운 식물별 보고서로 변환할 수 있는 완전한 프로토타입으로 작동합니다.
자신만의 버전을 만들 경우, 정확한 토양 센서에 대한 매뉴얼을 확인하고, 전압 레벨을 안전하게 유지하며, 첫 번째 읽기 세트를 최종 답변이 아닌 보정의 시작으로 간주하십시오.
읽어 주셔서 감사합니다. 이 프로젝트가 여러분이 자신만의 연결된 토양 분석기를 만드는 데 유용한 출발점이 되기를 바랍니다.

























