Page 1 of 2
Serial Communication
Posted: Thu Mar 01, 2012 6:52 pm
by ajack
Dear Ron,
I found your Scripting in Scripting FAQs forum, it's quite helpful for me. However, I'm still confused with these things:
1. When you use COM port in iX Panel, how to you shut down Communication driver (just like Host Link Communication and others, etc...)?
2. Is there any ready bit for polling in this library? Cause it's not a big deal when I try to send data, but it would require ready flag to receive data from other device (PLC, MCU, ect...)
3. Actually, when we use COM Port in manual scripting mode, IMO, it would be much faster, cause minimum polling rate of Host Link driver is 100ms - much slower than normal baud rate (9600).
Thanks and best regards,
Phong Duong
Re: Serial Communication
Posted: Fri Mar 02, 2012 11:32 am
by Ron L.
1. When you use COM port in iX Panel, how to you shut down Communication driver (just like Host Link Communication and others, etc...)?
The only way currently to turn off a "Communication Driver" is using the Action "Change Active Controller". This Action will display a dialog where you can select active controllers. A restart will then be required to change what controllers are enabled.
2. Is there any ready bit for polling in this library? Cause it's not a big deal when I try to send data, but it would require ready flag to receive data from other device (PLC, MCU, ect...)
There is not a way to detect if a driver is ready or not. The communication is automatic in the background. When the "ValueChanged" event occurs on a tag that is one way to tell that the communications are happening.
3. Actually, when we use COM Port in manual scripting mode, IMO, it would be much faster, cause minimum polling rate of Host Link driver is 100ms - much slower than normal baud rate (9600).
There are many factors that go into the performance of communication. Baud rate speed such is just on of them. When you select 100MS polling that is not guaranteed, it can vary depending on the amount of tags in the project that are being displayed at the same time. For example, if you only have 1 tag displayed, it will probably be able to get queried at 100MS, however 10-20 tags, may only be able to go up to 500MS queries. If you set a poll rate that is faster than possible, the HMI will query as fast as it can.
Re: Serial Communication
Posted: Sat Mar 03, 2012 8:39 pm
by ajack
Dear Ron,
The only way currently to turn off a "Communication Driver" is using the Action "Change Active Controller". This Action will display a dialog where you can select active controllers. A restart will then be required to change what controllers are enabled.
So, will that affect to serial communication when I try to send/receive data by RS232 port without turning off Communication driver (in this case is Host Link driver which is set in Controller -> Omron -> Host Link)?
There is not a way to detect if a driver is ready or not. The communication is automatic in the background. When the "ValueChanged" event occurs on a tag that is one way to tell that the communications are happening.
Actually, I intend to skip the built in Communication driver, and use System.IO.Ports namespace to transceive data through RS232 port (which is based on your project in FAQs)
Thanks and best regards,
Phong Duong
Re: Serial Communication
Posted: Mon Mar 05, 2012 8:39 am
by Ron L.
So, will that affect to serial communication when I try to send/receive data by RS232 port without turning off Communication driver (in this case is Host Link driver which is set in Controller -> Omron -> Host Link)?
If both your code and the driver are trying to use the same serial port then yes.
Re: Serial Communication
Posted: Wed Mar 21, 2012 4:00 am
by ajack
Dear Ron,
Thanks to your Serial Communication script, which was post in FAQs, I finally communicate HMI with another device using COM port. Sending bytes from HMI works flawless, but I encounter some problems when try to read data in serial buffer.
I try using
Code: Select all
Read(byte[] byte, int index, int count)
But it's very slow to get data from buffer
And, after some googling, I found this comment:
Read is one of the most commonly misunderstood methods. Because the help files do not describe the real behaviour, it it is logical to assume that the method:
BytesReceived = YourCOMPort.Read(buffer, offset, count)
is a blocking method, which does not return before "count" number of bytes are received. It is not!. If there are bytes available on the serial port, Read returns up to "count" bytes, but will not block (wait) for the remaining bytes. If there are no bytes available on the serial port, Read will block until at least one byte is available on the port, up until the ReadTimeout milliseconds have elapsed, at which time a TimeoutException will be thrown. Unless you check the actual number of received bytes, you may believe that all bytes in your buffer are valid. This may not be the case!
PS! SerialPort in .Net 3.5 is so full of errors that it may be regarded as useless. Use .Net 2.0 or a third party DLL.
So, instead, I try Readline() method to read data with LF end code, but it won't get better.
Did I make some mistakes when try using Read() or Readline()?
And moreover, I couldn't use DataReceived event, it just raise event 1 time only.
Thanks,
Phong Duong
Re: Serial Communication
Posted: Wed Mar 21, 2012 9:15 am
by mark.monroe
Hi Phong,
When you say it is 'slow' how slow is it? Can you put some timers in your code and come up with some numbers?
The serial port read timout defaults to 500 ms. You can set that to a smaller number that is still greater than 0.
serialPort.ReadTimeout = 500 //in ms
You can check to see how many bytes are in the buffer and are ready to read, before you call the read method.
numBytesReadyToRead = serialPort.BytesToRead
It might be the case that your serial device is simply not sending data to the HMI very quickly.
For .net 3.5 you might want to take a look at the documentation
documentation for the serial port class.
Re: Serial Communication
Posted: Wed Mar 21, 2012 10:22 am
by ajack
hi Mark,
Thanks for your reply.
I'm using a timer to read buffer of serial port, and using timer Tags to indicate timer interval each Timer event:
Code: Select all
private static void TimerProcessHandler(Object sender, EventArgs e)
{
timer.Enabled = false;
if (Globals.Tags.timer.Value++ == 255)
Globals.Tags.timer.Value = 0;
serialPort.Read(buffer, 0, serialPort.BytesToRead);
timer.Enabled = true;
}
Actually, when try to read from buffer, I did check how many bytes to read.
And, I did using timer to send data from HMI to serial device, it works properly without any errors.
Thanks,
Phong
Re: Serial Communication
Posted: Wed Mar 21, 2012 10:46 am
by mark.monroe
Hi Phong,
I would not simply get 'BytesToRead' number of bytes from the buffer. What happens if 'BytesToRead' is equal to zero? You will make a call anyways to the read function.
Why not do something like test it first:
Code: Select all
//Decrease the amount of time that you wait for a timeout from 500 ms to 25 ms
serialPort.ReadTimeout = 25;
//Check to make sure we have data to read in
if(serialPort.BytesToRead > 0)
{
//Looks like we have data.
//Now it is possible for the amount of data we have to be larger than the
//ReadBufferSize.
if(serialPort.BytesToRead > serialPort.ReadBufferSize)
{
//Only read in the ReadBufferSize, not more!
serialPort.Read(buffer, 0, serialPort.ReadBufferSize);
}
else
{
serialPort.Read(buffer, 0, serialPort.BytesToRead);
}
}
You could also try the 'SerialPort.ReadExisting' method. But that method will mess up the BytesToRead count because it sometimes leaves zeros in the read buffer.
Re: Serial Communication
Posted: Wed Mar 21, 2012 11:01 am
by Ron L.
You'll also want to keep track of the number of bytes that were actually copied to the array. This is returned by the "Read" function. I also like to put a try/catch block around the function in case something happens that I wasn't expecting.
Code: Select all
private byte[] inData = new byte[100];
private byte[] buff = new byte[10000];
private int buffLen = 0;
private void TimerEventProcessor(Object myObject, EventArgs myEventArgs)
{
if (sPort.BytesToRead > 0)
{
int bytesRead = 0;
try {
bytesRead = sPort.Read(inData, 0, inData.Length);
}
catch(Exception) {}
inData.CopyTo(buff, buffLen);
buffLen += bytesRead;
if (buffLen > (buff.Length - inData.Length - 1))
{
//this should not happen
buffLen = 0;
}
//code here to process data in buff
}
}
This is example is dealing with Byte arrays, but if your string data is ASCII, then the "ReadExisting()" function would be much better to use as it returns a string.
Re: Serial Communication
Posted: Wed Mar 21, 2012 8:00 pm
by ajack
Hi Ron and Mark,
Thanks for your replies,
I was so silly not to check whether Bytes To Read greater than 0 or not. If Bytes To Read = 0, Read methods would stand by and wait until there're some bytes in buffer...
ReadExisting() would be great if my system communication using ASCII data format. However, my receive datas are merely bits and bytes to display values and control command. That's the reason why I came up with "Read()" or' ReadLine()"
And, this is not the important case, but I just wonder why baudrate can't be greater than 19200?
when I setup com port:
Code: Select all
_serialPort = new SerialPort("COM3", _baudrate, Parity.None, 8, StopBits.One);
if "_baudrate" value is greater than 19200 (38400 or 115200), then
"_serialPort.BaudRate" just return "0".