Go Down

Topic: What is a faster alternative to parseInt()? (Read 1 time) previous topic - next topic

mr-matt

I'm making an led spectrum analyzer with an arduino due and my pc. The audio processing is done on the pc, and then sent to the arduino. The exact data sent is a 'coordinate', or more specifically, a number representing a particular band, and another number representing the maximum amplitude of that band. There are 11 bands.

This is my code as of now:

Code: [Select]

void loop()
{
  if (Serial.available())
  {
    xCoord = Serial.parseInt();
    yCoord = Serial.parseInt();

    if (xCoord != 0)
    {
      int r, g, b;

      for (int i = 0; i < 8; i++)
      {
        int fromCoordToIndex = ((xCoord - 1) * 8) + i;

        //
        //do some calculations for the color
        //

        strip.setPixelColor(fromCoordToIndex, strip.Color(r, g, b));
        strip.show();
      }
    }
  }
}


Problem is parseInt seems to be very very slow (it's not the timeout issue, its set to 1). From what I can see, it seems to be skipping some data, so every now and then a band gets missed out. The only way I can fix this is to insert a delay between each coordinate being sent. I found that 40ms works ok, but remember there are 11 bands, so that means ~half a second to refresh the whole board, which feels like a slide show...

I've tried inputting individual characters and then using toInt, I've tried parseInt obviously, I've tried native USB (its a due), and I've tried fiddling with baud rates. None seems to have had any affect.

Robin2

#1
Oct 29, 2017, 09:59 am Last Edit: Oct 29, 2017, 10:00 am by Robin2
Rather than use parseInt() to receive each item separately have a look at the examples in Serial Input Basics which receive a complete message before trying to parse any of it. That should ensure that you receive all the data as quickly as possible and without data loss. There is also a parse example in the link.

My guess is that if you do that you will find that the problem was not actually due to the parsing being slow.

However if the parsing really is still too slow it is probably due to the use of  the atoi() function to convert the text to an integer. If you send text in which the number is ALWAYS represented by (say) 3 characters - such as 061 or 235 - then you could write your own code ot convert those to an int which would probably be significantly faster than atoi().

Have you the scope to modify the format in which the PC sends data? If you really need the best performance then you should send the data in binary format - but I try to avoid that as it makes the debugging more difficult.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

sterretje

parseInt more than likely uses a timeout. So it waits till a non-numeric character is received or a timeout happens.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

mr-matt

Sterretje It is not the timeout. I have sent it with a comma between coordinates and sent it as a line (the new line should be considered a non-numerical character I think). Also, I've set the timeout to 1ms, so even if it was waiting, it would only wait for 1ms.

Robin, I can definitely control how the data is sent so I could format it as binary. Only question there is can I still convert it to an int to do some calculations for other things? Would that also be slow?

aarg

#4
Oct 29, 2017, 06:32 pm Last Edit: Oct 29, 2017, 06:40 pm by aarg
Sterretje It is not the timeout. I have sent it with a comma between coordinates and sent it as a line (the new line should be considered a non-numerical character I think). Also, I've set the timeout to 1ms, so even if it was waiting, it would only wait for 1ms.

Robin, I can definitely control how the data is sent so I could format it as binary. Only question there is can I still convert it to an int to do some calculations for other things? Would that also be slow?
You're missing the point. The real reason you are experiencing slowness is not because of the timeout. It is only there to prevent an infinite wait if no data is received. The real problem is that with parseint(), the entire message must be received before the program can continue. Additionally, it will wait during any transmission delays.So if the line you are parsing has 20 characters for example, it will be 20 (or more) times slower than processing one character at a time, before passing control to the rest of the program (using cooperative multitasking).

In both cases, the laws of causality dictate that you can't act on the message until it is fully received. The problem with parseint() is that you can't do anything else after you begin to receive.
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.


Robin2

I seem to have fixed it by changing the baud rate from 115200 to 9600.
For some definition of "fixed".

With the right code you would have no problems at 500,000 baud.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

mr-matt

Yes that is true, but it's not for scientific purposes or anything, I just want it to look good, which it does, so I'm happy.

Go Up