Code Monkey home page Code Monkey logo

rs485-moist-sensor's Introduction

rs485 soil moisture sensor

Digital (RS485 - based) soil moisture and temperature sensor

A version of I2C soil moisture sensor with several updates - antistatic protection, local voltage regulation and RS485 networking.

This is a contact-less capacitive soil moisture sensor, a continuation of my I2C soil moisture sensor. This particular version of the sensor is suited for more professional installations where long cable runs is a requirement. It adds a local voltage regulator to mitigate the voltage drop and RS485 transceiver to accommodate long wires, also reverse polarity and an additional ESD protection level is added.

This is the easiest and the most robust way to read soil moisture and temperature values into Raspberry Pi. I have written a tutorial how to do it.

The main features:

  • Capacitive soil moisture sensing
  • Temperature sensing
  • Good stability with temperature
  • Good stability with power variation
  • Suitable for long cable runs
  • Uses industrial Modbus protocol

Python library

A python library is available via pip. Type pip install chirp_modbus to install it. Check the source code for documentation. Usage example:

from chirp_modbus import SoilMoistureSensor
s = SoilMoistureSensor(1, '/dev/ttyUSB5')
print(s.getTemperature())
print(s.getMoisture())

Technical data

  • Supply voltage - 5V
  • Bus can be run on both 3V and 5V
  • Default serial settings: 19200, 8-bit frame, no parity, 2 stop bits
  • Default Modbus address: 1
  • Current consumption: Active: 9mA, Deep sleep: 11uA

Principle of operation

Sensor makes periodic measurements (by default, once every 500ms), delays between measurements can be updated by writing to one of the Modbus registers. The results of the measurements are kept in specific Modbus registers and can be read by master any time unless the sensor is in deep sleep.

Deep sleep is entered by writing a number of seconds to sleep into a special sleep register. The sensor will put the transceiver and all the periphery into the lowest possible power consumption mode and sleep for the specified amoutn of time. After the sleep the sensor will wake up, start taking measurements and be available on the bus till the next sleep command.

Serial communication parameters as baud rate, parity and address can be updated by writing to related registers. The sensor will reset and boot with the new parameters if any of those registers are written.

Input (read only) registers

Register number Size (bytes) Description
0 2 Soil moisture. Unsigned
1 2 Temperature. Signed. In tenths of degrees Celsius. I.e. 220 means 22.0C

Holding (read/write) registers

Register number Size (bytes) Valid values Default value Description
0 2 [1 - 247] 1 Modbus address
1 2 [0 - 7] 4 Baud rate
2 2 [0 - 2] 0 Parity Note: most cheap ebay USB to RS485 dongles don't support parity properly!
3 2 [1 - 65535] 500 Measurement interval in milliseconds
4 2 [1 - 65535] 0 Time to sleep in seconds. Write to this register to put the sensor to sleep.

Supported baudrates

Number Baudrate
0 1200
1 2400
2 4800
3 9600
4 19200
5 38400
6 57600
7 115200

Supported parity settings

Number Parity
0 None
1 Even
2 Odd

Note: most of the cheap ebay USB to RS485 dongles and/or their drivers do not support parity setting properly! You will have to use a proper parity supporting adapter to unbrick the sensor if you set this to something that your dongle does not support! Luckily Adruino with ATmega 16u2 can be used as USB to Serial adapter to solve this.

How to interpret the readings

Moisture values are relative. Meaning, more moisture will give you higher reading, less moisture - lower reading. It's up to you to calibrate it to amount of water in the soil as readings will be different for different types of soils.

Moisture is somewhat linear. I test all sensors before shipping and they give about 292 in free air.

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.

Controller support

The sensor will work fine with any controller supporting serial communication provided you have an RS485 transceiver. There are a lot of Modbus libraries readily available for a variety of micro-processor families. Thea easiest way to try the sensor is to use one of the abundant and cheap USB to RS485 dongles and connect it to a Raspberry pi or even directly to your computer.

I have written some basic test code in python that is available on github page.

Waterproofing

The sensor comes coated with PRF202 - a moisture resistant varnish for electronics. It's ok for play around in a flower pot but not enough for outdoor use. You must add an additional protection to the whole sensor after soldering cable to it! Some suggestions on making the sensor more robust after attaching the cable:

  • Polyester or epoxy resin - this method is the most bullet proof as the resin is totally resistant to the water. On the par side, note that sensitivity of the sensor will decrease depending on how thick the layer you are going to apply. Also applying the resin in uniform manner presents some challenge.
  • PlastiDip - some of my customers have tried this method - easy to apply by spraying and not a lot of loss of sensitivity.
  • Rubber balloon - yes, just roll a long balloon over the sensor :)

Be sure to coat the whole thing - the sensor part, the electronics and the cable connection itself so no bare copper or solder is accessible to the water.

rs485-moist-sensor's People

Contributors

miceuz avatar parallelpilgrim avatar wedvjin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rs485-moist-sensor's Issues

RS485 Bus stops after a few days

Hello,
i´ve encountered, that my sensors are not working after a few days of operation.

Setup

  • 3 Sensors
  • overall bus length 25m
  • Termination: VCC <-> 390Ohms <-> RS485-line-A <-> 220Ohms <-> RS485-line-B <-> 390Ohms <-> Ground
  • Termination is at my USB to RS485 Transceiver

Measurement

  • set measuerement interval to 500ms
  • do 100 measuerements, read the data once per second then calculate mean on the data
  • then do the next 100 measuerements

Result

  • This runs fine for about 2 days but occasionally stops.
  • Tested with the USBtoRS485 converter sold by @Miceuz and also with a different one. Same results.
  • Only pwer cycling the whole bus helps.

Has anyone else had similar issues? Maybe @cheeeeee?

Any help appreaciated, thanks and best regards

Possible to use 1-wire?

Hi Albertas,

I see you also have a version of the moisture sensor using RS-485. I was wondering if it is possible to use 1-wire, more specific. a DS2438Z+ ADC

My idea is to use the 1-wire bus to power the chirps as well. Perhaps not using the chirp function at all but do it centrally and use the moisture sensor purely as a sensor

Hope to hear your thoughts on this.

KR
Bert

measurement interval lost after sensor reboot

Hi,
i somehow have an issue with the measurement interval.
it seems that its not correctly stored in EEPRom and initialized to a very high value after power off->on.

here is what i did:

pi@raspberrypi:~/Documents/WateringSystem $ python3
Python 3.5.3 (default, Jan 19 2017, 14:11:04)
[GCC 6.3.0 20170124] on linux
Type "help", "copyright", "credits" or "license" for more information.
from chirp_modbus import SoilMoistureSensor
sensor = SoilMoistureSensor(10, "/dev/ttyUSB0")
sensor.getMeasurementInterval()
65524
sensor.setMeasurementInterval(123)
sensor.getMeasurementInterval()
123

Power off sensor, power back on

sensor.getMeasurementInterval()
65524

Reinitialize python object, turns out this was not the issue

sensor = SoilMoistureSensor(10, "/dev/ttyUSB0")
sensor.getMeasurementInterval()
65403
sensor.getMeasurementInterval()
65403
sensor.getMeasurementInterval()
65403
sensor.getMeasurementInterval()
65403
set another interval
sensor.setMeasurementInterval(123)
sensor.getMeasurementInterval()
123
sensor.getMeasurementInterval()
123
sensor.getMeasurementInterval()
123
sensor.getMeasurementInterval()
123
sensor.getMeasurementInterval()
123
sensor.getMeasurementInterval()
123
sensor.getTemperature()
26.4
sensor.getTemperature()
26.4
sensor.getTemperature()
26.4
sensor.getMoisture()
229

** here the test, if the data is updated fast, yes it is**

sensor.getMoisture()
416
sensor.getMoisture()
227
sensor.getMoisture()
227
sensor.getMeasurementInterval()
123
sensor.setMeasurementInterval(500)
sensor.getMeasurementInterval()
500
sensor.getMeasurementInterval()
500
sensor.getMeasurementInterval()
500
sensor.getMeasurementInterval()
500

** power off sensor, power back on**

sensor.getMeasurementInterval()
65524
sensor.getMeasurementInterval()
65524

Sensor readings incorrect when temp below zero

I have a range of sensors based on the schematic and layout of this project, which work brilliantly - apart from when the temperature goes negative. I get a reading from the registers of 65515, or close to (it's not exactly the same each read). Does anyone get this from the original RS485 sensors which are shipped via Tindie?

The firmware is from this project, up to date.

A few questions about the ATTiny441 programming

If you get a chance I had a few questions about some of the modbus programming in modbus.c and main.c

Possible problems:

In modbus.c --

Function Problems:

bool validateFrame()
Line 169 -- uint8_t requestedAdr = getRequestedAddress(); requestedAdr is never used in this function.
ISR(UART_RECEIVE_INTERRUPT)
Line 210 -- uint8_t parityError = (UCSR0C & _BV(UPM01) && (UCSR0A & _BV(UPE0)));never used in this function.

In main.c --

General Problems:

F_CPU
This is defined by default in delay.h as 1MHz and defines the clock cycle. This is probably undefined behavior.

Line 193 -- ISR(WDT_vect)
WDT_vect isn't supported on the ATTiny44 according to https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html. This is supported if you use Atmel's special header file iotn441.h
This might explain the comment saying you were having problems with it.

Function Problems:

modbusGet(void)
Line 123 -- if (modbusIsFrameAvailable()) when true this enters a switch case statement with a default behavior, however there is no error returned if modbusIsFrameAvailable() returns false.
Between line 160 and 161 a modbus error should probably be returned to handle a false boolean.

sleep()
Line 234 -- might not be a problem but I think you have an unneeded compare.
on line 228 you have secondsToSleep = holdingRegisters.asStruct.sleepTimes;
since you've assigned these values to be equal when you do the compare on line 235 while((sleepTimes > 0) || (secondsToSleep > 0)) I'm pretty sure you're just checking two numbers that are always the same in this particular function. You can probably use if and just check one.

Line 297 -- incorrect primitive for main

void main (void) {
}

should be

int main (void) {
}

Lines 318 and 324

Incorrect primitives for temp. Needs to be signed to allowed for negative values. Initial declaration is correct but is incorrect in function call.

(uint16_t*) &(inputRegisters.asStruct.temperature));
should be
(int16_t*) &(inputRegisters.asStruct.temperature));

Questions!

  1. What do you think the F_CPU cycle should be set to? I'm assuming 16MHz to match the crystal but it might be 8 MHz to match the ATTiny441 default clock.
  2. Currently if I write to a value to the sleep register it won't wake up until that counter expires or the sensor is power cycled. Is this intentional or a bug? It seems like requesting a read operation should wake the sensor. I think with the iotn441.h header fix this could be easily done with a watchdog interrupt.

You can find everything I've done to these files at https://github.com/cheeeeee/RS485_AtmelDebug Including some additional API documentation in main.c if you haven't looked at this in a while and need a refresher.

Home Assistant

Hi,
congrats for what it seems to be a great product!
Did anyone try if this works on Raspberry PI running Hass.io (Home Assistant)?
It would be a great thing!
Best regards,
Tomaz

python lib has wrong register numbers

Hi,
thanks for your great work.
i love your sensors.
Anyhow i think that there is a bug with the python implementation installed via pip and also in this repo.

  1. The register numbers found in /utils/lib/chirp_modbus.py are not the same as in https://www.tindie.com/products/miceuz/modbus-rs485-soil-moisture-sensor-2/
  2. Also reading the Firmware versions seems not to work, i get IO errors.

I discovered because i was not able to set the measurement interval (and i have my USB dongle on another tty than you and scanning has it hardcoded -> you may want to change that).

here is my version of the file (tty still hardcoded..):
chirp_modbus.zip

You may want to take a look at it, best regards :)

Compiler Toolchain and bin file

Hello,

I am having some problems with compiling the code.
I am using Mac and brew to setup the toolchain.
I am not able to compile using 4.9.2 compiler which isnt have attiny definitions, the minimum version I can use is 5.3 compiler, when I am using 5.3 compiler code compiles succesfully but, rs485 tranciever enable pin stuck at transmit mode so sensor is not able to receive any modbus data.
There is something I am missing but coulnt find root of the issue
I was wondering anyone can help me on toolchain setup. Or is there any precompiled binary ?

Regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.