Mysterious RS485 problem

Hi,

I'm building a remote controlled display system. Multiple displays can be connected to a single, halfduplex RS485 line. The chip i'm using to interface RS485 is max485. The problem is, when arduino wants to send data (to be a busmaster) the computer receives it successfully. When the computer wants to send data, Atmega328 doesn't understand the signal. Thus cannot react.

Here is the configuration:
PC <==> FTDI FT232RL <==>MAX485 (this is a self made device - seperate from arduino)
The TX pin is connected to pin4 (DI) of MAX485
The RX pin is connected to pin1 (RO) of MAX485
The RTS# pin is connected to pins 2 and 3 (DE/RE) of MAX485 (this pin is reversed with FTDI Util so now it is active HIGH)

ARDUINO <==> MAX485
The TX pin(1) is connected to pin4 (DI) of MAX485
The RX pin(0) is connected to pin1 (RO) of MAX485
The 3rd pin(2) is connected to pin3 (DE) of MAX485 and pin2 (RE) of MAX485 is connected to gnd.

and the MAX485s are on the bus. Bus is terminated with a 330ohm res.

For the normal operation every device listens to the bus and arduinos are not sending any data. They only send data if debugging enabled. So for the operation, half duplex is enough.

When arduino wants to send data, it first sets the pin(2) (3rd pin) to high thus enabling the DE line of MAX485 Then puts the data on the bus. Since the computer listens data, it receives correctly but with 0 bytes at the end of transmission. The 0 byte is not a problem for now. When the computer wants to send data, it uses the same procedure. Pulls the RTS line High thus enabling the DE line and then puts the data on the bus. But no reaction from arduino. Without rs485, arduino is functioning correct. No problem with the software in it. but when RS485 interface added this problem appears.

I've tried these to be the solution but none of them worked:
1- To pull-up or pull-down the RX line of arduino -> NO Success
2- Invert TX line of FT232RL -> NO Success
3- Added 470ohm resistors to TX and RX lines -> NO Success

I dont have an oscilloscope so i connected an LED to RX line (RO line of MAX485 of arduino). It blinks when i try to send data from PC to arduino. So I think that the bitstream comes to the RX pin of arduino. (I cannot say that is correct bitstream but every datasheet or appnote states that ..if you do like this it works. But actually not.

Help is much appreciated. Thank you.

When the computer wants to send data, Atmega328 doesn't understand the signal.

I think you are missing the point. On an RS485 bus there can only be one master. So if the Arduino is the master then for the PC to send data the Arduino has to request it, the PC responds and the Arduino receives it.
You seem to be implementing a multi master bus. RS485 is not designed to do this.

Grumpy_Mike:

When the computer wants to send data, Atmega328 doesn't understand the signal.

I think you are missing the point. On an RS485 bus there can only be one master. So if the Arduino is the master then for the PC to send data the Arduino has to request it, the PC responds and the Arduino receives it.
You seem to be implementing a multi master bus. RS485 is not designed to do this.

Do you mean that, although all devices are listening to the bus, the one which begins first to send data is the bus master and "others" are slaves, so even after receiving data and all devices begin to listen to the bus again, the one of the "others" cannot send data because it did not begin to send data first?

I planned the operation for the bus as half-duplex. Normally display devices don't send data to pc. They just receive. All the devices are listening to the bus.

485 is not a multi-master bus as Grumpy says, but you could fudge it with an extra "busy" or "request" line.

However I doubt just enabling a transmitter will work, especially with the standard bus termination. For example what's the logic state on the output of the MAX485 when there are no transmitters enabled? Is this state any different from that when there is a transmitter enabled? If not you can't tell what's happening.

If you use "failsafe" termination this might work. This has two resisters (approx 560R), IIRC pull line A high and B low. Now when nobody is transmitting the line will idle at a known state and you can maybe organise some handshaking technique whereby a prospective master transmits a 0 byte to tell the others it wants the bus.

However, any form of request like this is subject to race conditions, what happens if two masters request at the same time? Also the PC may be very slow at doing this because it's running under who knows what and may have a large latency. The longer the latency in such a scheme the more chance of a clash, and if you have clashes how will this be resolved?

Let's get back to basics, why do you need two masters?
What is this "debugging"?
Can the debugging occur by command from the PC? Or does the Arduino have to be autonomous?


Rob

When an RS485 device has stopes transmitting the drivers must be switched off into the high impedance state. If you want to do this from the PC end then you must directly control the handshake lines to do this. This is tricky because you have to know when the transmit buffer is empty and all of the last byte has been sent.
Also if you want a multi master setup you must include error checking in the data packets you use to detect data collisions and request a retransmission.

The debugging option is added to check if the transmission and the system running correctly. But in normal usage it is not used. In fact as you said i dont need two masters. Pc is the master. But according to protocol development i may need a second master. But this (second) master will act as requested. So protocol says no slave device can send info by themselves. This is certain.

As I read in the datasheet of MAX485, it says there is a Fail-Safe circuit inside the chip. This guarantees when there is no traffic, the RO line will be high. I checked this and this is ok. I thougt no biasing needed. Just the termination.

Yesterday night i tried sth and the thing start to work normal. Here are the details:

  • First i removed the MAX485 lines and checked with a TTL serial connection.
  • Very strange that ATmega328 does not understand the bit pattern even if it receives it.
  • I changed the code:
    • According to the protocol a command is formed with:
      1 Byte header; which is (byte) 90 --> (char)'Z'
      4 Byte address
      1 to 6 bytes command
      thus:
 if (Serial.available()){
        //incoming command
        byte rec = 0;
        rec = Serial.read();
        [i]//Serial.print(rec,DEC);  /*--> if i uncomment this line i see all data i've sent so data arrives at the chip and it replies back. but no action*/[/i] 
        //serial data filtering
        //first byte must be <Z>
        if (rec == 90){
            //following 4 bytes must be id
            //Serial.println("Serial Data begin"); //--> *
            if (checkIdNr()){
                //idNr is correct
                //Serial.println("ID nr match");  //--> * 
                //read command
                byte serialData = Serial.read();
                //...Command  Logic....

if i uncomment the lines marked with "--> * " the device works properly. I mean, it reacts all of the commands that pc send to it. I need to do some tests also this evening. and will report later. I think that this is related with transmission delay

Grumpy_Mike:
... This is tricky because you have to know when the transmit buffer is empty and all of the last byte has been sent...

. ATmega328 works at 16MHz and it is faster than a 80286 :slight_smile:

For normal operation if a slave is requested to reply, it first pulls high the outputEnable pin and then sends the data. So even if i uncomment the
"--> * " lines MAX485 does not send any data to PC. Because the chip is in "Listening Mode"

Thank you for the answers

Four-byte address, are you expecting a lot of slaves :slight_smile:

ATmega328 works at 16MHz and it is faster than a 80286

Whether that's the case or not, it has no bearing on the transmission speed and the fact that Grumpy was talking about needing to know when to turn off the transmitter.

This worries me

if (Serial.available()){  // works but really should be Serial.available() > 0
  .......
        if (rec == 90){
            ........
            if (checkIdNr()){  // you haven't got the address yet
                ........
                byte serialData = Serial.read(); // it's very likely the first byte hasn't been received yet, let alone all of them

Forgetting the multiple master stuff for the moment, and getting back to what Grumpy said, how do you know when to turn off the slave transmitter. For example

Serial.print ("Answer");
digitalWrite (txENpin, LOW);

will not work.

The answer will be cut off probably at the start of the "e" being transmitted. With the next Arduino cores (AFIAK they have buffered Tx) it will be even worse.

I suspect that uncommenting that line causes the program to block on the Serial.print(), thus when it continues the Rx data has arrived. Without the line the above problems occur.


Rob

RS485 is just a level definition hardware protocol that uses differential voltages instead of ground-source levels to communicate. This gives it much greater distance, but it works a whole lot like RS232 in actual practice. Where we get into trouble using RS485 is hooking the Arduino TX and RX pins to the level converter chip and also needing to debug the device by printing things. I recommend moving the connection of the converter chip to pins 2 and 3 then use NewSoftSerial to output the RS485 data to these pins. This gives you the serial pins free to debug all you want, while not flipping bits on the RS485 connection.

RS485 works best with only one master that says, "here's some stuff, now you give me a response back" Then the slave responds back. However, it will work pretty well with multiple masters that simply send checksums and have retransmission capabilities. This kind of thing lowers the bandwidth a lot, but for simple displays, it won't be noticed.

So, enable transmit, transmit the data, disable transmit and listen. If you suspect that you are turning off transmit in the middle of a character since you can't tell when it ends, send an extra sacrificial character that the other end doesn't use. This extra character can get cut off mid point and it won't matter. Personally, I've never seen this, everything I send goes out. But, again, I use NewSoftSerial 10C and my RS485 converter is connected to pins 2,3,4 with 4 being the transmit control.

I can type in the arduino serial port through my USB connection and the arduino sends it down pins 2 &3 and any RS485 response is handed to me through the serial as well. It's not a hard change and NewSoftSerial 10C works quite well.

I've never seen this, everything I send goes out. But, again, I use NewSoftSerial

That is no surprise because NewSoftSerial bit bangs the output and so doesn't return until it has finished, where as a hardware UART will report that the data buffer is empty as soon as the last byte has been transferred into the output shift register.

send an extra sacrificial character that the other end doesn't use

Much easier said than done. How many bytes does the receiver expect? If you are not sure if the last character will be cut short or even not sent at all how does the receiver know it has them all?

My experience has been that it doesn't care. It just times out after a character time expires and goes on its merry way. It has to do this or an incomplete character due to line noise would hang it up forever. Remember, the character and packet level protocol is not on the converter chip, that thing just converts levels. I spent hours on false starts because I kept thinking that RS485 was somehow special, it really isn't. It's just a different technique for getting data down the wire. Uarts and such devices or software do all the character level stuff after the conversion from 485 to 232. The complication is in having to raise the transmit pin before sending and remembering to lower it to receive.

The biggest problem is having to use the arduino serial port to debug, that mixes characters into the stream, causes ringing on the 485 link and generally messes up the results.

It has to do this or an incomplete character due to line noise would hang it up forever.

How does that happen? I

It's asynchronous so once a start bit has been received it just samples the next 9 bits at the appropriate time. You can't get a hang up due to line noise. As you say it's just signal levels. Most of the complexity is in handling the half duplex stuff.

You asked how the receiver knows how many bytes to receive. The answer is that something has to tell it; constant length, length in the header, timeout, special end character, combination of these or something else are all possible. Successful receiving code I've seen has something to tell it to give up or it will just wait forever. If we're talking about the bit level, it tries to form a character and gives whatever it got as you described. This is done by character timing based on baud rate once it gets the start bit.

If the concern is that the the character or characters get cut off because you switch the tristate buffer too soon, the simplest way to avoid this is to tack a character on the end that is ignored and look to see if it disappeared or got garbled. You can also time it based on baud rate to delay when you change the tx line.

Or, just use NewSoftSerial to separate debug data from the data stream you're interested in and don't worry about it.

Timing is OK but you always have to apply a small fudge factor and it either uses up a timer or you block with a delay function.

I'd rather poll the TXCn bit (also blocks) or use the USART Rx Complete interrupt.

Another option is a chip like the MAX13414 with auto direction control that doesn't need to have the Tx turned off.

I wonder where the OP is?


Rob

You're absolutely correct. I didn't even know there were chips that handled rx to tx automatically until after I had a converter already in hand. Oh well, I had extra pins on the arduino and time to play.

The OP is probably checking other forums for advice.

No No, OP is here :slight_smile: As i read and think, some new questions come but when i come to check i see that someone has already asked it. I'm following the thread carefully.

For the project, I'll try to insert delays instead "Serial.print" lines. But till now i could not have enough time to finish it. Thank you for answers. After doing more tests i'll share the results.

Mert

Hi everyone,
I have some short of "mysterious" problem as well with the RS485. In fact I have connected and LCD, a keyboard and a MAX485 to the chip. I have developed a menu that shows in the LCD and I can navigate through it using the keypad. I have also a sensor transmittting i n RS485 connected to the MAX485 that is connected to my serial port. Problems is:
-Only reception of data from sensor and display it in the LCD works fine
-Only navugation through the mmenu works fine (transmission disabled)

  • If I navigate while receiving, it works fine for a while, but suddenly the menus get stuck and reception stops. No more information is received (I have tested sensor is still sensing).
    Any idea why this can be happening?
    (I also checked problem of overflow in buffer, but there is not such a problem)
    Thanks!

Virginia:
Hi everyone,
I have some short of "mysterious" problem as well with the RS485. In fact I have connected and LCD, a keyboard and a MAX485 to the chip. I have developed a menu that shows in the LCD and I can navigate through it using the keypad. I have also a sensor transmittting i n RS485 connected to the MAX485 that is connected to my serial port. Problems is:
-Only reception of data from sensor and display it in the LCD works fine
-Only navugation through the mmenu works fine (transmission disabled)

  • If I navigate while receiving, it works fine for a while, but suddenly the menus get stuck and reception stops. No more information is received (I have tested sensor is still sensing).
    Any idea why this can be happening?
    (I also checked problem of overflow in buffer, but there is not such a problem)
    Thanks!

Using the 485 line in half duplex mode is not a good idea as i learned. But with your project for the RS485 line only the sensor is connected? Or all lcd, keypad and stuff are on a RS485 bus?

Only sensor is connected, keypad and LCD are directly connected to the micro

For the resolution of my problem i made these things and the system is now working:

  • I rechecked the needs for transmission from the slaves to master. If there is not a diagnosis by hand on going, the slave devices are not sending any messages to the master.
  • For the receiving, (i dont know why but) i kept the Serial.println lines, as the DE pin not enabled. by doing this the system works as expected. I think if i remove the Serial.println lines and add delay(10) for example the system is going to work because of the flow of my code.
  • For further projects, if i will need to send data in all directions i'll implement 2 max485 chips for each side, one is for sending and other for receiving.

Thank you very much for your answers.

Mert

Thnak you for the answer...but I tried and is still not working. It receives data for a while, while I am navigating through the menu is still receiving, but after some time the program stops, nothing works still