Example Code for Arduino-Read EC and PH

This project demonstrates how to use the RS485 Soil Sensor (EC&PH) with Arduino UNO R3 to read real-time soil EC and PH values and print them to the Arduino IDE serial monitor. Users will learn how to establish RS485 communication using the ModBus-RTU protocol, send query frames to the sensor, receive and parse response frames, and convert raw data into readable EC and PH values.

Hardware Preparation

Name Model/SKU Quantity Purchase Link
DFRduino UNO R3 DFRduino UNO R3 1 Buy Now
RS485 Shield for Arduino RS485 Shield for Arduino 1 Buy Now
RS485 Soil Sensor(EC&PH) SEN0603 1 Buy Now

Software Preparation

Wiring Diagram

Arduino Wiring diagram

Other Preparation Work

  1. Before uploading the code to Arduino UNO R3, set the RS485 Shield's transceiver mode switch to AUTO and the run/compile switch to OFF.
  2. After uploading the code, set the run/compile switch to ON.
  3. When opening the Arduino IDE serial monitor, select the baud rate to 9600.

Sample Code

uint8_t Com[8] = { 0x01, 0x03, 0x00, 0x00, 0x00, 0x04, 0x44, 0x09 };
float ph;
int ec;
void setup() {
  Serial.begin(9600);  
}
void loop() {
  readECPH();
  Serial.print("EC = ");
  Serial.print(ec, 1);
  Serial.print(" us/cm ");
  Serial.print("PH = ");
  Serial.println(ph, 1);
  delay(1000);
}
void readECPH(void) {
  uint8_t Data[13] = { 0 };
  uint8_t ch = 0;
  bool flag = 1;
  while (flag) {
    delay(100);
    Serial.write(Com, 8);
    delay(10);
    if (readN(&ch, 1) == 1) {
      if (ch == 0x01) {
        Data[0] = ch;
        if (readN(&ch, 1) == 1) {
          if (ch == 0x03) {
            Data[1] = ch;
            if (readN(&ch, 1) == 1) {
              if (ch == 0x08) {
                Data[2] = ch;
                if (readN(&Data[3], 10) == 10) {
                  if (CRC16_2(Data, 11) == (Data[11] * 256 + Data[12])) {
                    ec = Data[7] * 256 + Data[8];
                    ph = (Data[9] * 256 + Data[10]) /10.00;
                    flag = 0;
                  }
                }
              }
            }
          }
        }
      }
    }
    Serial.flush();
  }
}

uint8_t readN(uint8_t *buf, size_t len) {
  size_t offset = 0, left = len;
  int16_t Tineout = 500;
  uint8_t *buffer = buf;
  long curr = millis();
  while (left) {
    if (Serial.available()) {
      buffer[offset] = Serial.read();
      offset++;
      left--;
    }
    if (millis() - curr > Tineout) {
      break;
    }
  }
  return offset;
}

unsigned int CRC16_2(unsigned char *buf, int len) {
  unsigned int crc = 0xFFFF;
  for (int pos = 0; pos < len; pos++) {
    crc ^= (unsigned int)buf[pos];
    for (int i = 8; i != 0; i--) {
      if ((crc & 0x0001) != 0) {
        crc >>= 1;
        crc ^= 0xA001;
      } else {
        crc >>= 1;
      }
    }
  }

  crc = ((crc & 0x00ff) << 8) | ((crc & 0xff00) >> 8);
  return crc;
}

Result

Insert the soil sensor into the soil (ensure the stainless steel probe is fully buried), open the Arduino IDE serial monitor, and you will see the real-time EC and PH values printed as follows:

Was this article helpful?

TOP