RS485 to communicate with CUI Encoder (AMT21, RS485)

Hello,
I'm trying to get encoder readings from an encoder over RS485 through my Arduino Mega. The encoder that I am using is an AMT21.

I wired the A/B side of my RS485 interface to the encoder and the DL/DE/RE/RO pins to the Arduino as per this tutorial.

I haven't been able to get any readings from the encoder. To test, I upload the sketch to my Arduino and open the Serial Window. I type 'T' (as I believe this is command char) and I receive nothing in return. At no point is the encoder available.

Here is my code:

#include <SoftwareSerial.h>

//#define RX        19
//#define TX        18

#define RX        10
#define TX        11

#define RxTx 3

#define Transmit    HIGH
#define Receive     LOW

#define Pin13LED         13

SoftwareSerial RS485Encoder(RX, TX);

int byteIn;
int byteOut;

void setup()   /****** SETUP: RUNS ONCE ******/
{
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Serial ready for transmitting");
   
  pinMode(Pin13LED, OUTPUT);   
  pinMode(RxTx, OUTPUT);    
  
  //digitalWrite(RxTx, Receive);   //Initialize transciever to receive data  

  RS485Encoder.begin(2000000);        // set the data rate 

}//--(end setup )---


void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
  digitalWrite(Pin13LED, HIGH);       //On when not transmitting
  if (Serial.available())
  {
    Serial.println("Sent");           //Serial indicator
    byteOut = Serial.read();     //Locally store the transmitted string
    
    digitalWrite(RxTx, Transmit);     // Transmit   
    RS485Encoder.write(byteOut); // Send byte to encoder
    
    digitalWrite(Pin13LED, LOW);      // Off momentarily 
    delay(10);
    digitalWrite(RxTx, Receive);      // Receive   
  }
  
  if (RS485Encoder.available())       //Look for data from encoder
   {
    Serial.println("Received");
    digitalWrite(Pin13LED, LOW);        // Off momentarily
    byteIn = RS485Encoder.read();    // Read received byte
    Serial.write(byteIn);         // Show on Serial Monitor
    delay(10);
   }  
}

I appreciate any help you all can offer.

Thanks!
Adam

 RS485Encoder.begin(2000000);        // set the data rate

Software serial does not work well, and not at all at high data rates. Try it at 9600 Baud.

Altsoftserial and NeoSWserial are better options. If you have to go that fast, hardware serial is your only option.

I quote the manual:

The AMT21 utilizes a half-duplex RS485 interface where the host sends a command over the differential bus at the proper
baud rate (default 2 Mbps), then the encoder takes control and responds.

You won't ever get SoftwareSerial communication reliable with any baud rate higher than 38400, even that rate is only reached if the counterpart device is extremely timing tolerant. With standard hardware you might reach 9600 baud but nothing above that.

As you have a Mega, you don't need that crippled SoftwareSerial, you have 4 hardware serial interfaces. And fortunately the maximum baud rate supported by these is 2Mbit/s.

Thanks for your responses. Switching to hardware serial allowed me to communicate with the encoder. It seems like I get 3 responses though for each single command char sent.

Based on the documentation the encoder should respond with two bytes, so I'm not sure what the 3rd byte is for, although it seems like the first byte is always 84.

Any idea what this first byte is for or what the 3 bytes signify?

For instance:

command char 'T' sent
byteIn = 84
byteIn = 100
byteIn = 56

then I'll rotate the encoder a little
command char 'T' sent
byteIn = 84
byteIn = 152
byteIn = 179

my updated code:

#define RX        19  //For Arduino Mega
#define TX        18

//#define RxTx 3
#define Re    3
#define De    5

#define Transmit    HIGH
#define Receive     LOW

#define Pin13LED         13

uint8_t byteIn;
int byteOut;

void setup()   /****** SETUP: RUNS ONCE ******/
{
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Serial ready for transmitting");
   
  pinMode(Pin13LED, OUTPUT);   
  pinMode(Re, OUTPUT);
  pinMode(De, OUTPUT);    
  
  //digitalWrite(RxTx, Receive);   //Initialize transciever to receive data
  RS485Receive();  

  Serial1.begin(2000000);        // set the data rate 

}//--(end setup )---


void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
  digitalWrite(Pin13LED, HIGH);       //On when not transmitting
  if (Serial.available())
  {
    Serial.println("Sent");           //Serial indicator
    byteOut = Serial.read();          //Locally store the transmitted string
    
    RS485Transmit(); 
    Serial1.write(byteOut);      // Send byte to encoder
    
    digitalWrite(Pin13LED, LOW);      // Off momentarily 
    delay(10);
    RS485Receive();
    delay(250);    
  }
  
  if (Serial1.available())       //Look for data from encoder
   {
    Serial.println("Received");
    digitalWrite(Pin13LED, LOW);        // Off momentarily
    byteIn = Serial1.read();     // Read received byte
    Serial.println(byteIn);
    delay(10);
   }  
}

void RS485Transmit()
{
  digitalWrite(Re, LOW);   
  digitalWrite(De, HIGH);   
}

void RS485Receive()
{
  digitalWrite(Re, HIGH);   
  digitalWrite(De, LOW);  
}

Any idea what this first byte is for or what the 3 bytes signify?

84 is the ASCII code of "T", so it's what you sent. I guess your RS485 adapter is a cheap one which doesn't correctly define the RO pin if RE is high, so you get everything you sent back on the reading side.

The two values you got have the error checking bits correctly set, so the values are probably correct.

Hi, Iam trying to do the same. Read AMT21 Data via RS485. I made my own sketch that didnt work and now found and tried this one, and sadly thisone doesnt work either. Iam using a Teensy 3.5.. I just dont get a response from the Encoder. I have read the Datasheet carefully, but still have no clue as to what might be wrong except gotten delivered a dead on arrival encoder.

What i got:
-I can get back the sent command Char, transceiver (max485 based) seems to work. Also tried another one. Doesnt seem to be the problem.
-Tested the connections and plug pins. All OK.
-If I plug in the Encoder after sending the command Char (triggering the sketch into receive mode), I get a 255 back. Seems to be shorting somehow. What could this imply?
-When I send the command Char via serial monitor, I get two times "sent" back. What could be the issue here? LED on Teensy blinks as expected from the sketch.

Is there some kind of setup necessary to get the encoder to work in the beginning? Couldnt find anything, but who knows?
Any help would be highly appreciated.

Iam using a Teensy 3.5

A Teensy 3.5 is a 3V3 device. Post a complete wiring diagram! Post a link to your RS-485 adapter.

pylon:
A Teensy 3.5 is a 3V3 device. Post a complete wiring diagram! Post a link to your RS-485 adapter.

Thanks for the reply. Yes I know, but it is 5V tolerant. By manual manipulation of the Send/Receive pin, i can get the outgoing "call" back in. It seems the teensy can get the data from the breakout-board. But I already ordered another rs485 board (http://www.hobbytronics.co.uk/rs485-breakout) for exactly this 3.3 issue. The chip on the encoder should be fine with 5V as well, though Iam not a pro on this issues. Now Iam using one of those china rs485 transceiver boards utilizing a max485 (no real datasheet available). I will post an update when i tried the new rs485 breakout board.

Still no new Breakout Board but a different idea. As with Arduino one could simply power the encoder by Arduino 5V output, I had to power it from a seperate 5V powersupply. Digging into rs485 I found that there is talk of a "common ground" wire. How might this play into my problems?

Digging into rs485 I found that there is talk of a "common ground" wire.

With RS-485 you need only two wires, the signal is transferred differentially so a common ground is not needed. Of course you need a common ground between the Teensy and the RS-485 driver board.

Grounds are commonly used with RS485 to limit the voltage difference between endpoints to less than
about 10V. The ground is not used for signalling, just to keep the driver and receiver at close enough
voltages to work without needing isolation.

Thanks for the replies. I now got it working using the mentioned adafruit board. However. I also use new cables teensy everything, and hooking this setup up to the old teensy still doesnt work (of course using the same sketch). I should mention that on the old setup there is also a Pololu motor driver board (vnh5019) attached to the teensy (power over Analog GND and 3.3V (250mA max) - rs485 Transiver powered over GND and Vin). This board also pulls its power of the teensy, though if i disconnect it (the power pins only) there is still no rs485 functionality. Could the other used pins mess with the serial communication, although they arent used or defined in the sketch? The sketch with the motor functionality included doesnt work either (it also uses rs485). Any clues what could be going on here? Electrical issues?

In all sketches used i have,
Serial1.setRX(0);
Serial1.setTX(1);
included, the Teensy should know where its used serial pins are.

Hi I am trying to do the same, my CUI encoder is the 21 series and I was wondering if you can post your wiring diagram, I am trying to use this sketch but keeps coming up with an error: "Serial1 was not declared in this scope. I have tried the Arduino Uno and the 2560 Mega R3
Any help is appreciated.

Thanks

michellegmit:
Hi I am trying to do the same, my CUI encoder is the 21 series and I was wondering if you can post your wiring diagram, I am trying to use this sketch but keeps coming up with an error: "Serial1 was not declared in this scope. I have tried the Arduino Uno and the 2560 Mega R3
Any help is appreciated.

Thanks

Hi, although Iam not into Arduino per se, the Uno only has "Serial" and that should be the USB port, as I understand it. The Mega should have Serial1. As you have a software problem, I would sugest to check the Arduino IDE ("Sketch Program") There somewhere you can define for wich board the sketch is ment to be. Did you switch this to "Mega"? To me it seems that you try to compile for the UNO which of course doesnt have the Serial1, and that throws the error.

At the top of the program there is a line with pulldowns "File, Edit, Sketch, Tools, Help", under Tools there is "Board" where you can select your type of board. Also at the bottom right it is written for what board your momentary sketch is made. There it should read your Board, not Uno. This might do the trick.

Hello, Thank you for the tip that was the issue. I did not set the correct board on my sketch!..

Hello, thanks for the topic. I have a beginner's question. I am trying to use UNO+RS485 Shield (DFR0259 V.1) to communicate with AMT21 encoder. Since there is no Serial1 available for UNO, can you please tell me what command that I need to replace with in the sketch example provided above in order for UNO to receive correct data from the encoder at 2Mb/s? Or do I have to use MEGA in order to accomplish that? Any help is appreciated! Thanks.

Or do I have to use MEGA in order to accomplish that? Any help is appreciated!

What are your trying to achieve? If you need the communication channel to the PC, you should use an Arduino with a Serial1 (Leonardo or Mega2560). If the Arduino can act for itself (so you don't need to have a serial connection to the PC, an UNO is sufficient as you can use just Serial there.

Don't expect an AVR Arduino to reach 2Mb/s. If that baud rate is given, get an ARM based Arduino. The schematics of your shield aren't available anymore unfortunately, but it seems that the shield allows only for the serial on pins 0 and 1. So get a Leonardo if you need the connection to the PC or a Due if you need 2Mb/s.