-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLCONFIG_README
286 lines (251 loc) · 12.8 KB
/
LCONFIG_README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
LCONFIG.H
README
By Chris Martin
June 20th 2016
The LCONFIG or Laboratory CONFiguration header is a tool for automating
experiments and data collection with the LabJack T7 in the C language. The
philosophy is that researchers will construct their own executables that read in
configuration files with instructions on how to configure the DAQ for the test.
The most common things researchers need to specify should all be exposed through
the configuration file (e.g. PGA gain, differential/single-ended measurements,
sample rate, analog output functionality, etc...).
This document provides a quick introduction to using the header; assuming basic
familiarity with the C language. Detailed documentation is provided in the
header itself. The function prototypes are written with comments describing
their behavior and use.
***************
** Basic Use **
***************
Just to get started, let's assume we've already written a configuration file
that lays out how to find our device and how measurements should be taken. It's
time to write an application that implements the measurement. We'll learn how
to write a configuration file in the next section.
Be sure to start your code by including the header:
"""
#include "lconfig.h"
"""
The workhorse datatype of the LCONFIG functions is the DEVCONF struct. Short
for DEVice CONFiguration, it contains data taken from a configuration file for
one device. Your code should include something like this:
"""
DEVCONF dconf[8];
"""
This creates an array of 8 possible configured devices. Naturally, they don't
all need to be configured, but that will be up to the author of the
configuration file.
Loading a configuration file is straightforward. The dconf array will
automatically be configured based on the parameter-value pairs found in the
file. If the maximum number allowed in the current application is exceeded by
the file, an error is generated. All LCONFIG functions generate error messages
on their own, but the application can check the returned integer for an error;
0 implies success, and 1 implies an error was encountered.
"""
int err;
err = load_config(dconf, 8, "configuration_file_name");
"""
^ ^ ^ ^ ^
| | | | |
| | | | Name of the configuration file
| | | |
| | | Maximum # of devices allowed in dconf
| | |
| | The DEVCONF array to write
| |
| Functions defined by LCONFIG have detailed documentation above the
| function prototypes. load_config does exactly what the name implies.
|
The integer returned by almost all LCONFIG functions indicates whether an error
occurred.
Running an experiment can be simple. This example loads a single device from a
configuration file and writes 128 samples to a tab-delimited data file.
"""
load_config(dconf,1,"myconfig.conf"); // Open the config file and parse it
open_config(dconf, 0); // Open a connection to device 0
upload_config(dconf, 0); // Write the configuration parameters
start_file_stream(dconf, 0, 128, "output_file_name");
read_file_stream(dconf, 0);
stop_file_stream(dconf, 0);
close_config(dconf, 0);
"""
The data file will include a header that is also readable by load_config().
Using an output file as a config file will cause LCONFIG to repeat the
experiment that lead to the data (to the extent that it controls the
experiment).
For more information open lconfig.h and look at the comments above each function
prototype. Those represent the authoritative documentation for the file.
**********************************
** Writing a Configuration File **
**********************************
Configuration files are written in parameter-value pairs separated by
whitespace. For example,
"""
connection usb
"""
specifies the value "usb" for the parameter "connection".
Configuration files are completely case insensitive. All A-Z values are
replaced with their lower-case equivalents in load_config(), so feel free to use
any capitalization scheme that is pleasing to you. The strings are interpreted
into floats or integers as needed based on the individual parameter.
When a '#' is encountered at the beginning of a word, the remainder of the line
is ignored as a comment. When a '#' character appears in the middle of a word,
it is interpreted like any other character.
load_config() will stop processing the file either when the file ends or when it
encounters a double-# ("##") at the beginning of a word, signaling the end of
the configuration section. This is useful because it allows load_config() to
parse configuration directives at the head of a data file.
All of the configuration parameters are described authoritatively and in more
detail in the lconfig.h header itself. This should get you started, but the
best reference is the load_config() documentation above its prototype in the
header.
The device is identified either by its IP address or its serial number. If the
connection is over USB, the IP address is interpreted as a directive to be
written to the T7. If the connection is over ethernet, then the IP address is
the preferred way to identify the device. A serial number can be used in either
case, but it is extremely inefficient over ethernet.
As of version 1.1 of LCONFIG accepts the following parameters that configure the
device:
conneciton [eth|usb|any] How to connect to the T7?
serial The device serial number (41...)
IP The device's IP address (192.168.0.10)
gateway IP address of the subnet's gateway (only used in USB) (192.168.0.1)
subnet The subnet mask of the subnet (only used in USB) (255.255.255.0)
samplehz The stream sample rate in Hz (100)
settleus The settling time in microseconds (10)
Analog inputs are configured individually. Each of the global parameters above
only appear once in a configuration file, but these can appear multiple times.
A new analog input stream is created by the AICHANNEL parameter. All following
analog input parameters will be applied to that stream, so AICHANNEL always
appears first.
aichannel [0-13] Channel number of the analog measurement.
airange [0.01 | 0.1 | 1. | 10.] Bipolar voltage input range.
ainegative [aichannel+1 | 199 | differential | ground] Negative voltage source
(199<=>ground, aichannel+1<=>differential)
airesolution The resolution index used by the T7
The output stream works in the same way as the input streams. The AOCHANNEL
parameter indicates the creation of a new stream, and all output parameters
after apply to that stream. Outputs mimic a function generator; repeating in a
loop. The output parameters serve to configure the cyclical function.
aochannel [0 | 1] Channel number of the analog output
aosignal [constant | sine | square | triangle | noise]
aofrequency The signal repetition frequency in Hz (50)
aoamplitude The signal amplitude (1/2 pk-pk)
aooffset The signal offset
aoduty Duty cycle for square and triangle (0<= duty <=1)
The last class of parameters recognized as of version 1.1 is "meta." Meta
parameters are not inherently recognized by LCONFIG, but might be used by the
host application. For example, meta parameters might describe which equipment
was used, the condition of an experiment, references to other measurements,
etc. Because meta parameters are not hard-coded to be understood by LCONFIG,
the config file needs to tell LCONFIG the format of the data (integer, float,
or string). There are two ways to do this.
In version 2.01, meta parameters are identified in stanzas:
"""
meta flt # Begins a stanza of floats ("meta float" also accepted)
height 5.5 # All unrecognized parameters are new meta floats
weight 145.
meta int # Begins a stanza of integers ("meta integer" works too)
age 26
meta str # Begins a stanza of strings ("meta string" works too)
name Milo
meta end # Closes the meta stanzas. Now unrecognized paramers cause
# errors as they should.
"""
The legacy method for defining meta parameters still works in version 2.01.
Here, each parameter is given a three character type prefix separated by a
colon. These can appear in or out of the new-style stanzas. They will be
interpreted the same regardless of whether they agree with the stanza type.
"""
int:param 5 # creates an integer named "param" and stores 5 in it
flt:param 5.1 # creates a double named "param" and stores 5.1 in it
str:param five # creates a string named "param" and stores "five" in it
"""
To learn how to interact with meta parameters, see the get_meta_XXX() and
put_meta_XXX() functions in lconfig.h.
**************************
** High Speed Streaming **
**************************
Streaming to files limits speed quite severely. Requesting higher data
acquisition rates with the example above can cause buffer warnings. In these
applications, it is important to stream to memory instead.
"""
double data[512];
start_data_stream(dconf, 0, 128);
read_data_stream(dconf, 0, data);
stop_data_stream(dconf, 0);
"""
This approach solves the problem, but can get memory-intensive for long runs.
***********************
** Signal Generation **
***********************
The application software need do nothing to configure analog outputs. They
start when the stream starts. However, when driving a system with an output, it
is often important to let the system stabilize to a quasi-steady-state system
before conducting a measurement. That could be included as a meta-parameter,
but it is not currently offered as a formal parameter. Instead, here is a
convenient way to go about the process.
"""
double data[512];
start_file_stream(dconf,0,128);
read_data_stream(dconf,0,data);
read_file_stream(dconf,0);
stop_file_stream(dconf,0);
"""
The 128 samples read by read_data_stream would bypass the file.
********************
** Data Structure **
********************
In version 1.1 of LCONFIG, the device configuration appears as follows:
DEVCONF dconf[?];
+ int connection; // Identifies the connection type (USB/ETH)
+ char ip[LCONF_MAX_STR]; // IP address of the device
+ char gateway[LCONF_MAX_STR]; // Gateway IP address (usually host)
+ char subnet[LCONF_MAX_STR]; // Subnet mask (usually 255.255.255.0)
+ char serial[LCONF_MAX_STR]; // Device serial number
+ AICONF aich[LCONF_MAX_NAICH]; // Analog input configurations
|--+ unsigned int channel; // The T7 input channel
|--+ unsigned int nchannel; // The negative channel or ground (199)
|--+ double range; // Bipolar input range in V
l--+ unsigned int resolution; // Resolution index
+ unsigned int naich; // number of analog inputs
+ AOCONF aoch[LCONF_MAX_NAOCH]; // Analog output configurations
|--+ unsigned int channel; // The T7 output channel (0 or 1)
|--+ enum AOSIGNAL signal; // CONSTANT, SINE, SQUARE, TRIANGLE, NOISE
|--+ double amplitude; // Signal amplitude in V
|--+ double frequency; // Signal loop rate in Hz
|--+ double offset; // Signal offset in V
l--+ double duty; // Duty cycle 0 to 1
+ unsigned int naoch; // number of analog outputs
+ int handle; // device handle (used by LJM)
+ double samplehz; // Streaming sample rate
+ METACONF meta[LCONF_MAX_META]; // Meta configuration data
|--+ char param[LCONF_MAX_STR]; // Meta parameter name
|--+ union value; // Meta value (union for possible types)
| |--+ char svalue[LCONF_MAX_STR];
| |--+ int ivalue;
| l--+ double fvalue;
l--+ char type; // 'i' int, 's' string, 'f' double
+ FILESTREAM FS; // Used for streaming to a file
|--+ FILE* file; // The file receiving the stream
|--+ double* buffer; // A buffer for reading in data
l--+ unsigned int samples_per_read; // The size of the buffer
***************
** Debugging **
***************
If you want to verify that your parameters are being written properly, you can
always connect to the device using LabJack's Kipling software and look at the
registers.
LCONFIG includes two other options for you; download_config() and show_config().
The most basic is download_config(). This operation populates a configuration
struct to reflect the current status of the T7 as if it had been loaded from a
file.
"""
int err;
DEVCONF test;
err = download_config(dconf, 0, &test);
"""
The behavior isn't quite ideal, because some parameters cannot be detected from
the device (like what analog signal is in the buffer, or the number of samples
per read in AI streaming).
If you are using a Linux console, then there is show_config(). This operation
calls download_config and does a line-by-line comparison encoded by color to
indicate agreement or disagreement.