Windows does not flush COM-Buffer - c++

I'm seeing some pretty odd behaviour from windows regarding my COM-Buffers.
I use 3 USB-Serial Converter with FTDI chips. I open the com ports with CreateFile and it all works fine. All 3 ports have the same configuration except for the baud rates. 2 work at 38400 and one at 9600.
Here is the odd part:
I am able to successfully write out of the 9600 port and one of the 38400 port. The second 38400 ports seems to be buffering the data. I have connected to this port with Hyperterminal and see that on the working ports i immediately get a response and on the "weird" port i only get the data when i close my application...
Has anyone else experienced this? How did you resolve this?

This is kind of a shot in the dark... but.
Check the flow control settings for both ends of the "weird" connection. I've seen strange things like this when the flow control is mismatched. The act of closing the port clears the bits and allows the buffered data to flow.

Having worked a bit with FTDI chips, I would suggest you check out the advanced driver settings for each port. The driver supports both buffering and latency control in order to allow you to compromise between high throughput and low latency. So check the settings that work and use the same for the one that doesn't (if they're not the same).
On a side note, by using FTDI:s own API you don't have to keep track of COM-port reassignment and the like. The API is quite similar to the normal Win32 one but exposes more configuration options.

Related

Qt modbus serial port flow control handling

I'm writing a small program using QModbusDevice over the serial port (using the QModbusRtuSerialMaster class) and have some problems.
One of the problems seems to be that the flow control of the serial port is incorrect. Checking in a serial port sniffer I see that a working client sets RTS on when it sends requests, and then RTS off to receive replies. When I use QModbusRtuSerialMaster to send messages that doesn't happen.
The message is sent correctly (sometimes, subject for another question) compared to the working client. It's just the control flow that doesn't work and which causes the servers to be unable to reply.
I have set the Windows port settings for the COM-port in question to hardware flow control but it doesn't matter, the sniffer still reports no flow control.
Is there a way to get QModbusRtuSerialMaster to set the flow control as I would like? Or is there a way to manually handle the flow control (which is what the working client does)? Or is the only solution to skip the Qt modbus classes and make up my own using the serial port directly?
A short summary of what I'm doing...
First the initialization of the QModbusRtuSerialMaster object:
QModbusDevice* modbusDevice = new QModbusRtuSerialMaster(myMainWindow);
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter, "COM3");
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter, QSerialPort::NoParity);
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, QSerialPort::Baud115200);
modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, QSerialPort::Data8);
modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, QSerialPort::OneStop);
modbusDevice->setTimeout(100);
modbusDevice->setNumberOfRetries(3);
modbusDevice->connectDevice();
Then how I send a request:
auto response = modbusDevice->sendReadRequest(QModbusDataUnit(QModbusDataUnit::Coils, 0, 1), 1);
QtModbus does not implement an automatic toggling for the RTS line because it expects your hardware to do it on its own (with a dedicated line instead).
This should be the case for most RS485 converters (even cheap ones). You would only need the RTS line if you have a separate transceiver like this one with a DE/~RE input.
If you were on Linux and had some specific hardware you could try to use the RS485 mode to toggle the RTS line for you automatically. But you don't seem to be on Linux and the supported hardware is certainly very limited.
You can also toggle the line manually with port.setRequestToSend(true), see here. But note that depending on the timing needs of the device you are talking too, this software solution might not be very reliable. This particular problem has been discussed at length here. Take a look at the links on my answer too, I made some benchmarks with libmodbus that show good results.
Enabling or disabling flow control on the driver won't have any effect on this issue because this is not actually a flow control problem but a direction control one. Modbus runs on two-wire half-duplex links very often, and that means you need a way to indicate which device is allowed to talk on the bus at all times. The RTS (flow control) from an RS232 port can be used for this purpose as a software workaround.
In the end, it would be much less of a headache if you just replace your transceiver with one that supports hardware direction control. If you have a serial port with an FTDI engine you should be able to use the TXEN line for this purpose. Sometimes this hardware line is not directly routed and available on a pin but you can reroute it with MProg.
I would like to highlight that you did not mention if you are running your Modbus on RS485. I guess it's fair to assume you are, but if you have only a couple of devices next to each other you might use RS232 (even on TTL levels) and forget about direction control (you would be running full-duplex with three wires: TX, RX and GND).

Serial data initially wrong C++

I am sending data between an XBee transceiver and my PC.
The issue is that, initially (in my program) the data is random characters. Only after opening a serial connection in XCTU does it work.
So the serial data is being sent correctly, but XCTU does something to synchronise my pc to the XBee. Baud rates are set at 9600 both sides.
Does anybody know what XCTU is doing? Or how I can replicate it within my C++ program?
Hopefully the image below explain what is happening more clearly:
The serial port settings under Windows can be seen with GetCommState and set with SetCommState. Use the first one to see what the XCTU set. Your code can then use the same settings by calling SetCommState.
I found the issue. I was assuming default options with the boost serial_port object. After setting more of the options the serial communication works reliably.
Here are the options that I ended up setting:
port.set_option(asio::serial_port_base::baud_rate(9600));
port.set_option(asio::serial_port_base::character_size(8));
port.set_option(asio::serial_port_base::flow_control(asio::serial_port_base::flow_control::none));
port.set_option(asio::serial_port_base::parity(asio::serial_port_base::parity::none));
port.set_option(asio::serial_port_base::stop_bits(asio::serial_port_base::stop_bits::one));
where port is an asio::serial_port object.

What can cause CreateFile calls on a serial port to be extremely slow?

I've got a Qt app (Qt 4.8.1) that's doing some Windows serial port tasks. I'm finding that occasionally the CreateFileA call that I do to open the serial port is taking up to 30 seconds to complete! Obviously I'm doing something to trigger this odd behavior, and I want to know what it is I might be doing to cause this.
m_portHand = CreateFileA( portDevice.c_str(),
GENERIC_READ | GENERIC_WRITE,
0, // must be opened with exclusive-access
NULL, // default security attributes
OPEN_EXISTING, // must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // overlapped I/O
NULL ); // hTemplate must be NULL for comm devices
m_portHand is a HANDLE, and portDevice is an std::string and contains "COM5".
This call is triggered by a button push in the main thread of my app. At the time it happens the app has at most one other thread, but those threads (if any) are idle.
The only major thing going on in the system is a VM running Linux, but the system is a quad-core and 3 of the cores are as near to idle as you see on a Windows box, with only one doing anything with the VM.
The serial ports are on an 8 port USB serial box, could that be related?
Is this related to the Overlapped IO in some way?
In response to comments:
Port is not open by another app. Port was previously open by a previous invocation of this app, which was properly closed, and the port closed with 'CloseHandle'.
I have not been able to determine any correlations between it taking 30 seconds and not - sometimes I start the app up, click the button and we're off to the races, sometimes it takes up to 30 seconds.
The VM is intercepting some other USB devices on the same serial box.
Other than the serial box (with the VM polling 4 ports looking for devices), the USB bus is unloaded.
I've not seen the behavior in other apps. I'll try switching to a built-in port (COM1 on the motherboard) to see if that has any effect.
A thought just occurred to me: can the form of the port addressing have anything to do with it? Other similar apps I work on use the qestserialport library, which opens ports using the '\\.\COM#' notation. Is there some way that the notation used could affect the timing?
The USB serial device says 'VScom' on it, and normally it opens up right away (< 10 milliseconds for the CreateFile call). It's just an occasional issue where things get stuffed up, and I've got other programs that NEVER seem to exhibit this behavior.
The device I'm talking to is a medical monitor using the IEEE 11073 protocol. Anyway, I have the connection to the device working just fine, it's ONLY the serial port open that's problematic. Could the state of the serial control lines at open time have something to do with this? The device at the other end is polling it's ports looking for various things to talk to, so I have no idea what the serial lines look like at the exact moment things go wrong.
OK, problem is understood, if not solved. I was playing with a different serial device and the problem began manifesting even more frequently.
The problem seems to be that when the VM is in control of some of the serial ports, the drivers become intermittently slow to open the available ports.
My test program opens then closes the port 1000 times, timing the open call. It does NOT set the serial port parameters in any way. Prior to running the test program, I was doing actual work with a device that uses the baud rate 460800.
When the VM is in possession of 4 of the ports, then opens on the remaining 4 ports can sometimes (20-30 times out of 1000 attempts) take 20-30 seconds to complete. When the VM is not running, the opens happen quickly all 1000 attempts. With the VM running, but no USB serial ports in it's possession, the opens happened quickly on all 1000 attempts.
Since the VM is a development tool, not part of our intended deployment scenario, I can live with this issue.
Interestingly, this effect seems to be dependent on what baud rate the port was last used at. Prior to my initial inquiries I'd been operating at 9600 baud and below and don't recall ever seeing the problem. When I first asked the question, I was working with a device that was at 115000 baud, and was having the problem intermittently. With the latest device at 460800 baud, I get the problem often enough to be able to hunt the problem down. No idea why, but there it is.
The serial control lines interacting with a device driver issue is a likely cause.
Do you have the control signals correctly connected?
If not, connect RTS to CTS and connect CD, DTR and DSR. On a DB25, this means connecting pins 4 and 5 and connecting pins 6, 8 and 20. On a DB9, connect pins 7 and 8 and connect pins 1, 4 and 6.
If this fixes the problem, you should look for driver settings to ignore the control signals on open.

controling individual pins on a serial port

I know that serial ports work by sending a single stream of bits in serial. I can write programs to send and receive data from that one pin.
However, there are a lot more other pins on the serial port connection that normal aren't used but from documentation all seem to have some sort of function for signalling as opposed to data transfer.
Is it possible in any way to cause the other pins that are not used for direct data transfer to be controlled individually? If so, how would i go about doing that?
EDIT: more information
I am working with a modern CPU running windows 7 64-bit on an intel core i7 870 processor. I'm using serial to usb ports because its imposable for me to do anything directly with a usb port and my computer does not come with serial ports and also for some inexplicable reason i have a bunch of these usb to serial port adapters lying around.
My goal is to control mutipul stepper motors (200 steps per rotation, 4 phase motors). My simple circuitry accepts single high pulses and interprets it as a command to cause the motor to rotate one step. The circuit itself will handle the power supply and phase switching. I wish to use the data transfer pin to send the rotation signals (we can control position and velocity by altering the number of high pulses and frequency of high pulses through the pin, however there is no real pulse width modulation).
I have many motors to control but they do not need to be controlled simultaneously. I hope to use the rest of the pins and run them through a simple combination logic circuit to identify which motor is being moved and which direction it is to move in. This is part of the power switching circuitry.
The data transfer pin will operate normally at some low end frequency. However, i want to control the other pins to allow me to give a solid on or off signal (they wont be flipping very quickly, only changes when i switch to controlling another motor).
Based of the suggestion of Hans Passant , I'd like to suggest that you use an Arduino instead of an USB-to-serial converter. The "Duemilanove" is an Arduino-based board that provides 6 PWM outputs (as well as 8 other digitial I/Os and 6 analog). Some more specialized boards might be even cheaper (Arduino Pro Mini, $15 in volume, some soldering required).
Using the handshaking pins to send data can work very well, though probably not on a multitasking OS, it's just very processor intensive (because the port needs to be polled constantly) and requires some custom cables. In fact, back in the day, this is exactly how Laplink got such high transfer rates over serial connections (and why to get those rates you needed a special 'Laplink' cable). And you need both sides of hte link to be aware of what's going on and be able to deal with the custom communications. Laplink would send a packet of data over both the normal UART pins while trying to send data from the other end of the packet over the handshaking pins. If the correct cable wasn't used (or there was some other problem with sending over the handshaking pins) there was no problem - all the data would just get send normally.
Embedded developers might know this as 'bit banging' - often on small embedded systems there's no dedicated UART circuitry - to get serial communications to work they have to toggle a general I/O pin with the correct timing. The same can be done on a UART's handshaking pins. But like I said, it can be detrimental to the system if other work needs to be done.
You can use DTR and RTS only, but that is four possible states. You do need to be careful that the device on the other end uses TTL levels. At he end of this link Serial there are tips on hardware if you need it.
What kind of data rate are you thinking of when you say high frequency? What kind of serial port do you have? With the old 9 pin connectors on the back of the computer the best you can do is around 115Kbps. With a USB adapter I have done test where I could push close to 1Mbps through the port.
Here's an article from Microsoft that goes into great detail on how to work with serial ports:
http://msdn.microsoft.com/en-us/library/ms810467.aspx
It mentions EscapeCommFunction for directly controlling the DTR line.
Before you check out this information, I'm joining in with the others that say a serial port is inappropriate for your application.
I´ve been trying to find an answer to your question for 3 hours, seems like there is no "simple way" to get a simple boolean signal from a computer...
But, there is always a way, and jet, as simple (maybe even stupid) as this may sound, have you considered using the audio jack connector as an output?, It is stereo so you would have 2 outputs available,the programming would is not that difficult. and you don#t need to buy expensive shit to make it work.
If you also need an input, just disassemble a mouse... and bridge the sensors to the servos, probably the most cheap and easiest way of doing it...
Another way would be using the leds for the Num-lock, caps-lock and the dspl-lock on the keyboard, these can be activated using software, and you just need to take a cheap external keyboard, and use the connectors for these 3 leds.
you are describing maybe a parallel port - where you can set bit patterns all at once - then toggle the xmit line to send it all...
Lets take a look from the "bottom up" point of view:
The serial port pins
Pins on the serial port may be connected to a "controller" or directly connected to the processor. In order for the processor to have access (control) the pins, there must be an electrical connection from the pins to the processor. If not, the processor nor the program can control the pins.
Using a serial controller
A controller, such as a USART, would be connected between the serial port and the processor. The controller may function as to convert 8 parallel data bits into serial bitstream. In the big picture, the controller must provide access to the port pins in order for them to be controlled. If it doesn't, the pins can't be accessed. The controller must be connected to the processor in order to control the pins if a controller is connected.
The Processor and the Serial port
Assuming that the pins you want to control are connected to the processor, the processor must be able to access them. Sometimes they are mapped as physical addresses (such as with an ARM processor), or they may be connected to a port (such as the intel 8086). A program would access the pins via a pointer or using a i/o instruction. In some processor, the i/o ports must be enabled and initialized before they can be used.
Support from the OS
Here's a big ticket item: If your platform has an Operating System, the Operating System must provide services to access the pins of the serial port. The services could be a driver or an API function call. If the OS doesn't provide services, you can't access the serial port pins.
Permission from the OS
Assuming the OS has support for the serial port, your program must now have permission to access the port. In some operating systems, permission may only be granted to root or drivers and not users. If your account does not have permission to access the pins, you are not going to read them.
Support from the Programming Language
Lastly, the programming language must have support for the port. If the language doesn't provide support for the port you may have to change languages, or even program in assembly.
Accessing the "unused" pins of a serial port require extensive research into the platform. Not all platforms have serial ports. Serial port access is platform dependent and may change across different platforms.
Ask another, more detailed question and you will get more detailed answers. Please provide the kind of platform and OS that you are using.

How to read NMEA sentences in windows Vista using c++

I have a GPS device connected to my system which is running Windows Vista.
I wanted to read the NMEA sentences from GPS device and print on screen.
How I will come to know, on which port the GPS device has been connected, as there can be other devices also connected on various com ports. I am developing the application in c++,
Does Microsoft provide any API's for this?
What kind of port is it? If it is a serial port, try connecting to all serial ports, one at a time, and then just listen for a NMEA string. If one is received, use the port, if one is not received, go to the next port.
I'd tend to prompt the user for the port. NMEA typically comes in as an ASCII string through a COM port. Before bluetooth, this used to typically be COM1 to COM4 with 90% of cases being either COM1 or COM2. It is more common now to connect via bluetooth, where you regularly see COM ports up to COM20 and above, so brute force is a slow option. The time taken to check all ports depends on how often your GPS sends sentances (assuming it does not require prompting) and your time-outs. You could expect a search to take up to 30 seconds. If you enumerate the COM ports this will be much quicker, as there will rarely be more that half a dozen active ports at any one time.
Well, in old times you gave the user of your application the privilege to specify the proper port ;) Or indeed, check all of them. Format and the available set of NMEA sentences can differ depending on the particular device - read some info here, for example, but the sentences should be plain text. (If not then it's not NMEA format :) )