Practical Limits of Serial communications?

Graynomad:
Check out Serial.available()


Rob

Thanks graynomad,

I had used that in the past. No change in behavior.

/* 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.

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


Rob

Done. Using this code, I get "Setup complete", two zeros, nothing more. I wonder if one of the RS485 chips is dead... Re-verified that the RE/DE on the receiver is 0V and that the RE/DE on the transmitting chip is 5V. Nuts.

/* 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 ();
    Serial.println(Val,HEX);
  }
}//--(end main loop )---

According to the posted code your slave is running at 9600, master at 28800.


Rob

Hi Graynomad,

Thanks for the reply. I changed both of them down to 9,600 baud since my FTDI adapter seems to be flaky at 28,800. Might have to to with Win 7 not allowing the driver to be changed easily. So, they're both running at 9,600 baud now. I flipped the FTDI cable back and forth among the two Arduinos, I get clear-text messages on both (i.e. "setup complete", etc.) serial busses, just no communication between the two chips. I have a third RS485 board at home, I'll see if I can eliminate one of the RS485 chips as a possible culprit.

See current Master code below:

/* YourDuino RS485 Master Node S 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 (9600);
  Serial1.begin (9600);
  Serial.println ("Setup Complete."); //FTDI Header Send
}//--(end setup )---

void loop()    /****** LOOP: RUNS CONSTANTLY ******/
{
  // Send Data
  digitalWrite(LED_PIN, HIGH ); // turn on light
  digitalWrite(EN, HIGH ); // enable send
  Serial.print ( 'A' ); //FTDI Header Send
  delay (1); //wait for RS485 chip to be active
  Serial1.print ( 'A' ); //RS485 Bus Send

  delay(1000);  
  digitalWrite(LED_PIN, LOW ); // turn off light
  Serial.print ( 'B' );//FTDI Header Send
  Serial1.print ( 'B' ); //RS485 Bus Send
  delay (1000);
}//--(end main loop )---

The code looks OK I think, you don't need delay(1) but you should be seeing something if the hardware is kosher.

You could try not using a transceiver at all, just pin-to-pin.

This is where proper test equipment comes into its own.


Rob

The good news is that I got it to work with one of my other modules.

I presume the RS485 chip is either toast on the other module or the serial pins are not where I expected them to be. Hopefully it's the former!

the serial pins are not where I expected them to be

Then the second module wouldn't work as well, or are they different?

Anyway now you get get on with the fun part.


Rob

Thanks for all the help, Graynomad!

The other 'RS485 functioning' module features a 328P microprocessor as well. Only the master module has a 1284p on it, and this appears to be the one with a bum RS485 chip. At least I hope. Because if the serial pins have wandered from where I expect them to be, then I am in a lot of trouble. However, I doubt it's the serial pins since they appear to be hard coded by Atmel, no? As for the modules communicating with the master, I am planning on using the EasyTransfer library to make the transfers pretty painless.

Anyhow, I have a question that I hope you can answer... I am currently planning on using Ethernet wiring with RJ45 jacks. Two pairs are dedicated to power transmission (i.e. 5v and GND)while one pair is used for RS485 data communication. The remaining pair is scheduled to carry a clock signal (1Hz) and a spare line that may be useful for signaling (i.e. "bus about to be used, do not try to use also"). Would you endorse the use of a buffer chip on these remaining two lines or would it be overkill?

Thanks again for all the hand-holding and enjoy your stay on the east coast! My wife and I drove up to Brizzie from Sydney on our honeymoon, it was further than we thought! XD

What is the 1Hz for?

If you use 485 for the remaining wires you only get one signal, if the 1Hz is needed then that's it. If not you can implement another signal.

Such a signal can be used to say differentiate between an address byte and all others, this takes the load off the slaves as they only have to look at the line when this signal goes low. They read the following address then if it's not there's they can ignore the line until the next time.

If you have spare wires it's not a bad way to go.

As to whether 485 is required for this, probably not although I'd use it, especially if the line is long and/or subject to noise I can't find if you said how long).

We normally avoid the east coast, too many people, but at the moment it's the fastest way north where (hopefully) we can get warm. That said we pulled into a rest area 5 days ago and are still here so I guess we can't be in too big a hurry.

it was further than we thought!

Probably about the same as the length of the UK.


Rob

Hi Graynomad,

The 1hz signal is for timing purposes. I use a DS3231 on the main module to act as a timekeeper. It's SQW output is programmed to operate at 1Hz. This timing signal is used to calculate average power consumption, for example. When the power module senses the rise in the SQW signal, it stops calculating power consumption and squirts the results to the main module. Then the main module notes the power data and writes it to disk, along with a time stamp from the ds3231.

One of my projects ahead will be to change this setup to record on a second by second basis but then to only squirt summaries every 10 seconds. The reason being that this would allow the main module larger time windows to do time-intensive tasks like GPRS connections. Also, it gives all other modules on the chain more time to respond to data requests.

So you only have 1 spare wire, in which case you can't use 485 for another signal to help with the protocol.

Of course if you have a main module you don't need this timing signal, just get the master to ask for data every second. In which case you then have two spare wires and can use 485 on them to help with the protocol, maybe along the lines of what I said above.

Technically it's not necessary but such a signal can reduce the load on slave processors.


Rob

Agreed, in an ideal world I'd have the main module make that request / announcement via the rs485 bus and be done with it. However, if the main CPU is occupied trying to transmit something via GPRS (with its delays, etc) then maintaining the timing signal accuracy might become difficult.

So a quad buffer chip might be a better solution. One wire communicates the timing signal, the other reserves the use of the rs485 bus. Or, I skip bus reservations and use the pair solely to xmit the timing signal. I'd have to make the slaves a little smarter but nothing impossible, I reckon.

The slaves are crystal-driven right?

If so their timing is every bit as accurate as the RTC, so they can double buffer the readings and report the last buffer when asked. As long as the master doesn't take > 1sec to ask it works and is accurate.

Of course they would not all be in sync with each other, I don't know if that's a requirement.

That frees up a wire, not that you really need one, the comms can be done with a single 485 pair, it's just that the sync signal helps the slaves by freeing them from testing every byte on the wire.

record on a second by second basis but then to only squirt summaries every 10 seconds.

Then you can use the 1Hz signal as is to sync each slave, and after every falling edge on the 1Hz you poll the next slave. This way the existing signal does both jobs, slaves don't bother looking at the line until the sync signal drops, at this point they reset their internal timer and read the first byte. If it's not their address they carry on. If it is they respond.

That way you talk to each of the 5 slaves every 5 seconds. Naturally they have to be able to store that much data. How many readings does a slave take in a second?


Rob

Hi Graynomad and thanks for the extended help!

No, I use resonators on the slave modules. Primarily for cost / space reasons. That's where the rtc output was so useful. Of all the modules, it's probably the power module that takes the most readings, ie several thousand a second. However, the good news is that the data goes into just a few accumulators and the data being sent to the main module is quite limited (ie Vrms, Irms, app. power, real power) so a relatively small array can store 10 seconds of data easy.

Another option is to drop the array data into flash. Given the small size of the SRAM on the 328p's that might be a viable option given that all four variables above are floats and hence take up 4 bytes of data each, right? I don't remember how much of an impact writing to flash has vs using SRAM but it seems wasteful to dedicate almost 20% of the SRAM to this array alone.

It's the main module that accumulates kWhs and there is a lot more Ram to play with on a 1284p. That in turn makes writing data strings a lot easier. But even on the 1284p I'm considering the use of flash ram to store string data prior to batch writing to SD card because it seems like the right thing to do in order to keep the platform as expandable as possible.

So it probably makes the most sense to use a rs485 line to propagate the timing signal and then poll each slave in a ring-around-a-Rosie manner. If I go the flash route, the timing interval between pings becomes almost arbitrary. The only consideration for transmissions that are lengthy is the impact on the module that is supposed to be doing other things too, such as power readings. So I'll likely choose a ping interval between 10-30 seconds.

it seems wasteful to dedicate almost 20% of the SRAM to this array alone.

As long as you don't run out it doesn't matter if it's wasteful, it's not like you can pass the unused RAM on to your kids :slight_smile:

You can't use the internal flash, you can use external flash/EEPROM or the internal EEPROM but all those options are LOT slower than RAM.

The only consideration for transmissions that are lengthy is the impact on the module that is supposed to be doing other things too, such as power readings.

Hardware serial is interrupt driven, if the code it written well there will be almost no impact on the main task.

ping interval between 10-30 seconds.

Then using the scheme I suggested above you would transmit a (for example) 0 after every 1Hz pulse, no slaves will have that address so they will all ignore it. Every 20 or 30 seconds you send a valid address and read data.


Rob

Hi and thanks again!

I had been considering the use of Mikal Hart's Flash abstraction layer... Doesn't this use flash memory? It seemed like a pretty elegant way to store a lot of data without much trouble.

My worries re: the size of the data packets eing transmitted has to do with my experience with serial communications pre 1.0 IDE. There, I could discern performance differences as a function of transmission speeds. What is the buffer size for hardware serial?

Thanks again for your thoughtful responses, I really appreciate them.

That flash abstraction layer is now built into Arduino, as from 1.0 I think.

Regardless it's only for storing static data at compile time, not for dynamic data at run time. So it's good for reducing RAM usage when for example you have a lot of strings, but no use for saving sensor data etc.

serial communications pre 1.0 IDE

Buffered serial out was introduced in 1.0

What is the buffer size for hardware serial?

I think 64 bytes. Why it was not made variable is anyone's guess and somewhat typical of the (IMO) lack of thought put into some of the Arduino code. Presumably you can edit the appropriate .h file to change it.


Rob

Thanks! So I'll make use of that memory for static information... I have some lookup tables for thermistor measurements that are a perfect match for that kind of data.

One thought if I run out of RAM could be to store the power data in int arrays... Multiply the floats by 100x and then convert to int, transmit to the main module, then reverse on the other side. Saves two bytes per variable for vrms and Irms. The Ws data would suffice with a 10x multiplier. That way I could store 1 minutes's worth of data in only 480 bytes of RAM.

I'll try to think of a way to work around the 64 byte limit. Sounds like it would be a good idea to send multiple small squirts to minimize impacts. With the easy transfer overhead, maybe 5 measurements before the buffer is full and starts blocking. But if I send them with a couple of measurements in between each send, then I can take advantage of the non-blocking implementation of the 1.0 IDE, no?