Connecting a low cost TDR moisture content/EC/temp sensor to a NodeMCUv3

linkedinrssyoutubeinstagram
image_pdfimage_print

I have discussed moisture content sensors extensively in the past. I have written posts about the use of capacitive moisture sensors to measure volumetric moisture content, including how to create sensor stations and how to calibrate them. However, while capacitive moisture content sensors can be a low cost alternative for low resolution monitoring of moisture content, more precise applications require the use of higher accuracy sensors, such as Time Domain Reflectometry (TDR) sensors. In this post I am going to show you how to connect a low cost microcontroller (NodeMCUv3) to a low cost TDR moisture content sensor. Note, some of the product links below are amazon affiliate links, which help support this blog at no additional cost to you.

Diagram showing cable connections between moisture content sensor NodeMCUv3 and communication board.

While popular sensors like Teros-12 sensors cost hundreds of dollars, lower cost alternatives have been created by Chinese manufacturers. Using this github repository by git user Kromadg, I have been able to interface some of these low cost TDR sensors with a NodeMCUv3. The NodeMCUv3 is a very low cost microcontroller unit that you can get for less than 5 USD a piece. It is also WiFi enabled, so this project can be expanded to send data through Wifi to use in datalogging or control applications. For this project you will need the following things:

  1. Micro USB cable
  2. NodeMCUv3
  3. THC-S RS485 sensor (Make sure to get the THC-S model)
  4. TTL to RS485 communication board
  5. Breadboard and jumper cables to make connections or cables and a soldering kit to make final connections.

The above diagram shows you how to connect the sensor, TTL-to-RS485 communication board and the NodeMCUv3. You will also want to make sure you install the ESP Software serial library in your Arduino IDE, as the normal Software Serial library won’t work. You can do this by downloading the zipped library from github and then using the Sketch->Include Library menu option. Once you do so, you can upload the following code into your NodeMCUv3.

#include <SoftwareSerial.h>
#include <Wire.h>

// This code is a modification of the code found here (https://github.com/kromadg/soil-sensor)

#define RE D2
#define DE D3

const byte hum_temp_ec[8] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x03, 0x05, 0xCB};
byte sensorResponse[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
byte sensor_values[11];

SoftwareSerial mod(D6, D5); // RX, TX

void setup() {
    Serial.begin(115200);
    pinMode(RE, OUTPUT);
    pinMode(DE, OUTPUT);
    digitalWrite(RE, LOW);
    digitalWrite(DE, LOW);
    delay(1000);
    mod.begin(4800);
    delay(100);
}

void loop() {
    /************** Soil EC Reading *******************/
    digitalWrite(DE, HIGH);
    digitalWrite(RE, HIGH);
    memset(sensor_values, 0, sizeof(sensor_values));
    delay(100);
    
    if (mod.write(hum_temp_ec, sizeof(hum_temp_ec)) == 8) {
        digitalWrite(DE, LOW);
        digitalWrite(RE, LOW);
        for (byte i = 0; i < 12; i++) {
            sensorResponse[i] = mod.read();
            yield();
        }
    }

    delay(250);

    // get sensor response data
    float soil_hum = 0.1 * int(sensorResponse[3] << 8 | sensorResponse[4]);
    float soil_temp = 0.1 * int(sensorResponse[5] << 8 | sensorResponse[6]);
    int soil_ec = int(sensorResponse[7] << 8 | sensorResponse[8]);

    /************* Calculations and sensor corrections *************/

    float as_read_ec = soil_ec;

    // This equation was obtained from calibration using distilled water and a 1.1178mS/cm solution.
    soil_ec = 1.93*soil_ec - 270.8;
    soil_ec = soil_ec/(1.0+0.019*(soil_temp-25));

    // soil_temp was left the same because the Teros and chinese sensor values are similar

    // quadratic aproximation
    // the teros bulk_permittivity was calculated from the teros temperature, teros bulk ec and teros pwec by Hilhorst 2000 model
    float soil_apparent_dieletric_constant = 1.3088 + 0.1439 * soil_hum + 0.0076 * soil_hum * soil_hum;

    float soil_bulk_permittivity = soil_apparent_dieletric_constant;  /// Hammed 2015 (apparent_dieletric_constant is the real part of permittivity)
    float soil_pore_permittivity = 80.3 - 0.37 * (soil_temp - 20); /// same as water 80.3 and corrected for temperature

    // converting bulk EC to pore water EC
    float soil_pw_ec;
    if (soil_bulk_permittivity > 4.1)
        soil_pw_ec = ((soil_pore_permittivity * soil_ec) / (soil_bulk_permittivity - 4.1) / 1000); /// from Hilhorst 2000.
    else
        soil_pw_ec = 0;

    Serial.print("Humidity:");
    Serial.print(soil_hum);
    Serial.print(",");
    Serial.print("Temperature:");
    Serial.print(soil_temp);
    Serial.print(",");
    Serial.print("EC:");
    Serial.print(soil_ec);
    Serial.print(",");
    Serial.print("READEC:");
    Serial.print(as_read_ec);
    Serial.print(",");
    Serial.print("pwEC:");
    Serial.print(soil_pw_ec);
    Serial.print(",");
    Serial.print("soil_bulk_permittivity:");
    Serial.println(soil_bulk_permittivity);
    delay(5000);
}

Note that RE and DE are not placed on digital pins 2 and 3, as other pins in the NodeMCUv3 carry out other functions and the board will not initialize if it has the RS485-to-TTL communicator connected through those pins. The R0 and RI pins are connected to digital pins D5 and D6, this is because in the NodeMCUv3 pins D7 and D8 are used in serial communication by the Serial swap command and therefore create conflicts if you use them with SoftwareSerial. The above digital pin distribution is one of the few that works well. Note that connecting RE or DE to digital pin 4 also works, but this means the blue LED on the NodeMCUv3 is powered on every time there is serial communication, a potentially undesirable effect if you’re interested in battery powering the device.

The board should now be printing all the measurements on your serial connection, so you should be able to see the readings through the Serial Monitor in the Arduino IDE. In the future I will be sharing how to expand this code to include WiFi and MQTT communication with a MyCodo server.

If you use this code please share your experience in the comments below!

Facebooktwitterredditpinterestlinkedin

23 Comments

  • hyunchul.choe
    April 4, 2023 @ 2:04 am

    Hi,

    It was good information for soil sensor on NodeMCUv3 board.
    It it useful information.

    And could i ask power voltage connection ?
    It looks required external power for soil sensor. So Did you connect to VIn by external power battery as 9 ~ 24v ?

    Thank’s

    • admin
      April 4, 2023 @ 2:29 pm

      No external power is required for the sensor. It uses the same supply as the NodeMCUv3, it runs fine at 5V.

  • Gitpud
    April 6, 2023 @ 11:31 pm

    I’m not sure if my comment went through, but hello!

    Thank you for making this guide, it helped me quite a bit! I updated the code with newer formulas and calculations and tailored it more towards rockwool. I am a novice programmer and this is my first time working with a microcontroller, so it was exciting. Please check out my code: https://github.com/Gitpud/TDR-Sensor

    I added WiFi/MQTT communcation but have yet to test it as i do not have a MQTT or Mycodo server setup yet.

    • HB
      May 3, 2023 @ 5:28 am

      Thanks for adding the MQTT server and WiFi, did you mange to test it yet?

  • HB
    May 3, 2023 @ 5:26 am

    Thank you for doing this

    I have connected the sensor to the NodeMcu board and uploaded the code provided. I can monitor the outut in the Arduino serial monitor but the readings don’t look correct and don’t change. eg Humidity:6553.50,Temperature:6553.50,EC:1009,READEC:65535.00,pwEC:-0.01,soil_bulk_permittivity:327351.91

    This is with the sensor inside wet coco.

    Any ideas ?

    Thanks

    • admin
      May 3, 2023 @ 1:41 pm

      Thanks for writing. These are the reading you get when the sensor is not getting enough current. I suggest changing your Arduino’s power supply to something with a better current capacity. Adding a 1000uF capacitor between ground and VCC can also help solve this problem.

      • HB
        May 3, 2023 @ 2:28 pm

        Thanks for getting back to me and I have managed to get it working. A wire was loose and also after reseting the board i can view the data in Arduino serial monitor.

        I am now trying to get the other code to work that’s linked in the other comment. The wifi and MQTT have been added but I’m receiving a CRC check failed in the Arduino serial monitor after uploading the new code. Any help would be much appreciated, Thanks.

      • HB
        May 6, 2023 @ 6:10 am

        I have the sensor working now and sending data via MQTT to my Home Assistant server. I have used the code in the Github project linked from Gitpud (version without CRC check) and I have implemented the original formulas for calculating pore water Ec etc that are listed in the code above. If anyone can help updating the formulas used by Gitpud to be calibrated for a soilless medium that would be helpful as I would struggle to do it myself.

  • AS
    July 1, 2023 @ 4:48 pm

    This was my first aurduino project, and I found success after looking at a lot of references pages. Keen to get these on the Wi-Fi network and add battery packs to cut the cords.

  • Mrgreengenes
    December 18, 2023 @ 9:07 am

    Great info. Going to give this build a try! Ty…

  • jon
    December 29, 2023 @ 5:22 pm

    could this continuously monitor a reservoir? or would you run into isolation issues? seems like a potentially cost effective way.

    • admin
      January 12, 2024 @ 4:19 am

      You cannot use this to monitor a reservoir, these are meant for media monitoring.

  • Sam
    January 24, 2024 @ 10:12 am

    Thanks for putting this information together. I’ve got this assembled and integrated into Home Assistant. I popped the microusb connector off of the nodemcu twice during assembly, it’s very fragile.

    • admin
      January 24, 2024 @ 2:36 pm

      Thanks for sharing your experience!

  • BS
    January 30, 2024 @ 1:01 pm

    I bought 2 of these sensors months ago and just yesterday got around to connecting one. I didn’t use an Arduino and just connected it to my laptop with a random usb->485 adapter and I’m currently powering it with a separate 5v power supply. This seems to work fine, I suspect the “use exactly this 485 device” has more to do with the microcontroller software uart than the sensor.

    I rewrote the code above in python, mostly because that’s what I’ve been using to log other types of data in mysql, I’ll put my test version at the end.

    Here’s the output I get in a fully saturated 6x6x6 grodan block (tap water)
    Raw Humid 100.0
    Raw Temp 21.700000000000003
    Raw EC 236
    Corrected Temp 22.200000000000003
    Corrected EC 195.05703422053224
    Bulk Permittivity 91.6988
    Pore Permittivity 79.48599999999999
    Pore Water EC 0.2141432987666497

    Questions …
    The / 1000 makes me wonder what unit PWEC is?
    Can anyone explain why soil dielectric constant is calculated the way it is?
    I also noticed that the way Gitpud calculates it seems to have an error (using temp^2 instead of humidity) … But, I don’t actually know, maybe he’s right?
    Thanks Daniel for all the interesting content you produce …

    Using pyserial (pip install pyserial NOT pip install serial)
    import serial
    import time

    temp_correction = 0.5
    soil = serial.Serial(‘/dev/ttyUSB0’, 4800)
    string = bytes.fromhex(“01 03 00 00 00 03 05 CB”)
    while True:
    soil.write(string)
    response = soil.read(11)
    soil_hum = 0.1 * (response[3] << 8 | response[4])
    soil_temp = 0.1 * (response[5] << 8 | response[6])
    soil_ec = response[7] << 8 | response[8]
    corrected_temp = soil_temp + temp_correction
    corrected_ec = 1.93 * soil_ec – 270.8
    corrected_ec = corrected_ec / (1 + 0.019 * (corrected_temp – 25))
    soil_bulk_permittivity = 1.3088 + 0.1439 * soil_hum + 0.0076 * soil_hum * soil_hum
    soil_pore_permittivity = 80.3 – 0.37 * (corrected_temp – 20)
    soil_pw_ec = soil_pore_permittivity * soil_ec / (soil_bulk_permittivity – 4.1) / 1000
    print("Raw Humid", soil_hum)
    print("Raw Temp", soil_temp)
    print("Raw EC", soil_ec)
    print("Corrected Temp", corrected_temp)
    print("Corrected EC", corrected_ec)
    print("Bulk Permittivity", soil_bulk_permittivity)
    print("Pore Permittivity", soil_pore_permittivity)
    print("Pore Water EC", soil_pw_ec)
    time.sleep(5)

  • BS
    January 30, 2024 @ 5:30 pm

    I believe now that raw and adjusted EC are μS/cm and pore water EC is mS/cm
    So, I’ll divide raw and adjusted by 1000 to match what my hanna meter displays

  • DrDobbins
    February 24, 2024 @ 6:37 pm

    Yes I was afraid to buy one of these I am using the cheap capacitive sensors, and they kinda work for my fertigation system. There are unwanted measurements, like the capacitance changes when the temperature changes at lights off. They are a pain to calibrate, and trust, you usally need to use multiple sensors to get an idea of what is going on. I bought a TDR sensor yesterday, and I am gonna code it up, and test tomorrow. Thanks for this post I hope this works out. I am a good programmer so I understand modbus, and what is going on. I am concerned about the calibration polynomials but I will have a tensiometer for reference, and I have automated runoff, and runoff ec measurements.

    • DrDobbins
      February 26, 2024 @ 5:54 pm

      So I got this device working it was sold on amazon it claimed to be a Moisture, Temperature, and EC sensor it is only a moisture sensor, no temperature and definatly no EC. I am ok with this because I only wanted the soil moisture anyways. Plus if it is a true TDR sensor for $38 yankey bucks then it is a steal, I am afraid it is a resistive moisture sensor. I will have a tensiometer to check it against, If I knew more about the device I would probe it with my spectrum analyzer. I just don’t know the power of the signal and spectrum analyzers tend to blow out thier front ends if they get blasted with a powerful signal.

      • admin
        February 27, 2024 @ 2:38 am

        Be careful about which device you buy, there are a lot of devices that look similar but are completely different. To get this exact device reliably make sure you buy it from the aliexpress link and get the THC-S model. I can verify this is a TDR sensor and that it measures EC and temperature too. A lot of resistive sensor imitations are sold on amazon and aliexpress too.

        • DrDobbins
          April 9, 2024 @ 9:42 pm

          Yes, I did get the wrong one but I have the correct one now, and I am going thru the calibration using the teros method. Reminds me of the Cooking media 101 on one of your videos. However I am going to go the opposite route and add water in and take my samples that way. The ec of the sensor is kind of messing with me but first thing is first getting it to report the correct WVC. One sensor reports 40% full saturation the other it is 80% so I need to calibrate them both for my next grow. I also have 3 cheapo capacitive sensors, they match the tdr sensors but are very noisy, and require heavy filtering. Which isn’t so bad you don’t need second by second WVC when using these sensors to determine when to water. I wouldn’t use these sensors however to determine fertigation amounts, just frequency. Thanks for your time and effort in this reguards I was using an adaptive timer based solution that worked off time to runoff and that just grew fugus bugs. It was always over watering, best just to sense the soil moisture level and use that.

  • Matias
    July 21, 2024 @ 2:47 pm

    Hi Daniel, could you connect two or more sensors to the same bus? how did you do with the sensors addresses?

    • admin
      July 23, 2024 @ 9:28 am

      I have never tried connecting more than one sensor to the same bus.

      • Matias
        July 31, 2024 @ 11:16 am

        Hi Daniel, yes, it is possible to connect up to 32 devices to the same bus.
        In order to do this, you need to modify the device address with a write request.

        The address is in the register 2000 which by default is 1. Here is a nice datasheet https://www.slicetex.com.ar/modules/sensors/soil_mb_xxx/docs/SOIL-MB-THC-S-DS.pdf.
        I could modify this register using Modbus Poll + Rs485 to usb adapter in windows and sucessfuly read data in address 2. But you can also write the code to do this in the nodemcu.

        In your request, the address is the first element (0x01 = 1) from const byte hum_temp_ec[8] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x03, 0x05, 0xCB};
        So if you have many devices, you can iterate through all the directions and make a request for each

Leave a Reply

Your email address will not be published. Required fields are marked *

Subscribe Today!
Receive our FREE blog post updates and monthly newsletter
Thanks for signing up. You must confirm your email address before we can send you. Please check your email and follow the instructions.
We respect your privacy. Your information is safe and will never be shared.
Don't miss out. Subscribe today.
×
×
WordPress Popup Plugin