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
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
To support this sensor, the application code needs to use #define GEMHO. This sensor works by default with 9600 Baud.
WisBlock modules & enclosure:
-
RAK3172 Evaluation Board
- RAK19007 WisBlock Base Board
- RAK3372 WisBlock Core module with STM32WLE5
- (Alternative) RAK4631 WisBlock Core module with nRF52840
- RAK5802-M WisBlock RS485 module (modified variant)
- RAK19002 WisBlock 12V booster for supply of soil sensor
- Unify Enclosure 150x100x45 with Solar Panel
- 3200 mAh battery
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.
Figure 1: (Left) Finished prototype; (Right) Soil Sensor
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.
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
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
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:
-
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.
-
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.
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.
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.
2. Open the Codec tab. By default, the Payload codec is set to None. Change it to JavaScript functions to enable a custom decoder.
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.
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.
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.
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.
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.
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.
Figure 11: InfluxDB API Create Tokens Menu
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.
Figure 12: InfluxDB Create Organization
4. Use RAKwireless for both the organization and the bucket, and click CREATE.
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.
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.
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.
8. Choose InfluxDB as the new connection type.
- 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.
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.
// 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 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.
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.
Figure 23: Grafana New Dashboard
17. In the next window, select the option to add a visualization.
Figure 24: Add new visualization in Grafana
18. Then select InfluxDB as the data source.
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.
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.
Figure 27: Change the Panel Title
20. Click the Apply button to add the visualization to the new dashboard.
Figure 28: Apply the changes made
The panel displaying soil temperature is now shown on the dashboard.
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.
Figure 30: Add new visualization in the dashboard
- Duplicate the existing visualization, changing only the title and the Flux query.
Figure 31: Grafana Duplicate Option
If Duplicate is chosen, open the visualization menu and select Edit.
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.
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:
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)
Figure 35: WisBlock All Modules Assembly
-
Preparation of the Mounting Plate
- Cut two screw holes.
Figure 36: WisBlock Plastic Base Plate Modification
- WisBlock Assembly Wiring Inside the Enclosure
Figure 37: WisBlock Assembled Hardware
Figure 38: WisBlock Hardware Parts Names
- WisBlock Assembly Outside Wiring
Figure 39: Soil sensor pinout
- Wiring details
Figure 40: Soil sensor connection to WisBlock
- Connection protection with shrink tube
Figure 41: Cable protection with shrink tube
Assembly Inside the Enclosure
Figure 43: Final hardware assembly
|
|
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