MODBUS RTU communication

The ArduinoModbus library has been confirmed to work.

https://github.com/PaulStoffregen/ArduinoModbus
Paul, the ArduinoModbus library has been working great on a Teensy 3.1 board, until I tripped on the USB programming cable and ripped the microUSB connecter off the board. Note to self: tidy up my hobby room.

I decided to take the opportunity to move the project to a Teensy 3.5, using Serial5 instead of Serial1. That's where things have gone off the rails. I initially thought I'd made a wiring error but have confirmed good comms using the modified serialPassthrough sketch below:

Code:
void setup() {
  Serial.begin(9600);
  Serial5.begin(9600);
  Serial5.transmitterEnable(35);
}

void loop() {
  if (Serial.available()) {        // If anything comes in Serial (USB),
    Serial5.write(Serial.read());  // read it and send it out Serial1 (pins 0 & 1)
  }

  if (Serial5.available()) {       // If anything comes in Serial1 (pins 0 & 1)
    Serial.print(Serial5.read(),HEX);  // read it and send it out Serial (USB)
    Serial.print(" ");
  }
}

Modbus Master UART and resulting Serial Monitor traffic:
debug.png


But when I try the stripped down Modbus Slave sketch below, the Master times out.

Code:
#define RS485_DEFAULT_TX_PIN 33
#define RS485_SERIAL_PORT Serial5
#define CUSTOM_RS485_DEFAULT_DE_PIN 35
#define CUSTOM_RS485_DEFAULT_RE_PIN -1
#define debug

#include <ArduinoRS485.h> // ArduinoModbus depends on the ArduinoRS485 library
#include <ArduinoModbus.h>

const int numCoils = 5;
const int numDiscreteInputs = 5;
const int numHoldingRegisters = 20;
const int numInputRegisters = 5;

void setup() {

  Serial.begin(115200);
//  while (!Serial) ; // Needed for Leonardo only  MAY NEED TO DELETE FOR TEENSY
  Serial5.begin(9600);
  Serial5.transmitterEnable(35); // specific to teensy
  // start the Modbus RTU server, with (slave) id 1
  if (!ModbusRTUServer.begin(1, 9600)) {
    Serial.println("Failed to start Modbus RTU Server!");
    while (1);
  }
  // configure registers at starting address 0x00
  ModbusRTUServer.configureCoils(0x00, numCoils);
  ModbusRTUServer.configureDiscreteInputs(0x00, numDiscreteInputs);
  ModbusRTUServer.configureHoldingRegisters(0x00, numHoldingRegisters);
  ModbusRTUServer.configureInputRegisters(0x00, numInputRegisters);

  ModbusRTUServer.holdingRegisterWrite(5,1); // set initial display

}

void loop() {

// poll for Modbus RTU requests
  if(ModbusRTUServer.poll()) updateRegs();

} // Loop

// function to tie sketch variables to registers
void updateRegs() {
  #ifdef debug
    Serial.print("Coils:");
    for (byte i=0; i<numCoils; i++) {
      Serial.print(i); Serial.print(":"); Serial.print(ModbusRTUServer.coilRead(i),HEX); Serial.print(", ");
    }
    Serial.println();
    Serial.print("DI's:");
    for (byte i=0; i<numDiscreteInputs; i++) {
      Serial.print(i); Serial.print(":"); Serial.print(ModbusRTUServer.discreteInputRead(i),HEX); Serial.print(", ");
    }
    Serial.println();
    Serial.print("Holding Regs:");
    for (byte i=0; i<numHoldingRegisters; i++) {
      Serial.print(i); Serial.print(":"); Serial.print(ModbusRTUServer.holdingRegisterRead(i),HEX); Serial.print(", ");
    }
    Serial.println();
    Serial.print("II's:");
    for (byte i=0; i<numInputRegisters; i++) {
      Serial.print(i); Serial.print(":"); Serial.print(ModbusRTUServer.inputRegisterRead(i),HEX); Serial.print(", ");
    }
    Serial.println();
    Serial.printf("%02d:%02d:%02d ",lowByte(ModbusRTUServer.holdingRegisterRead(2)),highByte(ModbusRTUServer.holdingRegisterRead(3)),lowByte(ModbusRTUServer.holdingRegisterRead(3)));
    Serial.printf("%02d/%02d/%02d, ",highByte(ModbusRTUServer.holdingRegisterRead(1)),lowByte(ModbusRTUServer.holdingRegisterRead(1)),lowByte(ModbusRTUServer.holdingRegisterRead(0)));
  #endif

}

The one key difference is I'm attempting to now use Serial5 on the 3.5 instead of Serial1 on the 3.1 so my best guess is one of the cascaded libraries does not correctly handle Serial5? Any insight would be greatly appreciated!
 
Good news: got it working by following your advice in post #8. I commented out the last few lines of RS485.cpp and hardcoded my pin assignments:
Code:
/*
#ifdef RS485_SERIAL_PORT
RS485Class RS485(RS485_SERIAL_PORT, RS485_DEFAULT_TX_PIN, RS485_DEFAULT_DE_PIN, RS485_DEFAULT_RE_PIN);
#else
RS485Class RS485(SERIAL_PORT_HARDWARE, RS485_DEFAULT_TX_PIN, RS485_DEFAULT_DE_PIN, RS485_DEFAULT_RE_PIN);
#endif */
RS485Class RS485(Serial5, 33, 35, -1);

What I don't understand is why the #defines at the top of my sketch were not satisfying the (now commented out) #ifdef above.
 
What I don't understand is why the #defines at the top of my sketch were not satisfying the (now commented out) #ifdef above.

Because defines in a source file only apply to that file. Each .c, .cc, .cpp, .ino, etc. file is compiled separately. To apply a define to the whole project, you’d need to add it to the whole-project build options. The Arduino IDE doesn’t make this easy. I use PlatformIO with VSCode, personally.

There is an “Arduino way”, actually, to add project-level options, but it’s an “always option” that gets applied to everything and all projects until it’s removed or changed. See here for more information: https://github.com/ssilverman/QNEth...E.md#configuring-macros-using-the-arduino-ide
 
Back
Top