Go Down

Topic: Practical Limits of Serial communications? (Read 2081 times) previous topic - next topic

Constantin

Hi everyone,
As you may have read elsewhere, I am grappling with implementing RS485 on the Arduino platform using the hardware serial ports on the 1284P and the 328P. I am now wondering if I was over-complicating matters... whether it doesn't make more sense to just stick to serial communications between Arduinos and drop RS485 altogether. The folk at the Openenergy project are showing something akin, i.e. using  74AHC125 driver chips to isolate Arduinos from the serial line until needed - not unlike RS485 chips, mind you.

What other options should I be considering for line sets shorter than 50' and multiple arduinos?

Coding Badly

Quote
line sets shorter than 50' and multiple arduinos


Entire books can be (and have been) written on the subject when there are so few constraints.  Your question is not unlike this one: "How can I best travel 5 miles?  I will need to make 3 stops."  If the route is through suburban neighborhoods then foot, bicycle, scooter, motorcycle, and car are all reasonable choices.  If the route is through rugged mountainous terrain, none of those choices are reasonable.

Start with these constraints: Will the communications cable pass through electrically noisy areas?  Any large motors or fluorescent lights along the path?

Will the communications cable pass between buildings?  Will the cable need to be electrically isolated?  Protected from lighting?

robtillaart


in general the longer the lines the lower the baudrate that works.

googled baud rate cable length => http://www.chipkin.com/articles/cable-lengths-and-baud-rates-fro-rs485-or-bacnet-mstp -
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Constantin

Hi Coding Badly,

Indoor application only. Unlikely to be hit by large EMI sources as described above. Just a link between various dataloggers running on Arduinos to share power and a communications bus. My preferred implementation would be to use Ethernet wiring, thanks to to the abundance of cables at different pre-confectioned lengths, twisted pairs, and 8 conductors, where I'm proposing to use two pairs for power, one pair for interrupt signaling, and one pair for the serial / RS485 communications.

Communication / power sharing is happening among a master unit (1284p processor) and various modules that are using 328Ps.

Reading up more on the travails by others re: RS485 a couple of things have become apparent. For one, there are some considerations that have to be made regarding the hardware serial buffer, since those are the pins I am using right now. I also wonder if it would make sense for me to not use the hardware serial pins on the 328Ps and go with the SoftSerial library instead - I have spare pins.

Additionally, I neglected to use resistors as described here to give the FTDI header on the 328P boards priority whenever it is connected. But that shouldn't be a big concern on the 1284p since it has two serial ports. On the 328P boards, I worry if the FTDI cable may be causing some trouble, but I kind of doubt it - it just sits there on the bus, listening.

Constantin

No need for super-fast comms. The RS485 chips are rated for 5+MBits/s and I'm going to use maybe 250kbit/s...

Coding Badly


Constantin

#6
Apr 12, 2012, 12:10 am Last Edit: Apr 12, 2012, 12:12 am by Constantin Reason: 1
Typically 1 node. Max probably around 5.

I'm starting to wonder if I shouldn't just sacrifice one of the power pairs and go with full-duplex 485... allegedly 'transparent' as far as the UARTs go?

Coding Badly


Is it a master-slave network or peer-to-peer?

Constantin

#8
Apr 12, 2012, 12:45 am Last Edit: Apr 12, 2012, 02:08 am by Constantin Reason: 1
Master / Slave. The 1284p is the master, all other modules are slaves and only respond when addressed by the master.

I was hoping to keep it to half-duplex to minimize the number of lines necessary. However, I keep having trouble with getting anything intelligible across the divide.

As for other implementations, I wonder if the 74AHC125 chip from NXP might make sense. The openenergymonitor crew built a network around it that could transmit significant distances while maintaining simple TTL signalling. Not as robust perhaps as RS485 with its differential signalling, but unlikely a problem given the above parameters, I hope. Plus, a lot easier to troubleshoot since any FTDI cable and understand what is being sent.

Coding Badly

Quote
I wonder if the 74AHC125 chip from NXP might make sense


You still have the problem of disabling a slave's transmitter# (line driver) when the slave is not transmitting.  With the new interrupt driven Serial (and lack of buffer management methods) that will be difficult.

How are you handling that now with RS-485?  Or are you?


# The other three points (slave's receiver, master's transmitter, master's receiver) can be left active all the time.

Graynomad

If you can't get half-duplex running with RS-485 you won't get it running with the buffers, the software will be exactly the same.

Can you post your code? My guess is that are not waiting for the bytes to go before to turn the line around.

Quote
With the new interrupt driven Serial (and lack of buffer management methods) that will be difficult.

I feel that this will cause problems with many programs, the new buffered output should have been an option I think, extra parameter, ability to 0 the buffer size or whatever.

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

Constantin

I'm not even trying to turn the line at this point... strictly one-way communication not happening.

Here is some code from the Yourduino site I adjusted for the Slave. Note the constantly-'LOW' RE/DE pin, i.e. receive mode only.

Code: [Select]
/* YourDuino RS485 Slave Node A Example
terry@yourduino.com */

/*-----( Declare Variables )-----*/
int ledPin=13;
int EN = 6;
byte Val;

void setup()/****** SETUP: RUNS ONCE ******/
{
  pinMode(ledPin, OUTPUT );
  pinMode(EN, OUTPUT );
  Serial.begin (28800);
  Serial.println("Setup Complete.");
}//--(end setup )---

void loop()  /****** LOOP: RUNS CONSTANTLY ******/
{
  // receive Data
  digitalWrite (EN, LOW ); // enable receive
  Val = Serial.read ();
  Serial.println(Val);
  if (-1 != Val)
  {
    if ( 'A' == Val)
    {
      digitalWrite (ledPin, HIGH );
      delay (500);
      digitalWrite (ledPin, LOW );
      delay (500);
    }
 
  }
}//--(end main loop )---


And here is the master code. It is running on a 1284P, the first serial bus ends in the FTDI header, while Serial1 is attached directly to the RS485 chip inputs. I probably should simplify this to the point where the RE/DE pin is always high and see if that makes any difference.
Code: [Select]
/* YourDuino RS485 Master Node Example
terry@yourduino.com */

/*-----( Declare Variables )-----*/
int EN = 12;
int LED_PIN =7;

void setup() /****** SETUP: RUNS ONCE ******/
{
  pinMode(EN, OUTPUT );
  pinMode(LED_PIN, OUTPUT );
  Serial.begin (28800);
  Serial1.begin (28800);
}//--(end setup )---

void loop()    /****** LOOP: RUNS CONSTANTLY ******/
{
  // Send Data
  digitalWrite(LED_PIN, HIGH ); // turn on light
  Serial.print ( 'A' ); //FTDI Header Send

  digitalWrite(EN, HIGH ); // enable send
  delay (1); //wait for RS485 chip to be active
  Serial1.print ( 'A' ); //RS485 Bus Send
  delayMicroseconds (660); ////delay recommended by Nick Gammon to deal with the serial buffer clearing before TX is complete
  digitalWrite(EN, LOW ); // disable send
 
  delay(1000); 
  digitalWrite(LED_PIN, LOW ); // turn off light
  Serial.print ( 'B' );//FTDI Header Send
 
  digitalWrite(EN, HIGH ); // enable send
  delay(1); //wait for RS485 chip to be active
  Serial1.print ( 'B' ); //RS485 Bus Send
  delayMicroseconds (660);  //delay recommended by Nick Gammon to deal with the serial buffer clearing before TX is complete
  digitalWrite(EN, LOW ); // disable send
  delay (1000);
}//--(end main loop )---

Graynomad

One problem

Val = Serial.read ();

You're not waiting for a char for be received.

Check out Serial.available()

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

Constantin

#13
Apr 12, 2012, 01:07 pm Last Edit: Apr 12, 2012, 01:17 pm by Constantin Reason: 1

Check out Serial.available()
______
Rob

Thanks graynomad,

I had used that in the past. No change in behavior.
Code: [Select]
/* YourDuino RS485 Slave Node A Example
terry@yourduino.com */

/*-----( Declare Variables )-----*/
int ledPin=13;
int EN = 6;
byte Val;

void setup()/****** SETUP: RUNS ONCE ******/
{
 pinMode(ledPin, OUTPUT );
 pinMode(EN, OUTPUT );
 Serial.begin (9600);
 Serial.println("Setup Complete.");
}//--(end setup )---

void loop()  /****** LOOP: RUNS CONSTANTLY ******/
{
 // receive Data
 digitalWrite (EN, LOW ); // enable receive
 if (Serial.available()>0) {
   Val = Serial.read ();
   if ( 'A' == Val)
   {
     digitalWrite (ledPin, HIGH );
     delay (500);
     digitalWrite (ledPin, LOW );
     delay (500);
   }
 else Serial.println(Val);
 }
}//--(end main loop )---


I get a "Setup complete" and then nothing on the slave. I get some chatter on the slave as I connect and disconnect the master. I re-verified electrical continuity from one RS485 to the other. Enabling / Disabling the terminators does nothing either. I'm feeling rather blue, I must say.

Graynomad

I would just print the HEX of whatever you get without the tests.

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

Go Up