Reputation: 2486
I am trying to use a Serial Port to interface with a camera. Now, the camera has its own proprietary protocol, which is fairly simple and uses 6-byte commands and acknowledges.
Now, I am using C# to write the program which interfaces with the camera, since that allows me to use WPF, and I am comfortable with C# anyway.
My problem arises when I try to set up the camera to retreive an image. The Serial Port object works absolutely fine in doing this, when I step through the program. However, as soon as I run it at full speed, for some reason I end up with the messages at the port being very badly read and even missed. I get to the end of the setup process, just before I begin to retreive the actual data, and there are still commands and things which are still in the port's in buffer.
Now, this solution is, admittedly, just a very hacky attempt to learn the protocol and get the thing working at the moment, and I fully intend to improve it later, but I just cannot figure out why it does this. The camera isn't supposed to sent the next packet until I have acknowledged the last one, so I can only assume that the serial port object is problematic, not the camera or my handling of the protocol.
Could it be because I have (lazily, yes) got this function on the UI thread?
Here's the code:
private void retreivePhoto()
{
progressBar1.Visibility = Visibility.Visible;
photo = new FileStream(Environment.CurrentDirectory + @"/photos/" + (photoNum++) + ".jpg", FileMode.OpenOrCreate);
port.Open();
progressBar1.Value = 0.5;
setup.theMessage = setup.JPEG();
port.Write(setup.theMessage, 0, setup.theMessage.Length);
while (port.BytesToRead < 0) ;
port.Read(received.theMessage, 0, received.theMessage.Length);
setup.theMessage = setup.Package();
port.Write(setup.theMessage, 0, setup.theMessage.Length);
while (port.BytesToRead < 0) ;
port.Read(received.theMessage, 0, received.theMessage.Length);
setup.theMessage = (byte[])Message.SNAPSHOT.Clone();
port.Write(setup.theMessage, 0, setup.theMessage.Length);
while (port.BytesToRead < 0) ;
port.Read(received.theMessage, 0, received.theMessage.Length);
setup.theMessage = (byte[])Message.BLANK.Clone();
setup.theMessage[1] = (byte)Message.MessageTypes.GETPICTURE;
setup.theMessage[2] = (byte)Message.PictureType.SNAPSHOT;
port.Write(setup.theMessage, 0, setup.theMessage.Length);
while (port.BytesToRead < 0) ;
port.Read(received.theMessage, 0, received.theMessage.Length);
while (port.BytesToRead < 0) ;
port.Read(received.theMessage, 0, received.theMessage.Length);
int length = (received.theMessage[5] << 16) + (received.theMessage[4] << 8) + received.theMessage[3];
length /= data.theMessage.Length-6;
byte[] temp = {0xaa, 0x0e, 0x00, 0x00, 0x00, 0x00};
port.DiscardInBuffer();
port.Write(temp, 0, temp.Length);
int next = 0;
int bytes;
for (int i = 0; i < length; i++)
{
if ((bytes = port.BytesToRead) > 0)
{
port.Read(data.theMessage, 0, data.theMessage.Length);
if (bytes < data.theMessage.Length)
{
photo.Write(data.theMessage, 4, bytes - 6);
}
else
{
photo.Write(data.theMessage, 4, data.theMessage.Length - 6);
}
photo.Flush();
}
next = ((data.theMessage[1] << 8) + data.theMessage[0]) + 1;
byte[] nextBytes = System.BitConverter.GetBytes(next);
if (length - i == 1)
{
temp[4] = temp[5] = 0xf0;
}
else
{
temp[4] = nextBytes[0];
temp[5] = nextBytes[1];
}
port.Write(temp, 0, temp.Length);
}
progressBar1.Value = 1.0;
photo.Flush();
photo.Close();
port.Close();
progressBar1.Visibility = Visibility.Hidden;
}
Here is the camera's datasheet which describes the protocol. http://www.4dsystems.com.au/downloads/micro-CAM/Docs/uCAM-DS-rev7.pdf
Upvotes: 0
Views: 635
Reputation: 116178
while (port.BytesToRead < 0) ;
port.Read(received.theMessage, 0, received.theMessage.Length);
Doesn't mean that you will read received.theMessage.Length
bytes. it can be anything between 1 & received.theMessage.Length
. You should check the returned value
Upvotes: 1