C# SerialPort with Moxa UPort 1100 - c#

Morning all,
I'm developing a C# WPF application which continuously reads barcodes (about one every minute) from a DATALOGIC scanner (DS4800-1000) and send them to a server which replies with details about that specific barcode. This scanner is connected to a tablet running Windows 8.1 (non RT) through a USB-to-serial converter from MOXA (model UPort 1100).
Whenever a new barcode is read, the DataReceived event is fired and handled with the following method:
private void port1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Log.log(Log.LogLevel.Info, "MainScreen.port1_DataReceived");
Thread.Sleep(100);
String data = "";
// If the com port has been closed, do nothing
if (!comport1.IsOpen)
{
Log.log(Log.LogLevel.Info, "MainScreen.port1_DataReceived - COM CLOSED");
data = "COM CLOSED"; // Must be < 16 chars
}
else
{
// Obtain the number of bytes waiting in the port's buffer
int bytes = comport1.BytesToRead;
// Create a byte array buffer to hold the incoming data
byte[] buffer = new byte[bytes];
// Read the data from the port and store it in our buffer
comport1.Read(buffer, 0, bytes);
data = Encoding.Default.GetString(buffer);
Log.log(Log.LogLevel.Info, "Data received from barcode scanner number 1: " + data);
}
// COM port is handled by a different thread; this.Dispatcher calls the original thread
this.Dispatcher.Invoke((Action)(() =>
{
ExtractBarcodeData(data);
} ));
}
I'm observing a strange behavior: at random times, I see no reaction at all on the application, although the scanner actually reads a new barcode, while I would expect a new DataReceived event as the previous barcodes. Logs say me that the port is actually open and I can also close it using a specific button which closes and reopen it. Here comes the exception (on the Open() call): A device attached to the system is not functioning.
I can not reproduce this error in no way, it's totally unpredictable and random! Anyone has got any idea why the DataReceived event is not triggering?
Thanks,
FZ

Most USB-to-serial converters have this problem. They may disappear from the system and appear again. All opened handles at this situation become invalid.
Please, open the Device Manager and verify the power management tab for each USB hubs there. The system should not power off the hub.

Related

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.

IO operation aborted error thrown while reading serial port

We are trying to read data written by an external device (weighing scale in this case) connected to serial port using .Net serial port class.
First we initialize the serial port as below:
InitializeSerialPort()
{
if ((serialPort != null) && (serialPort.IsOpen))
{
serialPort.Close();
serialPort.Dispose();
serialPort = null;
}
serialPort = new SerialPort("COM2", 9600, Parity.None, 8,
StopBits.One) { Handshake = Handshake.None };
serialPort.DataReceived += serialPort_DataReceived;
serialPort.NewLine = "\r";
}
We are using background worker thread to poll the device on continuous interval by sending a command(understood by the weighing scale) on the serial port. As soon as we send the command the device connected to serial port reacts with a response output. We call ReadLine API of SerialPort class to get the data present on the serial port written by the device in the DataReceived event as shown in the code snippet below :
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
data = serialPort.ReadLine();
}
catch(System.IO.IOException ex)
{
//since serial port reading threw an error so there is no value to be parsed hence exit the function.
return;
}
//if no error then parse the data received
}
I'm using System.IO.Ports.SerialPort class of .Net framework 4.0. I can see a number of people posting this issue on other forums but with no specific resolution. Some of them terming .Net Serial port class as buggy which has not been fixed by Microsoft till date. One of the forums where this error is mentioned is here
I also tried the solution posted here but of no help. I need some input if any one else has come across this issue or its resolution.
We were able to solve this problem by locking the code inside serialPort_DataReceived method.
Object lockObject = new Object();
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
lock(lockObject)
{
try
{
data = serialPort.ReadLine();
}
catch(System.IO.IOException ex)
{
//since serial port reading threw an error so there is no value to be parsed hence exit the function.
return;
}
}
//if no error then parse the data received
}
We had set the polling interval to poll the device connected on serial port as 10 seconds. Possibly the entire code present inside serialPort_DataReceived method was sometimes taking more than 10 seconds. We were not able to exactly establish this fact as it was not happening every time may be.
So we locked the entire piece of code inside serialPort_DataReceived method using lock keyword in C# to ensure that the new execution for new data received from serial port doesn't start unless the older reading hasn't finished. The issue got resolved after implementing this code on trial and error basis. Hope this helps others as well if they come across such an issue.

SerialPort.DataReceived with USB TO COM cable act different then physical com

My C# desktop class library communicates with COM serial port.
The com is not real com, it is a USB to COM cable connected to USB to COM on another computer, the other computer uses a simulator to send data.
This solution works fine and then port opens successfully:
serialPort.Open();
if (serialPort.IsOpen)
{
serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
}
void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
var length = serialPort.BytesToRead;
byte[] buffer = new byte[length];
serialPort.Read(buffer, 0, length);
for (int i = 0; i < buffer.Length; i++)
{
System.IO.File.AppendAllText(#"c:\TestLogging.txt", string.Format("[Time = {0}] Data was received from serial port !", DateTime.Now)); }
}
The simulator send data all the time, and I receive the data in my class, BUT i dont receive it all the time, i see printing of 1 line every 30 seconds - although it suppose to print all the time!
What is weird - If i place break point in the line var length = .. then i see a the prints for the time i was halting on the break.. the data transferred seems to be "cached" and when i hit "Play" I receive the data but only for the time i was pausing the process.
I think you're too late registering the DataReceived eventhandler there. You should register to it before you open the port:
serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
serialPort.Open();
if (serialPort.IsOpen)
{
}
Try connecting your machines using HyperTerminal and check if the communication works. If it does, then it's your application's fault (double-check serialport settings). Otherwise it's probably the cable or the port itself.
Are you sure you're not getting any faulty data? Have you subscribed to SerialPort.ErrorReceived event handler? If you catch some SerialError.Frame errors there, then you probably have a faulty cable or the port is broken, or there are some conditions that are jamming the comunication (not vary likely but it can happen, for example if there is some strong source of power near by, for example an inverter).
OK, what is the problem ?
I am using USB to COM cable, and not true COM port.
The behavior of data receiving event from SerialPort is different.
I listen and catch the data event, but instead of getting array of bytes (as in real COM) - I receive every time a single byte (array in size of 1)..
Meaning: On DataReceived event when working with USB to COM port: i get this: 1-1-1-1-1-1 each DataReceived event give me 1 byte.
Real physical COM .DataReceived event give me: 5-30-42 etc.. Array of bytes
So my solution when working on USB to COM ports (some might call it "virtual COM port") I need to check if serialPort.BytesToRead is bigger then X, then i actually do
if (serialPort.BytesToRead > 2) //I dont want to get it 1-1-1.. want to get it atleast 2-2-2-2
serialPort.Read(buffer, 0, length);
Since serialPort.BytesToRead will tell me how many bytes are in current chunk, and Read. in my terms will get the buffer and clean it.

How can I read from a socket repeatedly?

To start I am coding in C#. I am writing data of varying sizes to a device through a socket. After writing the data I want to read from the socket because the device will write back an error code/completion message once it has finished processing all of the data. Currently I have something like this:
byte[] resultErrorCode = new byte[1];
resultErrorCode[0] = 255;
while (resultErrorCode[0] == 255)
{
try
{
ReadFromSocket(ref resultErrorCode);
}
catch (Exception)
{
}
}
Console.WriteLine(ErrorList[resultErrorCode[0] - 48]);
I use ReadFromSocket in other places, so I know that it is working correctly. What ends up happening is that the port I am connecting from (on my machine) changes to random ports. I think that this causes the firmware on the other side to have a bad connection. So when I write data on the other side, it tries to write data to the original port that I connected through, but after trying to read several times, the connection port changes on my side.
How can I read from the socket continuously until I receive a completion command? If I know that something is wrong with the loop because for my smallest test file it takes 1 min and 13 seconds pretty consistently. I have tested the code by removing the loop and putting the code to sleep for 1 min and 15 seconds. When it resumes, it successfully reads the completion command that I am expecting. Does anyone have any advice?
What you should have is a separate thread which will act like a driver of your external hardware. This thread will receive all data, parse it and transmit the appropriate messages to the rest of your application. This portion of code will give you an idea of how receive and parse data from your hardware.
public void ContinuousReceive(){
byte[] buffer = new byte[1024];
bool terminationCodeReceived = false;
while(!terminationCodeReceived){
try{
if(server.Receive(buffer)>0){
// We got something
// Parse the received data and check if the termination code
// is received or not
}
}catch (SocketException e){
Console.WriteLine("Oops! Something bad happened:" + e.Message);
}
}
}
Notes:
If you want to open a specific port on your machine (some external hardware are configured to talk to a predefined port) then you should specify that when you create your socket
Never close your socket until you want to stop your application or the external hardware API requires that. Keeping your socket open will resolve the random port change
using Thread.Sleep when dealing with external hardware is not a good idea. When possible, you should either use events (in case of RS232 connections) or blocking calls on separate threads as it is the case in the code above.

Improving a SerialPort Connection

Pretty simple question this time around. I have an application that communicates with another copy of the application on another machines. One application sends a pretty constant stream of data, the other receives it.
The code to send data looks like this (where serialPort is an instance of the System.IO.Ports.SerialPorts class in C# .Net 2.0):
private void bgDataWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e){
try{
string tempStr = Convert.ToString(String.Format("{0:0.000000}", data));
serialPort.Write(tempStr); // Write "data" out to 6 decimal places
}
catch (TimeoutException){ }
catch (InvalidOperationException err){ // Port is obstructed or closed
this.Invoke((MethodInvoker)delegate{
MessageBox.Show(this, "Couldn't send wireless data:\n\n" +
err.ToString(), "NanoMETER - Wireless Error (Data)",
MessageBoxButtons.OK, MessageBoxIcon.Error);
Global.remoteEna = false;
serialPort.Close();
usingBT = false;
});
}
}
It's called on a timer. The receive code is even more straightforward:
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) {
string buffer = serialPort.ReadExisting();
HandleInput(buffer);
}
Data gets sent and handled and it's all fine and dandy, but there's some unwanted choppiness where it's either not reliably sending data at a constant rate, or it's not picking up everything. I'm not sure if this can be fixed in my code, or if it's just the nature of having a few slow machines and a possibly shakey bluetooth connection. Any suggestions?
It's not uncommon for interns to be assigned to converting old code to a newer platform.
There are a few improvements you can make.
1) The following strategy is good when the bytes sent through the port is meant to be interpreted in blocks, such as commands. Do you have some sort of protocol? Something that dictates the format of the message you are sending. For instance, a specific delimiter to indicate the beginning and the length of the upcoming command. This allows you to quickly determine if the command was only half sent, or if there were missing bytes. Even better is to add a CRC at the end.
2) Instead of reading on a timer, base yourself on the events flagged by your serialport object. Here's an example of what i use:
//OnReceive event will only fire when at least 9 bytes are in the buffer.
serialPort.ReceivedBytesThreshold = 9;
//register the event handlers
serialPort.DataReceived += new SerialDataReceivedEventHandler(OnReceive);
serialPort.PinChanged += new SerialPinChangedEventHandler(OnPinChanged);
In the code above, i set a threshhold of 9, you should change that to whatever fits your context. Also, the Pinchanged event is something good to monitor, it will allow you to quickly identify if the cable has been disconnected. There is more on this, regarding CTSChanged but you can look it up if you are interested.
Lastly, if this doesn't help you get a little further, show an example of the problem that occured so the peolpe here can give you more help.

Categories

Resources