0
\$\begingroup\$

Im trying to control a temperature controller using Arduino MEGA over SoftwareSerial.

Im using Modbus-Master-Slave-for-Arduino library and I tried to test using example code below. It gives only 0 for each item of the received data array au16data[].

Im using RS-485 serial transceiver module for interface to temperature controller and SoftwareSerial pins. But, There is no any pin definition for DE and RE pins. How can I connect A and B terminal of the controller to Arduino?

#include <ModbusRtu.h>
#include <SoftwareSerial.h>

// data array for modbus network sharing
uint16_t au16data[16];
uint8_t u8state;

/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  u8serno : serial port (use 0 for Serial)
 *  u8txenpin : 0 for RS-232 and USB-FTDI 
 *               or any pin number > 1 for RS-485
 */
Modbus master(0); // this is master and RS-232 or USB-FTDI via software serial

/**
 * This is an structe which contains a query to an slave device
 */
modbus_t telegram;

unsigned long u32wait;

SoftwareSerial mySerial(12, 13);//Create a SoftwareSerial object so that we can use software serial. Search "software serial" on Arduino.cc to find out more details.

void setup() {
  Serial.begin(9600);//use the hardware serial if you want to connect to your computer via usb cable, etc.
  master.begin( &mySerial, 9600 ); // begin the ModBus object. The first parameter is the address of your SoftwareSerial address. Do not forget the "&". 9600 means baud-rate at 9600
  master.setTimeOut( 2000 ); // if there is no answer in 2000 ms, roll over
  u32wait = millis() + 1000;
  u8state = 0; 
}

void loop() {
  switch( u8state ) {
  case 0: 
    if (millis() > u32wait) u8state++; // wait state
    break;
  case 1: 
    telegram.u8id = 0x01; // slave address
    telegram.u8fct = 0x04; // function code (this one is registers read)
    telegram.u16RegAdd = 0x03E8; // start address in slave
    telegram.u16CoilsNo = 0x01; // number of elements (coils or registers) to read
    telegram.au16reg = au16data; // pointer to a memory array in the Arduino

    master.query( telegram ); // send query (only once)
    u8state++;
    break;
  case 2:
    master.poll(); // check incoming messages
    if (master.getState() == COM_IDLE) {
      u8state = 0;
      u32wait = millis() + 2000; 
        Serial.println(au16data[0]);//Or do something else!
        Serial.println(au16data[1]);//Or do something else!
        Serial.println(au16data[2]);//Or do something else!
        Serial.println(au16data[3]);//Or do something else!
        Serial.println(au16data[4]);//Or do something else!
        Serial.println(au16data[5]);//Or do something else!
        Serial.println(au16data[6]);//Or do something else!
        Serial.println(au16data[7]);//Or do something else!
        Serial.println(au16data[8]);//Or do something else!
        Serial.println(au16data[9]);//Or do something else!
        Serial.println(au16data[10]);//Or do something else!
        Serial.println(au16data[11]);//Or do something else!
        Serial.println(au16data[12]);//Or do something else!
        Serial.println(au16data[13]);//Or do something else!
        Serial.println(au16data[14]);//Or do something else!
        Serial.println(au16data[15]);//Or do something else!
    }
    break;
  }
}
\$\endgroup\$
  • \$\begingroup\$ why do you use SoftwareSerial on a MCU with 4 hardware Serials? \$\endgroup\$ – Juraj Oct 11 at 13:50
  • \$\begingroup\$ Actually Im testing my project. I have already made a PCB. I will change to HardwareSerial in next version. \$\endgroup\$ – user_fs10 Oct 12 at 5:25
0
\$\begingroup\$

These appear to be Driver Output and Receiver Output enable pins.

Your website link shows that you should do the following to these pins

RE..........Receiver Output Enable (Low to enable)

DE..........Driver Output Enable (high to enable)

Enables are not part of RS-485 and so won't be handled by the library, you'll have to control these pins yourself by using a DigitalWrite() before you transmit/receive.

\$\endgroup\$
  • \$\begingroup\$ Thanks for your answer. According to web site DE+RE should HIGH when transmitting and DE+RE should LOW when reeving. This should be done in library. \$\endgroup\$ – user_fs10 Oct 11 at 10:12
  • \$\begingroup\$ Good point, it looks like you should just hook these inputs up to some GPIOs and toggle them yourself. \$\endgroup\$ – VBwhatnow Oct 11 at 10:16
  • \$\begingroup\$ Yes. I have added it to my code. After case 1: line, put DE+RE to HIGH and after case 2:, DE+RE put LOW. Nothing changed. \$\endgroup\$ – user_fs10 Oct 11 at 10:35
0
\$\begingroup\$

Use RE+DE pin number when initializing the Modbus object like below. There is optional parameter for DE+RE pin.

#define SSerialTxControl 8
master.begin( &mySerial, 9600, SSerialTxControl );

This is the library function,

  /**
   * @brief
   * Initialize class object.
   *
   * Sets up the software serial port using specified baud rate and SoftwareSerial object.
   * Call once class has been instantiated, typically within setup().
   *
   * @param *sPort     pointer to SoftwareSerial class object
   * @param u32speed   baud rate, in standard increments (300..115200)
   * **@param u8txenpin  pin for txen RS-485 (=0 means USB/RS232C mode)**
   * @ingroup setup
   */
  void Modbus::begin(SoftwareSerial *sPort, long u32speed, uint8_t u8txenpin)
  {

    this->u8txenpin=u8txenpin;
      softPort=sPort;

      softPort->begin(u32speed);

      if (u8txenpin > 1)   // pin 0 & pin 1 are reserved for RX/TX
      {
          // return RS485 transceiver to transmit mode
          pinMode(u8txenpin, OUTPUT);
          digitalWrite(u8txenpin, LOW);
      }

      while(softPort->read() >= 0);
      u8lastRec = u8BufferSize = 0;
      u16InCnt = u16OutCnt = u16errCnt = 0;
  }
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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