Serial Parity/Wakeup Bit Beginning of Packet - c#

The protocol I am working with uses the Parity (Wakeup) bit to signal the beginning of a new message over RS-232 - all other bytes of the message have the Parity bit set SPACE. Packet contains length and CRC...
I need to be able to catch the first byte with the Wakeup bit set and then process the packet from the length information in the message itself.
I have done this in several application in assembly and c.
I am moving to C# and just need help in triggering the start of the capture of the message from the Parity/Wakeup bit of the packet frame - 11 bit with 1 start, 1 stop, 8 data and the Wakeup bit.

Related

Receiving uneven results from Serial Port in C#

I have 2 GUI applications, one in C++ and one in C#.
The applications are the same and there is a function that writes and reads from COM port.
When I run my C++ app I receive the right result from the Serial.Read which is a buffer with 24 bytes.
But when I run my C# app I receive uneven results:
* Just 1 byte buffer if I don`t put sleep between write and read.
* Different sizes if I do put sleep between write and read (between 10-22 bytes).
What could be the reason for that?
My C++ code:
serial.write(&c, 1, &written);
serial.read(read_buf, read_len, &received); // received = 24
My C# code:
serial.Write(temp_char, 0, 1);
received = serial.Read(read_buff, 0,read_len); // received = 1
C# with sleep:
serial.Write(temp_char, 0, 1);
Thread.Sleep(100);
received = serial.Read(read_buff, 0,read_len); // received = (10~22)
Serial ports just give a stream of bytes, they don't know how you've written blocks of data to them. When you call read, the bytes that have been received are returned, if that isn't a complete message you need to call read repeatedly until you have the whole message.
You need to define a protocol to indicate message boundaries, this could be a special character (e.g. a new line in a text based protocol) or you can prefix your messages with a length.

Serial port not reading all data

I have a microcontroller (Arduino Uno) running nanopb that is sending protobuf messages over the wire. I'm finding that under one specific case I'm not receiving my full message. I thought for a while that it was the microcontroller, but it appears to be on the C# side that's reading from it.
The issue ONLY happens for uint32 values GREATER THAN 16. 16 or less and it works fine.
I've setup a VERY simple program on the microcontroller to ensure it's not my other code that's causing it there. Essentially it's sending a struct over the wire with one uint32_t value in it:
//Protobuf message:
message Test { required uint32 testInt = 1 }
//Resulting struct:
typedef struct Test {
uint32_t testInt;
}
//Serial code:
Serial.begin(115200);
pb_ostream_t ostream;
//Removed ostream setup code as it's not relevant here...
Test message;
Test.testInt = 17;
pb_encode_delimited(&ostream, Test_fields, &message);
If I plug in my device and look at it's data output using Termite I see the following data (which is correct):
[02] [08] [11] (note Termite displays it in hex)
(That's saying the message is 2 bytes long, followed by the msg start byte, followed by the Test.testInt value of 17 - 0x11 in hex)
Now, if I bring this up in C# I should see 3 bytes when reading the message, but I only see 2. When the value in testInt is 16 or less it comes across as three bytes, 17 or greater and I only get two:
var port = new SerialPort("COM7", 115200, Parity.None, 8, StopBits.One);
port.Handshake = Handshake.RequestToSendXOnXOff;
port.Open();
while (port.IsOpen)
{
Console.WriteLine(port.ReadByte());
Thread.Sleep(10);
}
port.Close();
Console.ReadLine();
Output with 16: 2 8 16
Output with 17: 2 8 17
Any help is greatly appreciated, I'm at a loss on this one =(
You set the serial port to use Xon/Xoff. Why?
The code for XON is 17.
If you are sending binary data, don't use Xon/Xoff.
Looks like a simple race condition - there is nothing to ensure that the C# code gets 3 bytes. It could get one, two, three or more. If, say, it starts the loop when two bytes are in the UART buffer then it will get two bytes and output them. I suspect the 16/17 issue is just a coincidence.
Also, when there is nothing in the buffer your loop consumes 100% CPU. That's not good.
You'd be better off using the blocking SerialPort.ReadByte() call, get the length byte and then loop to read that many more bytes from the serial port.
Also, as a protocol, using protobuf messages alone with no header mark isn't great. If you get out of sync it could take a long while before you get lucky and get back in sync. You might want to add some kind of 'magic byte' or a sequence of magic bytes at the start of each message so the reader can regain sync.

C# / GTK# Serial Port Read Issue

So I'm trying to read real time data from the serial port object in C# / Gtk#. I have a product which talks over RF to the computer and every time it gets a command it sends back an ACK. If I use AccessPort and auto send a command every 500ms, I get my ACK. I've ran AccessPort for hours and been able to match every single command to an ACK, so I know this is physically working.
I wrote a small program in C# / Gtk# that send data out the serial port at X ms and has a delegated thread which reads the serial port for any bytes that come back. My problem is that no matter how I write the method for the serial reading, it never actually captures all the bytes that I know are there.
So far this is the "lightest" code I have:
private void readSerial(){
byte readByte = 0x00;
Gtk.Application.Invoke (delegate {
try {
readByte = (byte)serialPort.ReadByte();
Console.WriteLine(readByte.ToString("X2"));
} catch (System.ArgumentException sae) {
Console.WriteLine(sae.Message);
}
});
}
I have assigned that method to a thread in the main function:
writeThread = new Thread (writeSerial);
readThread = new Thread (readSerial);
And I start it when a connect button is pressed, along with the writeThread. The writeThread is working fine as I can see the product execute the correct instruction every X ms ( currently I'm testing at 500ms). The ACK should arrive at the computer every X ms + 35 ms * module ID, so if my end product has a module id of 2 the response would be delayed by 70ms and hence the computer should see it at 570ms or X + 70ms.
Is there a better way to do this? I'm I doing something boneheadedly wrong?
Some other code I've played with was reading 0x0E bytes from the serial port and storing the bytes into a buffer, this also missed a lot of the bytes I know are coming back.
Can anyone offer some help? I do know the readSerial method is actually starting as I do see a 0x00 pop out on the console, which is correct as 0x00 are dispersed among the data I'm looking for.
Figured it out!
I'm not sure what the exact issue was but when I removed the delegation and just used a while(true) look inside that method it worked fine.

Incomplete data reading from serial port c#

I'm having a problem in reading the data transmitted from serial port (incomplete data in every first time running the project).
I've tried two methods to read:
byte[] data = new byte[_serialPort.BytesToRead];
_serialPort.Read(data, 0, data.Length);
txtGateway.Text = System.Text.Encoding.UTF8.GetString(data);
And
txtGateway.Text = _serialPort.ReadExisting();
However, it only reads 14 bytes in every first time when I start the program. When I trace the program, _serialPort.BytesToRead gives only 14 in every first time. If I send the data for the second time, the data is read correctly.
The above two methods have the same result. I'm sure that writing data from serial port gives the complete data.
Serial ports don't have any message boundaries. If you want framing, you have to add it yourself.
As for only the most recent 14 bytes being in the serial port when your program starts, 14 bytes is a typical FIFO size for serial ports.
See also How do you programmatically configure the Serial FIFO Receive and Transmit Buffers in Windows?
Or just flush the receive buffer when the program starts.
Hi you can use array with carriage return \r and ascii code \x02 for STX
string data = _serialPort.ReadExisting();
string[] arr1 = data.Split('\r');
checkFinal = checkFinal.Replace("\x02", "").ToString().Trim();

Creating communication protocol over TCP Sockets?

I have an Arduino microcontroller with a Sparkfun WiFly shield.
I build a simple program in C#/.NET that connects to the Arduino using System.Net.Sockets:
Socket Soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
public void SendMsg(string msg)
{
try
{
byte[] buffer = StrToByteArray(msg);
if (Soc.Connected)
Soc.Send(buffer);
else
{
Soc.Connect(this.remoteIP);
Soc.Send(buffer);
}
}
catch (Exception e){}
}
On the arduino I have:
while(SpiSerial.available() > 0) {
byte b = SpiSerial.read();
Serial.println(b);
}
When a socket connection does a handshake, I get: "*OPEN*" and when closed, I get: "*CLOS*".
The problem is that I get the messages one byte by another and sometimes I don't get the full message on one while loop.
So if I use the code I showed above on the Arduino, my serial terminal looks like:
*
O
P
E
N
*
T
E
S
T
*
C
L
O
S
*
So how can I figure out the message the PC is trying to send?
I know I need somehow to use a special byte that will symbolise the end of my message. (A special byte that I won't use in my message, only to symbolise the end of a message)
But how can I do it? And which byte to use?
You need to design your own protocol here. You should define a byte (preferably one that won't occur in the data) to indicate "start", and then you have three choices:
follow the start byte with a "length" byte indicating how much data
to read
define an "end" byte that marks the end of your data
read data until you have a complete message that matches one of
the ones you expect
The third option is the least extensible and flexible, of course, as if you already have a message "OPEN" you can't then add a new message "OPENED" for instance.
If you take the second option and define an "end" byte then you need to worry about escaping that byte if it occurs within your data (or use another byte that is guaranteed not to be in your data).
Looking at your current example, a good starting point would be to simply prefix each message with a length prefix.
If you want to support long messages you can use a 2 byte length prefix, then you read the first 2 bytes to get the length and then you continue reading from the socket until you have read the number of bytes indicated by the length prefix.
Once you have read a complete message you are then back to expecting to read the length prefix for the next message and so on until the communication is terminated by one of the parties.
Of course in between all this you need to check for error conditions like the socket on one end being closed prematurely etc. and how to handle the potential partial messages that can result form the premature closing of the socket.

Categories

Resources