Sending different signals through serial port

Hello, I am creating an application in C# which plots data (in "real time") obtained from Arduino through serial port. The thing is, I need to send 3 different signals (I need to plot control signal and data from 2 sensors). What would be the best way to do that? The only solution I can think of is sending values one after another in one pack (1-2-3-1-2-3-1-2-3) and after receiving it, divide that pack and assign every value to particular signal.

Is there any better solution to do that? I appreciate every response.

serial input basics

to get you started.

Robodziej: The only solution I can think of is sending values one after another in one pack (1-2-3-1-2-3-1-2-3) and after receiving it, divide that pack and assign every value to particular signal.

That is the normal way to do it. It would be easier to parse if you separate the values with commas because Comma Separated Values (CSV) is a very common protocol.

The link that @groundfungus gave you is about receiving data in the Arduino but the same techniques would be equally appropriate for receiving data in a PC program.

...R

If the data is really real-time and critical, you might consider adding two more fields. One to identify the start of a sequence and one to identify the end. That allows your receiving program to synchronize with the sendor in case the communications gets corrupted.

The serial basics discussion suggests a carriage return or line feed, or both at the end. Pick some character to identify the start that cannot be confused with a data element.

Paul

Paul_KD7HB:
The serial basics discussion suggests a carriage return or line feed, or both at the end. Pick some character to identify the start that cannot be confused with a data element.

The 3rd example in serial input basics uses < and > as start and end markers, and they could easily be changed to other characters if necessary.

…R

I just send them ‘raw’ - that is, no stop/start markers - and also pack them such that there are no wasted bits (eg. no need to send a full byte if you’ve only got a range of 128 values) - I was lucky that the total was still a multiple of 8, but no reason you couldn’t do a modulus based ‘rolling’ unpack at the other end.

It was purely academic as the transfer rates were ok (115200 baud), but I was surprised at what little - i.e. zero - issues I had.

I thought I’d have issues with start and stops getting out of sync and so on, but it just didn’t happen.

1:1:
but it just didn’t happen.

yet.

…R

Which can be said about anything ;)

Its a valid approach in (non-critical) systems that otherwise need the transfer rates 'optimised'.

Is there any better solution to do that? I appreciate every response.

This code is for servos, but might work for your setup. For each component a data packet is sent. The packet contains a numeric value followed by a component identifier, followed by an end of packet delimiter.Each packet is captured and the desired actions are performed based on the contents of the packet.

//zoomkat 11-22-12 simple delimited ',' string parse 
//from serial port input (via serial monitor)
//and print result out serial port
//multi servos added 
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
Servo myservoa, myservob, myservoc, myservod;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);

  //myservoa.writeMicroseconds(1500); //set initial servo position if desired

  myservoa.attach(6);  //the pin for the servoa control
  myservob.attach(7);  //the pin for the servob control
  myservoc.attach(8);  //the pin for the servoc control
  myservod.attach(9);  //the pin for the servod control 
  Serial.println("multi-servo-delimit-test-dual-input-11-22-12"); // so I can keep track of what is loaded
}

void loop() {

  //expect single strings like 700a, or 1500c, or 2000d,
  //or like 30c, or 90a, or 180d,
  //or combined like 30c,180b,70a,120d,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >1) {
        Serial.println(readString); //prints string to serial port out

        int n = readString.toInt();  //convert readString into a number

        // auto select appropriate value, copied from someone elses code.
        if(n >= 500)
        {
          Serial.print("writing Microseconds: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.writeMicroseconds(n);
          if(readString.indexOf('b') >0) myservob.writeMicroseconds(n);
          if(readString.indexOf('c') >0) myservoc.writeMicroseconds(n);
          if(readString.indexOf('d') >0) myservod.writeMicroseconds(n);
        }
        else
        {   
          Serial.print("writing Angle: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.write(n);
          if(readString.indexOf('b') >0) myservob.write(n);
          if(readString.indexOf('c') >0) myservoc.write(n);
          if(readString.indexOf('d') >0) myservod.write(n);
        }
         readString=""; //clears variable for new input
      }
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

Firstly, is there actually a transfer rate issue here?

If not, do whatever you like :)

However, if there is an issue, the nature of the system will determine the best protocol. A metric that looks at average amount of the actual information you want transmitted per unit time - that is, with all the start/stop, error-checking and addressing bits removed - is what is important.

If your system dictates that you'll be updating every value every time, a valid approach is to do a bulk transfer by ditching the identifiers and relying on the ordering to unpack it.

Alternatively, maybe you wont update every value, every time, but can still opt for the approach just outlined - that is, knowing that you're 'wasting' the redundant info, but still gaining the advantage of not having the addressing bits.

The other extreme is similar to what zoomcat suggests - addressing all transfers - this would be a valid approach for a system with lots of variables that are updated infrequently and/or more randomly.

Also, keep in mind that serial comms has a 'hidden' overhead per transfer - so in general, you'll gain a higher average rate by sending bulk blocks, but at the same time get a higher latency. (google 'latency vs. throughput' ...)

Have a think about what is most important to your system, sometime it'll be clear and the system will determine (force) one approach over the other. Sometimes you're 'lucky' and free to have a harder think about it (heh heh).

My system needed reasonable throughput (within a spec), had a natural latency via other factors that I could work within aaaand the values were updated every period - hence I opted for a bulk transfer of all values with no addressing.

Robin:

2hrs a day avg, 5days a week avg, 6months so far

2*5* 52/2 = 210 hrs

at 115200 baud

210*60*60*115200 = 87091200000 bits

3 byte packets: 87091200000 / 24 = 3628800000 successful data transmissions so far

Maybe I bodged the math, logic and facts here - but the point remains that the number will be higher than if I had addressed the packets... and, I can't recall ever seeing a failure (the system is such that it should be apparent).

edit, yes I did bodge it! this assumes constant data transfer and no overhead ...

But yeah, YMMV and it's system specific. Good luck to you! :)

It just seems sensible to me to build in a little bit of "protection". In my examples in serial input basics I don't have any error checking byte (for simpicity) but I have included it in a system I use myself.

...R

Similar to the difference when a waiter repeats back a full tables order in a noisy restaurant compared to when you get your usual at the local - a nod will suffice.

Context is key :wink:

If you have a system that isn't pushing bandwidth limits then build in error check and correction, serial data has no guarantees. The more idiot you build in, the worse it will be if/when something goes wrong.

OTOH you could be working on a career with an "it's only a little spill" oil company or an "oops, we didn't think of that" nuclear generator company.