Data Acquisition from the Serial Port
A Real-Time Multi-threaded Application for the Win32 Platform
Author: Dr Grant Forrest, NHS FifeOriginal Publication Date: January 1997
Medical devices often have communication ports for transmitting data to other devices or computers. The Win32 application programming interface (API) gives the programmer access to various functions for reading data from the serial port of a computer running Microsoft Windows 9x/NT connected to such a device.
These operating systems allow applications to create multiple threads of execution. A multi-threaded program design can be more efficient for applications that have to wait for data from an external device.
A description of such an application that acquires data from a bedside cardiac output measurement device is presented. The specification requires that the data be read, processed and displayed in real time with trend display of several parameters and saved to a file at a user-defined interval.
Bedside medical devices often have communication ports for transmitting data to other equipment but there has been little effort by manufacturers to standardise the interface. The IEEE Medical Information Bus (MIB) standard has been in development since 1980 1, but the first two standard documents have only recently been approved for use. This represents an important step toward a standard interface, but it remains to be seen whether manufacturers will implement the IEEE recommendations. Many devices have RS-232 serial ports, an established communication protocol. Communication with a personal computer (PC) is possible but it's difficult to write a truly platform-independent application. A feature of Microsoft Windows 9x and NT is the ability to program using multiple threads of execution. A multi-threaded approach to serial comms programming has a number of advantages. The tasks for reading, processing and displaying data can be implemented as separate threads, and communication between threads allows them to wait efficiently for events to occur. For example, a thread can wait for data to arrive on the serial port, read it and signal a secondary thread to process the data. This secondary thread can perform any required formatting before signalling another thread to handle the display of the data. The Win32 Application Programming Interface (API) gives the programmer access to a number of functions for handling serial input and output (I/O). A serial port is opened for reading and writing in the same manner that a file is opened and a thread can call one of the Wait functions to wait for data to arrive at the port. The application presented here uses multiple threads to read, process and display data in real time with a separate thread for writing data to file at a user-defined interval. It was built using Borland Delphi 4.0 - as a consequence all the code examples are in object pascal. Examples in C++ are included in a subsection of the references page.
The program uses 6 threads:
- ReadCOM - Waits for data to arrive at the serial port. Has a function to read data then copy it to an array with access via a critical section.
- Data Object - retrieves the data from the shared array.
- Main Display - Queries the data object for parameter values and updates the main display area.
- Trend Display - Queries the data object for trend parameter values and updates the trend display grid.
- Haemodynamic Display - Updates the table of haemodynamic parameters.
- File Writing - Saves parameter values from the data object to file at a user-defined interval.
Communication between the threads is summarised in figure 1 .
The thread handling input of data from the serial port is given the highest thread priority. The syntax for opening a port using the Win32 API is similar to that for opening a file.
Example 1 - reading from the serial port
New data is copied to an array for retrieval by the data object. The array is protected from simultaneous reading/writing by a critical section.
The data supplied by the ReadCOM thread is an array of 160 bytes representing 10 blocks of 16 bytes, each containing the data for one or more parameters from the device. The Data Object thread processes this data into integer, floating-point and string values. As the name suggests, it uses a single object with 3 data subtypes:
- Ordinary (disposable) parameters
- Trend parameters
- Haemodynamic parameters
These are illustrated in figure 2 .
When ReadCOM acquires new data from the serial port it signals an event to indicate that there is new data available. The Data Object thread waits in an efficient loop for this event to become signalled before updating its parameter values. The ordinary parameters are erased at the next update but selected values for the trend grid are copied and kept in a separate structure for use by the Trend Display thread.
Following a valid thermodilution measurement haemodynamic data are transmitted from the device. Only the most recent measurement is transmitted but the program can save up to 5 sequential measurements. It uses the date and time of the measurement to detect new values with a resolution of one minute.
When the data object has been updated it signals a display event. The main display thread waits for this event to become signalled before updating the panel containing the ordinary parameter values such as heart rate, arterial pressure and cardiac output. The data object has member functions that return the integer/floating point parameters as strings suitable for display on the panel.
Trend Display Thread
The right hand panel of the main window is dedicated to display of the trend parameters: heart rate, arterial pressure, cardiac output, stroke volume and stroke volume variation. The display of each parameter can be toggled on and off with a menu option. The x-axis time scale can be selected from a menu option and scaling of the y-axis can also be toggled from a pop-up menu.
Following a thermodilution measurement the machine transmits the date and time of the measurement followed by values for bolus cardiac output, GEDV, ITBV, EVLW, Mtt, Dst, and a status value where 0 indicates a valid measurement. As the machine will transmit the most recent value only, the program maintains a separate record for a maximum of five measurements. A problem arises in the detection of new values as the time of measurement is recorded in minutes. If measurements are made with a frequency greater than one minute then the program will not detect new values. In practice it is rare for measurements to be made with a frequency greater than one minute as the thermal signal in the peripheral artery takes some time to stabilise after a bolus of cold solution.
The measurements are displayed in a table with the most recent at the bottom. Mean values for valid measurements are calculated and displayed in the bottom row. The user can toggle between absolute and indexed (corrected for body surface area) values. Individual measurements can be marked as invalid from a pop-up menu and excluded from the mean calculation.
File Writing Thread
The user has the option of saving the current values to a text file every 5, 12 or 60 seconds. When recording starts for the first time (or if a new patient record is started) they are prompted for a name and location for the text file using a standard Windows save file dialog box. Creation and execution of the file writing thread is controlled by a flag that is set when the user clicks <OK>. Clicking <Cancel> causes a dialog box to appear asking for confirmation that the user wants to continue without creating a file. The default file format is comma-separated value (*.csv) as this file type can be opened and read by Microsoft Excel.
If file writing is required then the thread executes. It opens the CSV file (by calling Append) then sets the time interval for save operations according to the status of the menu item. A one second timing event is generated by a timer component on the main form. The file write thread uses this event to increment a counter, keeping track of the number of writes performed. The current parameter values are retrieved by quering the data object and then a set of values is written as a single row with commas separating the individual parameters.
Upon termination, the thread closes the CSV file. If recording is restarted, a new thread is created that reopens the same CSV file. Values are appended and an entry is made in the file to indicate that recording was stopped. Using the Pause feature does not suspend the file write thread.
- Institute of Electrical and Electronic Engineering IEEE 1073
- 1073.3.1 (Transportation Profile)
- 1073.4.1 (Physical Layer)