LibUsbDotNet USBEndpointReader DataReceived event is not firing when I expect it to - c#

I have a USB device from which I need to read data via LibUsbDotNet.
If I use the following code after I've successfully opened the device...
protected UsbEndpointReader _libUsbReader = null;
protected UsbEndpointWriter _libUsbWriter = null;
.
IUsbDevice wholeUsbDevice = PhysicalLibUSBDevice as IUsbDevice;
if (!ReferenceEquals(wholeUsbDevice, null))
{
// This is a "whole" USB device. Before it can be used,
// the desired configuration and interface must be selected.
// Select config #1
wholeUsbDevice.SetConfiguration(1);
// Claim interface #0.
wholeUsbDevice.ClaimInterface(0);
}
// Create the reader and writer streams
_libUsbReader = PhysicalLibUSBDevice.OpenEndpointReader(LibUsbDotNet.Main.ReadEndpointID.Ep01);
_libUsbWriter = PhysicalLibUSBDevice.OpenEndpointWriter(LibUsbDotNet.Main.WriteEndpointID.Ep02);
_libUsbReader.DataReceivedEnabled = true;
_libUsbReader.DataReceived += OnDataReceived;
_libUsbReader.ReadThreadPriority = System.Threading.ThreadPriority.Highest;
_libUsbReader.ReadBufferSize = 32;
and define the method:
private void OnDataReceived(object sender, EndpointDataEventArgs e)
{
Console.WriteLine("Data received");
}
The event never fires. I know the packets are being received by my code as I have a USB analyser attached and can see them coming in.
If I change the code to remove the reliance upon the event callback and instead use the loop below on a background thread to read the reader object
while(true)
{
ErrorCode ec = ErrorCode.None;
Thread.Sleep(5);
int bytesRead;
byte[] buffer = new byte[32];
ec = _libUsbReader.Read(buffer, 1000, out bytesRead);
if(bytesRead>0) Console.WriteLine("Data Received");
}
Then everything works great.
I've tried playing around with the order I initialise, the values etc and can still get no joy. Can anyone suggest why the events aren't firing if I use the DataReceived event?
I'm using LibUsbDotNet 2.2.8.

I know this is old, but in your code:
...
_libUsbReader.DataReceivedEnabled = true;
_libUsbReader.DataReceived += OnDataReceived;
_libUsbReader.ReadThreadPriority = System.Threading.ThreadPriority.Highest;
_libUsbReader.ReadBufferSize = 32;
...
I have DataReceivedEnabled set after DataReceived (not sure if this makes a difference).
Also, I do not change thread priority and ReadBufferSize. The latter is 4096 by default. When data arrives, the EndpointDataEventArgs parameter to the event has the Count property with the actual number of bytes received.
Hope this helps.

Please try like this:
_libUsbReader.DataReceived += mEp_DataReceived;
private void mEp_DataReceived(object sender, EndpointDataEventArgs e)
{
try
{
Invoke(new OnDataReceivedDelegate(OnDataReceived), new object[] { sender, e });
}
catch
{
closeDevice();
}
}

When opening the endpoint for reading, you should define the endpoint type to interrupt, otherwise the Datarecieve event won't fire.
(Optionally define the size of the read buffer)
In your code you'll have to modify just this row:
_libUsbReader = PhysicalLibUSBDevice.OpenEndpointReader(LibUsbDotNet.Main.ReadEndpointID.Ep01, 64, EndpointType.Interrupt);

I think the sollution is that you should read the endpoint content at the event (or discard it). I had the same problem, when only printing at the console the message I only entered 1 time. When I process in the event the data on the endpoint with read command, the problem seems to be solved.

Related

c# constantly requesting and processing data from serial port

After a long time i need to program again.
I need to constantly send a command through serial port from a car ecu(? data).
Then i need to receive that data which i will process to be shown on a display(thinking racing display with car parameters like temperature etc).
I need to do this constantly
I wonder before i start whats best way to do this?
1 thread for constantly asking and receiving data
main thread for showing data in screen.
(store data in buffer and save once a minute or so)
anyone has any tips a guide or so how to start on this.
i tested receiving data with terminal and i got data back so config is working.
sent ? data => i got data back.
You could just use the SerialPort class and configure the BaudRate, DataBits etc.. and then just wait for the DataReceived event to fire:
public class SerialPortReader
{
public SerialPortReader(string yourPortName)
{
var serialPort = new SerialPort() {
PortName = yourPortName,
BaudRate = 57600; //This will control the rate at what you receive the data
}
serialPort.DataReceived += new SerialDataReceivedEventHandler(OnDataReceived);
serialPort.Open();
}
}
public void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
{
var serialPort = (SerialPort)sender;
// Process your data reading the stream with Read, ReadLine etc...
}
The approach we are using in our SerialPort Handler is, to have an AutoResetEvent to get notified as soon as there is an answer from the port.
SerialPort class of the FrameWork has a few issues with the integrated DataReceived event. It is sometimes fired when there is no complete package available (in case you defined the answer length). So you should check for the answer length you expect.
Our very stripped down implementation:
public class Serialport
{
private SerialPort _serialPort;
private List<byte> _buffer;
private AutoResetEvent _autoResetEvent;
private const int WriteTimeOut = 5;
private event EventHandler ReceivedDataChanged;
public Serialport()
{
_serialPort = new SerialPort();
// set PortName, BaudRate etc
_serialPort.Open();
_serialPort.DiscardInBuffer();
_serialPort.DiscardOutBuffer();
_serialPort.DataReceived += ReceiveData;
}
private void ReceiveData(object sender, SerialDataReceivedEventArgs e)
{
var bytes = _serialPort.BytesToRead;
byte[] buffer = new byte[bytes];
if (_serialPort.IsOpen)
{
_serialPort.BaseStream.Read(buffer, 0, bytes);
_buffer.AddRange(buffer);
}
ReceivedDataChanged?.Invoke(this, new ReceivedBytesEventArgs(_buffer.ToArray()));
_buffer.Clear();
}
private void SendData(byte[] message, int answerLength)
{
_serialPort.ReceivedBytesThreshold = answerLength;
_serialPort.WriteTimeout = WriteTimeOut;
_serialPort.Write(message, 0, message.Length);
}
public string SendDataCommand()
{
if (_serialPort.IsOpen)
{
ReceivedDataChanged += InterpretAnswer;
SendData(message, length);
if (_autoResetEvent.WaitOne(100))
{
ReceivedDataChanged -= InterpretAnswer;
//Data Received and interpreted and send to the caller
return _requestAnswer;
}
ReceivedDataChanged -= InterpretAnswer;
}
return "Connection not open";
}
private void InterpretAnswer(object sender, EventArgs e)
{
// handle all interpretation
// Set the event
_autoResetEvent.Set();
}
}
The serialPort is initialised and opened. After that, we wire up all needed events and call the SendDataCommand() Method. This method is the public visible method which is called from some task. This calls the method SendData. As soon as there is an answer, the event is triggered and the interpretation is started. If the interpretation is done in the specified amount of time (_autoResetEvent.WaitOne(msToWait)) the result is given back to the calling method.
This should be done in a separate task, so the ui will not Block while you wait for the answer
As mentioned, this is a very stripped down example. You should do more checking in the received handler of SerialPort, because there are some issues with the event. With this approach you will have a bit more of abstraction to your business logic.
Hope this helps.

How can I use EventWaitHandle to create an event?

I'm writing a program that listens on a Serial Port. I already have code that utilizes the VCP drivers (Virtual COM Port) to open a serial connection and then add an event handler for any time data is received. That code roughly looks like this:
public void OpenPort(string portNumber)
{
_port = new SerialPort(
portName: portNumber,
baudRate: 9600,
parity: Parity.None,
dataBits: 8,
stopBits: StopBits.One
);
_port.DataReceived += ReadData;
}
private void ReadData(object sender, SerialDataReceivedEventArgs e)
{
string data = _port.ReadExisting().Trim();
Console.WriteLine("Received: " + data);
}
This works great. It's very easy for me to understand how to set up events using the += notation. But I'm trying to switch over from using the VCP drivers to instead using the D2XX drivers provided by FTDI. I have most of the equivalent code that I need written, with the notable exception of being able to read data whenever a "data received" event occurs.
The D2XX driver includes one method for setting up event handlers whenever data is received, called SetEventNotification. Here's what the method signature looks like:
SetEventNotification(UInt32 eventMask, EventWaitHandle eventHandle);
The first parameter is straight-forward enough (they have some predefined uints you can pass in to determine when the event should trigger), but I've never worked directly with EventWaitHandles before, and I found the documentation difficult to grasp, so I'm having trouble getting started.
At the end of the day... I would like to have an event listener method which performs a read task, and which I can assign using the += operator, as I did above with the VCP driver.
Based on what I was reading, it looks like I'll have to create a new Thread that essentially polls continuously for the EventWaitHandle's signal? Or something like that? Any examples or sample code to get me started (or finished!) would be appreciated.
Here's what I have so far:
public void OpenPort(string portNumber)
{
_port = new FTDI();
var status = _port.OpenBySerialNumber(portNumber);
if (FTDI.FT_STATUS.FT_OK != status) throw new Exception();
status = _port.SetBaudRate((UInt32) 9600);
if (FTDI.FT_STATUS.FT_OK != status) throw new Exception();
status = _port.SetDataCharacteristics(
DataBits: FTDI.FT_DATA_BITS.FT_BITS_8,
StopBits: FTDI.FT_STOP_BITS.FT_STOP_BITS_1,
Parity: FTDI.FT_PARITY.FT_PARITY_NONE
);
if (FTDI.FT_STATUS.FT_OK != status) throw new Exception();
var evHandle = new EventWaitHandle(false, EventResetMode.AutoReset, "");
_port.SetEventNotification(FTDI.FT_EVENTS.FT_EVENT_RXCHAR, evHandle);
// ... now what?
}
public void ReadData(object sender, EventArgs e)
{
UInt32 bytesAvailable = 0;
_port.GetRxBytesAvailable(ref bytesAvailable);
string data;
UInt32 bytesRead = 0;
_port.Read(out data, bytesAvailable, ref bytesRead);
data = data.Trim();
Console.WriteLine("Received: " + data);
}
I'll have to create a new Thread that essentially polls continuously for the EventWaitHandle's signal
Polls, no. But waits, yes. All that an event handle can do is let a thread sleep until the event is signaled. Note that "event" here means something completely different from a C# "event", though of course you can use the former as part of an implementation of the latter.
Frankly, it's not clear at all why you are headed down this part. Are you dealing with data transmitted over the standard serial port? If so, then there should never be any need to use some third-party API; Windows and .NET provide all you need, and you should stick with that. What does using this third-party API gain you that you are unable to accomplish using the standard SerialPort class?
As far as the event itself goes, without more context (and no, it's unlikely anyone would sift through the PDF you linked to figure out how to produce a turn-key solution for you), all one can offer is a general outline of how you can use the event handle to implement an event:
public event EventHandler DataReceived;
private bool _done;
private void PortListener(EventWaitHandle waitHandle)
{
while (true)
{
waitHandle.WaitOne();
if (_done)
{
break;
}
EventHandler handler = DataReceived;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
public void StartListening(EventWaitHandle waitHandle)
{
_done = false;
new Thread(() => PortListener(waitHandle)).Start()
}
public void StopListening(EventWaitHandle waitHandle)
{
_done = true;
waitHandle.Set();
}
The above provides a DataReceived C# event that is raised any time the wait handle is signaled. It assumes an auto-reset event. You can also use manual reset, simply by (of course) manually resetting the event handle any time it's signaled and you've raised the C# event.
To do this, it simply maintains an internal flag _done indicating whether the thread should be running or not, and provides the Start... and Stop... methods, which clear the flag and start the thread with its loop, and set the flag and signal the event, respectively.

Serial Port Data Received only working when breakpoint set C#

I'm trying to read data from serial port. It reads data when I set breakpoint.
I have tried with parent delegate invoke, some delay also. It doesn't work for me.
Here is my code
Read code from class file:
public void comport_DataReceived2(object sender, SerialDataReceivedEventArgs e)
{
var bytes = comport.BytesToRead;
var buffer = new byte[bytes];
string test2 = comport.ReadExisting();
if (IsReadPDSS)
{
if(test2 != string.Empty && test2 != " " && test2.Length > 30)
{
test2 = test2.Substring(30);
test2.Replace("000000000000P0000W", "");
strReceived += test2;
}
}
else
{
strReceived = test2;
}
}
windows form retriving read data :
string ss=FormObj.strReceived.ToString();
When you do application debugging, your system is not entirely frozen. Only the application you debug. Thus, while your app is in a breakpoint, incoming data on the serial port still is being accumulated.
The control flow is a bit fuzzy (probably because you changed it over a few times while looking for the problem). As it is written now, you read the data from the serial port whenever the event is raised. It is not likely that 30 bytes have arrived at the time you read the data. If you break into the debugger and do single stepping, it is rather more likely that you will find more than 30 bytes in the receive buffer (depending on what your device which transmits does).
Hence, a better way to write the control flow would look like this:
public void comport_DataReceived2(object sender, SerialDataReceivedEventArgs e)
{
var bytes = comport.BytesToRead;
if( bytes > 30 )
{
var test2 = comport.ReadExisting();
// additional testing code as required...
}
}
Depending on how the event raising behavior works, you might need to accumulate the data yourself in an extra buffer if the event is not getting re-raised after being fired for the first time... But that should be easy enough to test and adapt.

serialport continuous real time data c#

Hi I'm trying to program a simple C# WPF that displays time information on a virtual scoreboard in real time from a timing system. I'm fairly new to programming so in depth explanation would be appreciated.
I have created a new thread to handle the incoming data from the COM port and as the app is developed this data will be interpreted. For now I just wanted to display the raw information (in hex) that is coming from the timer into a textbox. This works but not as intended. I am receiving tons of duplicate information, my only explanation is I am reading the data too slowly or its reading the same byte over and over. What I would like to happen is to take out each byte and display them, all controlled by one start/stop button.
Possible solutions include storing the entire buffer in a list or array which I'm not quite sure of yet, I don't want to add so many threads that the program freezes everything up.
Here is my code so far (I'm new to pretty much all the code I have written here, so if anything is bad practice please let me know):
public partial class MainWindow : Window
{
SerialPort comms;
Thread commThread;
bool flag;
string message;
public MainWindow()
{
InitializeComponent();
comms = new SerialPort();
}
private void PortControl_Click(object sender, RoutedEventArgs e)
{
if (!comms.IsOpen)
{
PortControl.Content = "Stop";
comms.PortName = "COM1";
comms.BaudRate = 9600;
comms.DataBits = 8;
comms.StopBits = StopBits.One;
comms.Parity = Parity.Even;
comms.ReadTimeout = 500;
comms.ReceivedBytesThreshold = 1;
commThread = new Thread(new ThreadStart(Handle));
comms.Open();
comms.DataReceived += new SerialDataReceivedEventHandler(ReadIn);
}
else
{
PortControl.Content = "Start";
flag = false;
comms.DataReceived -= ReadIn;
commThread.Join();
comms.Close();
}
}
private void ReadIn(object sender, SerialDataReceivedEventArgs e)
{
if (!commThread.IsAlive)
{
flag = true;
commThread.Start();
}
}
private void Handle()
{
while (flag)
{
if (comms.IsOpen)
{
try
{
message = comms.ReadByte().ToString("X2");
Dispatcher.BeginInvoke((Action)(() =>
{
ConsoleBox.Text += message + " ";
}));
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
}
Here is one solution.
The serial port is receiving the data in its own thread, and you should read the incoming bytes in the data received handler.
I propose to read the data and add it to a thread-safe FIFO list in the data received handler and read the data from the list in the main thread.
See my solution in post Serial port reading + Threads or something better?

Can I do a timer loop and timeout for serial port communication in C#?

I'm more familiar with C language and recently I've been ask to do C# for serial communication.
Below is my code for receiving data from COM port:
public void RxData()
{
int i = 0;
int Data;
bool StartRx = false;
int timer;
while (true)
{
Data = sp.ReadByte();
if (Data == 0x01)
{
StartRx = true;
}
if (StartRx == true)
{
RxBuffer[i++] = Data;
}
if (Data == 0x04)
{
RxChkSum = RxBuffer[i - 2];
break;
}
timer++;
if(timer>100)
{
timer = 0;
break;
}
}
}
Above is the way I receive data starting with 0x01 and ends with 0x04.
I'm incrementing a timer to count til 100 and quit the while loop in case I don't receive any data. Some sort like a timeout.
But seems like the timer don't work. When I don't receive any data, my program just stuck in the while loop forever.
I know this is the way we write in embedded c programming. But is this the right way to write in C#?
I think you might be interested in handling data coming from the serial port using an event handler. In the .net SerialPort class, you can register an event handler for data received:
var sp = new SerialPort("COM1") {
BaudRate = 9600,
Parity = Parity.None,
StopBits = StopBits.One,
DataBits = 8,
Handshake = Handshake.None
};
sp.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
You can also set the ReceivedBytesThreshold property on the SerialPort, which determines when your event handler will get fired.
Then, you just set up your event handler to read data and do what you need with it:
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string data = sp.ReadExisting();
}
Using this type of pattern, you don't have to loop, you just set the threshold you need, and let the framework call your event handler when the serial port's got that many bytes ready for you.
Hopefully that helps and I haven't missed your point completely. :)
ReadByte is a synchronous call. It will only return when there is a byte read.
To have your attempt getting to work you can check for available data before reading:
if(sp.BytesToRead > 0)
{
Data = sp.ReadByte();
}
Besides that I prefer asynchronous reading as hmqcnoesy suggested.

Categories