메이커 Maker

Arduino 토양 NPK 센서를 사용하여 토양 영양소 측정

지구빵집 2022. 2. 10. 09:26
반응형

 

 

이 튜토리얼에서는 토양 NPK 센서를 Arduino 보드와 인터페이스하고 토양에 존재하는 주요 토양 영양소 Nitrogen-N, Phosphorus-P 및 Potassium-K의 값을 측정하고 I2C 지원 및 직렬 모니터를 사용하여 OLED 디스플레이에 표시하는 방법을 배웁니다. 

 

NPK 값이란 무엇입니까? 식물을 모니터링하고 유지 관리하는 것이 왜 중요한가요?

 

토양의 NPK 값은 토양이나 기질에 질소, 인 및 칼륨이 얼마나 존재하는지 나타냅니다. 모든 식물에는 이 세 가지 필수 다량 영양소가 필요합니다. 식물의 필요에 따라 적절한 양의 외부 NPK 비료를 제공할 수 있으므로 토양 또는 기질의 NPK 값을 아는 것이 중요합니다. 

 

이 3가지 주요 영양소가 식물에 어떻게 도움이 되는지 분석해 보겠습니다.

 

  • N은 질소를 나타냅니다. 질소는 잎의 성장과 색깔이 좋은 식물의 성장에 필요합니다.
  • P는 인을 나타냅니다. 인은 뿌리 형성과 꽃과 열매 발달을 촉진합니다.
  • K는 칼륨을 나타냅니다. 칼륨은 식물의 물과 영양분 전달을 돕고 광합성을 돕습니다. 또한 질병에 대한 저항력을 높이고 건강한 뿌리 시스템을 지원합니다.

 

식물은 각 단계에서 이러한 영양소의 다른 양을 필요로 합니다. 식물에 충분한 양의 NPK 및 기타 영양소를 제공하는 것이 중요합니다. 그렇지 않으면 식물이 아래 이미지와 같이 결핍 증상을 보이기 시작할 수 있습니다. 

 

이미지 https://www.circuitschools.com/measure-soil-npk-values-using-soil-npk-sensor-with-arduino/

 

위의 이미지에서 옥수수 식물이 질소, 인, 칼륨과 같은 영양소 결핍으로 어떻게 변하는지 알 수 있습니다. 이들은 식물에 필수적인 영양소이므로 과량 또는 소량을 제공하면 식물이 손상될 수 있습니다.

 

과도한 양의 NPK를 제공하면 다음이 발생합니다.

 

  • 질소 : 과실과 꽃의 능력이 감소하면서 과도하게 성장하여 벌레를 유인하고 줄기의 강도를 감소시킨다.
  • 인: 토양에 존재하더라도 아연과 철과 적은 양의 미량 영양소를 흡수하는 능력을 감소시킵니다.
  • 칼륨: 질소, 마그네슘 및 칼슘과 같은 주요 영양소를 흡수할 수 없게 하여 결핍으로 이어집니다.

 

따라서 이러한 값을 모니터링하고 건강한 식물 성장을 위해 필요한 양의 NPK를 제공하는 것이 중요합니다. 따라서 이것을 고려하여 센서와 Arduino로 토양 NPK 모니터링 장치를 구축할 수 있습니다. 

 

Arduino 및 토양 NPK 센서를 사용한 DIY 토양 NPK 측정기  

 

목 차 

 

1 개요

2 BOM

3 토양 NPK 센서

3.1 사양

4 MAX485 TTL - RS-485 인터페이스 모듈

4.1 사양

4.2 핀아웃 및 모듈 연결

5 Arduino와 토양 NPK 센서 인터페이스

6 프로젝트 PCB 거버 파일 및 PCB 온라인 주문

7 NPK 센서용 Modbus 명령

7.1 1. 질소: {0x01,0x03, 0x00, 0x1e, 0x00, 0x01, 0xe4, 0x0c}

7.2 2. 인:{0x01,0x03, 0x00, 0x1f, 0x00, 0x01, 0xb5, 0xcc}

7.3 3. 칼륨:{0x01,0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xc0}

8 소스 코드/프로그램

9 OLED 디스플레이에서 토양 NPK 데이터 모니터링

10 비디오 튜토리얼 및 가이드 

 

개요

 

본 글에서는 토양 NPK 센서와 Arduino의 인터페이스에 대해 배우고 Arduino 토양 NPK 미터를 직접 제작합니다. NPK 토양 센서와 아두이노를 이용하여 토양 양분 함량을 쉽게 측정할 수 있습니다. 토양 함량 N(질소) , P(인) 및 K(칼륨)의 측정은 작물 비옥도를 높이기 위해 토양에 추가 영양소 함량을 결정하는 데 필요합니다.

 

토양 비옥도는 NPK 센서를 사용하여 감지됩니다. 토양 비료의 주요 구성 요소는 질소, 인 및 칼륨입니다. 토양 영양소 농도에 대한 지식은 식물 생산을 보증하는 데 사용되는 토양의 영양 결핍 또는 풍부에 대해 배우는 데 도움이 될 수 있습니다.

 

일부 광학 센서를 사용하거나 분광기를 사용하는 것과 같이 토양 영양소 함량을 측정하는 여러 방법이 있습니다. 그러나 스펙트럼 분석 방법은 편리하지 않고 데이터가 60-70% 만 정확하다는 단점이 있습니다. 스펙트럼 분석 방법을 기존 습식 화학 방법과 비교하는 동안 관련 데이터의 부족을 감안할 때 제품의 정확도는 아직 완전히 해결되지 않았습니다.

 

그래서 여기서는 JXCT 토양 NPK 센서를 사용하여 토양의 질소, 인 및 칼륨을 감지합니다. JXCT 토양 NPK 센서는 Modbus RS485와 함께 작동하는 저비용, 빠른 응답, 고정밀 및 휴대용 센서입니다. 기존의 감지 방법에 비해 이 센서의 장점은 매우 빠른 측정과 데이터가 매우 정확하다는 것입니다. 프로브를 토양에 삽입하고 Arduino를 사용하여 판독 값을 얻기만 하면 됩니다. 그럼 토양 NPK 센서와 아두이노의 인터페이스에 대해 자세히 알아보도록 하겠습니다. 

 

토양 영양소 연구에 도움이 될 수 있는 장치를 만드는 데 필요한 구성 요소는 다음과 같습니다. 아마존에서 거의 모든 구성 요소를 구입할 수 있습니다. 

 

부품 리스트

 

1. 아두이노 보드: 아두이노 나노

2. NPK 센서: JXCTIOT 토양 NPK 센서

3. OLED 디스플레이: 0.96" I2C OLED 디스플레이

4. 모드버스 모듈: MAX485 모드버스

5. 전원 공급 장치: 9V - 12V DC 공급

6. 연결 전선: 점퍼 와이어

7. 브레드보드 

 

토양 NPK 센서

 

토양 NPK 센서는 토양의 질소, 인 및 칼륨 함량을 감지하는 데 적합합니다. 토양의 비옥도를 결정하는 데 도움이 되므로 토양 상태의 체계적인 평가를 용이하게 합니다. 센서는 오랫동안 토양에 묻힐 수 있습니다. 그것은 프로브 부분의 장기간 작동을 보장하기 위해 고품질 프로브, 녹 저항 , 전해 저항 , 염 및 알칼리 내식성을 가지고 있습니다. 따라서 모든 종류의 토양에 적합합니다. 알칼리성 토양, 산성 토양, 기질 토양, 묘목 토양 및 코코넛 밀기울 토양의 검출에 적합합니다. 

 

토양 NPK 센서

 

센서에는 화학 시약 이 필요하지 않습니다. 측정 정확도가 높고 응답 속도가 빠르며 호환성이 우수하여 모든 마이크로 컨트롤러와 함께 사용할 수 있습니다. Modbus 통신 포트가 있으므로 마이크로 컨트롤러와 함께 센서를 직접 사용할 수 없습니다. 따라서 RS485/MAX485와 같은 Modbus 모듈이 필요하고 센서를 마이크로컨트롤러에 연결해야 합니다. 

 

센서는 9-24V 에서 작동하며 전력 소비는 매우 낮습니다. 센서의 정확도를 말하면서 최대 2% 이내입니다. 질소, 인 및 칼륨 측정 분해능은 최대 1mg/kg(mg/l) 입니다. 

 

토양 NPK 측정기

 

이 토양 NPK 센서를 사용하여 Arduino 토양 NPK 측정기 또는 클라우드 IoT 기반 토양 영양소 함량 모니터링 시스템을 만들 수 있습니다.

 

토양 NPK 센서 사양

 

1. 전력: 9V-24V

2. 측정 범위: 0-1999mg/kg(mg/l)

3. 작동 온도: 5-45°C

4. 분해능: 1mg/kg

5. 정밀도: ±2% FS

6. 출력 신호: RS485

7. 전송 속도: 2400/4800/9600

8. 보호 등급: IP68 

 

MAX485 TTL-RS-485 인터페이스 모듈

 

MAX485 TTL-RS-485 인터페이스 모듈을 사용하면 최대 1,200미터 또는 전기적으로 노이즈가 많은 환경에서 강력한 장거리 직렬 통신을 위해 RS-485 차동 신호를 사용할 수 있으며 산업 환경에서 일반적으로 사용됩니다. 최대 2.5MBit/Sec 의 데이터 전송률을 지원하지만 거리가 멀어질수록 지원 가능한 최대 데이터 전송률은 낮아집니다. 

 

MAX485 TTL-RS-485 인터페이스 모듈

 

데이터는 마이크로컨트롤러에 관한 한 일반적인 TTL 레벨 직렬로 시작하는 반면 RS-485 모듈 은 TTL과 RS-485에서 사용하는 차동 신호 간의 전기 신호 변환을 처리합니다. RS-485의 중요한 이점은 일반적으로 '멀티 드롭'이라고 하는 동일한 케이블에서 여러 장치 (최대 32개)를 지원한다는 것입니다. 

 

MAX 485 모듈 명세서

 

1. MAX485 인터페이스 칩 사용

2. 잡음 내성을 위해 차동 신호 사용

3. 최대 1,200미터 거리

4. 최대 2.5Mbit/초 속도

5. 멀티 드롭은 동일한 버스에서 최대 32개의 장치를 지원합니다.

6. 빨간색 전원 LED

7. 5V 작동 

 

MAX485 모듈 핀아웃 및 모듈 연결

 

MAX485 모듈은 양쪽에 8핀 4핀이 있습니다. 이름이 있는 모든 핀을 표시하는 핀 배치 다이어그램의 아래 이미지를 확인하십시오. 

 

MAX485 모듈 핀 배치 다이어그램

 

왼쪽 4 Pin 구성 

 

  • 수신기 출력(RO): 신호를 출력하는 RX에 연결해야 합니다.
  • Receiver Enable(RE): 이것은 기본적으로 활성 LOW이며 마이크로컨트롤러의 디지털 핀을 통해 수신기 구동 HIGH를 활성화합니다.
  • 드라이버 활성화(DE): 이것은 기본적으로 활성 HIGH이며 일반적으로 RE 핀으로 점퍼로 연결합니다.
  • 드라이버 입력(DI): 데이터를 입력으로 받기 때문에 마이크로컨트롤러의 TX에 연결해야 합니다. 

 

오른쪽 4핀과 나사 핀 구성 

 

  • VCC: 5v 전원 공급 장치에 연결해야 합니다.
  • B: 데이터 'B'에 대한 반전된 라인. 또한 그림과 같이 나사 핀에 연결합니다.
  • A: 데이터 A의 반전되지 않은 선입니다. 또한 이미지와 같이 나사 핀에 연결합니다.
  • GND: 접지. 

 

Arduino와 토양 NPK 센서 인터페이스 

 

이제 MAX485 Modbus 모듈을 사용하여 토양 NPK 센서를 Arduino Nano 보드와 인터페이스해 보겠습니다. 아래의 연결 다이어그램을 확인하십시오. 

 

Arduino와 토양 NPK 센서 인터페이스

 

소프트웨어 직렬을 사용하여 Modbus의 R0 및 DI 핀을 D2 및 D3 Arduino에 연결합니다. 마찬가지로 DE & RE를 높게 활성화해야 합니다. 이렇게 하려면 DE 및 RE 핀을 Arduino의 D7 및 D8 핀에 연결합니다. NPK 센서에는 4개의 와이어가 있습니다. 갈색 은 9V-24V 전원 공급 장치가 필요한 VCC입니다. 색상이 검은 색인 GND 핀입니다. 따라서 Arduino의 GND에 연결하십시오. B 핀인 파란색 선 은 MAX485의 B 핀에 연결되고 A 핀인 노란색 선은 MAX485 의 A 핀에 연결됩니다. 

 

Arduino와 토양 NPK 센서 인터페이스 

 

0.96″ SSD1306 OLED 디스플레이는 I2C 모듈입니다. OLED 디스플레이 VCC 및 GND 핀을 Arduino의 3.3V 및 GND에 연결합니다. 마찬가지로 SDA 및 SCL 핀을 Arduino의 A4 및 A5에 연결합니다. 회로도를 따라 브레드보드에 회로를 조립하거나 맞춤형 PCB를 만들 수 있습니다. 

 

NPK 센서용 Modbus 명령

 

Modbus 명령은 Modbus 장치에 다음을 지시할 수 있습니다.

 

1. 코일 및 홀딩 레지스터에 기록되는 레지스터 중 하나의 값 변경

2. I/O 포트 읽기: 개별 및 코일 포트에서 데이터 읽기

3. 장치에 명령 코일 및 홀딩 레지스터에 포함된 하나 이상의 값을 다시 보내기 위해

 

Modbus 명령에는 해당 장치의 Modbus 주소가 포함됩니다( 1 ~ 247 ). Modbus 주소는 조회 프레임 이라고도 합니다. 다른 장치가 명령을 수신하더라도 주소 지정된 장치만 명령에 응답하고 작동합니다.

 

NPK 센서에는 질소(N), 인(P) 및 칼륨(K) 값을 읽기 위한 3가지 다른 조회 프레임이 있습니다. 문의 프레임은 사용 설명서와 함께 제공됩니다. NPK 데이터의 경우 다음과 같은 개별 문의 데이터 포맷을 사용합니다.

 

1. 질소: {0x01,0x03, 0x00, 0x1e, 0x00, 0x01, 0xe4, 0x0c}

토양 질소 값을 얻기 위한 조회 프레임은 다음과 같습니다. 

 

응답으로 다음을 받게 됩니다.

 

받은 응답에서 토양 질소를 계산할 수 있습니다. 예를 들어, 응답으로 0030을 얻은 경우 토양 질소 값은 다음과 같습니다.

0020 H(16진수) = 32(10진수) => 질소 = 32mg/kg

 

2. 인: {0x01,0x03, 0x00, 0x1f, 0x00, 0x01, 0xb5, 0xcc}

토양의 인 값을 얻기 위한 조회 데이터 프레임은 다음과 같습니다. 

 

응답으로 다음을 받게 됩니다.

 

 

받은 응답에서 토양의 인을 계산할 수 있습니다. 예를 들어, 응답으로 0030을 얻은 경우 토양 질소 값은 다음과 같습니다.

 

0025 H(16진수) = 37(10진수) => 인 = 37/kg

 

3. 칼륨: {0x01,0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xc0}

토양 칼륨 값을 얻기 위한 조회 프레임은 다음과 같습니다. 

 

응답으로 다음을 받게 됩니다.

 

 

받은 응답에서 토양 칼륨을 계산할 수 있습니다. 예를 들어, 응답으로 0030을 받으면 토양 칼륨 값은 다음과 같습니다.

 

0030 H(16진수) = 48(10진수) => 칼륨 = 48mg/kg

 

소스 코드/프로그램

 

토양 NPK 센서를 Arduino와 인터페이스하고 Modbus 명령을 통해 센서에서 토양 영양소 값을 검색하는 소스 코드는 다음과 같습니다. 명령을 보내고 HEX 코드의 값을 검색할 수 있습니다. 측정된 토양 영양소 데이터를 얻으려면 HEX 코드를 10진수로 변환해야 합니다.

 

우리는 OLED 디스플레이를 사용하여 토양 영양소 값( 질소, 인 및 칼륨 )을 mg/kg 단위로 표시하기 때문에 OLED 라이브러리가 필요합니다. 다음 OLED 라이브러리를 다운로드하여 Arduino IDE에 추가하십시오.

 

1. Adafruit SSD1306 라이브러리 : 다운로드

2. Adafruit GFX 라이브러리 : 다운로드

 

다음은 전체 소스 코드입니다. 코드를 컴파일하고 Arduino Nano 보드에 업로드하십시오. 

 

#include <SoftwareSerial.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
 
#define SCREEN_WIDTH 128    // OLED display width, in pixels
#define SCREEN_HEIGHT 64    // OLED display height, in pixels
#define OLED_RESET -1       // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
 
#define RE 8
#define DE 7
 
//const byte code[]= {0x01, 0x03, 0x00, 0x1e, 0x00, 0x03, 0x65, 0xCD};
const byte nitro[] = {0x01,0x03, 0x00, 0x1e, 0x00, 0x01, 0xe4, 0x0c};
const byte phos[] = {0x01,0x03, 0x00, 0x1f, 0x00, 0x01, 0xb5, 0xcc};
const byte pota[] = {0x01,0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xc0};
 
byte values[11];
SoftwareSerial mod(2,3);
 
void setup() {
  Serial.begin(9600);
  mod.begin(9600);
  pinMode(RE, OUTPUT);
  pinMode(DE, OUTPUT);
  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //initialize with the I2C addr 0x3C (128x64)
  delay(500);
  display.clearDisplay();
  display.setCursor(25, 15);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.println(" NPK Sensor");
  display.setCursor(25, 35);
  display.setTextSize(1);
  display.print("Initializing");
  display.display();
  delay(3000);
}
 
void loop() {
  byte val1,val2,val3;
  val1 = nitrogen();
  delay(250);
  val2 = phosphorous();
  delay(250);
  val3 = potassium();
  delay(250);
  
  
  Serial.print("Nitrogen: ");
  Serial.print(val1);
  Serial.println(" mg/kg");
  Serial.print("Phosphorous: ");
  Serial.print(val2);
  Serial.println(" mg/kg");
  Serial.print("Potassium: ");
  Serial.print(val3);
  Serial.println(" mg/kg");
  delay(2000);
 
  display.clearDisplay();
  
 
  display.setTextSize(2);
  display.setCursor(0, 5);
  display.print("N: ");
  display.print(val1);
  display.setTextSize(1);
  display.print(" mg/kg");
 
  display.setTextSize(2);
  display.setCursor(0, 25);
  display.print("P: ");
  display.print(val2);
  display.setTextSize(1);
  display.print(" mg/kg");
 
  display.setTextSize(2);
  display.setCursor(0, 45);
  display.print("K: ");
  display.print(val3);
  display.setTextSize(1);
  display.print(" mg/kg");
 
  display.display();
}
 
byte nitrogen(){
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(10);
  if(mod.write(nitro,sizeof(nitro))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    //Serial.print(mod.read(),HEX);
    values[i] = mod.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}
 
byte phosphorous(){
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(10);
  if(mod.write(phos,sizeof(phos))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    //Serial.print(mod.read(),HEX);
    values[i] = mod.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}
 
byte potassium(){
  digitalWrite(DE,HIGH);
  digitalWrite(RE,HIGH);
  delay(10);
  if(mod.write(pota,sizeof(pota))==8){
    digitalWrite(DE,LOW);
    digitalWrite(RE,LOW);
    for(byte i=0;i<7;i++){
    //Serial.print(mod.read(),HEX);
    values[i] = mod.read();
    Serial.print(values[i],HEX);
    }
    Serial.println();
  }
  return values[4];
}

 

*참고: 이 코드는 최대 255mg/kg의 토양 NPK 값을 측정할 수 있는 유일한 것입니다. 8비트 값만 읽기 때문입니다. 센서의 데이터 시트에 따르면 최대 1999mg/kg까지 측정할 수 있습니다. 이러한 값을 읽으려면 16비트 데이터를 읽어야 합니다. 이러한 높은 값을 읽으려면 토양 EC 센서 코드를 참조하십시오 

 

아래는 구성은 동일하지만 회로 설계를 변경하여 구현한 참고 코드입니다. 위의 참고 코드와는 약간 다르니 참고용으로 포함합니다. 굳이 참고할 필요는 없습니다.

 

#include <bluefruit.h>
#include <stdio.h>
#include <stdlib.h>


int CRC16_MODBUS (const uint8_t *nData, uint16_t wLength) { 
 static const uint16_t wCRCTable[] = {                             // <<== 2022.02.05 추가 (죄송합니다.~ㅠㅠ)
 0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241, 
 0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440, 
 0XCC01, 0X0CC0, 0X0D80, 0XCD41, 0X0F00, 0XCFC1, 0XCE81, 0X0E40, 
 0X0A00, 0XCAC1, 0XCB81, 0X0B40, 0XC901, 0X09C0, 0X0880, 0XC841, 
 0XD801, 0X18C0, 0X1980, 0XD941, 0X1B00, 0XDBC1, 0XDA81, 0X1A40, 
 0X1E00, 0XDEC1, 0XDF81, 0X1F40, 0XDD01, 0X1DC0, 0X1C80, 0XDC41, 
 0X1400, 0XD4C1, 0XD581, 0X1540, 0XD701, 0X17C0, 0X1680, 0XD641, 
 0XD201, 0X12C0, 0X1380, 0XD341, 0X1100, 0XD1C1, 0XD081, 0X1040, 
 0XF001, 0X30C0, 0X3180, 0XF141, 0X3300, 0XF3C1, 0XF281, 0X3240, 
 0X3600, 0XF6C1, 0XF781, 0X3740, 0XF501, 0X35C0, 0X3480, 0XF441, 
 0X3C00, 0XFCC1, 0XFD81, 0X3D40, 0XFF01, 0X3FC0, 0X3E80, 0XFE41, 
 0XFA01, 0X3AC0, 0X3B80, 0XFB41, 0X3900, 0XF9C1, 0XF881, 0X3840, 
 0X2800, 0XE8C1, 0XE981, 0X2940, 0XEB01, 0X2BC0, 0X2A80, 0XEA41, 
 0XEE01, 0X2EC0, 0X2F80, 0XEF41, 0X2D00, 0XEDC1, 0XEC81, 0X2C40, 
 0XE401, 0X24C0, 0X2580, 0XE541, 0X2700, 0XE7C1, 0XE681, 0X2640, 
 0X2200, 0XE2C1, 0XE381, 0X2340, 0XE101, 0X21C0, 0X2080, 0XE041, 
 0XA001, 0X60C0, 0X6180, 0XA141, 0X6300, 0XA3C1, 0XA281, 0X6240, 
 0X6600, 0XA6C1, 0XA781, 0X6740, 0XA501, 0X65C0, 0X6480, 0XA441, 
 0X6C00, 0XACC1, 0XAD81, 0X6D40, 0XAF01, 0X6FC0, 0X6E80, 0XAE41, 
 0XAA01, 0X6AC0, 0X6B80, 0XAB41, 0X6900, 0XA9C1, 0XA881, 0X6840, 
 0X7800, 0XB8C1, 0XB981, 0X7940, 0XBB01, 0X7BC0, 0X7A80, 0XBA41, 
 0XBE01, 0X7EC0, 0X7F80, 0XBF41, 0X7D00, 0XBDC1, 0XBC81, 0X7C40, 
 0XB401, 0X74C0, 0X7580, 0XB541, 0X7700, 0XB7C1, 0XB681, 0X7640, 
 0X7200, 0XB2C1, 0XB381, 0X7340, 0XB101, 0X71C0, 0X7080, 0XB041, 
 0X5000, 0X90C1, 0X9181, 0X5140, 0X9301, 0X53C0, 0X5280, 0X9241, 
 0X9601, 0X56C0, 0X5780, 0X9741, 0X5500, 0X95C1, 0X9481, 0X5440, 
 0X9C01, 0X5CC0, 0X5D80, 0X9D41, 0X5F00, 0X9FC1, 0X9E81, 0X5E40, 
 0X5A00, 0X9AC1, 0X9B81, 0X5B40, 0X9901, 0X59C0, 0X5880, 0X9841, 
 0X8801, 0X48C0, 0X4980, 0X8941, 0X4B00, 0X8BC1, 0X8A81, 0X4A40, 
 0X4E00, 0X8EC1, 0X8F81, 0X4F40, 0X8D01, 0X4DC0, 0X4C80, 0X8C41, 
 0X4400, 0X84C1, 0X8581, 0X4540, 0X8701, 0X47C0, 0X4680, 0X8641, 
 0X8201, 0X42C0, 0X4380, 0X8341, 0X4100, 0X81C1, 0X8081, 0X4040 };

 uint8_t nTemp; 
 uint16_t wCRCWord = 0xFFFF; 

   while (wLength--) 
   { 
      nTemp = *nData++ ^ wCRCWord; 
      wCRCWord >>= 8; 
      wCRCWord ^= wCRCTable[nTemp]; 
   } 
   return wCRCWord; 
}


//#define PIN_SERIAL1_RX       (24)
//#define PIN_SERIAL1_TX       (0)

#include "Uart.h"
unsigned char tmp[10];
char tmprx[10];
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
   Serial.begin(9600);
  while ( !Serial ) delay(10);   // for nrf52840 with native usb


  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);  
  
  digitalWrite(12, LOW);
  digitalWrite(13, LOW);
  
  Serial1.begin(9600);
  Serial.print("start....\r\n");

  tmp[0]=0x01;
  tmp[1]=0x03;
  tmp[2]=0x00;
  tmp[3]=0x1e;
  tmp[4]=0x00;
  tmp[5]=0x01;
  tmp[6]=0xe4;
  tmp[7]=0x0c;
  
}
void set_rx()
{
  digitalWrite(12, LOW);
  digitalWrite(13, LOW);
}

void set_tx()
{
  digitalWrite(12, HIGH);
  digitalWrite(13, HIGH);
}

void set_led_on()
{
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
}

void set_led_off()
{
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
}

void loop() {
  Serial.printf("start ...\r\n");
  set_led_on();
  set_tx();
  delay(100);                       // wait for a second
  
  
   union { unsigned short a; 
  unsigned char b[2]; 
 }val; 
 val.a = CRC16_MODBUS(tmp, 6); 
  
  Serial.printf("send add:%x  crc: %x %x", tmp[0],val.b[0], val.b[1]);
  Serial1.write(tmp,8);
  
  delay(10);                       // wait for a second

  set_led_off();
  set_rx();

  for(int i=0;i<8;i++)
  {
    tmprx[0]=Serial1.read();
    if(tmprx[0] != 0xff )  Serial.printf("\nreceived : 0x%x ",tmprx[0]);
    //else Serial.printf(".");
   delay(10);  
  }

  Serial.printf("\r\n end ----------------------------------- \r\n");

}

 

OLED 디스플레이에서 토양 NPK 데이터 모니터링

 

Arduino Nano Board에 코드를 업로드하면 센서와 함께 OLED가 초기화됩니다. 센서가 안정되기까지 시간이 걸리며 처음에는 판독 값이 정확하지 않을 수 있습니다.

 

센서가 안정되면 센서를 토양에 담그면 NPK 판독 값을 얻을 수 있습니다. 토양의 암모늄 함량인 질소, 인 및 칼륨의 부피는 mg/Kg으로 표시됩니다. 

 

이것이 토양 영양 센서 Arduino를 인터페이스하고 NPK 판독 값을 얻는 방법입니다. 유사하게, 센서를 다른 토양 샘플에 넣습니다. 토양의 종류에 따라 NPK의 부피가 변하는 것을 볼 수 있습니다. 

 

토양 NPK를 측정하는 것 외에도 토양 수분 센서를 사용하여 토양 수분 함량 , 토양 pH 센서를 사용하는 토양 pH 및 토양 EC 센서를 사용하여 토양 EC 및 염분을 측정할 수 있습니다.

 

따라서 위의 가이드를 사용하여 Arduino 토양 NPK 측정기를 만들고 토양의 비옥도를 결정할 수 있습니다. 이 프로젝트의 고급 버전을 확인할 수도 있습니다. 고급 버전에서는 토양 NPK 센서, 온도 센서 및 토양 수분 센서를 Arduino와 결합할 수 있습니다. IoT 기반 토양 영양소 모니터링하는 방법도 참고하세요.

 

 

참고

본 문서 참고자료 - Arduino 및 토양 NPK 센서를 사용하여 토양 영양소 측정 

IoT Based Soil Nutrient Monitoring with Arduino & ESP32 

DIY Soil Ph Meter using Soil Ph Sensor & Arduino 

Interface Capacitive Soil Moisture Sensor v1.2 with Arduino 

상세 설명 Measure Soil NPK value using Soil NPK Sensor with Arduino 

 

 

반응형