0

Hello I want to know how to split an incoming serial message that comes in this format CxxxLxxx, x=number, so i can take the 3 numbers after the C and save them and then take the 3 numbers after the L and also save it, i have a code for this but it doesn't always work, can anyone tell me where I´m wrong or is the approach I´m taking is not the right one. Thanks.

int value = 0;
int channel;
int x;
String str;
int y;
String str1;
int le;


void loop()
{
if (Serial.read() == le)
{ }
  else
       {
        str = Serial.readStringUntil('C');
        str1 = Serial.readStringUntil('L');
        channel = Serial.parseInt();
        value = Serial.parseInt();
      DmxSimple.write(channel, value);
      le = Serial.read();
      Serial.println();

       }
} 
0

This:

if (Serial.read() == le)
{ }

looks very suspicious - sometimes it can read the C or L and therefore render the rest of your code useless.

Also Serial.parseInt shall be avoided - it returns the first thing which looks like a number, and will not wait for all three numbers.

However, your problem is likely the DMX write speed. While the DmxSimple.write is getting executed, no new incoming message can be processed. Depending on your actual Arduino board and chip, there is some buffer, but the solution is not rocket-proof at all.

You can:

  • make a solid protocol between the PC and the Arduino, i.e. the PC sends one command, arduino sends it out over the DMX, and Arduino answers an OK to the PC. The PC will not send out any new command unless it has received an OK first.
  • avoid these ad-hoc mess, i.e. serial-reads and serial.printlns here-and there.

For example, if you change the protocol so: CxxxLxxxE (E stands for end) you can utilize readStringUntil to read the input until a separator, and then use the toInt method to actually convert the read data to integer:

void loop() {
    strDummy = Serial.readStringUntil('C');
    strC = Serial.readStringUntil('L'); // xxx from CxxxL
    strL = Serial.readStringUntil('E'); // xxx from LxxxE
    channel = strC.toInt();
    value = strL.toInt();
    DmxSimple.write(channel, value);
} 

After learning that it is not possible to change the protocol, here is a new plan

int channel;
int value;
void loop() {
    if (Serial.read()=='C') { // wait for a C
        channel=Serial.parseInt(); // parse till first non-number
        value=Serial.parseInt(); // parse till first non-number
        DmxSimple.write(channel, value);
    }
} 

See https://www.arduino.cc/en/Tutorial/ReadASCIIString for a tutorial. Note that Arduino Serial commands are pretty confusing sometimes :) for example, parseInt will actually consume one non-number character implicitly after parsing a number.

Also note that this solution works well if the command is sent as one batch. If you are trying to send the command manually, e.g. from a terminal window, character by character, parseInt may time out. Consider increasing the timeout to 10 seconds or more by https://www.arduino.cc/en/Serial/SetTimeout

  • Thanks for the quick answer, the problem is that I get data from a program called Freestyler DMX, with the help of a program called Serialmon i saw that the protocol that the program uses is CxxxLxxx, and that why a cant add en 'E' to the protocol, I tried using Serial.readStringUntil, but cant get it to work the right way. – Hugiz Carrillo Apr 19 '16 at 15:37
  • Ok, then do this: read and discard anything until you get a C. Then read three characters and concatenate them to a string. Then read and discard anything until you get an L. Then read three characters and concatenate them to a string. The two strings now contains the two numbers. – Gee Bee Apr 19 '16 at 16:57
  • Ok, I tried this but it has some problem, also i dont know how to post in code again in the comment section sorry... C = Serial.read(); Serial.print(C); String channel_str = String(C); String value_str = String(C); channel_str.remove(4); // Remove from from index=4 leaving only Cxxx channel_str.remove(0,1); // Remove 1 character starting at index=0 leaving only xxx value_str.remove(0,5); // Remove 5 characters starting at index=0 leaving only xxx int channel = channel_str.toInt(); int value = value_str.toInt(); DmxSimple.write(channel, value); – Hugiz Carrillo Apr 20 '16 at 0:21
  • Unfortunately, code formatting does not work in comments. I am unsure what is the reason for printing out things what you read? and what is in C - that is one character only, it makes no sense to remove anything? Anyhow I have improved my answer with an example. – Gee Bee Apr 20 '16 at 12:23
  • Thanks for the help, i just made some changes and its ready to connect to the software FreeStyler, just having some minor problems with the processing speed but I can deal with that, thanks a lot. Should I post the code or leave it like that? – Hugiz Carrillo Apr 20 '16 at 17:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.