RS485 / Modbus RTU on Opta

I'm trying to send ModBus command from Arduino Opta to Delta ASDA-B3 servo drive.
What is working:

  • I can send via PC and "USB to RS485" module a Modbus signal via software QModMaster to the servo drive
  • I can send the same string from PC via serial connection via Tera Term software to servo drive
  • When I send data from Opta via serial connection to PC it receives something but not what I've send.

Unable:

  • To send Modbus commands from Arduino Opta to PC or servo drive

When I run program code below from Arduino opta to PC it receives different things. I already tried:

  • changing parity settings in PC
  • baudrates 9600, 19200, 38400
  • change A- & B+ wire
  • placing 130 ohm resistor at none, 1 or both ends (I don't have 120ohm for the moment)

What do you suggest to test next?

  • ...
  • Buy oscilloscope and analyse signals?
  • Buy MAX485 RS485 to TTL for arduino UNO/Nano (I have still a Uno and a Nano available) so I can test if same software works on these hardware?

When I send on Arduino: 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10
I receive on PC: ?~}>|{=
PC settings: Baud 19200 - Data size: 7 or 8 - Parity: None or Even or Odd - Handshake: OFF

Below full program:

/**
  Getting Started with RS-485 on Opta™
  Name: Opta_RS485_Sender
  Purpose: Sends values to Receiver Opta via Serial Monitor

  @author Giampaolo Mancini, Arduino
  @version 1.0 02/02/2023 
*/

#include <ArduinoRS485.h>

constexpr auto baudrate{ 19200 };

const unsigned long interval = 200;  // Interval in millisec
unsigned long previousMillis = 0;   // Time
unsigned long counter = 1;          // Startvalue

// Calculate preDelay and postDelay in microseconds for stable RS-485 transmission
constexpr auto bitduration{ 1.f / baudrate };
constexpr auto wordlen{ 9.6f };  // OR 10.0f depending on the channel configuration
constexpr auto preDelayBR{ bitduration * wordlen * 3.5f * 1e6 };
constexpr auto postDelayBR{ bitduration * wordlen * 3.5f * 1e6 };

void setup() {
  Serial.begin(baudrate);
  while (!Serial);
  
  RS485.begin(baudrate);
  RS485.setDelays(preDelayBR, postDelayBR);
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;  // Reset de tijd

    Serial.println(counter);
    RS485.beginTransmission();
    RS485.write(counter);
    RS485.endTransmission();
    
    if (counter >= 10) {
      counter = 1;
      delay(10000);
    } else {
      counter++;
    }
  }

}

If you get gibberish characters, it usually to do with baud rate, but Modbus is binary so you would not expect to get printable characters. Ideally you can set you terminal program to display hex.

Modbus typically uses 8 bit data, Even parity.

Looks like you have tried most of the things I would have done. An additional thing to look out for is a pullup/pulldown on the data lines. Often these need to be enabled in a transceiver with jumpers or similar.

A scope, even a cheap one is a highly useful tool. Usually within minutes of connecting a scope I get the "aha that's the problem" moment.

Thank you for your response. I was in the middle of writing a reply when, to my great surprise, I suddenly started receiving exactly what I sent. Please read on. This leads me to suspect that you may be right about pull-up and pull-down resistors. What resistor values would you recommend? And how can I implement a pull-up when I only have a 24V supply? Here is the reply I had started writing:


This evening, I went to a local store to buy an oscilloscope and an additional USB-RS485 module. Here are my tests so far:

  1. PC1 with USB-RS485 module (Waveshare SKU22456) connected to PC2 with USB-RS485 module (Delock 64055): Both set to baud rate 38400, 8,N,1. Using Putty on both sides, everything I typed on one side was successfully received on the other.
  2. Arduino Opta with both USB-RS485 modules: On the receiving end, I kept getting incorrect characters for anything I sent. I experimented with baud rate adjustments (±5% in steps of 0.1%) but without success.
  3. Oscilloscope observations: At first glance, the signals look very similar. However, I noticed that in an idle state, both A- and B+ hover around 2.2V. Here's a printout of a signal from test 1.
  4. Unexpected results during retesting: I didn’t take a printout during test 2, so I reconnected everything after disassembling it earlier. This time, I noticed that in idle mode, the signals are further apart—about 0.6V and 3.8V. To my great surprise, the values I sent are now being correctly received. Perhaps a small "hooray" before bed after all?

Yes, your idle state should definitely be more like picture 2!

Good questions. The resistor values depend on situation, but 1k is probably a good value to start. The spec says there should be a minimum 0.2V differential in the idle state. Some data sheets recommend smaller values, but if you go too low that may interfere with the transceivers in the active state.

If you have don't have access to 5V, I don't feel qualified to calculate a suitable value; I would have to consult an EE on that.

Only one node needs to have PU/PD enabled. Here is a typical example. Here "Master A" is D+ and "Master B" is D-. (A and B are often reversed in meaning).

I haven't found much detail on Opta 485, apart from the following https://docs.arduino.cc/tutorials/opta/user-manual/#rs-485 The following post indicates that the Opta does not have internal termination : Rs485 differential output looks single ended? - #9 by stitech

at home I had a 24V to 5V PCB. I finally managed to send a proper request to the servo drive. I'm not there yet, there will probably be some other hurdles to overcome.

But I notice that the idle signal resembles the second screenshot in my previous post until I also plug in the USB programming cable. Then the signals come closer to each other again. However, with the additional resistors, it is still possible to transmit signals.

To shed some light on the idle state:

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