// This attempt uses the SoftwareSerial & raw Modbus packets.
//
// RS485 module wired up as:
// RS485 DI signal to pin 3
// RS485 RO signal to pin 2
// RS485 RE signal to pin 8
// RS485 DE signal to pin 7
// RS485 VCC to 5V
// RS485 GND to GND
//
#include <SoftwareSerial.h>
#define RE 2
#define DE 3
const uint32_t TIMEOUT = 500UL;
// canned message to your RS485 device
// change this for any other canned modbus message you like
// remember to make sure that the checksum is correct!
uint8_t msg[] = {0x01, 0x03, 0x00, 0x13, 0x00, 0x01, 0x75, 0xCF};
uint8_t rxByte;
SoftwareSerial swSerial(0, 1); // Receive (data in) pin, Transmit (data out) pin
I can't understand how to see that my this line uint8_t msg[] = {0x01, 0x03, 0x00, 0x13, 0x00, 0x01, 0x75, 0xCF};
is correct or not because I can't make my 7 in 1 soil sensor work
Hello, do yourself a favour and please read How to get the best out of this forum and modify your post accordingly, including code tags (please fix your first post by editing it and adding the tags around the code portion) and necessary documentation for your ask. (what is the 7 in 1 soil sensor you are talking about, how is it wired to your Arduino, which Arduino, ...)
I will rephrase my question. I am working on 7 in 1 soil moisture sensor and trying to get its data.
The code I am attaching is just used for seeing that whether the sensor is responding or not.
// This attempt uses the SoftwareSerial & raw Modbus packets.
//
// RS485 module wired up as:
// RS485 DI signal to pin 3
// RS485 RO signal to pin 2
// RS485 RE signal to pin 8
// RS485 DE signal to pin 7
// RS485 VCC to 5V
// RS485 GND to GND
//
#include <SoftwareSerial.h>
#define RE 2
#define DE 3
const uint32_t TIMEOUT = 500UL;
// canned message to your RS485 device
// change this for any other canned modbus message you like
// remember to make sure that the checksum is correct!
uint8_t msg[] = {0x01, 0x03, 0x00, 0x12, 0x00, 0x02, 0x64, 0x0E};
uint8_t rxByte;
SoftwareSerial swSerial(0, 1); // Receive (data in) pin, Transmit (data out) pin
void setup() {
Serial.begin(4800);
swSerial.begin(4800);
pinMode(RE, OUTPUT);
pinMode(DE, OUTPUT);
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
delay(1000);
}
void loop() {
uint32_t startTime = 0;
Serial.print("TX: ");
printHexMessage( msg, sizeof(msg) );
// send the command
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay( 10 );
swSerial.write( msg, sizeof(msg) );
swSerial.flush();
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
Serial.print("RX: ");
// read any data received and print it out
startTime = millis();
while ( millis() - startTime <= TIMEOUT ) {
if (swSerial.available()) {
printHexByte(swSerial.read());
}
}
Serial.println();
delay(2000);
}
void printHexMessage( uint8_t values[], uint8_t sz ) {
for (uint8_t i = 0; i < sz; i++) {
printHexByte( values[i] );
}
Serial.println();
}
void printHexByte(byte b)
{
Serial.print((b >> 4) & 0xF, HEX);
Serial.print(b & 0xF, HEX);
Serial.print(' ');
}
When I am running this code I am only having TX values and the RX is empty. This mean that my sensor isn't responding I just don't what wrong I am doing. I am using Arduino Uno, RS485 and 7 in soil moisture.
I am attaching my circuit picture, and the output.
circuit pic 1
pin 4 of your uno will be the Rx pin, so should be connected to Tx pin of the sensor
pin 5 of your uno will be the Tx pin, so should be connected to Rx pin of the sensor
@areebkhan02 I see you found some of my early code (or a variant of it) that I generated whilst trying to help other users of NPK sensors.
Your sensor will use either 9600 baud (pretty common) or 4800 baud. Generally the NPK sensor has a default device address of 01, so that part of your canned modbus message is correct.
Do you have the user manual for your NPK sensor? If you don't, then it's guesswork as to what soil parameters are in what registers.
The canned modbus message is asking the sensor with device address 01 for 2 registers at register address 0x12 and 0x13, which would normally return 4 bytes of data as part of the response.
If your particular NPK sensor doesn't have registers at these addresses, then it will likely not respond and you will see nothing printed for the raw RX values.
Thankyou Markd833 for replying. So regarding the user manual. I just don't know what user manual is correct for this sensor, since my university bought it for my project. I tried contacting JHXCT for where I ordered the sensor. They said to me to contact the local buyer. I am attaching the box in which it came, incase other people can identify what is the correct manual for it. Currently I am using the manual which was released on 2020 and the register values are set according to it.
Ok, well this is a very long shot and prone to an epic number of errors but here goes!
I took your box image and cropped / rotated it and fed it into a simplified chinese OCR online app. That generated a plain text file of Chinese characters that I fed into google translate one line at a time. This is what came out:
Swallow atmospheric environment monitoring
Agricultural parameter monitoring
Heng Industrial Gas Detection
Professional provider of industrial IoT sensors and solutions
Xinsuda ⑩Safe Ginseng and Peace of Mind
High precision || negotiable sensor
Now, here's another long shot. I've just pulled this bit of code together and done basic testing of it so don't expect too much!
The code sends out a canned Modbus query to device address 01 asking for the contents of register addresses 0x00 up to 0x2F (0 to 47) and then repeats.
I have a specific hardware setup so I use AltSoftSerial which must use pins 8 & 9 on the UNO.
Have a read of the code and get the CRC16 and AltSoftSerial libraries if you don't have them. Or you can stick with SoftwareSerial and change the code accordingly to match your setup.
Hopefully you will get a response from some registers. If you don't, then try changing the software serial port baud rate to 4800 baud and running the code again.
// Attempt to access a JXCT type NPK sensor to read registers 0x00 to 0x2F
// to see if there is any response from the NPK sensor.
//
// This attempt uses the AltSoftSerial & raw Modbus packets.
// Get AltSoftSerial at https://www.pjrc.com/teensy/td_libs_AltSoftSerial.html
//
// Also requires the CRC library by Rob Tillaart - install it via Library Manager
//
// RS485 module wired up as:
// RS485 DI signal to pin 9
// RS485 RO signal to pin 8
// RS485 RE signal to pin 7
// RS485 DE signal to pin 6
// RS485 VCC to 5V
// RS485 GND to GND
//
#include <AltSoftSerial.h>
#include "CRC16.h"
#define RE 6
#define DE 10
const uint32_t TIMEOUT = 500UL;
uint8_t msg[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00};
uint8_t values[11];
uint8_t regAddr = 0;
AltSoftSerial swSerial;
CRC16 crc(CRC16_MODBUS_POLYNOME,
CRC16_MODBUS_INITIAL,
CRC16_MODBUS_XOR_OUT,
CRC16_MODBUS_REV_IN,
CRC16_MODBUS_REV_OUT);
void setup() {
Serial.begin(9600);
swSerial.begin(9600);
pinMode(RE, OUTPUT);
pinMode(DE, OUTPUT);
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
Serial.println("\n\nModbus NPK register scanner.\n\n");
delay(1000);
}
void loop() {
uint32_t startTime = 0;
uint16_t crcValue = 0;
// insert the register address
msg[ 3 ] = regAddr++;
// generate the CRC16 Modbus checksum
crc.restart();
for (uint8_t i=0; i<sizeof( msg )-2; i++ ) {
crc.add( msg[i] );
}
crcValue = crc.calc();
// and insert it into the test message
msg[ sizeof(msg)-2 ] = (crcValue & 0xFF);
msg[ sizeof(msg)-1 ] = ((crcValue >> 8) & 0xFF);
Serial.print("TX: ");
printHexMessage( msg, sizeof(msg) );
// send the command
digitalWrite(DE, HIGH);
digitalWrite(RE, HIGH);
delay( 10 );
swSerial.write( msg, sizeof(msg) );
swSerial.flush();
digitalWrite(DE, LOW);
digitalWrite(RE, LOW);
Serial.print("RX: ");
// read any data received and print it out
startTime = millis();
while ( millis() - startTime <= TIMEOUT ) {
if (swSerial.available()) {
printHexByte(swSerial.read());
}
}
Serial.println();
delay(500);
// reset register address back to 0x00 once we reach address 48
if ( regAddr > 0x2F ) {
regAddr = 0;
Serial.println("\n\n\Rescan from register address 0x00 again in 5 seconds.\n\n");
delay( 5000 );
}
}
void printHexMessage( uint8_t values[], uint8_t sz ) {
for (uint8_t i = 0; i < sz; i++) {
printHexByte( values[i] );
}
Serial.print(" - ");
}
void printHexByte(byte b)
{
Serial.print((b >> 4) & 0xF, HEX);
Serial.print(b & 0xF, HEX);
Serial.print(' ');
}
I tried your code. In explanation you have written RE to 7 and DE to 6 but in code its RE 6 and DE 10. I tried both. but both the cases didn't work. I am attaching what results I am getting