I am receiving data to send to FEZ mini motors, and I am splitting the incoming data on ‘,’ however occasionally I get 2 & 1/2 values which out grows the array throwing an exception.
Without a code sample we can only guess what is happening…
I would guess that you are assuming that each time you do a read you get one value. This would be a wrong assumption with streaming data. You could read one value, a half a value, two values etc. You have to parse the data stream separating the read data into values.
The code that actually does the serial port reading is not included in your code.
As I said, if your data is continually streaming, if is possible that you will receive more than one value in a single read. Add a Debug.Print to your ReadMessage method and see how the data is actually arriving.
you showed parenthesis around your value pairs. Are they actually included in the data? If not, then you will need some way of terminating each value pair. For example,
no the parenthesis are not part of the data just to separate them from the text one set is
10,10,
or
10,12,
Ok, so for some reason charBuffer.ToString(); didn’t like being printed out, but after the exception had been thrown I could see the buffer
the output is :
and incase it would help this is my ReadMessage method:
static string ReadMessage()
{
if (serialPort.BytesToRead > 0)
{
int noAvailable = serialPort.BytesToRead;
byte[] byteBuffer = new byte[noAvailable];
serialPort.Read(
byteBuffer, // buffer to store the data
0, // start location for data
noAvailable); // number of bytes to read
decoder.Convert(byteBuffer, 0, noAvailable,
charBuffer, 0, BUFFER_SIZE,
false, out bytesUsed, out charsUsed, out complete);
Debug.Print("recieved");
return new string(charBuffer);
}
return "";
}
you’re relying on getting all the data at once - you can’t make that assumption.
You need to de-queue data that you process and leave the remnants for subsequent processing. So in your scenario you need a higher-level object that contains the string that has been read but is yet un-processed, and use that as the first part of your “temp” string.
Let me also say however, string processing is going to be slower than you expect (and cause GC runs), perhaps you’re better off parsing the byte array? Grab a character from your last processed point, if a number “add” in the new value (you’ll need to handle before a decimal point and after a decimal point scenarios); if a comma or delimiter, move on to next value or next line.
do you mean something like this or am I missing the point ?
static sbyte[] ReadMessage()
{
sbyte[] retrievedMessage = new sbyte[2]{0,0};
if (serialPort.BytesToRead > 0)
{
int noAvailable = serialPort.BytesToRead;
byte[] byteBuffer = new byte[noAvailable];
serialPort.Read(
byteBuffer, // buffer to store the data
0, // start location for data
noAvailable); // number of bytes to read
for (int i = 0; i < noAvailable; i++)
{
if ((int)byteBuffer[i] < 39 && (int)byteBuffer[i] >= 30)
{
//store digits until ','
//add leftover bytes to storage for use on next recurrsion
}
}
}
return retrievedMessage;
}
Well, I guess it’d be worth seeing how you’re expecting to call the methods in question.
But I consider this a consumer/producer problem, and in need of a circular buffer. That’s how I would approach it…
Your producer is just a loop that, when there’s room on the CBuf, it just reads the number of available slots on the buffer, or the available bytes on the serial port, and adds them to the buffer.
You then have a consumer that looks if there’s a full sequence of data on the queue, and if so de-spool it and parse it, and then act on it.
First you are going to have to add a separator between value pairs. You can not make any assumptions that there will be a time delay between value pairs.
And then implement a mechanism as described by Brett.