Problem reading serial data from RS485 bus

Hello,
i am using an arduino mega 2560 board to try and read serial data from an encoder, which communicates via a RS485 bus. I have connected a MAX485 module to the arduino with pin 18 connecting to DI, pin 19 connecting to RO and pin 8 connecting to DE/RE. Writing the command to read the current position works without problems and the answer is written to pin 19 clearly. When trying to read the answer into the arduino, however, i am not able to read it in correctly.
This is the code i am using:

void setup() {
  Serial.begin(2000000);
  Serial1.begin(2000000); //Using Serial1 Port
  pinMode(8, OUTPUT);//DE/RE Controling pin of RS-485
  Serial.println("Starting");
//setting position of encoder to zero
  digitalWrite(8,HIGH);
  Serial1.write(0x56);
  Serial1.write(0x5E);
  digitalWrite(8,LOW);
}

void loop() {
  char getdata='m';
  int buffersize = 4;
  char buf[buffersize];

  //making sure the input buffer is not filled with other data
  while(Serial1.available() > 0) {
  char t = Serial1.read();
  Serial.print("inbetween1: ");
  Serial.println(t, BIN);
  }
  
  digitalWrite(8,HIGH); //DE/RE=HIGH Transmit Enabled M1
  Serial1.write(0x54);  //request current position from encoder
  //Serial1.flush();
  digitalWrite(8,LOW);  //DE/RE=LOW Receive Enabled M1
  
delay(50);
 
  if(Serial1.available()){ //If Serial Data is available
    while(Serial1.available() && getdata!='d')
    { 
    int length = Serial1.readBytes(buf, buffersize);
    Serial.print("I received: ");
    for (int i = 0; i < length; i++) {
      Serial.println(buf[i], BIN);
    	}
    Serial.println("");
    } 
  }

  delay(1000);

}

i have also tried reading the data with the following while loop. It results in the same data read.

 while(Serial1.available())
    { 
    getdata=Serial1.read();
    Serial.print("I received: ");
    Serial.println(getdata, BIN);
    }

Also, i have connected the arduino to itself with an additional MAX485 module, using Serial2 and its corresponding pins for that. Serial 2 was able to correctly read messages sent from Serial1.

Here are 2 example images with the message on the bus read with an oscilloscope and the incorrect data printed to the serial monitor (channel 3 was connected to pin 19, channel 2 to line B of the RS485 bus and channel 4 to pin 8):


Data_0

The communication and especially the reading of the data to the input buffer should still be working fine at 2MHz, which i am using, correct? Writing the command to the bus at 2MHz works just fine after all.
Am i making a silly mistake somewhere in the code?
Is there a problem with the format the answer of the encoder is written in?
Here is a link to the datasheet of the encoder in case there are questions about it: https://www.mouser.de/datasheet/2/670/amt21_v-1775847.pdf
If i understood correctly, one Serial.read() command should only read one byte of data from the input buffer. Why are some of the lines printed on the serial monitor much longer than 8 bit?
The shorter ones should just be shorter due to zeroes in the front not being printed, correct?

Sorry if i mistyped something or did something else wrong in the post, first time posting here, please point it out to me :slight_smile:
I appreciate any help/advice you have.

Thanks,
Fabian

Without a data sheet it's hard to tell what's wrong.

You mean a datasheet for the encoder? I put a link to that in my original post, is the link not working?

Right, sorry I missed it :frowning:

Pin numbers are hard to interpret. Why don't you use the pin labels like RX1 and TX1 instead?

I think that you should swap these lines, waiting before turning off the sender logic.

Why don't you simply catch 2 response bytes after the read position (0x54) command?

Sorry, will do. pin 19 is RX1 and pin 18 is TX1. pin 8 is a generic I/O pin and represents the line for the send/receive logic.

The delay is there to make sure the entire answer has been sent, so that Serial.available() doesn't miss it and the program skips over the read, which happened before.
The timing of the sender logic switch seems to be correct, switching after the read position command (0x54) from the arduino and before the answer of the encoder. You can also see this in the oscilloscope picture where the line for the sender logic is channel 4 (dark blue).

Can you elaborate what you mean by simply catching the 2 response bytes?
Should't any response automatically be written into the input buffer of Serial1?
Is there another practical way how i could catch the response?

Only the first few bits have been sent when you turn off the sender. You can let the receiver part enabled all the time and receive the echo of the command, and only on receipt of this echo turn off the sender.

Right, but you call for 4 bytes into buf - why 4 bytes?

By the first few bits, do you mean the first few bits of the read position command (0x54)?
The command has already been sent completely when the sender logic goes low. If it isn't low, the encoder can't send the response. The command ends at ca. the red line in this picture, while the send line is dark blue:


If you don't mean that, i didn't get what you were trying to say, sorry.

There is no real reason while I'm trying to catch 4 bytes. I guess i wanted to make sure that i don't cut any part of the response off in case there is something else written to the input buffer before the response of the encoder.
If i am writing more bytes into my own buffer than it should take for the response, shouldn't the response still be somewhere in it?

I wonder why the command does not appear on that line. Is B driven low only by the other station?

I wouldn't trust that digitalWrite() takes long enough to let pass the entire byte.

I also cannot match the text output with the preceding code:

B is driven low by the Encoder and the MAX485 module. The command does appear on that line (light blue) though?

It does consistently, only because i am sending at 2MHz though. When i was testing with lower frequencys, i had to use Serial.flush(). But at 2Mhz, Serial.flush() and digitalWrite() together take so long, that the sender logic goes low only after the encoder already starts to send its response.

To clarify, this was not the first transmission, so the "Starting" message is not visible here.
Also, the message "inbetween1: " only appears once after loading the code or resetting the arduino. So it appears, that after that, no data is written into the input buffer inbetween 2 communications.
Appart from that, i'm very confused by this as well. I don't believe that there should be more than 8 numbers written per line, which would correspond to the 8 bit per byte read from the input buffer.
I don't know why that is.
But i can assure you that this is the actual output of this code, i just don't know why..

That's the TX1 signal, I assume? Of course this is always sent because the UART is full duplex.

Can you watch the A line instead?

No, the light blue line (channel 2) is the B line. The A line is inverse to the B line and connected to it via a resistor, so it would show the inverse logic. This already shows that the command is correctly transmitted from the TX1 line onto the RS485 bus by the MAX485 module. The fact that the encoder sends a response means that it also received the command correctly.
However, i am not able to correctly read that response with the arduino.

Try this:

byte L, H;
while (Serial1.available < 2) ;
L = Serial1.read();
H = Serial1.read();
Serial.print(H, BIN); Serial.print(' ');
Serial.println(L, BIN);

With this i'm able to read the response correctly and the communication is fully functional!
Thank you very much for your help and your patience :grin:

I have a HCM375B sensor and I want to use it in the Arduino Uno, but I could not extract the data from the sensor and print them on the serial. Is there anyone who can help me please?

Please do not hijack an existing topic.

Make up a New topic and give links to the vendor site and the data sheet of the sensor.

Does the sensor come with an Arduino library or example code? If not, why don't you use a better supported sensor or supplier?

He does not have an Arduino library, he has a Windows program from his company, and this is the data for him

في الأحد، ٣ سبتمبر، ٢٠٢٣ ٣:٠٨ ص DrDiettrich via Arduino Forum <notifications@arduino.discoursemail.com> كتب:

HCM370B HCM375B-N HIGH ACCURACY 3D DIGITAL COMPASS.pdf (3.32 MB)

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