Arduino too slow for fast serial input (~10ms)? [SOLVED]

To get started with Arduino I am currently working on a project where I want some Game information from my Windows machine to be displayed on an 8x8 LED matrix and 4-digit display connected to an Arduino UNO R3.

Right now I already have a C# project that extracts hitpoints and some buff time information from the game in Windows and constructs a small string to send to the Arduino over Serial port.

The code I have written for the Arduino is pretty dumb and straightforward. It reads the serial string, extracts the numerical values and updates the connected LEDs accordingly.

Whenever I send this ~10 character string every second (1000ms) it seems to work fine. However, when I start sending serial strings every 100ms the Arduino seems to be unable to keep up with the messages sent and start ignoring them.

Eventually I would like to start sending messages even faster to the Arduino, in the range of 10ms. It seems completely unfeasable at this point. Increasing the baudrate on both ends doesn't seem to do anything. It seems like the problem lies in parsing the messages on the Arduino side.

Am I doing something structurally wrong, or am I simply asking too much from my Arduino UNO? I also have a Yún lying around which might be better suited to the task? If so, how should I best arrange the communication between PC and Arduino if Serial-over-USB is not a good option?

let's see your sketch.

cdekker:
To get started with Arduino I am currently working on a project where I want some Game information from my Windows machine to be displayed on an 8x8 LED matrix and 4-digit display connected to an Arduino UNO R3.

Right now I already have a C# project that extracts hitpoints and some buff time information from the game in Windows and constructs a small string to send to the Arduino over Serial port.

The code I have written for the Arduino is pretty dumb and straightforward. It reads the serial string, extracts the numerical values and updates the connected LEDs accordingly.

Whenever I send this ~10 character string every second (1000ms) it seems to work fine. However, when I start sending serial strings every 100ms the Arduino seems to be unable to keep up with the messages sent and start ignoring them.

Eventually I would like to start sending messages even faster to the Arduino, in the range of 10ms. It seems completely unfeasable at this point. Increasing the baudrate on both ends doesn't seem to do anything. It seems like the problem lies in parsing the messages on the Arduino side.

Am I doing something structurally wrong, or am I simply asking too much from my Arduino UNO? I also have a Yún lying around which might be better suited to the task? If so, how should I best arrange the communication between PC and Arduino if Serial-over-USB is not a good option?

At 115200, it should only take 8.68uS per bit, with start and stop bit that's 86.8uS per byte and 868uS per 10 characters, so if you keep your parsing minimal and fast, 100mS should be heaps of time, and 10mS shouldn't really be a problem either.
Maybe if you post your code someone can help more. (As Larry says, I just noticed. :slight_smile: )

Thanks for the fast replies!

While cleaning up the code in order to post it here I ended up rewriting / recopying from scratch and it seems be to processing my messages very fast now! I probably made a mistake with some looping variable that caused exponential time consumption. I still have trouble wrapping my head around this state-machine style coding, coming from an OO background.

Anyway, the code below does what it needs to do for me. A very early draft of what I want, but right now it shows the remaining time of 2 different buffs (named buffA and buffB for convenience) on one of the rows of the LED matrix.

Serial messages sent are, for example:
<A,1,170>
<A,1,230>
<B,1,183>
<B,1,35>

#include <LedControl.h>
#include <TM1637Display.h>
#include "binary.h"

// Device controls
LedControl lcMatrix = LedControl(12,11,10,1);
TM1637Display segDisp = TM1637Display(8,9);

// Game Variables
boolean buffAUp = false;
int buffADuration = 0; //0-255
boolean buffBUp = false;
int buffBDuration = 0; //0-255

// PC Communication variables
const byte numChars = 32;
char receivedChars[numChars];  // an array to store the received data
char tempChars[numChars];        // temporary array for use by strtok() function
boolean newData = false;

const char startMarker = '<';
const char endMarker = '>';

char messageFromPC[numChars] = {0};
int stacksFromPC = 0;
int durationFromPC = 0;

// Used loop variables
int i = 0;

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

  lcMatrix.shutdown(0, false);
  lcMatrix.setIntensity(0,15);
  lcMatrix.clearDisplay(0);

  segDisp.setBrightness(15);
}

void loop() {
  recvWithStartEndMarkers();
  if (newData == true) {
      parseData();
      processParsedData();
      newData = false;
  } 
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

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

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void parseData() {
  strcpy(tempChars, receivedChars);

  char * strtokIndx;

  strtokIndx = strtok(tempChars,",");
  strcpy(messageFromPC, strtokIndx);
  
  strtokIndx = strtok(NULL, ",");
  stacksFromPC = atoi(strtokIndx);

  strtokIndx = strtok(NULL, ",");
  durationFromPC = atoi(strtokIndx);
  
}

void processParsedData() {
  if (strcmp(messageFromPC, "A") == 0) {
    buffAUp = (stacksFromPC > 0);
    buffADuration = durationFromPC;
    updateLedMatrix();
  }

  if (strcmp(messageFromPC, "B") == 0) {
    buffBUp = (stacksFromPC > 0);
    buffBDuration = durationFromPC;
    updateLedMatrix();
  } 
}

void updateLedMatrix() {
  // First draw the duration of BuffA from right to left
  if (buffAUp) {
    for(i = 0; i<8; i++) {
      lcMatrix.setLed(0, 0, i, buffADuration > (i*32));
    }
  } else {
    lcMatrix.setRow(0,0,B00000000);
  }

  if (buffBUp) {
    for(i = 0; i<8; i++) {
      lcMatrix.setLed(0, 7, i, buffBDuration > (i*32));
    }
  } else {
    lcMatrix.setRow(0,7,B00000000);
  }
}

Glad you sorted it out. I won’t worry about wading through your code if it’s working fine. No need now. :slight_smile:

If it is of any value to you, an Uno can work much faster than 115200 baud. It should be perfectly reliable at 500,000 baud. It is just the Serial Monitor that has an upper limit of 115200.

...R

Robin2:
If it is of any value to you, an Uno can work much faster than 115200 baud. It should be perfectly reliable at 500,000 baud. It is just the Serial Monitor that has an upper limit of 115200.
...R

I don't know about cdekker, but I was unaware of this Robin. Handy to know.
The Serial.begin() documentation lists "300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, or 115200" and does say other baud rates can be used, but I wrongly assumed this meant other baud rates between 300 and 115200. It wouldn't have crossed my mind to try faster than 115200.

OldSteve:
It wouldn’t have crossed my mind to try faster than 115200.

The first thing I do when I get a new Uno is replace the bootloader with a 1 M baud version. The faster uploads are very nice.

[quote author=Coding Badly link=msg=2461924 date=1446542772]
The first thing I do when I get a new Uno is replace the bootloader with a 1 M baud version. The faster uploads are very nice.[/quote]
Right. Actually, I don't mind waiting for a few seconds for the actual upload. The compiling when the [Upload] button is pressed takes a little while anyway, when the source files are getting big.
Still interesting though. Another thing I wouldn't have thought of trying.