how to build an rs485 soil sensor with wisblock and rui3

This tutorial demonstrates how to set up a sensor node using WisBlock modules that can communicate over RS485 with a "7-in-1" soil sensor.

For agricultural applications, it is often necessary to operate independently of a permanent power supply. The sensor node described in this guide runs on a 3200mAh battery, which is recharged by a solar panel during the day.

The application supports two different soil sensor products:

  • Sensor 1 Tested and Verified: "No-Name" VEM SEE SN-3002-TR-ECTHNPKKPH-N01 sensor
  • Sensor 2 Not Tested and Verified: GEMHO 7-in-1 Soil Sensor with RS485

The 12V power supply required by the soil sensor is generated using a WisBlock 12V booster module.

Requirements

Soil Sensors

  • VEM SEE SN-3002-TR-ECTHNPKKPH-N01
🗒️
NOTE

To support this sensor, the application code needs to use #define VEMSEE. This sensor works by default with 4800 Baud.

  • GEMHO 7 in 1 Soil Sensor
🗒️
NOTE

To support this sensor, the application code needs to use #define GEMHO. This sensor works by default with 9600 Baud.

 

WisBlock modules & enclosure:

Hardware Assembly

Assembly is performed using the standard mounting plate of the Unify Enclosure. Sensor connections are made with the 5-pin IP65 connector of the Unify Enclosure with Solar Panel. The antenna used is a Blade Antenna with a gain of 2.3 dBi.

Assembled IoT deviceClose-up view of the sensor

Figure 1: (Left) Finished prototype; (Right) Soil Sensor

⚠️
IMPORTANT

The RAK19002 12V booster must be installed in sensor Slot B. To reduce power consumption, both the 12V booster and the connected soil sensor are powered down while the device is in low power mode. The booster is controlled through the GPIO WB_IO2, which directly manages the RAK19002 in Sensor Slot B.

 

Modbus/RS485 Wiring Diagram

The device utilizes the Unify Enclosure measuring 150mm x 100mm x 45mm, equipped with a solar panel and standard openings for the LoRa® antenna, as well as a waterproof 5-pin connector. The four wires from the soil sensor are connected to a 5-pin plug that fits into the enclosure's 5-pin connector.

 

wiring.png

Figure 2: RS485 Wiring Diagram

Firmware

The firmware is based on the basic RUI3-RAK5802-Modbus-Master code, with adjustments made for the RS485 sensor in use. The source code can be found in the GitHub repository RUI3-RS485-Soil-Sensor.

To ensure accurate sensor readings, the sensor is powered on for 5 minutes before data is collected. This allows the sensor sufficient time to complete its readings and calculations.


Custom AT Commands

Send Interval

The Send interval for the sensor values can be configured using a custom AT command. The interval time is specified in seconds.

ATC+SENDINT? - Command definition

ATC+SENDINT,: Set/Get the interval sending time values in seconds 0 = off, max 2,147,483 seconds
OK

ATC+SENDINT=? - Get current send interval in seconds

ATC+SENDINT=3600
OK

ATC+SENDINT=3600 - Get current send interval to 3600 seconds == 1 hour

ATC+SENDINT=3600
OK

 

⚠️
IMPORTANT

Send interval cannot be less than 2 times the sensor power on time. With the current settings the minimum send interval is 10 minutes.

 

Sensor Test

Sensor connection can be tested with a custom AT command.

ATC+STEST? - Command definition

ATC+STEST,R*W: Read sensor
OK

ATC+STEST=? - Start sensor test

ATC+STEST=?
OK

 

⚠️
IMPORTANT

After starting the test, it takes 15-20 seconds before a result is available.

 

The output of the command is:

  • Sensor found
> atc+stest=?
Sensor Power Up
OK
+EVT:Sensor Values: M:22.10-T:25.70-pH:3.00-C:140.0

The values measured are soil humidity (M), temperature (T), pH value (pH), and conductivity (C). If the sensor is not in the soil, these values may be zero or nonsensical.

  • Sensor not found
> atc+stest=?
Sensor Power Up
OK
+EVT:Error reading sensor

 

  • Sensor reading already active

This may be because a manually started test has not yet completed, or a scheduled automatic sensor reading is currently in progress.

> atc+stest=?
AT_BUSY_ERROR


Visualization of the Sensor Data

To visualize the sensor data, the following (free) extensions are used:

  • InfluxDB

    There are two options:

    1. Use the InfluxDB Cloud Serverless

    2. Install InfluxDB on your own server

In this case, Option 2 was chosen. InfluxDB is installed on a VPS.

  • Grafana

    Also has two options:

    1. Use Grafana Cloud

    2. Install Grafana on your own server

Option 2 was selected. Grafana is also running on the same VPS.

  • LoRaWAN Server Integration

    ChirpStack V4 was used to integrate InfluxDB with the LoRaWAN server. It is installed on the same VPS, alongside InfluxDB and Grafana.

🗒️
NOTE

The complete system is set up on a VPS using Docker containers. All required containers are installed using a custom Docker YAML file, and Portainer, a Docker management tool, is used for container maintenance. This setup includes the ChirpStack V4 LoRaWAN server, InfluxDB, and Grafana.

 

Register the Sensor Nodes in the LoRaWAN Server

No detailed instructions for this section. These steps are common for connecting sensor nodes to a LoRaWAN server.

1. Set up the LoRaWAN server and connect the gateway(s) to it. Ensure that both the LoRaWAN server and the gateway(s) are configured for the same LoRaWAN region.

2. Create an application on the LoRaWAN server. Register the sensor nodes within the application and provide the following details:

  • For OTAA: DevEUI, AppEUI, and AppKey.
  • For ABP: DevAddress, AppSKey, and NwSKey.

3. Verify that the application on the LoRaWAN server is receiving data from the sensor nodes.

sensor-data-in-lns.png

Figure 3: ChripStack Raw Data Received

Set Up the Codec in ChirpStack

To store data in the InfluxDB database, a payload decoder must be configured in ChirpStack. Payload decoders are defined within the Device Profiles

1. In the web UI, navigate to the Device Profiles and then select the Codecs.

chirpstack-add-decoder.png
Figure 4: ChripStack Device Profiles Tab

2. Open the Codec tab. By default, the Payload codec is set to None. Change it to JavaScript functions to enable a custom decoder.

chirpstack-change-codec-type.png

Figure 5: ChripStack Codec Tab

3. RAKwireless has a ready-to-use JavaScript decoder for Chirpstack. You can get it from the RAKwireless_Standardized_Payload GitHub repository.

chirpstack-get-decoder.png

Figure 6: GitHub Repository Payload Codec

4. Click the Raw button to view the JavaScript code as plain text. Then, copy the entire JavaScript code and paste it into the Chirpstack Codec functions text field.

chirpstack-paste-codec.png

Figure 7: ChripStack Codec Field

5. To verify that the decoder is working, return to the device page in ChirpStack and navigate to the Events tab. This section displays the received data packets.

6. Click the up button next to a received packet to view the decoded payload.

chirpstack-check-decoder.png

Figure 8: ChripStack Events Tab

Installation of InfluxDB and Grafana

The installation of InfluxDB and Grafana is accomplished using a Docker YAML file. It is important to note the local IP addresses of both applications, which can be obtained through the Portainer management tool.

portainer-docker-management.png

Figure 10: Portainer Management Tool List of Applications

Set Up the InfluxDB Database

In the InfluxDB web UI, create an access token for access.

1. Open the Load Data menu and select API Tokens.

influxdb-token-1.png

Figure 10: InfluxDB Main Menu

2. Create two tokens using the GENERATE API TOKEN button: one for Chirpstack and one for Grafana. These tokens will be required in the next steps.

influxdb-token-2.png

Figure 11: InfluxDB API Create Tokens Menu

 

⚠️
IMPORTANT

Make sure to copy the tokens into a safe place. They can only be read during the creation of the tokens.

 

3. Create an organization and a bucket to store the sensor data.

influxdb-organisation-1.png

Figure 12: InfluxDB Create Organization

4. Use RAKwireless for both the organization and the bucket, and click CREATE.

influxdb-organisation-2.png

Figure 13: InfluxDB Create Organization

Set Up the InfluxDB Integration in Chirpstack

5. In the ChirpStack web UI, open the application and select the Integrations tab.

chirpstack-integrations.png

Figure 14: ChripStack Applications Select InfluxDB

 

6. Fill out the connection details for the InfluxDB database.

  • This installation uses InfluxDB v2.
  • The API endpoint is the IP address of the InfluxDB Docker instance obtained from Portainer.
  • The organization and bucket are those we created in InfluxDB.
  • The token is the access token we generated in InfluxDB.

chirpstack-influxdb-setup.png

Figure 15: ChripStack Fill Application Fields

 

Set Up Grafana

7. In the Grafana web UI, open Connections and select Add new connection to set up the connection to the InfluxDB database.

grafana-connection-1.png
Figure 16: Grafana Add New Connection
 

8. Choose InfluxDB as the new connection type.

grafana-connection-2.png
Figure 17: Select InfluxDB as the new connection
 
9. Set up the connection using the IP address and token obtained earlier.
 
grafana-connection-3.png
Figure 18: Grafana Fill Application Fields
 
  • User name: The InfluxDB organisation user.
  • Password: The InfluxDB organisation password.
  • Organization name: The organization setup in InfluxDB.
  • Token: The token created in InfluxDB for the Grafana access.
  • Default bucket: The bucket created in InfluxDB.
 
grafana-connection-4.png
Figure 19: Grafana Fill Auth and Details Fields
 
10. Use the Save & test button to check if Grafana can access the database.


Verify Data Arrival in the Database

11. Open the InfluxDB web UI, navigate to the Data Explorer, and select the appropriate bucket. The easiest way to locate the data is to use the DevEUI of the soil sensors as the first filter.

12. Next, use _measurement as the second filter. You will now see all the data received from the soil sensor.

influxdb-select-device-data.png
Figure 20: InfluxDB Data Explorer Menu
 
As you can see, there are many entries. Each entry's name includes the sensor number assigned in the application code at the end.
// Cayenne LPP Channel numbers per sensor value
#define LPP_CHANNEL_BATT 1 // Base Board
#define LPP_CHANNEL_MOIST 2
#define LPP_CHANNEL_TEMP 3
#define LPP_CHANNEL_COND 4
#define LPP_CHANNEL_PH 5
#define LPP_CHANNEL_NITRO 6
#define LPP_CHANNEL_PHOS 7
#define LPP_CHANNEL_POTA 8
#define LPP_CHANNEL_SALIN 9
#define LPP_CHANNEL_TDS 10

For example:

device_frmpayload_data_temperature_3

refers to the soil temperature

// Add temperature level to payload
g_solution_data.addTemperature(LPP_CHANNEL_TEMP, coils_n_regs.sensor_data.reg_2 / 10.0);
 

13. Once device_frmpayload_data_temperature_3 is selected, add an additional filter with a value to retrieve the temperature data from the database query. Then, click the SUBMIT button. The graph will display the recorded temperature measurements.

influxdb-display-data.png
Figure 22: InfluxDB Data Explorer Submit Data Configuration
🗒️
NOTE

InfluxDB Data Explorer provides the option to view the query as a Flux query. This can be directly used in Grafana to retrieve data from the InfluxDB database.

 

14. Click on the SCRIPT EDITOR button to see the Flux query.

influxdb-get-flux-query.png

Figure 22: InfluxDB Script Editor

15. Copy and save the Flux Query; it will be used later in the Grafana dashboard.

Set Up Grafana Dashboard

16. Open the Grafana web UI and navigate to Home > Dashboards. Next, click the New button and select New dashboard.

grafana-new-dashboard.png

Figure 23: Grafana New Dashboard

17. In the next window, select the option to add a visualization.

grafana-new-visualization.png

Figure 24: Add new visualization in Grafana

18. Then select InfluxDB as the data source.

grafana-select-datasource.png

Figure 25: Grafana Select InfluxDB Data Source

19. A new window showing the visualization details will open. Paste the Flux query you previously copied from InfluxDB Data Explorer into the query field.

grafana-copy-flux-query.png

Figure 26: Paste Flux query from InfluxDB

There are several options for modifying the presentation of the data. In this case, only the Panel Title has been changed to Soil Temperature

For more information on the other options, refer to the Grafana documentation.

grafana-set-panel-title.png

Figure 27: Change the Panel Title

20. Click the Apply button to add the visualization to the new dashboard.

grafana-apply-visualization.png

Figure 28: Apply the changes made

The panel displaying soil temperature is now shown on the dashboard.

grafana-soil-temperature.png

Figure 29: Soil temperature Grafana dashboard

21. To add the other sensor values, you can use one of two methods:

  • Select the Add option from the top menu, choose Visualization, and repeat the steps above for the new sensor value.

grafana-add-next-visualization.png

Figure 30: Add new visualization in the dashboard

  • Duplicate the existing visualization, changing only the title and the Flux query.

grafana-duplicate-visualization.png

Figure 31: Grafana Duplicate Option

If Duplicate is chosen, open the visualization menu and select Edit.

grafana-edit-duplicate.png

Figure 32: Edit the duplicated visualization in Grafana dashboard

22. In the edit window, only two changes need to be made: the source in the Flux query and the title

  • The source should be updated to the moisture level (device_frmpayload_data_humidity_2).
  • The title should be changed to Soil Moisture.

grafana-change-duplicate.png

Figure 33: Change visualization name to Soil Moisture

Other sensor values can be added to the Dashboard in the same way. When all sensor values are visualized, the Dashboard will appear as follows:

grafana-soil-sensor-dashboard.png

Figure 34: Overall visualization dashboard in Grafana

Appendix

Soil Sensor Registers

  • VEM SEE SN-3002-TR-ECTHNPKKPH-N01 Soil Sensor register setup
ADDRESS MULTIPLIER REGISTER CONTENT
0x0000 /10 Moisture
0x0001 /10 Temperature
0x0002 *1 Conductivity
0x0003 /10 pH
0x0004 *1 Nitrogen content (temporary)
0x0005 *1 Phosphorus content (temporary)
0x0006 *1 Potassium content (temporary)
0x0007 *1 Salinity
0x0008 *1 TDS (for reference)
0x0022 *1 Temperature coefficient of conductivity
0x0023 *1 TDS coefficient
0x0050 *1 Temperature calibration value
0x0051 *1 Moisture content calibration value
0x0052 *1 Conductivity calibration value
0x0053 *1 pH calibration value
0x04e8 *1 Nitrogen content coefficient MSB (temporary)
0x04e9 *1 Nitrogen content coefficient LSB (temporary)
0x04ea *1 Nitrogen deviation (temporary)
0x04f2 *1 Phosphorus coefficient MSB (temporary)
0x04f3 *1 Phosphorus coefficient LSB (temporary)
0x04f4 *1 Phosphorus deviation (temporary)
0x04fc *1 Potassium content coefficient MSB (temporary)
0x04fd *1 Potassium content coefficient LSB (temporary)
0x04fe *1 Potassium deviation (temporary)
0x07d0 *1 Device address
0x07d1 *1 Baud Rate

 

Assembly Guide

  • Required Parts
ADDRESS MULTIPLIER REGISTER CONTENT
110082 RAK19007 Base Board
116032 RAK3372 RAK3372 Core Module US915 with RUI3 firmware
??? RAK5802-M RS485 module (Screw terminal version, used with RAK7391)
100018 RAK19002 12V Booster module
910421 Unify Enclosure 150x100x45 Unify Enclosure IP67 150x100x45mm with Pre-Mounted M8 5-Pin Connectors and RP-SMA Antenna and Solar panel
??? 3200mAh battery 2-pin version (as used in RAK10701)
926019 Blade antenna Black Blade antenna for 902-928 MHz
??? Soil sensor VEM SEE SN-3002-TR-ECTHNPKKPH-N01

 

  • WisBlock Assembly (Location of Modules)

wisblock-locations.png

Figure 35: WisBlock All Modules Assembly

  • Preparation of the Mounting Plate
    • Cut two screw holes.

wisblock-mounting-plate.png

Figure 36: WisBlock Plastic Base Plate Modification

  • WisBlock Assembly Wiring Inside the Enclosure

wisblock-wiring-1.png

Figure 37: WisBlock Assembled Hardware

 

wisblock-wiring-2.png

Figure 38: WisBlock Hardware Parts Names

 

🗒️
NOTE

 

  • The 5-pin connector inside the enclosure should consist of five colors: red, black, yellow, blue, and white.
  • If the 5-pin connector contains only three colors (red, black, and yellow repeated three times), it is necessary to identify the correct wires that match the colors of the outside cable plug.
  •  

     

    • WisBlock Assembly Outside Wiring

    wisblock-wiring-3.png

    Figure 39: Soil sensor pinout

    • Wiring details

    wisblock-wiring-4.png

    Figure 40: Soil sensor connection to WisBlock

     

    • Connection protection with shrink tube

    wisblock-wiring-5.png

    Figure 41: Cable protection with shrink tube

    Assembly Inside the Enclosure

    wisblock-assembly-inside.png

    Figure 43: Final hardware assembly

     


     

    bernd-giesecke.png

    Bernd Giesecke

    Electronics Engineer, 23 years of experience in industrial and automotive HW and SW R&D. Supporting Arduino open-source community since 2014.


    Changelog
    • Version 1 - How to Build an RS485 Soil Sensor with WisBlock and RUI3
      • Author: Bernd Giesecke
      • Reviewer: Harold Duarte
      • Date Published: 07/16/2025

     

     

     

     

    Updated