go_away

Author Topic: CMUcam Receiving Packets Issues  (Read 2246 times)

0 Members and 1 Guest are viewing this topic.

Offline airman00Topic starter

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 3,653
  • Helpful? 21
  • narobo.com
CMUcam Receiving Packets Issues
« on: February 19, 2009, 08:40:25 AM »
I have the CMUcam Version 1 and I am interfacing it with the Axon.
I'm having an issue with receiving a packet from the CMUcam because the packets can be of different lengths.
For example for the track color command , I receive back the following type of packet. Please note that the packet received is in ASCII so '30' is really two bytes - '3' and '0'

Quote
M mx my x1 y1 x2 y2 pixels confidence
So for example I could receive the following packet
Quote
M 30 29 6 15 43 89 11 7
That packet above is really 24 individual bytes
Quote
77 32 51 48 32 50 57 32 54 32 49 53 32 52 51 32 56 57 32 49 49 32 55 13

In my code I have each ASCII number converted to decimal , so the character '3' is converted to the value 3.
My problem is as follows:
I could receive a packet that is short and not necessarily 24 individual bytes
For example , I could get one of these
Quote
M 0 0 0 0 0 0 0 0
M 3 9 6 5 3 9 1 7

This means that I can't just do CMUcam_Echo(23); , because I don't know how many characters to expect

I guess my only option is to not expect any exact number of characters, and after every space character ( decimal value of 32) then expect one more character. Then once I receive the \r (carriage return) byte ( decimal value of 13), I know that I am done taking in bytes.

Is there another way to do it?


P.S.  The CMUcam_Echo is just a modified version of Admin's Blackfin_Echo
Code: [Select]
//Receive Repeat Response data from Blackfin, store into an array of size response_counter
void CMUcam_Echo(int response_counter) //echos # of characters expected for each command
{
int temp;   // set up temporary variable
int counter=0;  //set the counter to 0
int middleten;
int middle;

rprintfInit(uart1SendByte);//change UART to bluetooth

while(1)
{
temp=uart0GetByte();//returns -1 if no data present

      if (temp != -1)//if data received
{
// rprintf("%c",temp); // send "temp" out to USB
response[counter]=temp & 0x0F;//store values into an array, &0x0F strips ascii off to use in char strings

counter++;  // add one to "counter" array
      if(counter >= response_counter || temp == '\n')  // once the counter equals the echo_counter OR you get a new line from the temp

{
rprintf("\r\n\r\n"); // send out carrier return and new line out to USB
uartFlushReceiveBuffer(0);//flush out receive camera buffer to stop phase shifting

break; //Get out of the while routine and exit the subroutine
}
}
}
}
« Last Edit: February 19, 2009, 09:18:29 AM by airman00 »
Check out the Roboduino, Arduino-compatible board!


Link: http://curiousinventor.com/kits/roboduino

www.Narobo.com

Offline cosminprund

  • Robot Overlord
  • ****
  • Posts: 284
  • Helpful? 8
Re: CMUcam Receiving Packets Issues
« Reply #1 on: February 19, 2009, 10:36:22 AM »
If you need to parse variable length numbers then nice and easy no longer cuts it.
Take a look at this version:

Code: [Select]
//Receive Repeat Response data from Blackfin, store into an array of size response_counter
void CMUcam_Echo(int response_counter) //echos # of characters expected for each command
{
signed char temp;
int state = 1;

response[0] = 0; // 0 bytes in "response" are set

while(state) {
temp = uart0GetByte(); // read next byte; If we've got -1 then we need to bail out!
if (temp == -1) state = 0; // No more chars available! Bail out!
else
switch (state) {
case 1: // Start state (hunt for chars state)
switch(temp) {
case ' ':
break; // ignore all spaces
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
// I'm going to start reading an new byte!
response[0]++; // Start an new byte, count the byte!
response[response[0]] = temp & 0x0F; // Init the response
state=2; // Let the state machine know we're reading an number
break;
case 'M': // Add a similar for each other letter you might expect in the stream
case 'X': // Example of an other letter
response[0]++;
response[response[0]]=temp;
if (response[0] >= (response_counter-1)) state = 0;
break;
case 13:
case 10:
// Bug. Why am I getting "-1"?
state = 0;
break;
default:
// Error! I encountered something that shouldn't be!
response[0]=0;
state = 0;
break;
}
break;
case 2: // Read number
switch (temp) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
response[response[0]] = (response[response[0]] * 10) + (temp & 0x0F);
break;
case ' ':
// I'm done with this char
if (response[0] >= (response_counter-1)) state = 0;
else state=1;
break;
case 13:
case 10:
state = 0;
break;
default:
// Input error! I encountered something that shouldn't be!
response[0]=0;
state=0;
break;
}
break;
default:
// Bug! How do you handle such errors on an MCU?
state = 0;
break;
}
}

// Ok, I'm done parsing the input!
// This code was in the original proc, I'm not sure what it does / if it's necesary

//rprintf("\r\n\r\n"); // send out carrier return and new line out to USB
//uartFlushReceiveBuffer(0);//flush out receive camera buffer to stop phase shifting
}

Read a bit throw the code; Some bits at the beginning got lost. I'm not sure what the last two lines of code are supposed to do so I commented them out - you probably want to comment them back! Here's how this code works. You call it (I assume) the same way you called the old CMUcam_Echo(), passing the number of bytes available in the "response" array. The response on the other hand is different.

Example one:
Blackfin sends: "M 30 29 6 15 43 89 11 7"
You call CMUcam_Echo(100);
After the function returns you'll get the following data in the response array:
response[0] = 9 -> the function parsed 9 results into
response[1] = 'M' -> the first thing that was parsed
response[2] = 30 -> make no mistake, it's the parsed output; It's not an 3 followed by an 0, it's truly 30.
response[3] = 29
response[4] = 6
response[5] = 15
response[6] = 43
response[7] = 89
response[8] = 11
response[9] = 7

if you declare the "response" array as an array of integer then this function will be able to parse things that are longer then 256!

Give it a try and tell me how it works. I don't have an Blackfin and I tested the function using simulated input - technically the tough parts of the function are good and working, but you I have no idea how it works with the rest of the library.

Offline airman00Topic starter

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 3,653
  • Helpful? 21
  • narobo.com
Re: CMUcam Receiving Packets Issues
« Reply #2 on: February 19, 2009, 10:52:29 AM »
I'm gonna try it later when I get home.

I'm thinking to try this type of pseudo code

where final variable is the final parsed variable, so where there is 'M mx my ....', mx would be a final parsed variable.
temp1 and temp2 are int variables.

Wait for the 'M' byte
Wait to receive the 'space' byte
Store the next received byte into temp1
If the next byte received is a space , then we're done and that variable is filled
Else store the next byte into temp2
Now we get final variable = (temp1*10) + temp2
Repeat for the other amount of variables
You know you're done with that packet when you receive the carriage return byte
Check out the Roboduino, Arduino-compatible board!


Link: http://curiousinventor.com/kits/roboduino

www.Narobo.com

Offline cosminprund

  • Robot Overlord
  • ****
  • Posts: 284
  • Helpful? 8
Re: CMUcam Receiving Packets Issues
« Reply #3 on: February 19, 2009, 10:58:52 AM »
This kind of stuff is best dealt with by a "finite state machine": http://en.wikipedia.org/wiki/Finite_state_machine
You can get away with simpler approaches (because of the very simple stuff that needs to be parsed) but implementing a state machine still pays off if you ever need to alter it in any way!
The code I suggested does exactly that: It builds a two state state machine: State "1" is "waiting for a byte", state "2" is read a number!

Pseudocode:

init variables;
init state;

while (state not done) and (I've still got an other char to read)
{
   read next char;
   I'm in state "1"? Expect an "M", an number or an space char; If I get an "M" mark it and stay in state 1; If I get an space ignore it and stay in state 1; If I get an number start reading the number and move to state 2!
  I'm in state 2? If the current char is an number add it to the previously read number; If it's something else then mark the number done and go back to state "1" 
}

Offline pomprocker

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: CMUcam Receiving Packets Issues
« Reply #4 on: February 19, 2009, 11:50:39 AM »
A lot of people when converting between string, char, byte, etc have to get the length of the variable beforehand with something like strlen or sizeof functions.

Offline airman00Topic starter

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 3,653
  • Helpful? 21
  • narobo.com
Re: CMUcam Receiving Packets Issues
« Reply #5 on: February 19, 2009, 12:01:03 PM »
   I'm in state "1"? Expect an "M", an number or an space char; If I get an "M" mark it and stay in state 1; If I get an space ignore it and stay in state 1; If I get an number start reading the number and move to state 2!
  I'm in state 2? If the current char is an number add it to the previously read number; If it's something else then mark the number done and go back to state "1" 
I think I understand now

Funny how I was using Finite State Machines all this time in some of my other software projects and I didn't even know it had a name. :P
Check out the Roboduino, Arduino-compatible board!


Link: http://curiousinventor.com/kits/roboduino

www.Narobo.com

Offline cosminprund

  • Robot Overlord
  • ****
  • Posts: 284
  • Helpful? 8
Re: CMUcam Receiving Packets Issues
« Reply #6 on: February 19, 2009, 12:13:42 PM »
Here's an other version of the same function, without the state machine. It compiles to a SMALLER byte count! I'll need to look into the disassembly listing for the switch based function to figure out why's that. On a bigger processor I'd never worry and I'd be sure the switch-based function is faster but I'm not sure on the microcontroller. Besides, the function's bottleneck is receiving data from the USART (uart0GetByte), not the processing of the data.

Code: [Select]
//Receive Repeat Response data from Blackfin, store into an array of size response_counter
void CMUcam_Echo(int response_counter) //echos # of characters expected for each command
{
signed char temp;

response[0] = 0; // 0 bytes in "response" are set

temp = uart0GetByte();
while((response[0] < (response_counter-1)) && (temp != -1)) {
if ((temp >= '0') && (temp <= '9'))
{
response[0]++;
response[response[0]] = temp & 0x0F;
temp = uart0GetByte();
while ((temp >= '0') && (temp <= '9'))
{
response[response[0]] = (response[response[0]] * 10) + (temp & 0x0F);
temp = uart0GetByte();
}
}
else if (temp == ' ')
{
temp = uart0GetByte(); // Ignore space
}
else if (temp == 'M')
{
// Do something with the "M" if you find it interesting
temp = uart0GetByte(); // Prep the next byte
}
else
temp = -1; // bail out
}

// Ok, I'm done parsing the input!
// This code was in the original proc, I'm not sure what it does / if it's necesary

//rprintf("\r\n\r\n"); // send out carrier return and new line out to USB
//uartFlushReceiveBuffer(0);//flush out receive camera buffer to stop phase shifting
}

Offline airman00Topic starter

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 3,653
  • Helpful? 21
  • narobo.com
Re: CMUcam Receiving Packets Issues
« Reply #7 on: February 21, 2009, 05:07:06 PM »
I feel stupid now... theres a mode on the CMUcam to send data in the proper format I was looking for ( non-ASCII) . All i have to do is send the CMUcam the command "RM 1" - which is  Raw Serial output mode.

Now its just a matter of taking in bytes and storing them into an array.

Thanks for all your help guys.
Check out the Roboduino, Arduino-compatible board!


Link: http://curiousinventor.com/kits/roboduino

www.Narobo.com

Offline pomprocker

  • Supreme Robot
  • *****
  • Posts: 1,430
  • Helpful? 16
  • Sorry miss, I was giving myself an oil-job.
Re: CMUcam Receiving Packets Issues
« Reply #8 on: February 23, 2009, 01:44:30 PM »
Good find, thanks for the heads up when trying to configure a UART device :P

Offline Admin

  • Administrator
  • Supreme Robot
  • *****
  • Posts: 11,663
  • Helpful? 169
    • Society of Robots
Re: CMUcam Receiving Packets Issues
« Reply #9 on: February 26, 2009, 04:56:02 AM »
Quote
Funny how I was using Finite State Machines all this time in some of my other software projects and I didn't even know it had a name.
Its a very general term. Heck, the $50 Robot at default settings is a Finite State Machine. But I'm a fuzzy logic guy ;D


And out of curiosity, why do you want to use Raw Serial output mode?

Offline airman00Topic starter

  • Contest Winner
  • Supreme Robot
  • ****
  • Posts: 3,653
  • Helpful? 21
  • narobo.com
Re: CMUcam Receiving Packets Issues
« Reply #10 on: February 26, 2009, 10:26:52 AM »
And out of curiosity, why do you want to use Raw Serial output mode?
easy communication with the Axon
Check out the Roboduino, Arduino-compatible board!


Link: http://curiousinventor.com/kits/roboduino

www.Narobo.com

 


Get Your Ad Here

data_list