RS-485 Serial/Modbus gurus requested for Teensy4.1 running Paul's ModbusRTU library.

milesg

Member
Hi All,
I'm working on a project to control some servos with Automation Direct's SureServo2 line of products and I am running into an issue I can't seem to resolve.

I'm currently using Paul's Modbus RTU Library as found here: https://github.com/PaulStoffregen/Modbus-Master-Slave-for-Arduino

I modified one of the examples for testing as shown:

Code:
#include <ModbusRtu.h>

uint16_t au16data[16];
uint8_t u8state;

Modbus master(0,Serial1,2); // 

modbus_t telegram;

unsigned long u32wait;

void setup() {
  Serial.begin(9600); // for viewing result during testing
  Serial1.begin(38400, SERIAL_8N2); // servo drive default com parameters
  master.begin(38400); 
  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 = 127; // slave address
    telegram.u8fct = 3; // function code (this one is registers read)
    telegram.u16RegAdd = 18; // start address in slave
    telegram.u16CoilsNo = 2; // 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() + 1000; 
    
      for (int i=0; i<16; i++) {
        Serial.print(au16data[i]);
      }
      Serial.println("..");
    }
    break;
  }
}

As you can see I've only modified the parameters to match the default parameters that the Servo Drive requires. Then at the bottom I've added a little loop to spit out all the data via my serial monitor to see if everything is working.

Short answer: it's not :(

To clarify, the serial monitor is spitting out nothing but the following each loop:

0000000000000000..

However I've attached a screenshot from my logic analyzer to show that I should be receiving "7554" in there somewhere (this is just the encoder count for the servo's current rotational position, this will change a lot as it is rotating). Note that I am reading these data from my analyzer with the listed signals connected to the appropriate teeny pins (0,1 & 2 in this example)
Capture.jpg

I've gone through A LOT of troubleshooting. Here's what I've tried:
  • Different Teensy 4.1s
  • Different Serial Ports on the Teensys (Serial1 and Serial2)
  • Different MAX3485 ICs (with 120ohm resistor installed).
  • Changing parameters in the servo drive to use different speed, data format (and of course updating the code to reflect those changes)
  • Different libraries: both the Smarmengol library which Paul's was forked from, and 4-20ma's (Doc Walker) ModbusMaster library which I had successfully used previously with the previous generation of SureServo (not SureServo2) drives via RS232 with a MAX3232 chip.

With my current hardware setup and this new model of servo drive, the result is always the same: query goes out, expected response comes back, but I don't get any usable data out of the library functions.

Please tell me I'm not overlooking something simple! I've been going nuts trying to get something I can work with, but I've had no luck so far. Actually, I will take a simple fix! Anything to help me move on and start being able to use my servos :p

Thanks in advance for any insight ya'll might be able to provide.
 
UPDATE: Solved it... I guess third time's a charm because I put in a 3rd MAX3485 and things started working!

I wasn't aware that my RX line going low with the enable line was wrong. I saw the "break condition" in my analyzer, but I just assumed that was normal since I don't know much about the nitty gritty of Serial comms.

Apparently 2/3 of my chips from Mouser exhibited this fault. I've attached an updated screenshot of the signal where the RX line stays high regardless of the EN signal and that's what seems to be working.

Capture2.jpg

Hopefully this info will help anyone else experiencing a similar issue with their transceiver chips.
 
When you say the RX line goes low with enable line makes me suspect a particular problem. If you disable the RS485 receiver when you enable the transmitter you will have trouble unless you have something to pull up the receiver output. Which is a tri-state. No pullup and it just floats around.
 
That is an interesting thought that I hadn't considered.

Double checking the datasheet shows that this is only a property of the RX output of the MAX3485 chip. Very interesting indeed *strokes imaginary goatee*.

Since it does work very consistently with 1 of my 3 chips (and does NOT work consistently with the other 2), I assumed it was an issue with some bad chips, but perhaps it's some esoteric variation in the manufacturing that makes the one 'good' chip tend to float high.

Could I just add a line to setup() like this?
Code:
pinMode(0, INPUT_PULLUP); // pin 0 is RX of Serial1


I would think that could make the pin state more reliable unless my Serial1.begin() or other subsequent serial commands nullify that pullup.

Because it was easy, I did try adding the pullup line as shown above, but it still did not work with my 'bad' chips. If you think I actually need a more hefty pullup resistor (like a 2.7k that I'm using elsewhere in my circuit already) I could give it a shot.

EDIT: It's nearing the end of my work-day here, but I went ahead and shoved a 2.7k pullup on Pin0 of my T4.1 and it didn't help. I think I can safely say that I've got a couple of duds here.

Thanks for the insight!
 
Last edited:
Sorry to resurrect this thread.

I just wanted to post an update for anyone else having similar issues with their MAX 485/486 and 3485/3486 chips. The issue was NOT bad chips. It was that I didn't have biasing resistors on my A and B output lines (A needs a pullup and B needs a pulldown). These resistors are not present on many circuit diagrams posted around the 'net and many articles neglect to mention their importance (some even say they aren't needed). The resistors aren't even shown on the reference circuits in the Maxim datasheet for these chips (What the heck!?) I can't find anything in the datasheet which talks about biasing or additional resistor requirements.

There are documents floating around which talk about their importance and what values should be selected based on cable length, noise, voltage, etc.... I've seen values suggested as low as 560Ohm, and as high as 100kOhm. I opted for 2.7kOhm resistors as that is what I'm already using a lot of in my circuit. Sure enough, all my previously marked 'bad' chips began to work when these resistors were in place.

I only found one other person in all my searches that was describing a similar issue with the RX line going low at the wrong times (just like in my screenshot above.) I believe this must be a more common problem than it seems to be online. Especially, considering all the incomplete documents and tutorials that lead me to believe I didn't need these resistors. So, I hope I can spread the word and help someone else keep from tearing their hair out.

The More You Know!
 
Eeleker, glad to hear it! I have been using 2.7k resistors as mentioned for probably hundreds, if not thousands of development hours at this point and I haven't had a single communication glitch (though, I'm not pushing the baud rate too hard). I'm not exactly sure what UhClem means about the slightly altered input thresholds, but the resistors were certainly necessary in my use case. Regardless, the article UhClem linked is quite helpful in understanding the nuances of the RS-485 standard, but I expect you may be like me and just be happy to continue developing instead of troubleshooting. Best of luck on your project.
 
Back
Top