Arduino Nano Slave --> Max485 --> Click PLC

I'm trying to use a Nano connected to a GPS module to send speed data to a Click PLC from Automation Direct (C2-03CPU).

I have the GPS Module connected to D10 and D11 and am able to view good data in the serial monitor.

After getting that to work, I turned my attention to getting communication between the Arduino and Click PLC. I couldn't read anything on the PLC so I decided to see what I can read using the computer first as the Master.

I have an Arduino Nano connected to a Max 485 module, which is connected to a Waveshare USB to RS-485 converter.

My connections are as follows:
RE / DE on the max 485 --> Pin 7 on the arduino
RO on the Max 485 --> Pin 9 on the arduino
DI on the Max 485 --> Pin 8 on the arduino
A on the Max 485 ---> A on the Waveshare USB to 485 converter
B on the Max 485 ---> B on the Waveshare USB to 485 converter

I loaded the following code and viewed it in Putty... and it successfully spit out "Hello From Arduino" every second. I'm hoping that means that my wiring is correct?

#include <SoftwareSerial.h>

#define MAX485_DE_RE 7
#define MAX485_RO 9
#define MAX485_DI 8

SoftwareSerial rs485Serial(MAX485_RO, MAX485_DI);

void setup() {
  pinMode(MAX485_DE_RE, OUTPUT);
  digitalWrite(MAX485_DE_RE, HIGH);
  rs485Serial.begin(9600);
}

void loop() {
  rs485Serial.println("Hello from Arduino!");
  delay(1000);
}

So then I loaded the ModbusRtu library and tried running some of the examples with some modifications for my setup. Then I tried to use QModBus to communicate with the Nano, but I keep getting an error

.

Here is the latest version of the code that hasn't worked:

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

// Define the pins used by the MAX485
#define MAX485_DE_RE_PIN 7 // Connected to RE / DE pins on the MAX485
#define MAX485_DI_PIN 8     // Connected to DI pin on the MAX485
#define MAX485_RO_PIN 9     // Connected to RO pin on the MAX485

// Create a SoftwareSerial object for communication with the MAX485
SoftwareSerial rs485Serial(MAX485_DI_PIN, MAX485_RO_PIN); // RX, TX

// Data array for Modbus network sharing
uint16_t au16data[16] = {
  3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, -1
};

// Modbus object declaration
Modbus slave(1, rs485Serial, MAX485_DE_RE_PIN); // Slave ID 1, using SoftwareSerial and DE/RE control

void setup() {
  // Initialize serial communication with baud rate 19200
  Serial.begin(19200);

  // Initialize SoftwareSerial for communication with the MAX485
  rs485Serial.begin(9600);

  // Setup the Modbus slave
  slave.start();
}

void loop() {
  // Poll the Modbus slave to handle incoming requests
  slave.poll(au16data, 16);
}

I have double checked all the wiring... after spending a few days and fighting the urge to throw the computer against the wall, I am reaching out for help.

My goal is to transfer the speed value from the GPS module to the Click PLC.
Attached is my GPS sketch if someone is interested.
GPS_Testing.ino (1.4 KB)

I was finally able to get these to communicate by abandoning the SoftwareSerial for the modbus and just using the TX and RX pins on the Nano. After debugging using QModBus software and the USB to RS485 converter, it was easy to connect to the Click PLC.

Here is the code I'm running now if anyone is interested:

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

// GPS pins
#define GPS_RX_PIN 10
#define GPS_TX_PIN 11

// RS485 pins
#define TXEN 7

// Modbus setup
uint16_t inputRegisters[16] = {0}; // Array for input registers

TinyGPSPlus gps; // Create an instance of the TinyGPS++ library
SoftwareSerial gpsSerial(GPS_RX_PIN, GPS_TX_PIN); // RX, TX

// Modbus slave setup
Modbus slave(1, Serial, TXEN); // Modbus slave ID 1

void setup() {
  // Initialize serial communication for debugging
  Serial.begin(9600);
  Serial.println("GPS Data:");

  // Initialize GPS serial communication
  gpsSerial.begin(9600);

  // Initialize Modbus communication
  slave.start();
}

void loop() {
  // Read GPS data
  while (gpsSerial.available()) {
    if (gps.encode(gpsSerial.read())) { // Feed each character to the TinyGPS++ library
      if (gps.speed.isValid()) { // Check if the GPS speed data is valid
        // Store speed in the first input register (scaled to integer)
        inputRegisters[0] = gps.speed.mph() * 100; // Scale by 100 to preserve decimal places

        // Debugging output
        Serial.print("Speed: ");
        Serial.print(gps.speed.mph());
        Serial.println(" mph");
      }
    }
  }

  // Poll the Modbus slave to handle requests
  slave.poll(inputRegisters, 16);
}

Always better to use hardwareserial, if possible.
Anyway, you had rx and tx inverted in your softwareserial modbus code.

Ugh... Really? I'm not a pro, but I should have been able to catch that. Thanks

Happens all the time, pro or not. And sometimes modules have labels inverted.
That's why in serial communication problems, first remedy is to swap rx/tx.. :wink:

generally TX is transmit out and RX is receive in
however, I have come across systems where Tx is transmit into device and Rx is transmit out to an external receiver - causes real problems if custom PCB has been built

if in doubt use a multimeter to check voltages - transmit signal when idle should be logical 1
TTL voltages 3.3V or 5V logical 1 and 0V logical 0 - idle state is logical 1 (3.3V or 5V)
RS232 voltages -6 to -12V logical 1 and +6 to +12V logical 0 - idle state is logical 1 (-6 to -12V)

e.g. RS232 transmitting letter a (hex 0x61 binary 01100001) at 9600baud

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.