SoftwareSerial or Arduino Mega?

Hi all,

I'm trying to figure this question out. I have some information which I am reading into the Arduino (an Uno at the moment) in the following sample format:

[1:5:15:30:other numbers]

I need to send this message back out of the Arduino to an external serial device in the same format and at the same data rate as it was received (9600-N-1).

My current code for dealing with this message is this (note that this does not resend the data, it only reads it in and filters out the characters ready for the loop() function to deal with the rest of the string):

void serialEvent() {
  while (Serial.available()) { // is there data to be processed?
    char inChar = (char)Serial.read(); // get the new byte
   	if (inChar != '[' && inChar != ']') { // filter out the [ and ] brackets
    inputString += inChar; // add it to the inputString:
   }
    // if the incoming character is ']' (ie end of message from PC), 
    // set a flag so the main loop can do something about it:
    if (inChar == ']') {
      stringComplete = true;
    } 
  }
}

The code I'm thinking of using to achieve the resend is this:

void serialEvent() {
  while (Serial.available()) { // is there data to be processed?
    byte inByte = (byte)Serial.read();
    mySerial.write(inByte);
    char inChar = char(inByte);
   	if (inChar != '[' && inChar != ']') { // filter out the [ and ] brackets
    inputString += inChar; // add it to the inputString:
   }
    // if the incoming character is ']' (ie end of message from PC), 
    // set a flag so the main loop can do something about it:
    if (inChar == ']') {
      stringComplete = true;
    } 
  }
}

I guess what I need to know is whether SoftwareSerial is up to the job or whether an Arduino Mega is more suited to the task. This is for a display for a timing program for RC model cars, so the byte information comes into the Arduino once every second. A maximum delay of 250ms is acceptable as it's close enough.

Thanks!

Joe

The code I'm thinking of using to achieve the resend is

exactly the same as the crappy code for reading the data. There is NO reason to be using a String. If the String instance can hold the longest string you will send, a string can, too.

I guess what I need to know is whether SoftwareSerial is up to the job

It is, IF the Arduino isn't doing much else. Or, even if it is, if the data arrives infrequently and involves a small amount of data. There are not enough details in your post to answer the question.

Where is the data coming from? Where is it going? Why does the sender need to send the [ and ]?

Hi Paul, thanks for your reply.

I'll look into using a string rather than a String, thanks for that. Apologies for the code, I've just started coding and am finding my feet.

To answer the questions from your reply, the data is coming from a program that is used to count the number of laps for RC model car racing. It stores all sorts of data, however the information it outputs for display purposes is in the format:

[roundno:raceno:minutes:seconds:car1,carN,:laps1,lapsN,:improver1,improverN,:]

The data from mySerial.write(inByte) is going to a wired external display board (with RS232 input) that cost a lot of money to buy a few years ago, it expects the data in this format (to answer your last question), hence the reason that the timing program sends it in that format.

My project uses this information and other information (for race start/finish lights) then transmits it via 433Mhz RF to other Arduinos for extra display boards and start/finish lights.

Video of the project so far (the displays are not representative, they're just for development): RC Timing Information Board Progress #2 - YouTube

The data coming into the Arduino on the USB connection is arriving once a second.

My blog for the project is here: - https://rcinfoboard.wordpress.com/

I hope that information fills in a few of the details, please let me know if not and I'll be happy to fill in the blanks.

Thanks!

What I'd need to know is something like "The sending device sends 80 characters, once per second, at 115200 baud...". Then, I could comment on the appropriateness of SoftwareSerial for reading the data.

Sure. The PC sends out to the Arduino between ~19 and ~74 characters, once a second at 9600 baud. The Arduino will need to send out to the display device exactly the same data at the same frequency (once a second), and at the same speed (9600 baud). Hope that helps. Thanks once again for your advice!

The Arduino will need to send out to the display device exactly the same data

Except for the [ and ]? Then, it is not exactly the same data.

SoftwareSerial will work at 9600 baud, 80 characters per second, with the Arduino doing not much else.

No, the Arduino will be resending exactly the same message as it receives via USB as the mySerial.write(inByte) is done before the [ and ] characters are filtered out.

So the serial input and mySerial output of the Arduino will be:

[roundno:raceno:minutes:seconds:car1,carN,:laps1,lapsN,:improver1,improverN,:]

whilst the code in the loop() function (once the stringComplete flag has signalled a complete message) will see:

roundno:raceno:minutes:seconds:car1,carN,:laps1,lapsN,:improver1,improverN,:

The complete code I'm intending to use is here:

https://codebender.cc/sketch:248551

Thanks for the info on SoftwareSerial! Given me confidence that I can do this project with a Uno or Atmega with Arduino bootloader.

For the small amount of data you’re sending, and the fact that it is clear text, not binary values (i.e., ASCII char values < 128), I would recommend NeoSWSerial, a SoftwareSerial alternative that will have no problem at 9600 baud (as shown in your sketch).

SoftwareSerial is an absolute CPU killer, and it is vulnerable to other interrupts.

Cheers,
/dev

P.S. Ditch the String. Although it looks easy to use, it has numerous pitfalls just waiting to manifest. Besides adding at least 1600 bytes to your sketch, you will also get flaky behaviour and random hangs. Instead, use char arrays, aka C strings.

@JoeK1973, I would use the 3rd example in Serial Input Basics to receive the data (changing the start- and end-markers to [ and ]. It will save the received data into a char array called receivedChars and you can send the data elsewhere simply with mySerial.println(receivedChars);

(Please note that the demo code assumes 32 bytes - but that is easily changed)

I am assuming you are allowing sufficient time for the data to be received and transmitted.

...R

I face a similar problem and I bought a Mega. I figured that I would have less problems down the road and the $80 investment wasn't much.

My project also has the possibility to expand, that was another factor in purchasing the mega.

@Robin2 - many thanks for the link to your 'Serial Input Basics' tutorial - it really helped a lot. I've used your code so now my project uses char arrays rather than String objects.

I've kept the event running after loop() for now, no reason not to call it myself I know :wink:

Here's the code:

void serialEvent(){
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '[';
    char endMarker = ']';
    char rc;
 
 // if (Serial.available() > 0) {
    while (Serial.available() > 0 && stringComplete == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                rideChars[(ndx + 1)] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                rideChars[(ndx + 1)] = rc;
                rideChars[(ndx + 2)] = '\0';
                recvInProgress = false;
                ndx = 0;
                stringComplete = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
            rideChars[ndx] = rc;
        }
    }
}

It's basically the same as your tutorial with the exception of another char array - rideChars - which picks up the '[' and ']' characters as I need them to be transmitted by the SoftwareSerial object mySerial, whist the receivedChars char array is processed by the loop() function for transmission by VirtualWire.

My entire code for the transmitter - RCINFOBOARD_TX_3 by joekeaveney

@/dev, thanks for the link to the NeoSWSerial library, I'll take a look at this now.

Thanks again guys, really appreciate the advice!