Publisher’s version / Version de l'éditeur:
Vous avez des questions? Nous pouvons vous aider. Pour communiquer directement avec un auteur, consultez la Questions? Contact the NRC Publications Archive team at
[email protected]. If you wish to email the authors directly, please see the first page of the publication for their contact information.
https://publications-cnrc.canada.ca/fra/droits
L’accès à ce site Web et l’utilisation de son contenu sont assujettis aux conditions présentées dans le site LISEZ CES CONDITIONS ATTENTIVEMENT AVANT D’UTILISER CE SITE WEB.
Student Report; no. SR-2011-06, 2011-04
READ THESE TERMS AND CONDITIONS CAREFULLY BEFORE USING THIS WEBSITE.
https://nrc-publications.canada.ca/eng/copyright
NRC Publications Archive Record / Notice des Archives des publications du CNRC : https://nrc-publications.canada.ca/eng/view/object/?id=006c232d-45c3-472f-80c4-4ab5a24522d8 https://publications-cnrc.canada.ca/fra/voir/objet/?id=006c232d-45c3-472f-80c4-4ab5a24522d8
NRC Publications Archive
Archives des publications du CNRC
For the publisher’s version, please access the DOI link below./ Pour consulter la version de l’éditeur, utilisez le lien DOI ci-dessous.
https://doi.org/10.4224/19541699
Access and use of this website and the material on it are subject to the Terms and Conditions set forth at Data acquisition software for port interfacing devices
DOCUMENTATION PAGE REPORT NUMBER
SR-2011-06
NRC REPORT NUMBER DATE April 2011 REPORT SECURITY CLASSIFICATION
Unclassified
DISTRIBUTION Unlimited TITLE
Data Acquisition Software for Port Interfacing Devices
AUTHOR (S) Mitchell Chaulk
CORPORATE AUTHOR (S)/PERFORMING AGENCY (S)
Institute for Ocean Technology, National Research Council, St. John’s, NL PUBLICATION
SPONSORING AGENCY(S) IOT PROJECT NUMBER 42-2364-26
NRC FILE NUMBER KEY WORDS
Data Acquisition, IMU, Inertial Measurement Unit, Java, Serial Devices
PAGES vi, 12 App. A-D FIGS. 3 TABLES SUMMARY
Data acquisition is a problem that is frequently encountered in the world of research and experimentation. There are many existing software applications that are abstract enough to handle data acquisition for a large range of scenarios, but sometimes a more specialized approach is needed.
I designed the Data Logger application to be a lightweight standalone application to translate data sent from multiple serial-ports, which interface with IMUs (Inertial
Measurement Units), and then record the data in log files. These log files would then be used during post experimental processing to determine conclusions based on IMU
performance. This application was written in Java using only one external library, the Java Communications API (also known as javax.comm). The software was designed with extensibility in mind. This is to say that it would be easy for any other serial-port interfacing device (not just IMUs) to have its data recorded by Data Logger. All that’s required is for someone to implement the translation of the data streaming from the serial port. The software architecture is also setup so that it should be simple to add new modules to communicate with and record data from other sources, including different kinds of ports. Throughout design and implementation, a few concerns and problems were noticed and addressed. Solutions have been found for some, such as accurate time stamping, but there are other issues that remain unsolved, such as time-synchronization.
ADDRESS National Research Council Institute for Ocean Technology Arctic Avenue, P. O. Box 12093 St. John's, NL A1B 3T5
National Research Council Conseil national de recherches Canada Canada Institute for Ocean Institut des technologies Technology océaniques
DATA ACQUISITION SOFTWARE FOR PORT INTERFACING DEVICES
SR-2011-06
Mitchell Chaulk
EXECUTIVE SUMMARY
Data acquisition is a problem that is frequently encountered in the world of research and experimentation. There are many existing software applications that are abstract
enough to handle data acquisition for a large range of scenarios, but sometimes a more specialized approach is needed.
I designed the Data Logger application to be a lightweight standalone application to translate data sent from multiple serial-ports, which interface with IMUs (Inertial
Measurement Units), and then record the data in log files. These log files would then be used during post experimental processing to determine conclusions based on IMU performance. This application was written in Java using only one external library, the Java Communications API (also known as javax.comm).
The software was designed with extensibility in mind. This is to say that it would be easy for any other serial-port interfacing device (not just IMUs) to have its data recorded by
Data Logger. All that’s required is for someone to implement the translation of the data
streaming from the serial port. The software architecture is also setup so that it should be simple to add new modules to communicate with and record data from other
sources, including different kinds of ports.
Throughout design and implementation, a few concerns and problems were noticed and addressed. Solutions have been found for some, such as accurate time stamping, but there are other issues that remain unsolved, such as time-synchronization.
TABLE OF CONTENTS
LIST OF FIGURES... V
1.0 INTRODUCTION... 1
2.0 INSTALLATION... 1
2.1 Installing the Java Communications API on Windows XP... 1
2.1.1 Installing comm.jar ... 2
2.1.2 Installing win32com.dll ... 2
2.1.3 Installing javax.comm.properties ... 2
2.2 Installing and Running Data Logger... 2
2.2.1 Creating a Shortcut ... 3
3.0 INPUT FILE AND SCRIPTING LANGUAGE ... 3
3.1 Grammar... 4
3.1.1 Properties... 4
4.0 SOFTWARE DESIGN ... 5
4.1 MainFrame... 6
4.1.1 Pressing the “Quit” Button... 6
4.2 DataCore ... 7 4.3 DeviceManager... 7 4.4 PortFinder ... 7 4.5 PortWriter... 7 4.6 PortReader ... 7 4.6.1 SerialReadAndWrite... 8 4.6.2 ParallelReadAndWrite... 8 4.7 PortParser... 8 4.7.1 HexParser ... 9 4.7.2 MicrostrainParser ... 9 4.7.3 MotionPakParser... 9 4.7.4 PhinsParser ... 9 4.7.5 WatsonParser ... 9 4.7.6 Xsens Parser ... 9 4.8 Logger... 9 5.0 EXTENSIBILITY... 10 5.1 Future Extensibility ... 10
6.0 ERRORS AND ISSUES MET... 10
6.1 Time Stamping... 10
6.2 Time Synchronization ... 11
7.0 CONCLUSIONS AND RECOMMENDATIONS ... 11
LIST OF FIGURES
Figure 3-1. Parsed Data Structure ...4 Figure 4-1. Data Logger Software Architecture ...5 Figure 4-2. Quit Event...6
List of Appendices
Appendix A: Example Input File
Appendix B: Data Logger Construction
Appendix C: Observer Design Pattern
1.0 INTRODUCTION
Data Logger is data acquisition software written in Java and makes use of the Java
Communications API. This software was originally designed with serial port communication in mind, but it has been implemented in such a way that further
functionality is easy to add. The Data Logger application parses an input file as a simple node-tree data structure. This data structure is used to determine communication, and data logging, parameters. This document includes how to install Data Logger, a detailed look at its design and existing modules, as well as problems encountered and
recommendations for the future.
2.0 INSTALLATION
Data Logger is a Java application and as such requires installation of the Java Runtime
Environment (JRE). You can download and install the JRE for free from Java’s website at http://java.com/en/download.
Data Logger also requires installation of the Java Communications API (also known as
javax.comm). The necessary files can be downloaded in a bundle from
http://www.oracle.com/technetwork/java/index-jsp-141752.html. If you do not have an account with Sun, the installation CD that comes with this document will contain all the necessary files. This library can function on multiple platforms (such as Windows, Linux, and Solaris), but Data Logger was implemented on a Windows XP machine and
therefore this document will only detail the installation on this platform.
2.1 Installing the Java Communications API on Windows XP
This installation guide is largely based on the online article “How to install The Java Communications API in a Windows Environment” by user Circuit Negma at
http://circuitnegma.wordpress.com/2007/02/07/how-to-install-the-java-communications-api-in-a-windows-environment.
You should now have the following three files on your machine: comm.jar
win32com.dll
javax.comm.properties
The aforementioned article details how to install these files with the assumption that you’ve installed the Java Development Kit (JDK), but it’s still possible to install these files if you’ve only installed the JRE. This guide will detail how to install the Java Communications API if you’ve installed only the JRE.
Let JAVA_HOME represent the location of your installed JRE folder. The path here would be something like “C:\Program File\Java\jre”. The JRE folder may also include the version number, such as: “C:\Program File\Java\jre6”.
Let WINDOWS_DIR represent the location of the Windows directory folder, usually having a path similar to “C:\Windows”.
2.1.1 Installing comm.jar
Copy this file into the following folder: JAVA_HOME/lib
2.1.2 Installing win32com.dll
Copy this file into the following folders: JAVA_HOME
JAVA_HOME/bin
WINDOWS_DIR/system32
2.1.3 Installing javax.comm.properties
Copy this file into the following folders: JAVA_HOME
JAVA_HOME/lib
2.2 Installing and Running Data Logger
Once the JRE and Java Communications API have been installed, it is possible to run the Data Logger application. What is required is a compiled DataLogger.jar file (which is included on the CD) and an input text file that contains text following the scripting
language that is detailed in section 3.0. Once these two files are on your machine, the application can be executed via the Command Prompt by entering the following:
java.exe -jar DataLogger.jar input.txt
Note that you will have to specify the full path to the three files: java.exe,
DataLogger.jar, and input.txt. Since these paths are usually long, it can be confusing and tedious to frequently type them out. It is therefore recommended that you create a shortcut that automatically sets this up for you. A shortcut will allow you to run the application by double-clicking it.
2.2.1 Creating a Shortcut
To create the shortcut file, right click on your desktop, or within a folder, and go to “New” “Shortcut”. Browse to whatever file you wish for the shortcut to reference, such as the DataLogger.jar or java.exe file. Then name your shortcut something distinguishable, such as “runDataLogger”.
Once your shortcut has been created, right click it and go to “Properties”. In the text box labelled “Target:”, type exactly what you would in the Command Prompt to run the Data
Logger application. For example:
"C:\Program Files\Java\jre6\bin\java.exe" -jar "C:\Documents and
Settings\Administrator\Desktop\DataLogger\bin\DataLogger.jar" "C:\Documents and Settings\Administrator\Desktop\DataLogger\input.txt"
Once this is done, you should be able to startup and run the application by double clicking your new shortcut.
3.0 INPUT FILE AND SCRIPTING LANGUAGE
The Data Logger application’s input file is parsed into a node-tree data structure. Each node is capable of having multiple child nodes, where curly bracket characters are used to indicate nodes. Each node can also contain a list of properties. For example:
A { Color = red Height = 3.5 B { Color = blue D { Color = green Size = 5 } } C { Weight = 60 } } END
Figure 3-1. Parsed Data Structure 3.1 Grammar
Although there is indentation in the previous example, tabbing is ignored when the script is parsed. The entirety of the input file could have been written on one line, spaces being the only thing of importance. The previous example was only written in this way for the ease of readability.
3.1.1 Properties
All property values are parsed as character strings, even if they contain only numerical characters. For example:
Height = 545
The above property is parsed as having the name “Height” with the value “545”, a character string.
It is also true that all node and property names are all only one word in length. However, property values can be a character string containing spaces if the entirety of the value is surrounded in quotation marks. For example:
Path1 = “C:\Program Files”
In the above example, Path1 is parsed properly while the parsing of Path2 would result in an error and the application would shut down.
4.0 SOFTWARE DESIGN
The software architecture of the Data Logger application is designed to be simplistic and highly extensible. This section will detail the responsibility of each class, but to see more details with respect to available functions, members, and constructors, see the API included on the available CD.
In looking at figure 4-1; note that, in this diagram, italic font denotes abstract classes; such classes cannot be instantiated. Also note that the child classes of PortParser (such as MicrostrainParser and PhinsParser) are specialized classes designed to interrogate and record returned data from Inertial Measurement Units (IMUs).
4.1 MainFrame
MainFrame is the GUI for the application. It is passed an instance of DataCore upon
construction. Its only purpose is the quit function. It contains one button labelled “quit” which propagates the quit call down to all objects that require notification before quitting. See section 4.1.1.
Figure 4-2 demonstrates the chain of events that occur once the quit button is pressed in the Data Logger’s GUI. Note that the object named “Port” simply represents some port owned by an instance of PortReader (such as a serial or parallel port).
This quit function is necessary so that all running threads end, and opened ports do not remain open once the application exits. It’s also necessary because if the Logger class doesn’t properly quit, then the text file it creates and modifies will not properly save. A future alternative to this solution may be through the use of Java “Shut Down Hooks”.
4.2 DataCore
You can see from figure 4-1 that the DataCore class owns the input text file, described in section 3.0. DataCore inherits from the Node class; it is the root node of the parsed data structure (also described in section 3.0). DataCore creates the DeviceManager object, which is passed DataCore’s child node named “Devices”.
DataCore contains the runnable main function to compile the Data Logger application.
4.3 DeviceManager
DeviceManager is responsible for searching through the “Devices” Node for child nodes
that contain a property named “Port”. These child nodes are assumed to be used for port communication and the DeviceManager creates an instance of PortFinder for each of them (passing down the child Node).
4.4 PortFinder
This class checks to see if there exists a port with the same name as specified in its Node’s “Port” property. If a port with the given name exists then it creates the
appropriate child class of PortReader ( SerialReadAndWrite or ParallelReadAndWrite).
4.5 PortWriter
PortWriter is very basic class given a Java OutputStream upon construction. Its only
functionality is to send data to the given output stream.
4.6 PortReader
PortReader is an abstract class that is meant to outline the structure of any object
designed for communicating with a port. PortReader merely assures that its child classes are Java Runnables, meaning they operate on their own Threads, and they define a run and quit function. It contains protected members simply so they do not have to be continuously re-declared for all inheriting modules.
Note that although its name may suggest it is only capable of reading from a port, the functionality to write to a port is not taken from it. Therefore this class could likely be renamed to something of the effect of PortCommunicator.
4.6.1 SerialReadAndWrite
This class inherits from PortReader and is designed for setting up, and communicating with, a serial port. The node that is parsed from the input file, describing the
communication parameters for this port, will be handed down to PortReader’s constructor. Upon construction, SerialReadAndWrite checks this node for all the necessary properties; “LogFile”, “BaudRate”, “DataBits”, “StopBits”, and “Parity”. Note that all of these parameters are required or else it will fail to construct and will exit its
Thread. LogFile is simply a path to where the Logger object should create and write to a
text file, while the other properties are standard parameters of serial port communication.
SerialReadAndWrite also checks to see if it is aware of a PortParser class with the
device name passed into its constructor. If it cannot find an appropriate parser, then it will exit its Thread.
This class also implements the javax.comm.SerialPortEventListener interface. This means that its function named “serialEvent” will be called whenever there is readable activity on its serial port. This follows the conventional Observer design pattern, in software development.
The function run is called infinitely, propagating the call down to the
SerialReadAndWrite’s PortParser, until quit is called.
4.6.2 ParallelReadAndWrite
This module has yet to be implemented and contains no functionality. It is intended to be used to communicate with parallel ports.
4.7 PortParser
PortParser is an abstract class to outline the functionality of an object whose
responsibility is to be used by a PortReader to translate data. Upon construction it is handed a Java InputStream to read from, and PortWriter to write to, a log file name to pass to its Logger, and a Node representing the device it is communicating with. It also contains a few static functions to aid with byte array communication (helpful when reading serial port data). For more information concerning these functions, see the API in the included CD.
To communicate with its port, a child class of PortParser should use its event function to read from the InputStream, and its run function to write to the PortWriter. For more details see the API in the included CD.
4.7.1 HexParser
A PortParser created to record serial port data in a text file as hexadecimal data.
4.7.2 MicrostrainParser
A PortParser created to communicate and record data from the 3DM-GX1 IMU (Inertial Measurement Unit) by Microstrain. This is designed to function with serial port
communication.
4.7.3 MotionPakParser
A PortParser created to communicate and record data from the MotionPak II IMU by Systron Donner Inertial. This is designed to function with serial port communication.
4.7.4 PhinsParser
A PortParser created to communicate and record data from the Phins INS’s (Inertial Navigation System’s) IMU by iXsea. This is designed to function with serial port communication.
4.7.5 WatsonParser
A PortParser created to communicate and record data from the AHRS-E304 IMU by Watson. This is designed to function with serial port communication.
4.7.6 Xsens Parser
A PortParser created to communicate and record data from the MTi IMU by Xsens. This is designed to function with serial port communication.
4.8 Logger
A simple class whose purpose is to create a new text file, and provide functionality to add text to the newly created file. If a function with the given name already exists, a number is appended to the end of the new file. For example, if we were to create a new text file named “test”, the Logger object would create a file named “test.txt”. If we tried to create another file named “test” in the same location, the Logger object would create a file named “test(2).txt”. This number will continue to increment until a unique file name is found.
Note that Logger must have its quit function called upon destruction in order to properly save and close the text file that it has created.
5.0 EXTENSIBILITY
The Data Logger application was designed with ease of extensibility in mind. While functionality has only been created for serial port interfacing devices, it should be simple enough to add functionality for parallel ports, or any other data stream, as well. Any new communication source would simply inherit from PortReader, and any new parsing object would simply inherit from PortParser.
Knowledge of new communication sources (besides serial and parallel ports) would have to be added to PortFinder, so that it would know when to create the appropriate instance of PortReader. Knowledge of new PortParsers would also have to be added to the appropriate implementations of PortReader. For example, if a new parser was created to translate and record serial port streamed data, then knowledge of this new parser would have to be added to the SerialReadAndWrite class. This is an obvious shortcoming of Data Logger’s current state of extensibility.
5.1 Future Extensibility
It is advisable, in the future, to make use of Java Reflection library to mend the
shortcoming mentioned in section 5.0. What this library allows you to do is to describe a class name with a character string, and call that class’ constructor if it exists. This
means that in the future, it would be possible to put a class name in the input file, and then Data Logger would search for a class with that name to construct, without having to add any new knowledge to PortFinder, or PortReaders (as mentioned in section 5.0). This means that creating new PortReaders and PortParsers could be done by simply creating new Java classes, that extend from those two classes, and then putting paths to the new classes within the input file (editing existing classes would not be necessary).
6.0 ERRORS AND ISSUES MET
The current build of Data Logger has been tried and tested and seems to have no run time issues. Throughout development however, there have been two key issues that arose and needed solving:
6.1 Time Stamping
Asking for file time on a Windows platform isn’t as accurate as Data Logger requires. This was a problem encountered when originally trying to design Data Logger in MATLAB, and C++. Asking Windows XP for the time will get you around 15 ms resolution, which is not a desirable accuracy. To solve this issue you can query the performance counter (returns a hardware counter value), and query the performance frequency. These two values should be enough to get you fairly accurate time stamping values. Luckily, in Java, there exists the function System.nanoTime, which uses the exact method mentioned.
6.2 Time Synchronization
There is a delay in time from which a device measures a value, and that value is collected and recorded by Data Logger. Since this delay will be different for every device, it results in an error of time synchronization. A solution for this problem has not yet been found, so there is no implementation to account for it. It is hoped that this delay is constant enough so that collected data will simply be shifted with respect to time, and therefore easy to correct after the data has been logged.
7.0 CONCLUSIONS AND RECOMMENDATIONS
It is highly recommended that use of the conventional State Machine design pattern is used when writing implementations of the PortParser class. This design pattern
(included in Appendix D) solved many issues and complications related to knowing when it was okay to read versus write to a port.
While this design is robust and modular, further extensibility can be achieved using the Java Reflection library as described in section 5.1. This change is highly recommended, as it will greatly increase the ease with which someone can add functionality to the Data
Logger.
Data Logger is a software application capable of parsing an input file, and translating
that information into communication parameters without the need of being re-compiled. It is multi-threaded and records data as accurately as I know possible. Through tests and trials, Data Logger seems to be reliable and is not prone to any known run-time errors.
8.0 ACKNOWLEDGEMENTS
Dr. Chris Williams and Mr. David Shea provided insight towards the actually functionality of IMUs (how they work and communicate).
David Shea wrote the original MATLAB data acquisition applications. These were referenced while implementing Data Logger.
9.0 REFERENCES
[1] Glen McCluskey (January 1998), “Using Java Reflection”, “http://java.sun.com/ developer/technicalArticles/ALT/Reflection“
[2] Mitchell Chaulk (April 2011), IOT-NRC, “Inertial Measurement Unit (IMU) Testing Procedure”.
[3] Wikipedia (April 2011), “State Pattern”, “http://en.wikipedia.org/wiki/State_pattern”.
[4] Wikipedia (April 2011), “Observer Pattern”, “http://en.wikipedia.org/wiki/ Observer_pattern”.
Appendix A Example Input File
Devices {
Microstrain {
Port = COM3
LogFile = "C:\Documents and Settings\Administrator\Desktop\DataLogger\Microstrain-test" BaudRate = 38400 DataBits = 8 StopBits = 1 Parity = None } MotionPak { Port = COM2
LogFile = "C:\Documents and Settings\Administrator\Desktop\DataLogger\MotionPak-test" BaudRate = 9600 DataBits = 8 StopBits = 1 Parity = None } Phins { Port = COM1
LogFile = "C:\Documents and Settings\Administrator\Desktop\DataLogger\Phins-test" BaudRate = 115200 DataBits = 8 StopBits = 1 Parity = None } Watson { Port = COM4
LogFile = "C:\Documents and Settings\Administrator\Desktop\DataLogger\Watson-test" BaudRate = 38400 DataBits = 8 StopBits = 1 Parity = None } Xsens { Port = COM5
LogFile = "C:\Documents and Settings\Administrator\Desktop\DataLogger\Xsens-test" BaudRate = 115200 DataBits = 8 StopBits = 1 Parity = None } } END
Appendix B
Appendix C
Appendix D