Instrument Control (GPIB, Serial, VISA, IVI)

cancel
Showing results for 
Search instead for 
Did you mean: 

How to control character timing on COM1 port?

A quick question for anyone familiar with serial port communication, assuming anybody still uses it...
 
I have written a LabView program to communicate with a dinosaur of a chiller by means of RS-232 on COM1.  I am experiencing an intermittent and infrequent loss of communication with the chiller after which it is impossible to re-establish communication with anything short of a power-on restart of the chiller.  I can live with this for my purposes, but it would be real nice to get this rock solid.
 
While digging through some documentation, I found the following statement: "The host must maintain maximum of 10 msec between the characters in the same message.  If chiller didn't receive the next character on time, message will be ignored and the chiller shall not respond."
 
This sounds an awful lot like the behavior that I'm seeing.  Problem is, I don't know how to control the timing between characters sent from the COM1 port, short of specifying the baud rate (which I have set to 9600 per the chiller manufacturer's instructions).  I've got a few ideas kicking around, like high-level register access commands, or possibly messing with the baud rate on the COM1 port (this would be easy to do), but I don't want to dive into a major programming effort without relatively high confidence it will succeed.  Does anybody have suggestions on how I might successfully control character timing through the COM1 port?  Example code would be greatly appreciated.
 
Thanks, Tom
0 Kudos
Message 1 of 8
(5,027 Views)
Tom,

you did not provide any detals about the programming environment you use to create your program, so an example is not so easy to provide 😉

Well, your question is quite unfamiliar these days when PCs have CPUs with several GHz. It is more likely that older devices can not cope up when modern PCs sending data as quick as the baud rate allows.

Let me first start with an explanation of serial communication in PCs:
The serial port is provided by a special chip, a so-called UART. The CPU writes some bytes into a buffer within the UART and this sends it out. If the UART buffer gets almost empty, it sets an interrupt request, which lets the CPU fill up the buffer with new data. When receiving data, the same holds true when the UART buffer gets almost filled.
With higher baud rates of up to 460kbaud or even more, a serial port can transmit up to about 46kByte per second )or more). If the UART requests data transfer when there is -say- 10 bytes room, the CPU has to finish thew requested action within about 200 µs (10 bytes/46kbytes/s). This can not be guaranteed by application programs under normal OS (like Winx, Unix etc). So this is done with kernel or system drivers, that move data between the UART and some user space buffer. This user space buffer is much larger than the UART internal one and is what we can use with application programs. So as we have such a buffer, it is best use to write as many bytes into it as it can hold (on Winx this can be up to 32764 bytes) or as are availabel.

To return to your question: If you do send the whole command as a single string, it will be send as quick as the baud rate allows. If you need slower speed send the data in a loop one byte a a time. This gives a usual delay of about 1..2 ms between each byte, but can insert several seconds delay once in w while, depending on the actual system load.

I would take a look into te devices documentation to see if it needs some flow control mecahnisms. I would also send the whole command as a single string. And I would check if the device needs some termination character(s) that needs to be appended onto the command string before sending it.

HTH   and
Greetings from Germany!
--
Uwe

ps:
you wrote:

> A quick question for anyone familiar with serial port communication, assuming anybody still uses it...
There are a whole lot of people using serial connections, either physical or logical serial ports. We have 'em in our medical devices, cause it is relatively easy to provide electrical separation between patient and the environment of the device...

Message Edited by LuI on 03-24-2006 10:22 AM

0 Kudos
Message 2 of 8
(5,019 Views)

Uwe,

Thanks for your response.  I am using a 2.2GHz Pentium 4 machine running Windows 2k, programming in a LabView 7.1 environment.   Looks like my assumption that everybody else must also be using the same programming environment was invalid.  😉

The three suggestions you provided are good ones, and I've actually already tried them.  There are some finicky timing considerations which I think I have captured; I am currently sending the entire command as a single string; and I have implemented termination character identification.  These three implements have dramatically improved stability over the previous version of this code.  What happens now is that the code will run for hours and hours, happily communicating with the T502 once every 3 seconds, but then eventually - and intermittently - the write string will be sent, and nothing will be received.  Communication is entirely lost from that point on (aside from an occasional XON signal from the chiller). 

I will try increasing the UART buffer size - that sounds like it may be the best option.  If that doesn't fix the problem, I'll try your suggestion about sending a single character at a time. 

Incidentally, if transmission is too fast, why not just use a lower baud rate? 

Thanks, Tom

P.S. Where in Germany are you located?  I was there many years ago.  Pretty country, Deutschland...

0 Kudos
Message 3 of 8
(4,996 Views)
Hi Tom -

It sounds like you have an instrument that requires modifying the character delay in the serial settings. Unfortunately, you cannot access such a setting from LabVIEW by specificying a delay between each character sent.

The workaround is to parse each of the characters in the command and send them one by one. Remember that LabVIEW will send whatever is in the output buffer, so if you send a command and the whole command is in the buffer, then it will send it as a chunk. That is why you have to parse it and get each character. The character delay can be changed by changing the timing within the loop that writes each character.

Check the following document that explains how to write each character at a time.

How Do I Send 1 Byte or Character at a Time to My Serial Instrument?  - http://digital.ni.com/public.nsf/websearch/959349F1CCCA7D3686256C300066B46F?OpenDocument

I hope this information helps you get started.


Mark W.
0 Kudos
Message 4 of 8
(4,990 Views)

Thanks for the suggestions.  I've tried a few different things:

1. Sent characters individually with 1ms timing between each.  This satisfied (in the absence of any major timing glitches) the <10ms transmission delay between characters, but I still encountered an unrecoverable loss of communication.  I unfortunately didn't have a log set up to measure the actual intervals, but based on data mentioned below, I'm inclined to think long delays are not the root cause.

2. Set the UART I/O buffers to the max (32764?); still encountered an unrecoverable communication loss.

3. Set the baud rate to 19200; this resulted in an immediate _recoverable_ loss of communication.

4. Set the baud rate to 4800; this resulted in an immediate _unrecoverable_ loss of communication.

5. Repeating #1 above, but am using a 100ms interval between each character.  It's running smoothly so far, but it's too early to tell; I usually have to wait some number of hours before communication craps out.

If this last item doesn't work for preventing the problem, I'm pretty much out of options for preventing the problem.  Automatic recovery would also be acceptable, however.  Does anyone have any suggestions on how to re-establish communication with the chiller via software?  I have tried some things like closing and re-opening the serial port, but none have been successful and thus far there's really not much method to my madness.

Regards, Tom

0 Kudos
Message 5 of 8
(4,976 Views)
Tom,

you had some questions:

> Incidentally, if transmission is too fast, why not just use a lower baud rate? 

The baud rate limits the maximum transmission rate on a channel, but must fit on both sides of the channel. So you cannot change it in your VI and leave it at the device...

> Set the UART I/O buffers to the max (32764?)
You cannot set the UART buffer size. Thats fixed in silicon on the UART chip. You can set the buffer limits where the UART sets an interrupt to exchange data with a system buffer. This happens in kernel mode and can be very fast (within some CPU cycles, say  ~10 ns with your machine). What you meant andor did was setting the system buffer size, which can be accessed by your VI. This runs in user mode and requires a lot more time and can be delayed by other processes.
Some years ago I had an app with 13 parallel highspeed transmissions (230kBaud each), that required the maximum system buffer size. After a lot of tests it turned out that the maximum system buffer size is not 2^15, but 2^15-4. Weird, but so it was. Since than I use this limit and was happy with it.

>
Where in Germany are you located?  I was there many years ago.  Pretty country, Deutschland.
I live in Potsdam which is located side by side with Berlin.
Well, and so I can say for north america, say the US and Canada, where I have been several times and have worked several years ago.

To return to your primary problem:
your messages sound a bit like your device might be the problem. If you encounter an unrecoverable loss of communication, what do you do to re-establish it? Can this be done by LabVIEW as well?
What could be causing your problem is that no user mode program in Windows can assure a real-time reaction of less than the devices required 10ms. It will allmost ever happen within that time frame, but occasionally it might have a longer delay. There's nothing you can do when using Windows. Period.
You either have to use a kind of real-time OS or a transmitting device or you have to re-activate your chiller when it had run into its mad state.

A transmitting device could be a microcontroller with some serial buffer. Not too much HW. but needs some firmware. I'd go with the third way, trying to reset the chiller.

Greetings from Germany!
--
Uwe

0 Kudos
Message 6 of 8
(4,967 Views)

Just wanted to say thanks belatedly to those who offered their inputs ... I think I've got the problem fixed.  Ended up sending one character at a time with a 50ms pause in between each send, and I haven't seen a comm failure since I made that change.  All the insight was much appreciated.

Tom

0 Kudos
Message 7 of 8
(4,905 Views)
50 ms per char is quite a long time, means less than 20 chars per second. Seems like a small device receive buffer and maybe polling instead of interrupt driven character transfer...
Greetings from Germany!
--
Uwe

Message 8 of 8
(4,866 Views)