Pages: [1] 2   Go Down
Author Topic: Mysterious RS485 problem  (Read 3638 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

     

Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 639
Posts: 34726
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 130
Posts: 8625
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
« Last Edit: May 15, 2011, 10:44:52 pm by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 639
Posts: 34726
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
Code:
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
... 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 smiley

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
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 130
Posts: 8625
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Quote
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

Code:
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

Code:
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

« Last Edit: May 16, 2011, 04:54:45 am by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

New River, Arizona
Offline Offline
God Member
*****
Karma: 19
Posts: 936
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Trying to keep my house under control http://www.desert-home.com/

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 639
Posts: 34726
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.

Quote
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?
Logged

New River, Arizona
Offline Offline
God Member
*****
Karma: 19
Posts: 936
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Trying to keep my house under control http://www.desert-home.com/

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 639
Posts: 34726
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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.
« Last Edit: May 17, 2011, 01:55:06 am by Grumpy_Mike » Logged

New River, Arizona
Offline Offline
God Member
*****
Karma: 19
Posts: 936
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Trying to keep my house under control http://www.desert-home.com/

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 130
Posts: 8625
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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
« Last Edit: May 16, 2011, 07:15:01 pm by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

New River, Arizona
Offline Offline
God Member
*****
Karma: 19
Posts: 936
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Trying to keep my house under control http://www.desert-home.com/

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No No, OP is here smiley 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
« Last Edit: May 17, 2011, 06:50:18 am by mertgulsoy » Logged

Pages: [1] 2   Go Up
Jump to: