Arduino 1.0 new Serial commands

Hey everyone,
So for a new project of mine I am trying to use the new Arduino 1.0 system. But I seem to be having a bit of trouble with the new serial commands. Basically what I am trying to do is send 6 bytes to the arduino and have the arduino parse out those bytes and act accordingly. The byte is structured as such:

  1. negotiator, such as '!"
  2. motor/command selection '0-6'
    3)motor speed, byte1
    4)motor speed, byte2
    5)motor speed, byte 3
    6)terminator, such as '~'
    The motor speed is made up of three bytes because I would like to send values '000' through '255' through the three bytes.

Does anyone have a good idea as to how i can receive the bytes, look for the negotiator, parse the next four bytes, and wrap/end everything up with the terminator??
I think I should be using the Serial.findUntil() and the Serial.parseint() commands but I can't get everything to work properly together.
I have the following code:

void useSerial()
{
//This function is for commanding the qik only through Serial
while(Serial.available() > 0)
{
  Serial.println(Serial.available());
  boolean ready = Serial.findUntil("!","~");
  if(ready)
  {
    Serial.println(Serial.available());
    if (Serial.available() == 4)
    {
      byte1 = Serial.read();
      byte2 = Serial.read();
      byte3 = Serial.read();
      byte4 = Serial.read();
      Debug();
    }
  }
}
}

and basically Serial.available seems to always be either 1 or 0, no matter how much info i send through.
Any help would be greatly appreciated.

Don't use == for the result of available - if more is available you will hang forever - the correct test would be

  if (Serial.available () >= 4)
  {
    // now read the bytes.
  }

This way the code won't lock up if its too slow and 5 or more bytes are in the buffer.

well i only want the bytes after the '!' byte.
i think the bigger issue is that when I run input something like '!0100~' i get a response of:
'1
1
2'
since the only serial.print commands are for the printing of available bytes, i think there may be some issue with the new serial commands, such as the serial.findUntil. i cant get it to work quite right

If you are sending a string like !0100~ then you probably need to capture the string and then use the string functions to parse it. I tweeked the below code to use the ~ as the end of string delimiter. Not sure if you really need the ! to signal the start of the string in your setup.

//zoomkat 3-5-12 simple delimited ',' string parce 
//from serial port input (via serial monitor)
//and print result out serial port
// CR/LF could also be a delimiter

String readString;

void setup() {
  Serial.begin(9600);
  Serial.println("serial delimit test 1.0"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like wer,qwe rty,123 456,hyre kjhg,
  //or like hello world,who are you?,bye!,

  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
        //do stuff with the captured readString 
        readString=""; //clears variable for new input
      }
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

Your program works (by fluke) at a high baud rate (e.g. 115200), but not at a low baud rate. The reason for this is that the findUtil() function reads and discards any communication that is not in the right format (e.g. !...~). At a high baud rate, the buffer can fill up before the findutil has time to process it, meaning that it finds the start character and the terminal character successfully.

At a low baud rate, however, it gets called before the buffer has enough information in, e.g. !xx, and because it does not comply to the format, this gets discarded. Then the rest of the string comes in as xx~, and once again, it does not comply, and gets discarded, so you have lost your entire packet.

The fix is simple. In addition to MarkT's fix, your while loop should also check the length of the available buffer, and it should contain enough characters to hold your whole packet.
I also suggest prefixing some of the information before printing it. Having a bunch of numbers and not knowing which print statement wrote it, is difficult to debug.
So the code should be something like this:

while(Serial.available() >= 6)
{
  Serial.print(F("raw: "));
  Serial.println(Serial.available());
  boolean ready = Serial.findUntil("!","~");
  if(ready)
  {
    Serial.print(F("processed: "));
    Serial.println(Serial.available());
    if (Serial.available() >= 4)
    {
       ... 
    }
  }
}

thanks for the sample code and explanation. with your help it seems to be working well now
although i do have one question, what does the F() do in F("raw: ")
my code is now:

void useSerial()
{
//This function is for commanding the qik only through Serial
while(Serial.available() >= 6)
{
  Serial.print(F("raw: "));
  Serial.println(Serial.available());
  boolean ready = Serial.findUntil("!","~");
  if(ready)
  {
    Serial.print(F("processed: "));
    Serial.println(Serial.available());
    if (Serial.available() >= 4)
    {
       command = Serial.read();
       Serial.print("Command is:  ");
       Serial.println(command);
       byte3 = Serial.read();
       Serial.print("Byte3 is:  ");
       Serial.println(byte3);
       byte4 = Serial.read();
       Serial.print("Byte4 is:  ");
       Serial.println(byte3);
       byte5 = Serial.read();
       Serial.print("Byte5 is:  ");
       Serial.println(byte5);
    }
  }
}
}

I am a bit old-fashion. I will use the below logic if I need to make sure I receive the right content:

  1. if serial.available(), serial.read()
  2. if read!='!' return to step 1 else go to step 3
  3. start a timer now by storing the millis in a variable called start.
  4. if millis()-start>=threshold, report time out while receiving command else go to 5.
  5. if serial.available () serial.read()
  6. if length of received string == length expected go to step 7 else go to step 4.
  7. if read=='~' then process the command in step 8, else report wrong format received, discard received content and go to 1.
  8. process the result with old-fashion sscanf or motor=bytes[1]-'0' to get motor number from ASCII to int, then speed=(bytes[2]-'0')*100+(bytes[3]-'0')*10+(bytes[4]-'0').
  9. operate the motor at the requested speed.

It's a bit long but it makes sure what it reads conforms with the expected format. You can also just keep buffering incoming characters until you find '~' and then check the buffer for a valid complete entry to process.

phinsil6:
although i do have one question, what does the F() do in F("raw: ")

It is a macro that ensures that constant strings are kept in flash memory (32 KBytes), and not loaded into SRAM. you only have 2048 bytes of SRAM, and every character takes up a byte. the F() macro ensures that only 1 character at a time is loaded from flash into RAM before being passed to the UART.

You can do this much simpler now with the parseInt and parseFloat commands.
If you use newline as terminator (/n) you can just type the command in your serial monitor and press enter.

The example online.

Just put commas, spaces or other characters in between the numbers, it works all.