เซ็นเซอร์วัดความชื้นในดิน Capacitive I2C soil moisture sensor


(Permpol Thanapunnamas) #1

I2C soil moisture sensor เป็นเซนเซอร์วัดความชื้นในดินแบบ Capacitive ที่ได้รับการปรับปรุงจากต้นแบบเดิมที่เป็นแบบอ่านค่าจากความต้านทาน (Resister) หลักการคือใช้แผ่นทองแดงไปสัมผัสกับดินโดยตรง ทำให้มีข้อเสียบางประการคือ หัววัดหมดสภาพง่ายและเป็นสนิม ทำให้ได้ค่าความชื้นคลาดเคลื่อนได้

แต่เซนเซอร์วัดความชื้นในดินแบบ Capacitive ใช้หลักที่แตกต่างออกไปคือ การตรวจสอบประจุของวัสดุ ค่าประจุแปรผันตรงกับค่าความชื้น ถ้ามีค่าประจุมาก ค่าความชื้นมากตามไปด้วย เนื่องจากการใช้วิธีวัดประจุ ทำให้แผ่นเซนเซอร์ไม่ต้องสัมผัสโดยตรงกับดิน จึงทนทานและแม่นยำกว่า

โมดูลรุ่นนี้ ให้ค่าออกเป็นค่า Analog นำไปใช้ต่อกับบอร์ดจะได้ค่าระหว่าง 0 - 614 สามารถนำค่านี้ไปใช้ได้ทันที

ข้อมูลเชิงเทคนิค

The sensor can be read via I2C protocol and provides these features:

  • Soil moisture sensing
  • Light sensing
  • Reset chip
  • I2C address change
  • Deep sleep

This is the second version of my sensor with some improvements:

  • 16MHz crystal for better repeatability and better Raspberry Pi support

  • Thermistor for accurate temperature measurements

  • Increased moisture reading resolution (almost double!)

  • Holes to fasten a cable with a zip-tie

  • Version 2.7.5

  • Supply voltage 3.3V - 5V

  • Current consumption: 1.1mA @ 5V, 0.7mA @ 3.3V when idle, 14mA @ 5V, 7.8mA @ 3.3V when taking a measurement. When constantly polling sensor at full speed, current consumption averages to 4.5mA @ 5V, 2.8mA @ 3.3V

  • Operating temperature 0°C - 85°C

  • Moisture reading drift with temperature - <10% over full temp range

  • Don’t forget to provide pullups for SCL and SDA lines

  • Default I2C address is 0x20 (hex)

  • To read soil moisture, read 2 bytes from register 0

  • To read light level, start measurement by writing 3 to the device I2C address, wait for 3 seconds, read 2 bytes from register 4

  • To read temperature, read 2 bytes from register 5

  • To change the I2C address of the sensor, write a new address (one byte [1…127]) to register 1; the new address will take effect after reset

  • To reset the sensor, write 6 to the device I2C address.

  • Do not hotplug the sensor into the active I2C bus - address change command has no protection and this might result in a random number set as an address of the sensor. Use I2C scan sketch to find out the address if the sensor stops responding with proper values.

How to interpret the readings

Both light and moisture sensors give relative values. Meaning, more moisture will give you higher reading, more light, lower reading.

Moisture is somewhat linear. I test all sensors before shipping and they give about 290 - 310 in free air at 5V supply.

I didn’t measure linearity of the light sensor, it gives 65535 in a dark room away form desk lamp. When it’s dark, it takes longer to measure light, reading the light register while measurement is in progress will return the previous reading. Be aware, light sensor is pretty noisy.

Temperature is measured by the thermistor on the body of the sensor. Calculated absolute measurement accuracy is better than 2%. The returned value is in tenths of degrees Celsius. I.e. value 252 would mean 25.2°C.

Note Upon reading the moisture or temperature value, a value form the previous read command is returned and the new measurement is started. If you do rare measurements and want to act instantly, do two consecutive readings to get the most up to date data. Also you can read GET_BUSY register via i2c - it will indicate when the measurement is done. Basically the process goes like this: read from GET_CAPACITANCE, discard results, then read from GET_BUSY until you get ‘0’ as an answer, then read form GET_CAPACITANCE again - the returned value is the soil moisture NOW.

ซัพพอต Controller

The sensor works fine with Arduino and RaspberryPi. Examples are available on github page.

Thanks guys for writing this software, open source yay!

image

Code สำหรับนำไปใช้กับ Arduino หรือ ESP8266

#include <Wire.h>

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

void writeI2CRegister8bit(int addr, int value) {
  Wire.beginTransmission(addr);
  Wire.write(value);
  Wire.endTransmission();
}

unsigned int readI2CRegister16bit(int addr, int reg) {
  Wire.beginTransmission(addr);
  Wire.write(reg);
  Wire.endTransmission();
  delay(1100);
  Wire.requestFrom(addr, 2);
  unsigned int t = Wire.read() << 8;
  t = t | Wire.read();
  return t;
}

void loop() {
  Serial.print(readI2CRegister16bit(0x20, 0)); //read capacitance register
  writeI2CRegister8bit(0x20, 3); //request light measurement 
  delay(9000);                   //this can take a while
  Serial.print(", ");
  Serial.println(readI2CRegister16bit(0x20, 4)); //read light register
  delay(500);
}