Serial Communication

A forum devoted to the discussion of all topics having to do with scripting and other advanced programming using iX Developer.
ajack
Posts: 44
Joined: Wed Feb 22, 2012 12:01 am

Serial Communication

Post 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

User avatar
Ron L.
Posts: 214
Joined: Fri Jul 15, 2011 3:21 pm

Re: Serial Communication

Post 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.
Best Regards,

Beijer Electronics, Inc.
Ron Lloyd | Applications Engineer

ajack
Posts: 44
Joined: Wed Feb 22, 2012 12:01 am

Re: Serial Communication

Post 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

User avatar
Ron L.
Posts: 214
Joined: Fri Jul 15, 2011 3:21 pm

Re: Serial Communication

Post 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.
Best Regards,

Beijer Electronics, Inc.
Ron Lloyd | Applications Engineer

ajack
Posts: 44
Joined: Wed Feb 22, 2012 12:01 am

Re: Serial Communication

Post 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

mark.monroe
Posts: 824
Joined: Tue Mar 13, 2012 9:53 am

Re: Serial Communication

Post 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.
Best Regards,
Mark Monroe

Beijer Electronics, Inc. | Applications Engineer

ajack
Posts: 44
Joined: Wed Feb 22, 2012 12:01 am

Re: Serial Communication

Post 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

mark.monroe
Posts: 824
Joined: Tue Mar 13, 2012 9:53 am

Re: Serial Communication

Post 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.
Best Regards,
Mark Monroe

Beijer Electronics, Inc. | Applications Engineer

User avatar
Ron L.
Posts: 214
Joined: Fri Jul 15, 2011 3:21 pm

Re: Serial Communication

Post 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.
Best Regards,

Beijer Electronics, Inc.
Ron Lloyd | Applications Engineer

ajack
Posts: 44
Joined: Wed Feb 22, 2012 12:01 am

Re: Serial Communication

Post 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".

Post Reply