0
\$\begingroup\$

I am working on project using Hukseflux SR05-D2A2 thermal sensors. These sensors support Modbus communication through a TTL interface. The objective is to read the value at a specific address in the sensor (in my case, it is the register holding the irradiation value measured by the sensor).

Reading from one sensor is easily done as follows:

  • Connect the TTL interface of the sensor with a microcontroller's serial pins (Arduino for example).

  • Use a library that implements the Modbus communication functions (for example, ModbusMaster for Arduino) to issue requests.

  • Read the data received on the receiver pin of the Arduino.

Everything works well in this case. However, when trying to connect 2 sensors to 1 master (Arduino), I am having problems. I have tried to connect both TXs and RXs of the 2 sensors together and then to the Arduino's RX and TX respectively. Then, I tried to send requests for the sensors by using their addresses, and I am getting an error. Here is the code:

#include <ModbusMaster.h>

#define Common 13

// instantiate ModbusMaster object
ModbusMaster node;

void preTransmission()
{
  digitalWrite(Common, 1);
}

void postTransmission()
{
  digitalWrite(Common, 0);
}

void setup()
{
  uint8_t result;
  pinMode(Common, OUTPUT);
  
  digitalWrite(Common, 0);

  // Communication of the arduino and the serial monitor
  Serial.begin(19200);
  //Communication of arduino with sensors
  Serial1.begin(19200, SERIAL_8E1);
  
  // Modbus slave ID 1
  node.begin(1, Serial1);
  // Callbacks allow us to configure the RS485 transceiver correctly
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);
  do
  {
    result = node.readInputRegisters(0x0000, 1);
    Serial.println(result);
    Serial.println(node.getResponseBuffer(0x00));
    
  } while (result != 0);

  delay(1000);
  //Modbus ID slave 2
  node.begin(2, Serial1);
  node.preTransmission(preTransmission2);
  node.postTransmission(postTransmission2);
  
  do
  {
    result = node.readInputRegisters(0x0000, 1);
    Serial.println(result);
    Serial.println(node.getResponseBuffer(0x00));
    
  } while (result != 0); 
}

void loop()
{
  
}

I would appreciate it if anybody could suggest solutions to this problem. Note that I am open for using pyModbus to communicate with the sensors using a Raspberry Pi if anybody can suggest a solution that uses it.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Are the sensors transmitters disabled (aka tri-state) when they are not transmitting? \$\endgroup\$
    – user28910
    Commented Jan 24, 2023 at 19:00
  • \$\begingroup\$ I do not think so. To let the sensor receive a request, you should put the Common terminal ON (as far as I understand). However, the transmits whenever it receives a correct request. \$\endgroup\$
    – RandomEye
    Commented Jan 24, 2023 at 20:51
  • \$\begingroup\$ Disconnecting the common wire is probably not a good idea. Ideally you should have chosen the RS485 version of the sensor as this would avoid the problems you observe. What I think is your current problem is the the TX signals fight with each other. To resolve this, insert a 1N4148 diode in each of the sensors TX wires with the diode cathode towards the sensor. The other end of the diodes are connected together and then to the Arduino RX. Add a 10k resistor between the Arduino RX and 5V pins. Note that with TTL level signals that is is unwise to have them over a couple of metres in length. \$\endgroup\$
    – Kartman
    Commented Jan 24, 2023 at 21:24

1 Answer 1

2
\$\begingroup\$

You can NOT mix Modbus devices with RS-485 and TTL signals together on one bus!

And yes, the RS-485 option would have been the better choice.

As far as I know you do not need the RS-485 transceivers for getting Modbus up and running with multiple TTL devices, as long as they tri-state their TX pins as long as they are not addressed.

You can connect the master's TX (set to output all the time) directly to all slaves RX pins.

You can also connect all slaves TX pins together to the master's RX pin (set to input. If a physical pull-down or an internal pull-up must be used, is up to testing ;).

BUT: All TX pins of all slaves MUST be set to input (or tri-state) as long as no slave was addressed. Serial resistors on the slaves TX pins (47 Ω or so) could minimize current draw should this sometimes not work as expected.

Only the slave that actually received a valid request is allowed to set it's TX to output mode before transmitting the response, and it must reset it's TX to input immediately afterwards. Not doing so will block the slaves from sending due to outputs working against each other.

Basically what the TX-Enable pin does on an RS-485 interface could be done with switching the slave's TX pins from input to output and vice versa.

If you'd program the slaves yourself, you should replace beginTransmission() and endTransmission() functions with code that instead of toggling the DE signal changes the pin direction.

On the master any Modbus library could be used. Those may toggle the DE pin despite it is not needed in this situation.

If these devices support modbus over TTL they should already be able to disable their TX pins. The datasheet leaves this point a bit open. I recommend to ask the manufacturer about this point.

PS: do not forget the 2 ms of silence between any request from the master (put a delay of 2 ms before each write). This pause is mandatory and usually not handled by the libraries. If it is missing all sorts of collisions may happen.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.