Labwindows CVI
Labwindows CVI
LabWindows/CVI ®
Printer:
p/u file
virt_inst_series.fm
Advanced Topics in
LabWindows/CVI
◆ Shahid F. Khalid
Prentice Hall books are widely used by corporations and government agencies for training,
marketing, and resale.
The publisher offers discounts on this book when ordered in bulk quantities.
For more information, contact:
Corporate Sales Department
Prentice Hall PTR
One Lake Street
Upper Saddle River, NJ 07458
Phone: 800-382-3419; FAX: 201-236-7141
Email (Internet): [email protected]
All rights reserved. No part of this book may be reproduced, in any form or by any means, without permission in writing
from the publisher.
The author of this book has used his best effort in preparing this book. These efforts include the development, research, and
testing of the theories and programs to determine their effectiveness. The author makes no warranty of any kind, expressed
or implied, with regard to these programs or the documentation contained in this book. The author shall not be liable in any
event for incidental or consequential damages in connection with, or arising out of the furnishing, performance, or use of
these programs.
Trademarks: CVI™, LabVIEW™ are the trademarks of National Instruments Corporation. Microsoft™ is the trademark of
Microsoft Corporation. Word ™, Word 97™, Excel™ are the trademarks of Microsoft Corporation. All other product names
mentioned herein are the trademarks of their respective owners.
10 9 8 7 6 5 4 3 2 1
ISBN 0-13-089229-7
1
Programmatically Creating the Graphical User Interface 1
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Analyzing the Source Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
main Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
CreateGUI Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
RingCB Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
StartGUICB Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
SamplesControlCB Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
DoneGUICB Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
ClearGraphCB Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
PlotUniformCB Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
ExitGUICB Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Library Function Prototypes and Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
DeleteGraphPlot Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
DiscardPanel Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
NewCtrl Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
NewPanel Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
viii Contents
PlotY Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
RefreshGraph Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
SetPanelAttribute Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2
Plotting on Graph Controls 33
Graph Attributes and Cursors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Manual Zooming and Panning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Creating Graph Legends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Plotting Geometric Patterns on Graph Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Library Function Prototypes and Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
CreateMetaFont Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
GetAxisScalingMode Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
GetGraphCursor Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
GetGraphCursorIndex Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
LGCreateLegendControl Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
LGInsertLegendItemForPlot Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
LGSetLegendCtrlAttribute Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
PlotArc Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
PlotLine Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
PlotOval Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
PlotRectangle Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
PlotText Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
SetAxisScalingMode Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
3
Using DataSocket 75
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Communicating Using DataSocket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
DataSocket Data Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Creating a DataSocket Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Analyzing the Writer Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
Analyzing the Reader Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
DataSocket Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Accessing the DataSocket Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
DataSocket Server Manager Configurations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
Server Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
Permissions Groups . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
Contents ix
4
Table Control 121
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
Table Control Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
Table Control States . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
Moving Around in the Table Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
Resizing Rows and Columns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
Using the System Clipboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
Table Control Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
Browsing the Table Control Dialog Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
Table Control Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
Examining the Project Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
Header and main Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
Load Data Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
Selecting Columns to Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
Sort Ascending/Descending . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
Search Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
Highlighting/Pasting Rows to Clipboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
Library Function Prototypes and Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
ClipboardGetTableVals Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
ClipboardPutTableVals Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
DeleteTableRows Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
x Contents
5
VXI Communication Using VISA 175
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
Short History . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
VXI Chassis, Modules, and Connectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
Controlling the VXI System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
VXI Address Space and Configuration Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
VXI Device Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
Communicating with Message-Based Devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
Resource Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
Basics of Programming with VISA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
VISA Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
Header and main Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
Finding System Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
Setting Up Communication with the Function Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
Configuring the Function Generator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
Contents xi
6
Data Acquisition 219
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
Data Acquisition Board Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
Signal Conditioning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
Analog Input/Output Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
Range, Gain, and Code Width . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
DAQ Designer Tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
Installing and Setting Up the DAQ Board . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
Using the DAQ Channel Wizard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
Hardware Configurations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
Using DAQ Library Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
Analog Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
Analog Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
Digital Input/Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
Counter Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263
Counter Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265
Event Counting and Timing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266
Pulse Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268
Pulse Measurement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
Frequency Measurement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
xii Contents
7
Creating and Using Function Panels 301
Purpose of a Function Panel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302
Creating a Function Tree . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 304
Creating a Function Panel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 308
Testing the Function Panel Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 319
Function Panel Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
Numeric Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321
Slide Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
Binary Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324
Contents xiii
8
Creating Instrument Drivers 331
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332
Creating an Instrument Driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334
Generating Driver Files Review . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
Function Panel File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
Initialize Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347
Configuration Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 348
Measure Output Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
Action/Status Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
Utility Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
Close Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
Source File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 349
Include File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
.sub File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
Using the Attribute Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 350
Attribute Editor Controls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 353
Editing High-Level Instrument Driver Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 356
Deleting High-Level Instrument Driver Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
Adding High-Level Instrument Driver Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 359
Creating Instrument Driver Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
Creating the Instrument Driver Text File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 360
Creating the Instrument Driver Windows Help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
Testing the Instrument Driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 362
Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 363
9
OpenGL 365
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
OpenGL Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 367
Source Code Analysis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
Header and main Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 370
Load Data File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 372
xiv Contents
Bibliography 399
Index 401
The Author 423
Illustrations
What Is LabWindows/CVI?
LabWindows/CVI is a fully integrated interactive development environment
with easy-to-use development tools that allow you quickly to create, config-
ure, and display measurements on an easy-to-create graphical user interface
(GUI). Engineers and scientists use LabWindows/CVI to create virtual instru-
ments to acquire, analyze, and display data. Virtual instrumentation refers to
the combination of hardware and software elements that provide you com-
plete flexibility of designing and controlling the elements of stand-alone or
embedded instruments from your computer system.
LabWindows/CVI was developed by National Instruments Corporation and
uses all the features of the American National Standards Institute (ANSI) C
programming language to develop your source code and create your applica-
tions expeditiously, using the power of its built-in tools and libraries. The
LabWindows/CVI environment provides for a drag-and-drop editor for build-
ing GUIs, generating code automatically from the user interface to create the
“skeleton” of an application source code, and includes a multitude of run-
time libraries for instrumentation control and analysis. Optionally, when you
obtain the data acquisition hardware from National Instruments, you also get
the NI-DAQ (data acquisition) libraries to communicate and perform the nec-
essary data acquisition functions. LabWindows/CVI has built-in libraries to
communicate with hardware interfaces such as: General Purpose Interface
Bus (GPIB), VME (Versa-Modular Eurocard) eXtensions for Instrumentations
(VXI), PCI (Peripheral Component Interconnect) eXtensions for Instrumenta-
tion (PXI), serial interface communications, and data acquisition, to name a
few. For simplicity, LabWindows/CVI is referred to throughout as CVI.
xxvi Preface
Using CVI’s Utility Library functions, you can easily create a multithread-
safe application that gives you complete control for creating, debugging, and
deploying multithreading applications.
You can create distributed computing applications using the power of Ac-
tiveX, Transmission Control Protocol/Internet Protocol (TCP/IP), and Dy-
namic Data Exchange (DDE) libraries included with CVI. Among other
things, ActiveX-enabled applications on one machine can control an ActiveX
application on another machine across the network.
CVI allows you to create Interchangeable Virtual Instruments (IVI) instru-
ment drivers for various instrument classes using the Instrument Driver De-
velopment Wizard. CVI also contains a User Interface (UI) Localization
Utility to translate and display the text on the GUI in the selected language
of your choice.
CVI interfaces with configuration management systems such as Microsoft
Visual Source Safe, Perforce, Continuous, and ClearCase, allowing you to
manage individual and team projects easier. This is useful, as it protects
code from inadvertently being changed when shared across various devel-
opment teams, keeping track of code changes, archiving, and controlling the
software versions released.
Microsoft Word Reports and NI-Reports instrument drivers, included
with CVI, allow you to save and print professional-looking text reports.
Using these instrument drivers, you can set margins, add headers and foot-
ers, and set font style and size programmatically to create a report format to
your liking.
CVI supports all OpenGL functionalities. The OpenGL instrument driver
can be used to display and view data using different perspectives and fields of
view in two or three dimensions.
The CVI environment supports open software architecture, enabling you
to reuse existing programs within its environment. If you are programming
in C using your preferred environment, CVI complements your present ef-
forts and streamlines your future development. You can incorporate stan-
dard ANSI C source code, object files, and dynamic link libraries (DLLs)
within CVI. You have the flexibility to use the projects created in CVI in any
of the following external C/C++ compilers with which you may be more fa-
miliar: Microsoft Visual C++, Borland C++, C++ Builder, Symantec C, or
WATCOM C/C++. Note that starting with CVI version 6.0, the Symantec
and Watcom compilers will not be supported.
xxviii Preface
Note that if you are using a CVI version prior to 5.5, you will not be able to
benefit fully from Chapters 3 and 4 since you will not be able to run the pro-
jects included in these chapters. These two topics were included in CVI start-
ing with version 5.5. You can, however, read the remaining chapters, as they
are not based on the concepts explained in these chapters. Each chapter is or-
ganized as a separate topic and does not require knowledge of preceding
chapters. The exception to this rule is Chapter 7, Creating and Using Function
Panels, which must be understood before reading Chapter 8, Creating Instru-
ment Drivers, since function panels are used in creating instrument drivers.
Here is a short description of the chapters:
Chapter 1, “Programmatically Creating the Graphical User Interface,”
shows you how to create the graphical user interface entirely using the CVI
library functions. You can create a panel and manipulate controls on the
panel during run-time, change their attributes, and hide/display the con-
trol(s) as needed. These features enhance your application by making the
GUI more versatile and providing you further flexibility.
Chapter 2, “Plotting on Graph Controls,” discusses the many features of
graph control. You are shown the graph control features of using the cursor con-
trols, zooming and panning, and creating graph legends using the toolbox. This
chapter shows you how to draw geometric objects such as lines, arcs, rectangles,
and ovals on the graph control and to label these objects. You are shown how to
add a header to your graph control using different font attributes.
Chapter 3, “Using DataSocket,” explains the fundamentals of DataSocket,
a National Instruments’ proprietary technology. DataSocket transfers data
between applications on the local computer, computers on the network, or
to remote computers via the Internet. The various features of configuring the
DataSocket Server Manager are also explained.
Chapter 4, “Table Control,” shows you the features and capabilities of the
table control to display, sort, select, and manipulate data in the cells that
comprise the rows and columns of the table control, similar to a spreadsheet.
Chapter 5, “VXI Communication Using VISA,” introduces you to the
basic features of a VXI system and to establish communication with the VXI
devices. You are introduced to the VXI hardware and to the address space
mapping. The different VXI device classes and their configuration registers
are explained. The functions performed by the VXI Resource Manager and
the VISA Default Resource Manager are shown. You are shown how the
VISA functions are used to set up communication and “talk” to devices.
xxx Preface
To install and run CVI on Windows requires using at least a Pentium 133-
MHz processor (Pentium 266 MHz or higher recommended), a minimum of
70 MB of free hard disk space for full installation, and at least 32 MB of RAM
(64 MB recommended). To install versions prior to CVI 5.5 on a SPARC sta-
tion, you will need 12 MB of free disk space, a minimum of 32 MB of disk
swap space, and 23 MB of main memory.
To get really effective results in creating and displaying GUIs, it is rec-
ommended that you have at least a 17-inch Super VGA monitor and a high-
resolution video card which supports a resolution of at least 800 by 600. The
GUIs included on the CD-ROM with this book are designed using a resolu-
tion of 1024 by 768 pixels on the monitor. The GUIs have been tested to
work on 17-inch through 21-inch monitors. However, if your display is dif-
ferent, you may have to resize the panel(s) in the User Interface Editor.
As in any Windows programming task, use of a Microsoft-compatible
mouse or trackball is a great convenience and is recommended for use with
CVI. In this book, only mouse interactions are used to access objects or to se-
lect menu commands. Keyboard commands are only used to show alterna-
tive capabilities in controlling and running projects.
It is assumed that you are familiar with the Windows environment on the
PC or the operating environment of Sun workstations.
monospace bold Bold monospace text is used for messages that the
computer prints to the screen automatically.
At various places in the text, I have referenced CVI manuals for you to use
to obtain more information on certain topics. This information may refer ei-
ther to paper manual(s) or to On-line Help. You have to determine where it
is located depending on the CVI version you are using since many of the
paper manual(s) of earlier CVI versions are available as On-line Help or
merged into other manuals.
The user interface controls, menus, menu items, context menus, and vari-
ous options and features to perform certain tasks may vary from that shown
in the book, as they depend on the CVI version you are using. The menus in
this book are based on CVI version 5.5. You should have little problem in re-
lating these to different version(s) of CVI.
The CVI library functions introduced in this book are explained at the end of
the chapter in which they are first introduced. However, the library functions
that were introduced in the book LabWindows/CVI Programming for Beginners
Preface xxxiii
are not repeated in this book. The reader should consult this book or the man-
ual(s) to learn more about these functions.
All the projects in this book are included on the CD-ROM accompanying
this book. These projects are included in their respective chapter folder
names under the AdvProjects folder. For example, the projects explained
in Chapter 2 are included in the Chapter2_Proj folder located under the
AdvProjects folder. To use these projects, it is best to copy these folders
from the CD-ROM on to your hard disk and remove the read-only (R) and
archive (A) attributes from all the files. You can change the file attributes by
first selecting the file(s) and right-clicking with the mouse button. Select
Properties from the pop-up menu that is displayed and remove the check
marks from the Read-only and Archive boxes. These projects are created
using CVI version 5.5 and are compatible with higher versions of CVI. Some
of the projects may not run with CVI versions released prior to version 5.5.
Acknowledgments
To write a book requires the help of many people without whose help the
book would have been deficient in many aspects. There are people who
helped edit the book for correctness, completeness, and linguistic style. Oth-
ers supplied me with the appropriate literature and necessary hardware to
enable me to write the chapters and run and test the programs. I would like
to acknowledge the following people, without whose help this book would
not have been possible.
I would like to thank Ravi Marawar, Academic Program Manager at Na-
tional Instruments, who introduced me to a group of CVI experts at National
Instruments who reviewed the book and made extremely positive sugges-
tions in improving this book. Ravi Marawar also supplied me with interface
cards, test equipment, and course manuals that enabled me to write the vari-
ous chapters.
Luis Gomes, LabWindows/CVI Group Manager at National Instruments,
deserves special appreciation and thanks for doing such a thorough job of
reviewing all the chapters and projects included in this book. He sacrificed
many weekends and numerous hours working days and nights that were
crucial in improving the quality of the book.
I greatly appreciate the willingness of Jeff Laney, Product Marketing Man-
ager at National Instruments, to write a very informative foreword to the book.
Some of the engineers at National Instruments were assigned the task of
reviewing the specific chapters that fall into their CVI specialty. I am thankful
xxxiv Preface
Jeff Laney
Product Marketing Manager
National Instruments
1
PROGRAMMATICALLY CREATING THE
GRAPHICAL USER INTERFACE
Chapter Highlights
■ Introduction
■ Analyzing the Source Code
■ Summary
■ Library Function Prototypes and Definitions
Creating the graphical user interface (GUI) programmatically gives you the
flexibility to add and replace controls during run-time, change their attrib-
utes, make the control invisible when not required, and display the control
again when needed. Such features enhance your application by making your
GUI more versatile.
In this chapter you will not be using the User Interface Editor but create all
the controls on the GUI using the CVI library functions through the Source
Editor. Creating a GUI programmatically has its advantages and disadvan-
tages, which are mentioned in this chapter. Only the requirements of your
project will decide which is a more favorable approach for you to use. A bal-
anced approach would be to create most of the GUI using the User Interface
Editor and perform control manipulations programmatically.
2 Chapter 1 • Programmatically Creating the Graphical User Interface
Introduction
The process of creating a graphical user interface (GUI) is usually accom-
plished through use of the CVI User Interface Editor. In this section you will
learn how to create a GUI programmatically using the Source Editor. Creat-
ing a GUI using the Source Editor gives you the capability of changing the
controls and their attributes dynamically at run-time. Sometimes you would
like to create most of the GUI using the User Interface Editor and program-
matically modify the controls during execution.
Here you will be shown how to programmatically create the panel and
add controls to the panel using the CVI library functions. The panel and con-
trol attributes that you configure using the Edit dialog box will be demon-
strated using the CVI library functions. You will also be shown how to hide
a control and display another control in its place on the panel. These features
add flexibility to the creation and manipulation of controls on your GUI.
Load project1-1.prj from the AdvProject\Chapter1_Proj folder
located on the CD that came with this book. For best results, copy the project
to your local hard disk and load the project from there. The Project window
list shown in Figure 1–1 will be displayed. Notice that in this Project window
list there is no user interface file(s) or associated header file(s). There is only
one file in the project: project1-1.c. You cannot, therefore, use the Code-
Builder to create the “skeleton code.”
The code for this project has to be entered manually in the Source Editor.
The GUI that you will create from the source code is shown in Figure 1–2.
Figure 1–1
project1-1 Window List
Chapter 1 • Programmatically Creating the Graphical User Interface 3
Note that functions listed in the Select Function control in Figure 1–2 are part
of the CVI Advanced Analysis Library package that uses the header file
analysis.h. The Advanced Analysis Library is part of the full CVI pack-
age. Unless you have installed this library package, these functions will not
run. You can, however, substitute your own functions at the appropriate
places in the code to execute this program if you desire. Please note that this
program is not a demonstration of using functions, but demonstrates the
concepts in creating and manipulating controls using the source code.
main Function
The program header files, function prototypes, global variables, and the
main function listing are shown in Figure 1–3. The function prototype for the
Figure 1–2
Project1-1 GUI
4 Chapter 1 • Programmatically Creating the Graphical User Interface
user-created files and the callback functions are shown at lines 9–34. At line
54 the user-defined function CreateGUI is called to create the GUI shown in
Figure 1–2. The GUI created by CreateGUI function is displayed by the li-
brary function DisplayPanel at line 55 and the panel discarded by the library
function DiscardPanel when the panel is no longer needed.
1 #include <formatio.h>
2 #include <analysis.h>
3 #include <utility.h>
4 #include <userint.h>
5 #include <ansi_c.h>
6
7 /******************Function Prototypes ************************/
8
9 void CreateGUI(void); //Create the GUI
10 void CreateDisplayDataPanel(void); //Create Data panel
11
12 //Invoked when any item on Ring control is selected
13 int CVICALLBACK RingCB (int panel, int control, int event,
14 void *callbackData, int eventData1, int eventData2);
15 //Invoked by "Start" command button
16 int CVICALLBACK StartGUICB (int panel, int control, int event,
17 void *callbackData, int eventData1, int eventData2);
18 //Invoked by "Stop" command button
19 int CVICALLBACK StopGUICB (int panel, int control, int event,
20 void *callbackData, int eventData1, int eventData2);
21 //Invoked by "Exit" command button
22 int CVICALLBACK ExitGUICB (int panel, int control, int event,
23 void *callbackData, int eventData1, int eventData2);
24 //Invoked by "CLEAR" command button
25 int CVICALLBACK ClearGraphCB (int panel, int control, int event,
26 void *callbackData, int eventData1, int eventData2);
27 //Plot Uniform random numbers
28 int CVICALLBACK PlotUniformCB (int panel, int control, int event,
29 void *callbackData, int eventData1, int eventData2);
30 //Done entering data
31 int CVICALLBACK DoneGUICB (int panel, int control, int event,
32 void *callbackData, int eventData1, int eventData2);
33 //Change Samples Callback
34 int CVICALLBACK SamplesControlCB(int panel, int control, int event,
35 void *callbackData, int eventData1, int eventData2);
36
37 /**************************************************************/
38 static int GUI_Handle, Child_Handle;
39
40 //User Interface control IDs
41 int GUI_START_ID, GRAPH_ID, TEXT_BOX_ID, CLEAR_PLOT_ID, PLOT_UNI_ID,
42 AMPLITUDE_ID, PHASE_ID, CYCLES_ID, SAMPLES_ID,TEXT_MSG, SELECTED_ITEM,
43 TABLE_MSG, RING_BOX;
44
Figure 1–3
Project1-1 Header and main Function (continued)
Chapter 1 • Programmatically Creating the Graphical User Interface 5
Figure 1–3
Project1-1 Header and main Function (continued)
CreateGUI Function
The code for the CreateGUI function is listed in Figure 1–4.
1 void CreateGUI(void)
2 {
3
4 int DEC_BOX_CMDS,DEC_BOX_GRAPH, DEC_BOX_FUNC,TEXT_MSG_FUNC,
5 GUI_EXIT_ID;
6
7 //Create a new panel
8 GUI_Handle = NewPanel (0, "PROGRAMMATICALLY CREATED GUI",
9 VAL_AUTO_CENTER, VAL_AUTO_CENTER, 500, 800);
10
11 //Make the Panel movable
12 SetPanelAttribute (GUI_Handle, ATTR_MOVABLE, 1);
13 //Create Recessed decoration box for Commands
14 DEC_BOX_CMDS = NewCtrl (GUI_Handle, CTRL_RECESSED_BOX, "", 180, 75);
15
16 //Set dimensions of Decoration box
17 SetCtrlAttribute (GUI_Handle, DEC_BOX_CMDS, ATTR_LEFT, 75);
18 SetCtrlAttribute (GUI_Handle, DEC_BOX_CMDS, ATTR_HEIGHT, 125);
19 SetCtrlAttribute (GUI_Handle, DEC_BOX_CMDS, ATTR_WIDTH, 100);
20 //Set frame color of Decoration box
21 SetCtrlAttribute (GUI_Handle, DEC_BOX_CMDS, ATTR_FRAME_COLOR,
22 VAL_OFFWHITE);
23
24 /************ Create a "START" square command button ***************/
25 GUI_START_ID = NewCtrl (GUI_Handle, CTRL_SQUARE_COMMAND_BUTTON,
26 "START\n<F1>", 200, 100);
27
Figure 1–4
CreateGUI Function Listing (continued)
6 Chapter 1 • Programmatically Creating the Graphical User Interface
Figure 1–4
CreateGUI Function Listing (continued)
Chapter 1 • Programmatically Creating the Graphical User Interface 7
Figure 1–4
CreateGUI Function Listing (continued)
8 Chapter 1 • Programmatically Creating the Graphical User Interface
Whether you create the GUI using the User Interface Editor or from the
Source Editor, you always start by creating the panel on which you will
place the controls. The panel for this GUI is created at line 8 using the library
function NewPanel.
The NewPanel function creates either a new top-level panel (called the par-
ent panel) or a child panel within a parent panel. Using the NewPanel function,
you can specify the panel title for this panel and set the panel coordinates,
height, and width. This function returns a panel handle that is assigned
uniquely to this panel and is used when referencing the panel.
The SetPanelAttribute library function on line 12 is used to set the panel at-
tributes: for example, to make the panel movable during program execution.
There are other panel attributes that you can set using the SetPanelAttribute
function. To understand these attributes, highlight SetPanelAttribute in your
code and select View>>Recall Function Panel (or <Ctrl-P> for short). From
Figure 1–5
SetPanelAttribute Function Panel
Chapter 1 • Programmatically Creating the Graphical User Interface 9
the displayed function panel, click on the Panel Attribute box and Figure 1–5
is displayed, showing the various panel attributes. You can select other panel
attributes from this function panel.
Line 14 creates a new control using the NewCtrl library function. Here a re-
cessed decoration box is created. The NewCtrl function can be used to create
any control on the panel that is normally developed using the Create menu
command from the User Interface Editor. Again, using the function panel
gives you the numerous choices of the available controls and various associ-
ated attributes. The return value of this function (DEC_BOX_CMDS in this
case) is the control identifier used to reference this control from other functions.
The SetCtrlAttribute library function is used to set the attributes of the con-
trol. When you create a GUI using the User Interface Editor, you select the
attributes of the control from the controls attribute dialog box. At lines 17–21
the attributes of the decoration box are set using these functions. The attrib-
utes configured here are the horizontal position, height, width, and color of
the decoration box. Notice that the control identifier DEC_BOX_CMDS for
the decoration box created at line 14 is used in all SetCtrlAttribute function
calls to reference this decoration box.
The START square command button is created at line 25 at vertical and hor-
izontal coordinates 200 and 100, respectively, using the NewCtrl library func-
tion. The label assigned to this command button is “START,” with “<F1>” on
the next line on the command button below “START.” Line 30 assigns the
width of the command button, and lines 34–40 set the color, label, and font
style for this command button. At line 40, “metafonts” is used for the font type.
Metafonts are scalable fonts that are independent of the monitor screen resolu-
tion. Line 43 assigns the shortcut key F1 to the START command button.
The InstallCtrlCallback library function at line 32 assigns the user-defined
callback function StartGUICB to the START command button. Whenever
you click on the START command button, the StartGUICB function is called.
This is similar to when you assign the callback function name by entering it
in the Callback Function box of the control using the User Interface Editor.
To disable (dim or gray-out) the control, assign a value of 1 to the value of
ATTR_DIMMED in the SetCtrlAttribute function, as shown on line 47. Simi-
larly, lines 50–67 create and set the attributes for the EXIT command button.
The callback function ExitGUICB is assigned to this control.
Lines 71–76 create another decoration box, where you will add a ring con-
trol. Lines 82 and 83 create a new ring control at the specified location with the
assigned width. A callback function RingCB is assigned to this control at line
86. On lines 88–90 three list items are added to the ring using the library func-
tion InsertListItem. Note that the library functions for the ring control are the
10 Chapter 1 • Programmatically Creating the Graphical User Interface
same as for list box control. List box functions, though, have more capabilities
than do ring control functions. The three functions that are listed in the Select
Function ring control, namely, Sine Pattern, Uniform Random Numbers,
and White Noise, will be plotted on the graph control shown later in this sec-
tion. These functions are part of the CVI Advanced Analysis Library package
that is part of the full CVI package, as mentioned earlier. If you do not have
the full CVI package, you can substitute your own functions here.
A decoration box to place the graph control is created at line 98 and its at-
tributes set at lines 101–104. The graph control is created using the NewCtrl
function at line 107. The labels for the X and Y axes are created using the
SetCtrlAttribute function at lines 112–114.
In this project three different graphs will be plotted on the same graph
control. If the graph is not cleared, these functions will be plotted over each
other. Creating the CLEAR command button will give you the option to
clear the graph before plotting another graph. The CLEAR command button
is created at line 119 and its attributes assigned at lines 122–139.
At line 141 the SetPanelAttribute library function causes the panel to
close and quits the project when you click on the “X” box on the top right
corner of the panel window. This is accomplished by setting the panel at-
tribute to ATTR_CLOSE_CTRL and pointing to the control ID of the com-
mand that will receive the commit event when the “X” box is selected. The
control ID for this command is entered as the last argument in the SetPanel-
Attribute function. In this project the EXIT command button is assigned to
closing the panel and exiting the project. Therefore, the control ID of the
EXIT command button (GUI_EXIT_ID) is entered as the last argument in
the SetPanelAttribute function.
RingCB Function
When you click on the Select Function ring control to select a function for
which you want to display the data on the text box or plot on the graph con-
trol, the RingCB function is called. The listing for the RingCB function is
shown in Figure 1–6. Here the START command button is enabled. To dis-
play the data or plot the graph for the function selected, select START from
the GUI to invoke the callback function StartGUICB.
StartGUICB Function
Recall that when you created the START command button above, you had dis-
abled it using the SetCtrlAttribute function. The reason is that the user must first
make a selection from among one of the functions in the ring control before
Chapter 1 • Programmatically Creating the Graphical User Interface 11
Figure 1–6
RingCB Function Listing
he/she can plot on a graph control. In this project you have a choice from
among the Sine Pattern, Uniform Random Numbers, White Noise functions,
as shown in Figure 1–7. When Uniform Random Numbers is selected from the
Select Function ring control, data is displayed on the text box. To plot this data
on the graph control, select the PLOT command button that replaces the
Figure 1–7
Select Function Control Pull-Down List
12 Chapter 1 • Programmatically Creating the Graphical User Interface
CLEAR command button on the GUI. When Sine Wave and White Noise are
selected from the Select Function ring control, the graph is plotted without dis-
playing the data.
Upon selecting one of these functions, the RingCB callback function that
was assigned to the ring control is invoked and enables the START com-
mand button. The listing for the StartGUICB function is shown in Figure 1–8.
Figure 1–8
StartGUICB Function Listing (continued)
Chapter 1 • Programmatically Creating the Graphical User Interface 13
Figure 1–8
StartGUICB Function Listing (continued)
14 Chapter 1 • Programmatically Creating the Graphical User Interface
94 //Display Header
95 Fmt(buf,"%s<Samples Value");
96 InsertTextBoxLine(GUI_Handle, TEXT_BOX_ID,-1, buf);
97
98
99 for (i=0;i< samples;i++){
100 Fmt(buf,"%s< %d %f", i, Y_axis[i]);
101 InsertTextBoxLine(GUI_Handle, TEXT_BOX_ID,-1, buf);
102
103 }
104
105 break;
106 case 2: // White Noise
107 amp=5.0;
108 samples=50;
109 seed=15;
110 WhiteNoise(samples, amp, seed, Y_axis);
111 PlotHandle = PlotY (GUI_Handle, GRAPH_ID, Y_axis,
112 samples, VAL_DOUBLE,
113 VAL_CONNECTED_POINTS,
114 VAL_ASTERISK, VAL_SOLID, 1,
115 VAL_WHITE);
116 break;
117 default:
118 printf("Error in Ring control selection\n");
119 break;
120
121 } //switch(SelectedIndex)
122 //Enable the CLEAR command button
123 SetCtrlAttribute (GUI_Handle, CLEAR_PLOT_ID, ATTR_DIMMED, 0);
124 break;
125 }
126 return 0;
127 }//StartGUICB
Figure 1–8
StartGUICB Function Listing (continued)
At line 11 a text message box is created using the NewCtrl function. This
text message box will display the header “PLOT FOR “ on the graph decora-
tion box just above the graph control. The index of the function selected to
plot is obtained from ring control at line 15 using the GetCtrlIndex function.
This index is used as an argument in the GetLabelFromIndex function to obtain
the label of the item selected.
This label is created and displayed at line 19 as a text message on the
graph decoration box next to the “PLOT FOR “ text message control. At line
21 the index from the ring control determines the function to plot. When
White Noise is selected, lines 106-116 are executed, calling the Advanced
Analysis Library function WhiteNoise.
Chapter 1 • Programmatically Creating the Graphical User Interface 15
When Uniform Random Numbers is selected from ring control, the pro-
gram executes at line 28. In this section of code the graph control will be hid-
den, a new text box control created in the same location as the graph control,
and the uniform random numbers displayed on this text box. The CLEAR
command button is hidden and a PLOT command button is created in its
place. When the PLOT command button is selected, the text box is hidden
and the graph control made visible with the plot of the random numbers
that were displayed on the text box. Let us look at how this is accomplished
by going through the code.
At line 30, a text message label ”DATA FOR:” is displayed on the graph
decoration box, the graph control is hidden at line 33, and a new text box
control is created at line 36 over the graph control. The attributes for this text
box are configured at lines 39–55. A square command button with the label
“Plot” is created at line 63 over the CLEAR command button that is made
invisible at line 59. The PlotUniformCB callback function is assigned to the
PLOT command button at line 71. The remaining attributes for the PLOT
command button are set between lines 74 and 85.
Lines 90–101 are used to set the sample size and the seed, to display the
header, and to generate the uniform random numbers using the library
function Uniform at line 93. The Uniform function creates random numbers in
the array Y_axis that are distributed uniformly between 0 and 1.
At line 123 the CLEAR command button is enabled. After the data values
are displayed on the text box, you can plot the data on the graph control by
selecting the PLOT command button.
When the index for the Sine Wave function is selected, the user-defined
function CreateDisplayDataPanel at line 24 is called. This function creates a
child panel with the controls where the user can specify the values for the
various parameters of the Sine Wave plot. The listing for the CreateDisplay-
DataPanel function is shown in Figure 1–9.
The child panel created by the function CreateDisplayDataPanel is shown in
Figure 1–10 and is titled SELECT DATA. Let us look how each of these con-
trols is created and their attributes assigned by examining the CreateDisplay-
DataPanel code listing.
At line 10 the NewPanel function creates the child panel with the dimen-
sions and location specified on the parent panel with the panel handle
Child_Handle. Notice that the first argument of the NewPanel function is
the name of the parent panel. Thus the new panel will be created on this
panel as a child panel.
16 Chapter 1 • Programmatically Creating the Graphical User Interface
Figure 1–9
CreateDisplayDataPanel Function Listing (continued)
Chapter 1 • Programmatically Creating the Graphical User Interface 17
Figure 1–9
CreateDisplayDataPanel Function Listing (continued)
18 Chapter 1 • Programmatically Creating the Graphical User Interface
Figure 1–10
SELECT DATA Child Panel
Lines 16–30 create a numeric control with the label Samples. This control
will receive data of type integer, then set the control mode to Hot, the de-
fault value to 20, the minimum value to 1, and the maximum value to 1000.
At line 32 the callback function SamplesControlCB is invoked whenever the
value in the Samples control is changed. The SamplesControlCB function is
explained below.
Similarly, at lines 35–48 another numeric control with the attributes speci-
fied and the label Amplitude is created.
Lines 51–65 create a horizontal slider with the label Phase, to enter a
phase value between 0.0 and 180.0.
To enter the number of cycles, a knob control is created at lines 68–84 with
the label Cycles, the default value is set to 2, and the minimum and maxi-
mum values are displayed on Cycles control knob.
When all the data has been entered on this panel, you need to click on the
DONE command button that is created at lines 90–101. This command button
is assigned a callback function DoneGUICB that accepts the data entered and
plots the graph. The listing for DoneGUICB function is given in Figure 1–12
and explained in that section.
Chapter 1 • Programmatically Creating the Graphical User Interface 19
SamplesControlCB Function
The SamplesControlCB function is called when the Samples control box on
the SELECT DATA panel (Figure 1–10) is selected. This function obtains
the new value from the Samples control and sets this as the new maxi-
mum value of the Cycles control knob. Setting this value on the Cycles
knob ensures that the cycles value cannot be greater than the samples
value, thus avoiding a possible run-time error. The default value of the
Cycles control is always initialized to 2. You can change this value from
the Cycles knob if you desire. This listing for the SamplesControlCB func-
tion is given in Figure 1–11.
DoneGUICB Function
The DoneGUICB function is called when you select the DONE command
button on the SELECT DATA panel (Figure 1–10). The DoneGUICB function
listing is shown in Figure 1–12.
The values entered in the SELECT DATA panel are obtained using the
GetCtrlAttribute function. Here you could also have used the GetCtrlVal li-
brary function instead to obtain the same values. Control attributes have
{
switch (event)
{
case EVENT_COMMIT:
//Get the samples value
GetCtrlVal(Child_Handle, SAMPLES_ID, &samples);
//Cycles must be less than samples
GetCtrlAttribute (Child_Handle, SAMPLES_ID, ATTR_CTRL_VAL, &samples);
//Set Maximum value of Cycles control to samples value
SetCtrlAttribute (Child_Handle, CYCLES_ID, ATTR_MAX_VALUE, samples);
//You can select the cycles by changing the value on the user interface
SetCtrlVal(Child_Handle, CYCLES_ID,2); //Set Cycles to 2
break;
}
return 0;
}//SamplesControlCB
Figure 1–11
SamplesControlCB Function Listing
20 Chapter 1 • Programmatically Creating the Graphical User Interface
Figure 1–12
DoneGUICB Function Listing
different data types and different valid ranges, which are given in detail in
the LabWindows/CVI User Interface Reference Manual and are available through
On-line Help.
To retrieve the value of the control, ATTR_CTRL_VAL is used for the control-
Attribute argument in the GetCtrlAttribute function. The values of the controls
are obtained using this function at lines 10–13. At line 15 the library function
SinePattern takes the values entered in the SELECT DATA panel as its argu-
ments and creates a data array in the variable Y_axis. The child panel is hid-
den at line 16 and the data is plotted using line 18 on the graph control on the
parent panel using the PlotY function. The function SinePattern is part of the
CVI Advanced Analysis Library functions.
The PlotY function plots the values of an array on the y-axis against the
array indices on the x-axis on the graph control. The Sine Wave plot is shown
in Figure 1–13 with the following selections from the SELECT DATA panel:
Samples 25
Amplitude 5.0
Phase 0.0
Cycles 2.0
Chapter 1 • Programmatically Creating the Graphical User Interface 21
Figure 1–13
Sine Wave Sample Run
ClearGraphCB Function
To delete the plot on the graph control, select the CLEAR command button.
This will also hide the text message boxes on the graph decoration box and
display the text messages when the next selection from the ring control is
made. The listing for the callback function ClearGraphCB associated with the
CLEAR command button is shown in Figure 1–14.
At line 8 the DeleteGraphPlot library function deletes one or all of the
plots from the graph control. You can delete all the plots on the graph con-
trol by entering –1 in the third argument of the DeleteGraphPlot function.
The RefreshGraph library function shown on line 10 redraws the plot area
immediately. The SetCtrlAttribute functions on lines 12 and 13 hide the
text message boxes on the graph decoration box in order for the new mes-
sages to be displayed.
22 Chapter 1 • Programmatically Creating the Graphical User Interface
Figure 1–14
ClearGraphCB Function Listing
PlotUniformCB Function
The listing for the callback function PlotUniformCB associated with the
PLOT command button is shown in Figure 1–15.
At line 10 the CLEAR command button is made visible and the PLOT
command and text message for the text box are discarded at lines 12 and 14.
The graph control is made visible at line 16 and the text box is hidden at line
18. Line 23 plots the uniform random numbers displayed on the text box
using the PlotY library function.
ExitGUICB Function
The ExitGUICB callback function is selected when the EXIT command but-
ton is selected. The listing for ExitGUICB is shown in Figure 1–16.
Summary
This chapter gave you an overall idea of how to use the CVI library functions to
create a GUI using the Source Editor entirely. In this chapter you learned how
to create the GUI programmatically without using the User Interface Editor.
Chapter 1 • Programmatically Creating the Graphical User Interface 23
Figure 1–15
PlotUniformCB Function Listing
Figure 1–16
ExitGUICB Function Listing
24 Chapter 1 • Programmatically Creating the Graphical User Interface
The library functions explaining the various features were shown by means of
examples in the code listing. Many aspects of changing control attributes were
introduced, opening the way for you to experiment with the various features of
the controls and library functions. A blend of creating most of the controls from
the User Interface Editor and manipulating controls programmatically may
seem most desirable, depending on your application.
DeleteGraphPlot Function
The DeleteGraphPlot function deletes one or more plots from a graph control.
Its prototype is shown below and its arguments described in Table 1–1.
Input/
Output Name Type Description
The refresh argument allows you to select when to delete the plot from the
graph control. It consists of the following choices:
DiscardPanel Function
The DiscardPanel function removes from memory the panel displayed and
clears it from the screen if visible. Its prototype is shown below and its argu-
ments described in Table 1–2.
Input/
Output Name Type Description
NewCtrl Function
The NewCtrl function creates a new control and returns a control identifier
that you can use in subsequent function calls. Its prototype is shown below
and its arguments described in Table 1–3.
controlTop and controlLeft positions are referenced from the top left corner of
the panel just below the panel’s title bar. These coordinates of the control ap-
pear before the panel is scrolled.
NewPanel Function
The NewPanel function creates a new panel and returns a panel handle that
is used in subsequent function calls to refer to this panel. Its prototype is
shown below and its arguments described in Table 1–4.
Input/
Output Name Type Description
■ panelVerticalCoord. For the parent panel this is referenced from the top
left corner of your screen and is the vertical distance at which to place
the upper left corner of the panel.
■ panelHorizontalCoord. For the parent panel this is referenced from the
top left corner of your screen and is the horizontal distance at which to
place the upper left corner of the panel.
To center either the parent panel or the child panel, use VAL_AUTO_CENTER.
28 Chapter 1 • Programmatically Creating the Graphical User Interface
PlotY Function
The PlotY function plots an array of y values against its indices along with
the x-axis on a graph control. Its prototype is shown below and its argu-
ments described in Table 1–5.
Input/
Output Name Type Description
(continued)
Chapter 1 • Programmatically Creating the Graphical User Interface 29
lineStyle integer line style to use for the plot from the
following selection:
■ VAL_SOLID
■ VAL_DASH
■ VAL_DOT
■ VAL-DASH_DOT
■ VAL_DASH_DOT_DOT
Output plotHandle integer handle for the plot for possible use in
subsequent reference to DeleteGraphPlot,
SetPlotAttribute, and GetPlotAttribute
functions
30 Chapter 1 • Programmatically Creating the Graphical User Interface
RefreshGraph Function
The RefreshGraph function redraws the graph. Its prototype is shown below
and its arguments described in Table 1–6.
SetPanelAttribute Function
The SetPanelAttribute function sets the value of a particular panel prototype.
Its prototype is shown below and its arguments described in Table 1–7.
Note that attributeValue has different data types that depend on the panel-
Attribute selected and are displayed when you move your cursor to the
Attribute Value box on the function panel and select <Enter>.
Input/
Output Name Type Description
Input/
Output Name Type Description
Graph controls are useful when you want to display your data in a graphical
format. This chapter explains the graph control attributes, cursor controls,
zooming and panning, and creating graph legends using the toolbox. The
ways to draw geometric objects such as lines, arcs, rectangles, and ovals are
shown using the library functions. Adding text to the graph control is ex-
plained by creating a new metafont based on the existing metafont by
changing the point size and other font attributes. You will see how to enter
any text string on the graph control to label an item on the graph control or
to add the header to the graph control.
34 Chapter 2 • Plotting on Graph Controls
Figure 2–1
project2-1 GUI
Chapter 2 • Plotting on Graph Controls 35
Graph cursor features facilitate better viewing of the data plotted on the
graph control. For example, in this graph control you will use three graph
cursors. The first cursor is located at the x and y coordinates of 25 and 5.0,
respectively, as shown by an open circle on the graph control. An open circle
locates the second cursor at the x and y coordinates of 75 and –5.0 respec-
tively. These are the default cursor locations. During execution of the pro-
gram you will be able to move these cursors using the mouse.
The marker cursor is shown as a cross hair located at the center of the
graph control. You can assign a marker cursor to display the current value of
the data plotted at a certain point on the graph. The marker cursor can be
moved to any specific point on the plot to display the particular value on the
Marker Coordinates indicator control boxes shown on the GUI.
To understand how to set the graph control cursors, double-click on the
graph control and select Cursors… from the Edit Cursors dialog box shown
in Figure 2–2. From this dialog box you can set the number of graph cursors
in the Number of Cursors: box. The number of cursors is limited only by the
memory available. Prior to CVI version 5.5 you were limited to using a max-
imum of 10 cursors. The graph control in project2-1 will use three cur-
sors. By selecting the Cursor Number:, you can set the attributes for that
particular cursor in the following dialog boxes.
The Color: box assigns the color for this graph cursor. The Mode: specifies
the behavior of the cursor and gives you a choice of setting the cursor to Free
Form or Snap to Point. When using Free Form you can move the cursor to
any location inside the plot area. Snap to Point makes the cursor attach to
the nearest data point plotted. Point Style: is the cursor shape that is as-
signed to this cursor on the graph control. You have a choice from among
the selections shown in the pull-down menu in Figure 2–2.
The Cross Hair Style: pull-down menu shown in Figure 2–3 assigns the
available cursor styles. You can experiment with these options and select the
cross-hair style you wish to use.
There are two y-axes associated with a graph. By default only the left
y-axis is used. You can assign the cursor selected to the right y-axis by
checking the Use Right Y Axis. To make the cursor operable, check the
Enabled box.
You can set the attributes for the other graph cursors similarly. Selecting
OK from the Edit Cursors dialog box returns you to the Edit Graph dialog
box shown in Figure 2–4. Constant Name: is the identifier used for the
graph control. Callback Function: UpdateMarkerCB is called whenever an
event is generated on the graph control using the mouse.
36 Chapter 2 • Plotting on Graph Controls
Figure 2–2
Edit Cursors Dialog Box
Figure 2–3
Cross Hair Style: Pull-Down Menu
Chapter 2 • Plotting on Graph Controls 37
Figure 2–4
Edit Graph Dialog Box
38 Chapter 2 • Plotting on Graph Controls
The X-axis…, Left Y-axis…, and Right Y-axis… command buttons shown
in Figure 2–4 all have very similar attributes, and when either one of these
command buttons is selected it brings up an Edit Axis Settings dialog box
similar to that shown in Figure 2–5 when the X-axis… command button is
selected. These axis-setting attributes are described below.
Axis Name: is the name you would like to associate with that axis on the
graph control. This label is displayed next to the assigned axis.
Minimum: and Maximum: values indicate the range you specify for your
value labels on that axis.
Offset: is the number you add to the value label for the axis selected.
Gain: is the factor that you use to multiply the value label. Gain is always
multiplied with the value label first before Offset is added.
By default the Divisions: control box is disabled. To enable the Divisions:
control box, uncheck the Auto Divisions: box. In the Divisions dialog box
you can set the number of tick marks you want displayed on the axis, rang-
ing from 1 to 100. If the Auto Divisions box is checked, the tick marks are
computed and displayed automatically by CVI.
In the Precision: box you can enter the significant decimal points you
want displayed on the assigned axis or set it to Auto in the dialog to be dis-
played automatically by the program.
Figure 2–5
Edit Axis Settings Dialog Box
Chapter 2 • Plotting on Graph Controls 39
greater than or equal to the largest value of all the plots is used for the maxi-
mum value. Similarly, the largest multiple of the loose fit factor that is less than
or equal to the smallest value of all plots is used for the minimum value.
Mark Origin, when checked, marks the tick marks of the origin for the
axis specified.
Let us look at the features of the main function shown in Figure 2–6.
1 /**************************Include files*************************************/
2 #include <cvirte.h>
3 #include <userint.h>
4 #include <ansi_c.h>
5 #include <analysis.h>
6 #include "project2-1.h"
7
8 /***************** Function prototype ***********************************/
9
10 void DisplayCursorPosition(void);
11
12 /***************************************************************************/
13 static int GraphPanelHandle;
14 double X_StartMin,X_StartMax,Y_StartMin, Y_StartMax;
15 int ScaleMode;
16
17 //Main function
18 int main (int argc, char *argv[])
19 {
20
21 if (InitCVIRTE (0, argv, 0) == 0)
22 return -1;
23 //Load panel and obtain panel handle
24 if ((GraphPanelHandle =LoadPanel (0, "project2-1.uir", CURSORS)) < 0)
25 return -1;
26
27 //Display the panel
28 DisplayPanel (GraphPanelHandle);
29
30 //Store the Starting Axis values for display before any zoom
31 GetAxisScalingMode (GraphPanelHandle, CURSORS_GRAPH, VAL_XAXIS, &ScaleMode,
32 &X_StartMin, &X_StartMax);
33
34 GetAxisScalingMode (GraphPanelHandle, CURSORS_GRAPH, VAL_LEFT_YAXIS,
35 &ScaleMode, &Y_StartMin, &Y_StartMax);
36 RunUserInterface();
37
38 //Discard panel and release resources
39 DiscardPanel (GraphPanelHandle);
40 CloseCVIRTE ();
41
42 return 0;
43 } //main
Figure 2–6
project2-1 Header and main Function Listing
Chapter 2 • Plotting on Graph Controls 41
Figure 2–7
PlotData Function Listing
42 Chapter 2 • Plotting on Graph Controls
if (event == EVENT_COMMIT)
{
//Update the marker values on the panel
DisplayCursorPosition ();
}
return 0;
}//UpdateMarkerCB
Figure 2–8
UpdateMarkerCB Function Listing
Figure 2–9
DisplayCursorPosition Function Listing
44 Chapter 2 • Plotting on Graph Controls
Figure 2–10
SelectZoomCB Function Listing (continued)
Chapter 2 • Plotting on Graph Controls 45
Figure 2–10
SelectZoomCB Function Listing (continued)
Figure 2–11
Zoom Control Label/Value Pairs
46 Chapter 2 • Plotting on Graph Controls
Figure 2–12
Legend Control Function Panel
Figure 2–13
project2-2 GUI
plot samples along with an explanation of the legend items. This function
also enables the REMOVE ALL, INSERT ITEM, and DELETE ITEM com-
mand buttons. Each of the library functions to create and control the leg-
end is discussed below.
The LGCreateLegendControl library function at line 9 creates the legend
control. You will see below how to change the legend control attributes
using the library function LGSetLegendCtrlAttribute.
At line 9 (Figure 2–14) the relative position of the legend control was spec-
ified at the center, below the anchor control. Line 12 uses the LGSetLegend-
CtrlAttribute function to move the legend control 25 pixels down from the
anchor control.
The LGSetLegendCtrlAttribute sets the attributes of the legend control. At line
18 the LGSetLegendCtlrAttribute enables autosizing of the legend control. If you
prefer to make the legend control border visible, use the SetCtrlAtrribute func-
tion to enable ATTR_BORDER_VISIBLE, as shown on line 15 (Figure 2–14).
Chapter 2 • Plotting on Graph Controls 49
Figure 2–14
AddLegendCB Listing
Figure 2–15
project2-3 Graph Plots GUI
Figure 2–16
Select Plot Ring Control
Figure 2–17
Select Color Control
52 Chapter 2 • Plotting on Graph Controls
Figure 2–18
Line Plotting and Text Sample
Chapter 2 • Plotting on Graph Controls 53
Figure 2–19
TEXT ENTRY and Font Attributes GUI
Figure 2–20
Existing Metafont Selections
The text is displayed on the top of the graph control in Figure 2–18 using
the metafont created and attributes selected. Examine the source code for
the main function as shown in Figure 2–21. The project2-3.uir GUI is
loaded and displayed at lines 30 and 33, respectively. This GUI is shown in
Figure 2–15. The panel is discarded at line 36 using the library function
DiscardPanel, which takes the panel handle as its only argument.
54 Chapter 2 • Plotting on Graph Controls
1 /*******************Include files***************************/
2 #include <formatio.h>
3 #include <cvirte.h>
4 #include <userint.h>
5 #include <ansi_c.h>
6 #include <analysis.h>
7 #include "project2-3.h"
8 #include "TextEntry.h"
9 #include "angleselect.h"
10
11 /***************** Function prototype *******************/
12
13 void DisplayCursorPosition(void);
14
15 /**********************************************************/
16 static int GraphPanelHandle, ArcPanelHandle, TextPanelHandle;
17 double X_StartMin,X_StartMax,Y_StartMin, Y_StartMax;
18 static double X1_Position, X2_Position;
19 static double Y1_Position, Y2_Position;
20 int SelectedColor, FillColor, StartPlotFlag=0;
21
22 #define Marker 1
23
24 //Main function
25 int main (int argc, char *argv[ ])
26 {
27 if (InitCVIRTE (0, argv, 0) == 0)
28 return -1;
29 //Load panel and obtain panel handle
30 if ((GraphPanelHandle =LoadPanel (0, "project2-3.uir", PLOTS)) < 0)
31 return -1;
32 //Display the panel
33 DisplayPanel (GraphPanelHandle);
34 RunUserInterface();
35 //Discard panel and release resources
36 DiscardPanel (GraphPanelHandle);
37 CloseCVIRTE ();
38 return 0;
39 } //main
Figure 2–21
main Function Source Code Listing
Figure 2–22
UpdateMarkerCB Source Code Listing (continued)
56 Chapter 2 • Plotting on Graph Controls
Figure 2–22
UpdateMarkerCB Source Code Listing (continued)
Line 11 selects the index of the shape to plot from the Select Plot control.
The color used for the plot is selected from the color palette in the Select
Color control at line 12. If you would like to fill the object with the color se-
lected, click on the Fill Color toggle button. The value for the Fill Color tog-
gle button is obtained at line 15. Based on the Select Plot index selected, the
appropriate item is plotted using the library functions explained below.
The StartPlotFlag is checked to distinguish between the first or second
time the mouse is right-clicked. If the mouse is right-clicked the first time
and the Plot Text is not selected, the library function GetGraphCursor is
called at line 23 to capture the starting x and y positions of the graph marker
in the variables X1_Position and Y1_Position. When the graph marker
is moved to another position and the right mouse button is clicked again,
lines 31–65 are executed and the ending plot position is saved in the vari-
ables X2_Position and Y2_Position using the GetGraphCursor at line 31.
To plot a line, the PlotLine library function is called at line 38. This func-
tion plots the line on the graph control between the starting and ending
points using the color selected.
If you want to plot an arc on the graph control, you will need the starting
angle and the sweep angle of the arc to define its shape. You will also need
to enter the starting and ending coordinates which define the two opposite
corners of the rectangle that enclose the arc. When Arc Plot is selected from
the Select Plot control, the Arc Plot Angles GUI shown in Figure 2–23 is dis-
played by means of the InstallPopup library function at line 44. You enter the
Chapter 2 • Plotting on Graph Controls 57
Begin Angle (starting angle) and the Arc Angle (sweep angle) values in this
GUI that are used in the PlotArc library function. Begin Angle and Arc
Angle are used in the PlotArc library function prototype.
When OK is selected from Arc Plot Angles GUI (Figure 2–23), the Angles-
SelectedCB callback shown in Figure 2–24 is invoked. The Begin Angle and
Arc Angle values are obtained from the Arc Plot Angles GUI and used in
the PlotArc library function at lines 14–16. The other arguments for this func-
tion are what you selected from the GUI in Figure 2–18.
Figure 2–23
Arc Plot Angles GUI
Figure 2–24
AnglesSelectedCB Source Code Listing
58 Chapter 2 • Plotting on Graph Controls
To plot a rectangle on the graph control, select Plot Rectangle from the
Select Plot control. The PlotRectangle library function is called at lines 47–49
in Figure 2–22. You plot the rectangle by selecting its two opposite corners.
Lines 52–54 in Figure 2–22 show the library function PlotOval to plot an
oval on the graph control. Selecting the two opposite corners of the rectangle
will define the bounds to plot the oval.
When you plot the objects on the graph control, you may want to annotate
the objects with text. An example of text annotation is shown in Figure 2–25.
This figure shows the various plots created using the library functions that
we discussed above.
To create text on the graph control, first select Plot Text from the Select
Plot control. Move the graph marker to the place on the graph control where
you want to insert the text and right-click using the mouse button. The TEXT
ENTRY GUI is displayed as shown in Figure 2–26. Enter the text in the Enter
Text String: box. Select the Existing Font: by clicking on this control and
choosing from among the available choices shown in Figure 2–20. Select the
attributes of the fonts such as Point Size, Bold, Italics, Underline, Strikeout,
and Color to create the new font with which to write the text string.
Figure 2–25
Sample of Various Plots
Chapter 2 • Plotting on Graph Controls 59
Figure 2–26
TEXT ENTRY GUI
Summary
This chapter showed you the many features of the graph control by means
of projects. You saw how you could use the graph cursors and marker to ob-
tain the value of any point on the plot. You were introduced to the features
of zooming and panning both programmatically and manually. Legends are
useful when you have multiple plots on the graph control to distinguish
among the various plots. You learned how to create legends using the CVI
toolbox. Plotting objects on the graph control and adding text to them comes
in handy in many cases when you do not want to use the legend control but
wish to annotate on the graph control.
60 Chapter 2 • Plotting on Graph Controls
Figure 2–27
TextOKCB Source Code Listing
Chapter 2 • Plotting on Graph Controls 61
CreateMetaFont Function
The CreateMetaFont function creates a new metafont based on a predefined
font. Its prototype is shown below and its arguments described in Table 2–1.
GetAxisScalingMode Function
The GetAxisScalingMode function obtains the scaling mode and the range of
one of the graph axes or the y axis of a strip chart. Its prototype is shown
below and its arguments described in Table 2–2.
Input/
Output Name Type Description
■ VAL_MANUAL. This specifies that the axis is scaled manually, and the
min and max values indicate the low and high ends of the axis range.
■ VAL_AUTOSCALE. This specifies that the axis will be scaled automati-
cally by CVI, depending on the values plotted. The min and max values
are not used. This option is not available for strip charts.
■ VAL_LOCK. This specifies that the axis will be locked and you will not
be able to change the scaling. The axis is locked to the current range
specified. This option is not available for strip charts.
GetGraphCursor Function
The GetGraphCursor function obtains the current position of a specific graph
cursor. The position is relative to the current range of the x and y axes. Its
prototype is shown below and its arguments described in Table 2–3.
GetGraphCursorIndex Function
The GetGraphCursorIndex function obtains the plot handle and array index of
the point to which the cursor is currently attached. Its prototype is shown
below and its arguments described in Table 2–4.
LGCreateLegendControl Function
The LGCreateLegendControl function creates a legend control. Its prototype is
shown below and its arguments described in Table 2–5.
Input/
Output Name Type Description
Input/
Output Name Type Description
The relativePosition argument indicates where the legend control will be placed in
reference to the anchor control. The following are its valid values:
■ LG_POS_DON'T_MOVE 0
■ LG_POS_ABOVE_LEFT 1
■ LG_POS_ABOVE_CENTER 2
■ LG_POS_ABOVE_RIGHT 3
■ LG_POS_RIGHT_TOP 4
■ LG_POS_RIGHT_CENTER 5
■ LG_POS_RIGHT_BOTTOM 6
■ LG_POS_BELOW_RIGHT 7
■ LG_POS_BELOW_CENTER 8
■ LG_POS_RIGHT_LEFT 9
66 Chapter 2 • Plotting on Graph Controls
■ LG_POS_LEFT_BOTTOM 10
■ LG_POS_LEFT_CENTER 11
■ LG_POS_LEFT_TOP 12
Note that if the anchorControl is not a valid control, the relativePosition pa-
rameter is ignored and you must set the position of the legend using the
SetCtrlAttribute function. If the anchor control is a graph control or strip
chart, the legend’s background color and border color are taken from the
graph or strip chart.
LGInsertLegendItemForPlot Function
The LGInsertLegendItemForPlot function inserts a legend in a legend control
at the position specified. The plot style, point style, line style, and color of
the sample plot are set to the same values as the plot handle specified. Its
prototype is shown below and its arguments described in Table 2–6.
Input/
Output Name Type Description
LGSetLegendCtrlAttribute Function
The LGSetLegendCtrlAttribute function sets an attribute of the legend control.
Its prototype is shown below and its arguments described in Table 2–7.
The various legend control attributes and their values are listed in Table 2–8.
PlotArc Function
The PlotArc function plots an arc on the graph control. Its prototype is
shown below and its arguments described in Table 2–9.
Input/
Output Name Type Description
Attribute
Attribute Value Type Attribute Value
Input/
Output Name Type Description
PlotLine Function
The PlotLine function plots a line on the graph control. Its prototype is
shown below and its arguments described in Table 2–10.
PlotOval Function
The PlotOval function plots an oval on the graph control. Its prototype is
shown below and its arguments described in Table 2–11.
Input/
Output Name Type Description
Input/
Output Name Type Description
PlotRectangle Function
The PlotRectangle function plots a rectangle on the graph control. Its proto-
type is shown below and its arguments described in Table 2–12.
Input/
Output Name Type Description
PlotText Function
The PlotText function plots a text string on the graph control. Its prototype is
shown below and its arguments described in Table 2–13.
Input/
Output Name Type Description
SetAxisScalingMode Function
The SetAxisScalingMode function sets the scaling mode and the range of ei-
ther one of the axes of a graph, or the Y axis of a strip chart. Its prototype is
shown below and its arguments described in Table 2–14.
Input/
Output Name Type Description
Introduction
DataSocket is an Internet programming technology that allows you to read,
write, and share data between applications on a local computer or a host of
computers on a network using a variety of communication technologies.
DataSocket technology was developed by National Instruments and in-
cluded with the CVI software starting with version 5.5. You do not have to
do anything special to load the DataSocket libraries and the DataSocket
Server since they are installed automatically when you install CVI.
DataSocket Server is an executable that enables the exchange of data be-
tween multiple applications. It receives and stores information from data
sources and relays it to other data targets, whether they are on the same
computer or on other computers connected through a Transmission Control
Protocol (TCP) Ethernet network.
DataSocket provides an easy-to-use high-level interface using the CVI
DataSocket library functions in which the low-level Transmission Control
Protocol/Internet Protocol (TCP/IP) communication protocols are already
established for you. The DataSocket technology is built on top of TCP/IP
and itself has little overhead. DataSocket manages the TCP that is used to
share live data between applications on one computer or between one or
many computers connected through the network via the Internet and re-
spond to multiple users remotely using the Web browser. Live data (also
called streaming data) is the data that is not retrieved from a file or any stor-
age media but is transmitted as soon as it is created.
Using the DataSocket technology, all you need is to open a DataSocket
connection, write data to that connection, simultaneously read the data on
the receiver, and disconnect from the DataSocket when done. There are other
technologies, such as TCP/IP and Dynamic Data Exchange (DDE), that ac-
complish the same objective but require considerable low-level TCP/IP pro-
gramming and are not suitable for live data exchange. DataSocket technology
was designed specifically to transfer the measurement and test data.
data, data values, and data attribute values, including multiple waveforms and
arbitrary data attributes, or any data type supported by DataSocket. Presently
writing to .wav files is not supported, although you can write waveform data
in the DSD format. DataSocket can transfer large data files, as there are no limi-
tations on the size of data to transfer, although performance will tend to de-
crease. The speed of transferring data on the network is limited only by the
network bandwidth and the traffic on the network. The speed of transferring
data between machines connected by 10BaseT Ethernet can be on the order of
320 kB/s.
Figure 3–1
WRITE DATA GUI with DataSocket Server Launched
DataSocket Server. Notice that the Target: control box on WRITE DATA
GUI and Source: control box on READ DATA GUI are both pointing to the
same data source dstp://localhost/wave for both applications to estab-
lish communication.
To start communication between the two applications, click first on the
CONNECT command button on the WRITE DATA GUI and then on the
CONNECT command button on the READ DATA GUI. The data written
to the DataSocket Server by the WRITE DATA project is displayed on the
text box with the time stamp on the WRITE DATA GUI and transferred si-
multaneously to the reader application from the DataSocket Server and dis-
played on the READ DATA GUI. A sample run of this is shown in Figure
3–3. The arrow connections that are indicated in this figure represent the di-
rection of data flow. It is important to understand that these two projects
communicate through the DataSocket Server only and not directly with
each other. project3Send writes the data to the DataSocket Server, and
project3Receive reads the same data from the DataSocket Server.
80 Chapter 3 • Using DataSocket
Figure 3–2
READ DATA GUI
To stop the data transfer, first click on the DISCONNECT command but-
ton on the READ DATA GUI and then on the DISCONNECT command
button on the WRITE DATA GUI. You will notice that data is no longer cre-
ated and updated on both the writer and reader GUIs. To start communica-
tion again, click on the CONNECT command button on the WRITE DATA
GUI and after that the CONNECT command button on the READ DATA
GUI. This will retransmit the data as before.
Figure 3–3
project3 Sample Run Showing Data Path
main Function
Figure 3–4 lists the header and the main function for this project. The data is
transferred using the structure shown on lines 20–24. Two structure members
are used in this application. The random number is stored in the structure mem-
ber data. The count of the number of items written and read will be tracked in
the structure member index, which is a DataSocket attribute of data. Data-
Socket attributes are additional data items that are sent/received in support of
the data. These are customized information items that are used to enhance the
data sent/received along with the data. Attributes may consist of such informa-
tion as the timestamp when the data was acquired, test number, operator name,
number of data items sent/received, data acquisition rate, and so on. Each at-
tribute has a user-defined name by which you can access it, as you will see later
when the UpdateDSCallback function (Figure 3–6) is explained.
82 Chapter 3 • Using DataSocket
1 #include <cvidef.h>
2 #include <cvirte.h>
3 #include <userint.h>
4 #include <cviauto.h>
5 #include <ansi_c.h>
6 #include <utility.h>
7 #include "dataskt.h"
8 #include <formatio.h>
9 #include "Project3Send.h"
10
11 /* This is the callback function prototype for DataSocket */
12 void CVICALLBACK UpdateDSCallback (DSHandle DSWriteHandle, int event, void *callbackData);
13 int Checkerror(int ); //Checks error of datasocket functions
14 static int WritepanelHandle;
15 static DSHandle DSWriteHandle = 0;
16 HRESULT error;
17 char errorBuf[260];
18
19 //Structure to write data
20 typedef struct WriteDataStruct
21 {
22 short data; //random number
23 short index; //counter
24 } WriteDataStruct;
25 WriteDataStruct WriteData;
26
27 //Main function
28 int main (int argc, char *argv[])
29 {
30 if (InitCVIRTE (0, argv, 0) == 0) /* Needed if linking in external compiler; harmless
31 otherwise */
32 return -1; /* out of memory */
33 if ((WritepanelHandle = LoadPanel (0, "Project3Send.uir", WRT)) < 0)
34 return -1;
35 DisplayPanel (WritepanelHandle);
36 //Start the DataSocket Server
37 error =DS_ControlLocalServer (DSConst_ServerLaunch);
38 Checkerror(error);
39
40 RunUserInterface ();
41 //Close the DataSocket Server
42 error = DS_ControlLocalServer (DSConst_ServerClose);
43 Checkerror(error);
44 return 0;
45 }// main
Figure 3–4
project3Send Header and main Function
in this function. You can hide or display the DataSocket Server using
DSConst_ServerHide or DSConst_ServerShow argument in this function,
respectively. Checking for errors makes the program more robust and is done
throughout this project by the user-defined function Checkerror(error). If there
is an error, the library function DS_GetLibraryErrorString is called in the
Checkerror(error) function to convert the integer value passed in error to a
meaningful string that is displayed on the GUI.
Figure 3–5
project3Send ConnectCB Callback Function
84 Chapter 3 • Using DataSocket
You can update the data written to or read from the data source in either
the AutoUpdate mode or the non-AutoUpdate mode. You can control when
you want to send or receive data from the server. When writing data in the
AutoUpdate mode the most recent data is sent to the server immediately.
When reading data in the AutoUpdate mode, the most recent data is re-
trieved from the server immediately. Use the non-AutoUpdate mode when
you want the data sent or received per your request. Use the non-Auto-
Update mode when you want data synchronized with its attributes. When
connecting to other data sources besides DataSocket Servers (dstp) or OPC
Servers (opc) it is advisable to connect in non-AutoUpdate mode. If you are
connecting to OPC Servers, non-AutoUpdate mode allows for better error
checking and more control over the communication between your applica-
tion and the OPC Server. However, if you are connecting to multiple items
on the OPC Server, your application will run faster in the AutoUpdate mode
since the OPC Server sends all the item changes at once.
In the code for the ConnectCB function, the second argument, DSConst_
Write, in the DS_Open function configures the data object for updating data
manually. Whenever DataSocket data is updated or the status of the connec-
tion between a DataSocket object and its DataSocket data source is changed,
the DataSocket object invokes and executes the code in the callback function
specified in the third argument of the DS_Open function (Update-
DSCallback in this case). The UpdateDSCallback function is discussed in the
next section. The status of the DataSocket object can be one of the following
conditions:
■ The DataSocket object is not connected to any data source or data target.
■ The DataSocket object is in the process of transferring data or waiting
for an update.
■ The DataSocket object has connected to the data source and transferred
the data.
■ The DataSocket object encountered an error connecting to the data
source or target.
The callbackData parameter contains the value that you pass to this
callback function. In the listing shown in Figure 3–6, the DS_EVENT_STATUS-
UPDATED event is used. The library function DS_GetLastMessage returns a
string containing a description of either the last communication error, last
data update, or last interaction between the DataSocket object and the
DataSocket data source. This message is displayed in the Error/Status: con-
trol box on the GUI (Figure 3–1).
switch (event) {
case DS_EVENT_STATUSUPDATED: /* on status updated*/
//Obtain the last message and update the message box
error =DS_GetLastMessage (DSWriteHandle, message, 1000);
Checkerror(error);
SetCtrlVal (WritepanelHandle, WRT_STATUS, message);
break;
}
}//UpdateDSCallback
Figure 3–6
UpdateDSCallback Function
86 Chapter 3 • Using DataSocket
Figure 3–7
TimerCallback Function
Chapter 3 • Using DataSocket 87
Figure 3–8
DisconnectCB Function
file:../directoryName/filename.dsd
This string is created at line 32 and is displayed on the Target: control box on
the WRITE DATA GUI. The DS_Open function uses this string for the URL
argument to inform the DataSocket Server to write the data to this file. The
data is written to a data socket file that you entered for the file name in the
pop-up panel above. The file name is appended with a .dsd extension.
1 //Write data to file. Invoked when the "WRITE FILE" command button is selected
2 int CVICALLBACK WriteToFileCB (int panel, int control, int event,
3 void *callbackData, int eventData1, int eventData2)
4 {
5
6 char prjDir[261], FileURL[261], dirName[261], DSFileName[261];
7 short len;
8 int nPrevState;
9 switch (event)
10 {
11 case EVENT_COMMIT:
12 len =0;
13 do
14 {
15 //Enter file name to write data
16 PromptPopup ("DATASOCKET FILE NAME",
17 "Enter the file name to write data (no extension)", DSFileName, 260);
18
19 len = strlen (DSFileName);
20 //Check file name entered is at least one character long
21 } while (len ==0 );
22
23 SetCtrlVal(WritepanelHandle, WRT_SOURCE, "");
24 GetProjectDir(prjDir);
25 nPrevState= SetBreakOnLibraryErrors(0);
26 sprintf(dirName, "%s\\datafiles",prjDir);
27 //Make the directory
28 if ( SetDir(dirName) !=0) MakeDir (dirName);
29 SetBreakOnLibraryErrors(nPrevState);
30 SetDir(dirName); //Set the path
31 //Create the path name to write to ".dsd" file
32 sprintf(FileURL,"file:../datafiles/%s.dsd",DSFileName);
33 SetCtrlVal(WritepanelHandle, WRT_SOURCE, FileURL);
34 }
35 return 0;
36 } //WriteToFileCB
Figure 3–9
WriteToFileCB Function
90 Chapter 3 • Using DataSocket
main Function
The file header and the main function for project3Receive.c are shown
in Figure 3–10. Notice that in Figure 3–3 the data source name used in the
Source: control for this GUI is the same as in the Target: control box of the
WRITE DATA GUI, so both DataSocket applications (writer and reader) are
pointing to the same data source.
#include <cvidef.h>
#include <cviauto.h>
#include <dataskt.h>
#include <formatio.h>
#include <ansi_c.h>
#include <cvirte.h>
#include <userint.h>
#include <utility.h>
#include "project3Receive.h"
// Structure to Read
typedef struct WriteDataStruct
{
short data;
short index;
} WriteDataStruct;
Figure 3–10
project3Receive Header and main Function (continued)
Chapter 3 • Using DataSocket 91
//Function prototype
void CVICALLBACK DSCallback(DSHandle DSReadHandle, int event, void *callbackData);
//main function loads the GUI and launches the DataSocket server
int main (int argc, char *argv[])
{
if (InitCVIRTE (0, argv, 0) == 0)
return -1; /* out of memory */
if ((PanelHandle = LoadPanel (0, "project3Receive.uir", DS_READ)) < 0)
return -1;
DisplayPanel (PanelHandle);
RunUserInterface ();
return 0;
} //main
Figure 3–10
project3Receive Header and main Function (continued)
Figure 3–11
ConnectReadCB Function
Chapter 3 • Using DataSocket 93
1 //This callback function is executed whenever the data or the status changes
2 void CVICALLBACK DSCallback(DSHandle DSReadHandle, int event, void *callbackData)
3 {
4 char msg[1000];
5 unsigned int StringLen;
6
7
8 switch(event)
9 {
10 case DS_EVENT_DATAUPDATED:
11 errorCode = DS_GetDataType (DSReadHandle, NULL, &StringLen, NULL);
12
13 if (StringLen ==0) //No data received
14 {
15 MessagePopup ("DATASOCKET ERROR",
16 "No data received. Connect Write DataSocket first");
17 //Wait a while for the operator to enable the DataSocket Writer
18 Delay (3.0);
19 //Disable DISCONNECT button
20 SetCtrlAttribute (PanelHandle, DS_READ_DISCONNECT,
21 ATTR_DIMMED, 1);
22 //Enable CONNECT button
23 SetCtrlAttribute (PanelHandle, DS_READ_CONNECT ,
24 ATTR_DIMMED, 0);
25 return;
26 }
27 else
28 ReadString= malloc(StringLen +1);
29
30
31 //Get the string from DataSocket Writer
32 errorCode = DS_GetDataValue (DSReadHandle, CAVT_CSTRING,
33 ReadString, StringLen+1, 0, 0);
34 Checkerror(errorCode);
35
36 //Get the index value from DataSocket Writer
37 errorCode = DS_GetAttrValue (DSReadHandle, "Index", CAVT_SHORT,
38 &WriteData.index, sizeof(short), 0, 0);
39 Checkerror(errorCode);
40
41 //No errors, write data
42 if (errorCode>=0)
43 {
44 InsertTextBoxLine(PanelHandle,DS_READ_RD_DSP, -1, ReadString);
45
46 SetCtrlVal(PanelHandle, DS_READ_INDEX,WriteData.index);
47 }
48
49 //Enable DISCONNECT button
50 SetCtrlAttribute (PanelHandle, DS_READ_DISCONNECT,
51 ATTR_DIMMED, 0);
52 //Disable CONNECT button
Figure 3–12
DSCallback Function (continued)
94 Chapter 3 • Using DataSocket
Figure 3–12
DSCallback Function (continued)
file:..//directoryName/filename.dsd
This string is written to the Source: control box on the READ DATA GUI.
When the CONNECT command button on this GUI is selected, this string
from the Source: control box is retrieved and entered in the DS_Open library
function and the connection established with this data source. While the
writer is writing the data to the file constantly, you can click on UPDATE
command button on the READ DATA GUI to obtain the latest value written
to the data socket file.
96 Chapter 3 • Using DataSocket
switch (event)
{
case EVENT_COMMIT:
GetProjectDir(ProjectDir);
sprintf(Directory, "%s\\datafiles", ProjectDir);
FileSelected = FileSelectPopup (Directory, "*.dsd", "","SELECT
DATASOCKET FILE", VAL_LOAD_BUTTON, 0, 1, 1, 0,
SelectedDataSocketPath);
sprintf(FileSource,"file:../datafiles/%s",SelectedFile);
SetCtrlVal(PanelHandle, DS_READ_SOURCE, FileSource);
}
else
SetCtrlVal(PanelHandle, DS_READ_SOURCE, "");
break;
}
return 0;
} //ReadFileCB
Figure 3–13
ReadFileCB Function
//Update Data
int CVICALLBACK UpdateCB (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event)
{
case EVENT_COMMIT:
errorCode=DS_Update(DSReadHandle);
Checkerror(errorCode);
break;
}
return 0;
} //UpdateCB
Figure 3–14
UpdateCB Function
DataSocket Applications
You saw above how the DataSocket could be used for transferring data be-
tween two applications on the same computer. Ideally, you would like to
publish data from one computer to multiple computers on the network. If
you prefer, your data can be published within your company’s domain
using an intranet or to any place in the world using the Internet. An example
of such an application would be to run long tests in a laboratory for which
you would like to view the data periodically at a remote location. You can
set up the computer conducting the test to stream the test data to your com-
puter at a remote location on the network. This same application can be ex-
panded to have multiple clients view the same live test data at different
locations connected across the network.
You can send your live test data to another computer for analysis, prepare
the test results report, and publish it to yet another computer. In this way
you can distribute various tasks across the network. You do not have to
overload one computer with all the tasks and assign only process-intensive
tasks to the computers with faster processors. You can keep the test and
measurement computer inside the Internet firewall by assigning the publish-
ing task to a different computer, preventing clients from gaining access to
the test and measurement computer and keeping your test data secure. A
firewall is a security measure to prevent unauthorized Internet users from ac-
cessing private networks connected to the Internet, such as intranets. Fire-
walls can be implemented in hardware, software, or both.
98 Chapter 3 • Using DataSocket
DataSocket can also be used to post data and reports to clients across the
Internet using a Web server once created in HyperText Markup Language
(HTML) format. This can be advantageous even if your clients are using dif-
ferent operating systems on their machines since Web servers publish data
in a format that is available on most of the common computing platforms.
For example, you can publish your reports on a Web server that is running
on Windows 2000, and post it to the client machine, which may be using a
Linux or Macintosh operating system. Using the Web-based tools, you can
embed animation, graphics, and even sound into your Web page to add en-
hancement to your report.
DataSocket finds its use in monitoring the process variables on the pro-
duction floor and sending the live data to various computers located on the
network. This facilitates in keeping the production manager, who may be
physically located in a different part of the plant, apprised of the current
productivity data. If the floor productivity is not meeting the factory goals,
the manager can take immediate action to solve the problem. This data can
be used to create a periodic report and to send it to upper-level management
through the network.
DataSocket technology has made it possible to take remote measurements
used for monitoring the environment in locations that may be inaccessible or
hazardous to human beings. For example, you can set up a measurement de-
vice in such a location and link it to the client computers located in a safe area,
using an Ethernet connection. The client computer can be used to publish the
Chapter 3 • Using DataSocket 99
Figure 3–15
DataSocket Server Path
Figure 3–16
DataSocket Server
Server Settings
The Server Settings group shown in Figure 3–17 consists of MaxConnections
and MaxItems.
Figure 3–17
DataSocket Server Manager Configuration
Permissions Groups
The Permissions Groups shown in Figure 3–17 consists of the following five
items: Administrators, DefaultReaders, DefaultWriters, Creators, and
Sample Group. These items are defined below.
■ Creators. The Creators can create new data items on the DataSocket
Server. The default host is localhost. Select Add Host to add another
host, as shown above.
■ Sample Group. This is a sample user-defined group. You can create
your own custom group by clicking on the NewGroup button and en-
tering the Description, Name of the group, and Hosts in the dialog
boxes. Figure 3–19 shows the new group MyGroup that we have created
with hosts localhost, labwin.com, and mycomputer.sk.com.
You use localhost and everyhost to refer to special types of hosts. The
DataSocket Server Manager uses an IP address of 127.0.0.1 for localhost to
refer to your local machine, and everyhost is used for communication with
any machine on the Internet. After the Permissions Groups have defined
the hosts that belong to a certain group, you can assign permissions for the
group through the Predefined Data Items discussed next.
Figure 3–18
Setting Up Permission Groups for DefaultReaders
Chapter 3 • Using DataSocket 103
Figure 3–19
MyGroup Permission Group
create your own data items and define which groups have access and the
kind of access they have to that data item(s). To add a new data item, click on
the NewItem button. A dialog window appears, as shown in Figure 3–20.
Enter a short description in the Description box to describe the data item
you are creating. In the Name box enter a descriptive name for the data item.
Click on the Read Access: box to assign the appropriate read permissions from
Figure 3–20
NewItem Creation Dialog Window
104 Chapter 3 • Using DataSocket
the pull-down list. Similarly, click on the Write Access: box to assign the write
permissions for this data item. If you want multiple writers to be able to con-
nect to the DataSocket Server, check the box next to Allow Multiple Writers.
The box next to the Initial Value: gives you a choice from among Boolean,
Number, and String. It is useful to assign an initial value to the data item, as it
aids in determining if your program is communicating with the DataSocket
Server by checking the value of the data item returned. For example, if a
DataSocket Reader is connected and the DataSocket Writer is not connected,
DataSocket returns a zero or an empty string to the Reader. If the default value
that you specified in the Initial Value: dialog box is returned, you know that
the DataSocket connection is good.
Caution: Changes made to the DataSocket Server using the DataSocket Server Manager are
implemented only when you close the DataSocket Server Manager and restart the DataSocket
Server.
Summary
In this chapter you learned how to set up a simple application to transmit
and receive data using the DataSocket technology on a local computer. You
were shown the functions required to open a DataSocket connection, to
transmit data, and to receive data through another application. All the
DataSocket library functions used in the examples were explained. You were
introduced to configuring the DataSocket object in various write and read
modes and the advantages of using each. You were also given a taste of
writing data to and reading data from a DataSocket file. You learned how to
Chapter 3 • Using DataSocket 105
configure the items in the DataSocket Server Manager. Many areas where
DataSocket technology is being used and how it can be used to your advan-
tage were mentioned. DataSocket technology is in its inception stage and is
expanding as the growth of data dissemination across the network and In-
ternet continues to increase rapidly.
DS_ControlLocalServer Function
This function is used to start, close, display, or hide the DataSocket Server
application on a local machine. The DS_ControlLocalServer function proto-
type is shown here and its arguments explained in Table 3–1.
DS_GetAttrValue Function
The data value of a DataSocket objects’s attribute is obtained with this func-
tion. The DS_GetAttrValue function prototype is shown here and its argu-
ments explained in Table 3–2.
Input/
Output Name Type Description
Input/
Output Name Type Description
■ CAVT_DOUBLE
■ CAVT_FLOAT
■ CAVT_LONG
■ CAVT_SHORT
■ CAVT_UCHAR
■ CAVT_CSTRING
■ CAVT_BOOL
■ CAVT_VARIANT
(continued)
Chapter 3 • Using DataSocket 107
Output value void* for type array or string, pass the variable
of large enough size to hold the data
value; for scalar types, pass the address
of the variable to receive the data value
■ String—length of string
■ One-dimensional array—size of first
dimension of array
■ Two-dimensional array—size of first
dimension of array
■ Others—not defined
DS_GetDataType Function
The type of DataSocket object data value is obtained with this function. The
DS_GetDataType function prototype is shown here and its arguments ex-
plained in Table 3–3.
Input/
Output Name Type Description
■ CAVT_DOUBLE
■ CAVT_FLOAT
■ CAVT_LONG
■ CAVT_SHORT
■ CAVT_UCHAR
■ CAVT_CSTRING
■ CAVT_BOOL
■ CAVT_VARIANT
(continued)
Chapter 3 • Using DataSocket 109
DS_GetDataValue Function
The value of the DataSocket object data is obtained with this function. The
DS_GetDataValue function prototype is shown here and its arguments ex-
plained in Table 3–4.
DS_GetLastMessage Function
The status message of the DataSocket object is obtained with this function.
The status message consists of one of the following:
Input/
Output Name Type Description
■ CAVT_DOUBLE
■ CAVT_FLOAT
■ CAVT_LONG
■ CAVT_SHORT
■ CAVT_UCHAR
■ CAVT_CSTRING
■ CAVT_BOOL
■ CAVT_VARIANT
Output value void* for type array or string, pass the variable
of large enough size to hold the data
value; for scalar types, pass the address
of the variable to receive the data value
■ String—length of string
■ One-dimensional array—size of first
dimension of array
■ Two-dimensional array—size of first
dimension of array
■ Others—not defined
(continued)
Chapter 3 • Using DataSocket 111
DS_GetLibraryErrorString Function
The DS_GetLibraryErrorString function converts the error code returned by
one of the DataSocket Library functions and converts it to a meaningful
string. The DS_GetLibraryErrorString function prototype is shown here and
its arguments explained in Table 3–6.
void DS_GetLibraryErrorString (HRESULT errorCode,
char errBuffer[],unsigned int errorBufferSize);
Input/
Output Name Type Description
Input/
Output Name Type Description
DS_GetStatus Function
The DS_GetStatus function returns the status of the connection between a
DataSocket object and its DataSocket data source. When the DataSocket ob-
ject’s status changes, it calls the callback you specified in the call to DS_Open
to create the DataSocket object. The DataSocket object passes the value
DS_EVENT_ONSTATUSUPDATED in the event parameter of your callback.
The DS_GetStatus function prototype is shown here and its arguments ex-
plained in Table 3–7.
Input/
Output Name Type Description
DS_Open Function
The DS_Open function creates a DataSocket object and connects it to a data
source. Each DataSocket object is connected to a single DataSocket data
source. The DS_Open function prototype is shown here and its arguments
explained in Table 3–8.
Input/
Output Name Type Description
(continued)
114 Chapter 3 • Using DataSocket
■ DSConst_WriteAutoUpdate. The
DataSocket object is configured as a
writer and data is updated
automatically when the data or any
of the data attributes are changed
DS_SetAttrValue Function
The DS_SetAttrValue function sets the data value of the attribute you specify
when the DataSocket object is configured for writing. The DS_SetAttrValue
function prototype is shown here and its arguments explained in Table 3–9.
Input/
Output Name Type Description
■ CAVT_DOUBLE
■ CAVT_FLOAT
■ CAVT_LONG
■ CAVT_SHORT
■ CAVT_UCHAR
■ CAVT_CSTRING
■ CAVT_BOOL
■ CAVT_VARIANT
(continued)
116 Chapter 3 • Using DataSocket
DS_SetDataValue Function
The DS_SetDataValue function sets the data value of the DataSocket object
you specify when the DataSocket object is configured for writing. The
DS_SetDataValue function prototype is shown here and its arguments ex-
plained in Table 3–10.
DS_Update Function
The DS_Update function causes the DataSocket object to synchronize its data
value and attributes with the DataSocket data source to which the
DataSocket object is connected. If the DataSocket object is configured for the
read mode, it obtains the current data value and attributes from the
DataSocket data source. If the DataSocket object is configured for the write
mode, it sends the current data value and attributes to the DataSocket data
source. This function has no effect on DataSocket objects that are configured
for ReadAutoUpdate mode or WriteAutoUpdate mode. The DS_Update
function prototype is shown here and its arguments explained in Table 3–11.
Input/
Output Name Type Description
■ CAVT_DOUBLE
■ CAVT_FLOAT
■ CAVT_LONG
■ CAVT_SHORT
■ CAVT_UCHAR
■ CAVT_CSTRING
■ CAVT_BOOL
■ CAVT_VARIANT
(continued)
118 Chapter 3 • Using DataSocket
MakeDir Function
The MakeDir function creates a new directory with the name you specify.
This function is part of the CVI Utility Library and is listed under the Direc-
tory Utilities. The MakeDir function prototype is shown here and its argu-
ments explained in Table 3–12.
SetBreakOnLibraryErrors Function
The SetBreakOnLibraryErrors function displays the run-time error if debug-
ging is enabled and suspends execution when a CVI library function reports
an error. This function is part of the CVI Utilities Library. The SetBreakOn-
LibraryErrors function prototype is shown here and its arguments explained
in Table 3–13.
Input/
Output Name Type Description
Input/
Output Name Type Description
0 success
-1 one of the path components not
found
-3 general I/O error occurred
-4 insufficient memory to complete
the operation
-5 invalid path
-6 access denied
-8 disk is full
-9 directory or file already exists with
same pathname
1 enabled
0 disabled
120 Chapter 3 • Using DataSocket
SetDir Function
The SetDir function sets the directory to the specified working directory that
you specify. This function is part of the CVI Utility Library and is listed
under the Directory Utilities. The SetDir function prototype is shown here
and its arguments explained in Table 3–14.
Input/
Output Name Type Description
0 success
-1 specified directory not found or is
out of memory
4
TABLE CONTROL
Chapter Highlights
■ Introduction
■ Table Control Basics
■ Browsing the Table Control Dialog Windows
■ Table Control Project
■ Examining the Project Code
■ Summary
■ Library Function Prototypes and Definitions
This chapter will introduce you to the features of table control. Table control
did not exist in CVI versions prior to 5.5. You will be shown the capabilities
of table control to display data in the cells that comprise the rows and
columns. You will learn the features of the various buttons on table control’s
property windows and you will be walked through the various attribute di-
alog windows. You are shown how to sort the columns in ascending and de-
scending order, search for a cell value, and paste it to the system clipboard.
At your request the system clipboard data is then displayed on table control.
You are shown how to set the cell, row, and column attributes and to en-
able/disable the grid lines on table control.
122 Chapter 4 • Table Control
Introduction
Table control lets you display and control data in rows and columns much
like a spreadsheet. Using table control you have the ability to control and
manipulate an individual cell, a range of cells, or rows and columns. You
have the ability to change the value and attributes of the individual cells.
You can sort and display the data on table control, search the data value on a
particular cell, and perform many database operations just as you would on
a spreadsheet application. Right-click on table control and you have the op-
tion through a built-in pop-up menu to go to a target cell, find a cell in the
range selected, or sort the cell for the range selected. You can also customize
this table control pop-up menu to create your own menu items. These same
features can be accomplished programmatically through the use of a variety
of table control library functions, as you will see later when we discuss the
project. Using ActiveX you are able to interface with spreadsheet programs,
but the advantage of using table control is that you can embed it in your GUI
and manipulate data from your customized command buttons and software.
The interface to table control is faster than using the ActiveX interface since
it uses fewer Windows resources.
A sample table control is shown in Figure 4–1. The table control shown
here consists of numeric cells, string cells, and picture cells, all of which are
explained in the next section.
Figure 4–1
Sample Table Control
Chapter 4 • Table Control 123
State. Also note that in the Edit State, using the <Ctrl> key in conjunction
with the arrow key will take you to the adjoining cell in the direction of the
arrow key selected.
To select a range of cells using the keyboard, hold down the <Shift> key
in conjunction with the other keys mentioned above. Using the mouse, you
can select the entire row or column by clicking on the label for that row or
column. To select the entire table, click on the upper left corner of the table.
You can select a range of cells by holding down the left mouse button and
moving the mouse over the cells to select.
EVENT_LEFT_CLICK EVENT_GOT_FOCUS
EVENT_LEFT_DOUBLE_CLICK EVENT_LOST_FOCUS
EVENT_RIGHT_CLICK EVENT_DISCARD
EVENT_RIGHT_DOUBLE_CLICK EVENT_COMMIT
EVENT_KEYPRESS EVENT_VAL_CHANGED
Figure 4–2
Edit Table Control
Figure 4–3
Table Mode: Dialog Box
from the row cells, set the table attribute ATTR_TABLE_MODE to VAL_ROW
in the library function SetCtrlAttribute, and to use the cell attributes from the
table, set the table attribute ATTR_TABLE_MODE to VAL_GRID in the library
function SetCtrlAttribute.
Chapter 4 • Table Control 127
The Row group shown in the top middle section of Figure 4–2 is shown sep-
arately in Figure 4–4. This group contains the controls to create the rows on the
table, set the default cell attributes, control the appearance of the data inside
the individual cell, and set the row label appearance for the selected row. To set
any of these row attributes, you have to insert a row on the table control by se-
lecting either the Insert Row Above or the Insert Row Below command button
from this Row group. When you insert a row, the box next to the Row label is
enabled with the number of the row for which you can set the attributes. To set
the attributes of a different row, just enter a different number in the Row box
(top of Figure 4–4), provided that a row number exists.
When you select the Edit Row… command button shown at the bottom of
Figure 4–4, the Edit Row dialog window is displayed as shown in Figure
4–5. From this window you can set the Size Mode: to determine the method
to set the height of the row. This is equivalent to setting the ATTR_SIZE_
MODE attribute from the library function SetTableRowAttribute, as explained
in the section Resizing Rows and Columns.
The Size Mode pull-down menu allows you the following choices:
When you select the Size Mode as Use Explicit Size, the actual row
height is the value entered in the Height: dialog box below the Size Mode:
Figure 4–4
Row Controls
128 Chapter 4 • Table Control
Figure 4–5
Edit Row Window
Chapter 4 • Table Control 129
Figure 4–6
Edit Default Cell Values (Row) Window
130 Chapter 4 • Table Control
■ Character
■ Word
■ Line
If you select Character, the text is wrapped to a new line after the last
character that fits the line. For Word, the text is wrapped to a new line after
the end of the last word that fits on the line. Line wrap mode is the default
and puts the text on a new line only after a new line character (\n).
In the Min Num Lines Visible control box, specify the number of lines of
text to take into account when performing the calculations associated with the
VAL_SIZE_TO_CELL_TEXT value of ATTR_SIZE_MODE. When a row is au-
tosized to the text (VAL_SIZE_TO_CELL_TEXT or VAL_SIZE_TO_CELL_
IMAGE_AND_TEXT), the table adjusts automatically to the maximum “text
height” of all cells in the row. Only the font used in each cell in the row deter-
mines the “height” of each cell. However, you might decide that for a given
cell you want to display more than one line of text on a given cell, which
would cause the text to be chopped off. In order to take this factor into account
when calculating the height of the row, you decide how many lines of text you
wish to display at a given cell. Note that this attribute is used only for the pur-
pose of calculating the row height. It doesn’t prevent users from displaying
however many lines they want at any given cell.
The Column group is shown in the lower-middle section of Figure 4–2,
below the Row group. This is shown in Figure 4–7 for clarity. This grouping
contains the controls to create the columns on the table and to set its attributes.
To set any of these column attributes, you have to insert a column on the table
control by selecting either the Insert Column Above or the Insert Column
Below command button from this Column group. The column number for
which you are setting the attributes is displayed next to the Column label (top
of Figure 4–7). To set the attributes of another column, enter the column num-
ber in the box next to Column, if that column exists.
When you select the Edit Column... command button (from Figure 4–7),
the Edit Column dialog window is displayed (see Figure 4–8).
Selecting the Edit Default Cell Values... command button will bring up
the Edit Default Cell Values dialog window (Figure 4–9) to set the column
cell default values for the column selected. Again, if you have set Table
Mode to something other than Column, CVI will display a warning message
to change Table Mode to Column since you will be setting the attributes of
the column “master” cells here. This will be of use only when Table Mode is
set to Column. This is equivalent to setting the ATTR_SIZE_MODE attribute
Chapter 4 • Table Control 131
Figure 4–7
Column Controls
Figure 4–8
Edit Column Window
Figure 4–9
Edit Default Cell Values (Column) Window
When you select Size Mode as Use Explicit Size, the actual column
width is the value entered in the Width: dialog box below the Size Mode:
dialog box. In this case the ATTR_SIZE_MODE constant is set to VAL_USE_
EXPLICIT_SIZE and the Width attribute, ATTR_COLUMN_WIDTH, contains
the actual value of the column width. Similarly, when Size Mode is selected
as Size To Cell Images, the largest width of the images in all picture
cells in the column is used. The rest of the explanation for editing the default
column cell values is the same as explained in Edit Default Cell Values... for
the rows above.
You can configure the table’s “master” cell using the Edit Default Cell
Values... command button (Figure 4–2). Enter the values in the dialog win-
dow that is displayed (Figure 4–10). The dialog boxes are similar to the Edit
Default Cell Values explained for Rows and Columns above.
The Size/Scroll Options... command button (Figure 4–2) affects the ap-
pearance of the table at the time it is loaded. When you select this command
button the Size/Scroll Options dialog window appears (Figure 4–11). Here
you can set the number of rows and columns that you want visible on the
table control, starting with the row and column numbers selected. The Auto
Chapter 4 • Table Control 133
Figure 4–10
Edit Default Cell Values Window
Size (when loaded) check box assures that the same number of rows and
columns are displayed when table control is created on the GUI, as when
displayed when the program is executed. The row height of each row may
depend on the font you are using in each cell. It is possible that the font used
may be different on the development machine than on the execution ma-
chine because the system fonts can vary in typeface and size. This could re-
sult in rows “growing” or “shrinking” from the time they are created on the
user interface to when loaded at execution. To avoid this situation so that the
table control displays the same number of settings as when created, you
should check mark the Auto Size (when loaded) check box.
There is a convenient feature in table control where you can change the at-
tributes of the individual cells or a group of cells using the Quick Edit Window
shown on the top right side of the Edit Table dialog window (Figure 4–2). To
do this you must first set Control Mode: in the Edit Table dialog window to a
mode other than Indicator. If there are no rows displayed in the Quick Edit
Window, add the rows by clicking on the Insert Row Above or Insert Row
Below command buttons. In the Quick Edit Window click on the Operate
Mode icon on the toolbar (hand icon) to select the individual cell to change the
134 Chapter 4 • Table Control
Figure 4–11
Size/Scroll Options Window
cell’s type, default value, or other attributes by selecting the Edit Cell... com-
mand button. When you select multiple cells, the Edit Cell... command button
changes to Edit Cell Group..., where you can edit the attributes of a range of
cells instead of just a single cell.
face if the data fails. Here we are not interested in the actual data values or
the criteria for pass/fail but in showing you how to manipulate the data on
the table control.
Once the data is displayed on the table control, you can sort on any of the
columns by selecting any column label from the ring control under Select
Sort Column in the SORT group. Any selection in this ring control undims
the ring control Sort Results as: to enable you to select either Ascending or
Descending from the ring control.
The search feature is demonstrated by clicking on any cell whose value
you want to search. The cell value selected is shown bold and the rows con-
taining the cell value(s) searched are highlighted using a certain color when
you select the SEARCH command button. When you search on a different
cell value, that cell is shown bold and the rows containing the cell value
searched are again highlighted using a different color. The search results are
written to the system clipboard and pasted to a separate table when re-
quested using the DISPLAY command button.
For this project Table Mode is set to Column. Six columns are created for
this project, and the default attributes values of the cell are created using the
Edit Table properties window(s).
Figure 4–12
project4 Table Control GUI
136 Chapter 4 • Table Control
1 #include <formatio.h>
2 #include <ansi_c.h>
3 #include <cvirte.h>
4 #include <userint.h>
5 #include “project4.h”
6 #include “Project4SearchTable.h”
7 #define NMBR_OF_ROWS 15 //Total number of rows in the table
8
9 //Define the columns of the table control
10 #define CURRENT_COL 1
11 #define VOLTAGE_COL 2
12 #define PRESSURE_COL 3
13 #define TEMP_COL 4
14 #define RESULTS_COL 5
15 #define PICTURE_COL 6
16
17 static int TablePanel,SearchedPanel, SearchedRows=0;
18 int status, DataLoaded=1, visible, smilePicture,
19 frownPicture, SelectedColumnIndex;
20
21
22 //Function prototype
23 int HighlightRow(Point NewCell, int SearchNumber);
24
25 //Main
26 int main (int argc, char *argv[])
27 {
28 if (InitCVIRTE (0, argv, 0) == 0)
29 return -1; /* out of memory */
30 if ((TablePanel = LoadPanel (0, “project4.uir”, PNL)) < 0)
31 return -1;
32
33 //Hide the right click option to Find item.
34 //We will do the search programmatically
35 HideBuiltInCtrlMenuItem (TablePanel, PNL_TAB, VAL_SEARCH);
36
37 DisplayPanel (TablePanel);
38 //Panel to display searched data
39 if ((SearchedPanel = LoadPanel (PNL, “project4SearchTable.uir”, SRCH_PNL )) < 0)
40 return -1;
41
42 //Load the bitmap files for happy and sad faces
43 GetBitmapFromFile (“smiley.ico”, &smilePicture);
44 GetBitmapFromFile (“frown.ico”, &frownPicture);
45
46 RunUserInterface ();
47 DiscardPanel (TablePanel);
48 return 0;
49 }//main
Figure 4–13
project4 Header and main Function
138 Chapter 4 • Table Control
Figure 4–14
Pop-up Menu for Table Control
Before displaying the data on the table control, the library function
DeleteTableRows at line 12 deletes all the rows on the table if any rows are
created from a previous data load. You can specify the DeleteTableRows func-
tion to delete the specified number of rows or all the rows in the table con-
trol. Here all the rows are deleted.
The library function SetTableColumnAttribute at line 14 sets the column at-
tribute in a table control. Here the background color attribute of the master
cell of the Results column is set. All cells that are created under this column
will later inherit this background color attribute. The InsertTableRows library
function at line 21 inserts new rows in the table control at the one-based
index specified. In this code, the InsertTableRows function is inside a for loop
that is called for the number of rows (NMBR_OF_ROWS) in the table, creating a
new row at the end of the table for each iteration of the for loop. The indices
of the existing rows are incremented automatically for the rows beyond
where the row(s) are inserted. This function also creates a new cell for each
column in the table. The same could have been achieved if the Insert-
TableRows function was placed before the start of the for loop and
NMBR_OF_ROWS entered in the number of rows argument for this function.
This will create a table with NMBR_OF_ROWS rows and insert NULL data in
the cells. Either approach would be acceptable for inserting rows in a table
control. Note that it is more efficient to insert as many rows or columns that
need to be created inside a single InsertTableRows function.
Chapter 4 • Table Control 139
1 //Create and display data on Table. Invoked from “LOAD DATA” command button
2 int CVICALLBACK LoadDataCB (int panel, int control, int event,
3 void *callbackData, int eventData1, int eventData2)
4 {
5 short int index, result;
6 double volts_array[ NMBR_OF_ROWS+1], pressure, temperature,
7 current_array[ NMBR_OF_ROWS+1];
8 switch (event)
9 {
10 case EVENT_COMMIT:
11 //If rows exit then delete them before loading the data again
12 if (DataLoaded==0) DeleteTableRows (TablePanel, PNL_TAB, 1, -1);
13 //Set background color of “Results” column
14 SetTableColumnAttribute (TablePanel, PNL_TAB, RESULTS_COL,
15 ATTR_TEXT_BGCOLOR, VAL_LT_GRAY);
16
17 //Create and load data
18 for (index=1; index <= NMBR_OF_ROWS; index++)
19 {
20
21 InsertTableRows (TablePanel, PNL_TAB, -1, 1,
22 VAL_USE_MASTER_CELL_TYPE);
23
24 //Read the simulated data from the ASCII files
25 //The data from the file is input to current_array
26 FileToArray (“Current.txt”, current_array, VAL_DOUBLE,
27 NMBR_OF_ROWS, 1,
28 VAL_GROUPS_TOGETHER,
29 VAL_GROUPS_AS_COLUMNS, VAL_ASCII);
30 //The data from the file is input to volts_array
31 FileToArray (“Volts.txt”, volts_array, VAL_DOUBLE,
32 NMBR_OF_ROWS, 1,
33 VAL_GROUPS_TOGETHER,
34 VAL_GROUPS_AS_COLUMNS, VAL_ASCII);
35
36 //Create random data for pressure and temperature
37 pressure = rand ()/10.0;
38 temperature = rand ()/250.0;
39
40 //Display results on the table
41 SetTableCellVal(TablePanel,
42 PNL_TAB,MakePoint(CURRENT_COL,index),
43 current_array[index-1]);
44 SetTableCellVal(TablePanel,
45 PNL_TAB,MakePoint(VOLTAGE_COL,index),
46 volts_array[index-1]);
47 SetTableCellVal(TablePanel,
48 PNL_TAB,MakePoint(PRESSURE_COL,index), pressure);
49
50 SetTableCellVal(TablePanel,
51 PNL_TAB,MakePoint(TEMP_COL,index),
52 temperature);
Figure 4–15
LoadDataCB Function Listing (continued)
140 Chapter 4 • Table Control
Figure 4–15
LoadDataCB Function Listing (continued)
Chapter 4 • Table Control 141
The FileToArray library function at lines 26 and 31 writes the data from the
files Current.txt and Volts.txt to the arrays current_array and
volts_array, respectively. The purpose of the FileToArray function is to
read the data from a file into an array. The data read into an array must be of
the same data type. This function opens the file, reads it, and then closes it
after the data has been read. At lines 41 and 44 the SetTableCellVal function
loads the data from these arrays into the appropriate column cells for each
row. In some applications it will be more efficient to use the library function
SetTableCellRangeVals to replace the values in a cell range by values from an
array. You can also use FillTableCellRange if you want to replace the same
value in all the cells in the cell range. Either of these functions can be used in
place of the library function SetTableCellVal.
Notice that the third argument in SetTableCellVal function is a library
function MakePoint. The MakePoint function will be used frequently when
addressing the cells of the table control and needs to be explained. A cell on
a table control is always referenced by a Point structure. The Point structure
is defined as follows:
typedef struct
{
int x;
int y;
} Point;
The one-based column index of the cell is passed in the x field of the struc-
ture and the one-based row index to the y field of the structure. For example,
if you are referencing a cell at row 4 and column 6, you will use
Figure 4–16
Select Sort Column Ring Control
Chapter 4 • Table Control 143
Figure 4–17
SortColumnSelectCB Function Listing
Sort Ascending/Descending
You can sort in either Ascending or Descending order by choosing from the
Sort Results as: ring control (Figure 4–18), which calls the SortResultsCB
function, whose listing is shown in Figure 4–19.
Figure 4–18
Sort Results as: Ring Control
144 Chapter 4 • Table Control
Figure 4–19
SortResultsCB Function Listing
Chapter 4 • Table Control 145
Figure 4–20
Sorting Using the Built-in Menu Table Control
146 Chapter 4 • Table Control
Search Function
The search function searches a cell value in the column specified, and if the
cell value is found, shows the cells selected in bold and highlights all the
rows containing that cell value. The row(s) containing the cell(s) searched
is/are placed on a system clipboard to be displayed later when the DISPLAY
command button is selected from the GUI. When you make another selection
on the table, the rows containing that cell value are highlighted using a differ-
ent color and the rows are pasted on the system clipboard again.
To search for a cell value, click on the cell with the left mouse button whose
value you want to search. Click the SEARCH command button on the GUI in
Figure 4–12 to start the search. The SearchCB function is called and its listing is
shown in Figure 4–21. The first item this routine checks for is to determine if
you have selected a cell on the table control. The library function GetActive-
TableCell at line 15 returns the Point structure of the cell, indicating the one-
based row and one-based column of the cell selected. The GetTableCellVal at
line 18 obtains the value of the cell selected. If no cell is selected on the table
control (indicated by the cell value being 0) and you clicked on the SEARCH
command button, a pop-up message is displayed at line 23 asking you first to
select a cell. Otherwise, the cell selected is obtained at line 29 and is shown in
bold using the library function SetTableCellAttribute at line 30. The cell is shown
in bold to indicate the cell selected for searching. Lines 34–40 determine if the
cell searched is a picture cell, and if so, displays a pop-up panel indicating that
it cannot search on this cell type. In this function the code is set to search on ei-
ther a numeric or a string cell. Line 41 determines if the cell selected is a string
by checking the column number of the cell selected. If a string is to be searched,
the library function GetTableCellVal obtains the search value in a string variable
SearchString at line 44; otherwise, the value is contained in a numeric vari-
able SearchValue at lines 48 and 49.
The library function GetNumTableRows at line 52 determines the number of
rows in the table to search. The SetActiveTableCell library function sets the cell
selected as active and obtains the cell structure at line 57. The GetActiveTable-
Cell library function at line 59 assigns a variable NewCell to the cell selected.
This cell structure is used in the GetTableCellVal library function at line 62 or
Chapter 4 • Table Control 147
Figure 4–21
SearchCB Function Listing (continued)
148 Chapter 4 • Table Control
53
54 //Search on all the values in that column
55 for (row=1; row <= RowsInTable; row++)
56 {
57 SetActiveTableCell(TablePanel, PNL_TAB,
58 MakePoint(SearchCell.x,row));
59 GetActiveTableCell (TablePanel, PNL_TAB, &NewCell);
60 if (SearchCell.x != RESULTS_COL)
61 //Get the selected cell value
62 GetTableCellVal(TablePanel,
63 PNL_TAB,NewCell,&NewValue);
64 else //Searching on string value
65 //Get the selected cell value
66 GetTableCellVal(TablePanel,
67 PNL_TAB,NewCell,NewStringValue);
68
69 //If value found and is not string
70 if ( (SearchCell.x != RESULTS_COL) && (SearchValue ==
71 NewValue))
72 {
73 //Highlight the row and put on clipboard
74 HighlightRow(NewCell, SearchNumber);
75 SearchFlag=1;
76
77 }//if
78 else if ( (SearchCell.x == RESULTS_COL) &&
79 (strcmp (SearchString,NewStringValue) ==0 ))
80 {
81 //Highlight the row and put on clipboard
82 HighlightRow(NewCell, SearchNumber);
83 SearchFlag=1;
84 }//else if
85
86 }//for
87
88 //Enable the DISPLAY command button if there is data on clipboard
89 if (SearchFlag)
90 SetCtrlAttribute (TablePanel, PNL_DISPLAY, ATTR_DIMMED, 0);
91
92 SearchNumber++; //increment the search color index
93 if (SearchNumber== RESULTS_COL) SearchNumber=0; /*Reset SearchColor
94 number*/
95
96 break;
97 }
98 return 0;
99 } //SearchCB
Figure 4–21
SearchCB Function Listing (continued)
line 66, depending on whether the active cell contains a number or a string.
The value of each cell searched is compared against the value selected at line
70 if the cell value is numeric and on line 78 if it is a string. In either case the
user-defined function HighlightRow is called.
Chapter 4 • Table Control 149
Figure 4–22
HighlightRow Function Listing
150 Chapter 4 • Table Control
The row containing the cell value selected is enhanced using a color from
among five different colors in the SearchColor array at line 5. Every time a
new search value is selected, the searched rows are highlighted with the next
color in the array. The colors are selected round robin, so after the fifth selec-
tion the first color is used to paint the selected row. The SetTableCellRange-
Attribute library function at line 14 is used to color the row with the color se-
lected. At line 39 in the main function of this project (Figure 4–13), a panel
handle SearchedPanel is created to display the search results in a table con-
trol. This GUI is shown in Figure 4–23. The ClipboardPutTableVals function at
line 21 of the HighlightRow function puts onto the system clipboard the cell
range selected for the table control. Every time the cell value is searched, a
new row is created on the SEARCHED DATA GUI using the InsertTableRows
library function at line 25. Line 29 pastes the data from the system clipboard
onto the table control in the SEARCHED DATA GUI (Figure 4–23) using the
library function ClipboardGetTableVals.
When selected, the RESET command button in Figure 4–12 calls the Reset-
TableCB function (not listed in text) and removes the colors from the rows
searched and removes unbolds from the cell(s) selected. The data searched,
however, is not removed from the system clipboard.
Figure 4–23
SEARCHED DATA GUI
Chapter 4 • Table Control 151
Summary
The table control basics were explained in this chapter. You learned how to
set the attributes of the cells, rows, and columns of table control. You were
shown how to control the attributes of table control through use of the Edit
window in the User Interface editor and through the use of library func-
tions. You were introduced to the table control pop-up menu. You were
shown how to hide, display, and create menu items on this pop-up menu.
You were also shown how this pop-up menu could be used to sort a row or
a column on a table control. The project demonstrated the various table con-
trol library functions to search and sort on the cells and how to paste and re-
trieve data from the system clipboard.
ClipboardGetTableVals Function
The ClipboardGetTableVals function retrieves the text data from the system
clipboard and formats it into the cell range specified for the table cells. It also
indicates if the text data is available on the system clipboard. Its prototype is
shown here and its arguments explained in Table 4–1.
ClipboardPutTableVals Function
The ClipboardPutTableVals function copies the data from the cell range speci-
fied for a table control to the system clipboard. Its prototype is shown here
and its arguments explained in Table 4–2.
Input/
Output Name Type Description
1 data is available
0 there is no data on the clipboard
Input/
Output Name Type Description
DeleteTableRows Function
The DeleteTableRows function deletes from the table control the number of
rows specified. Its prototype is shown here and its arguments explained in
Table 4–3.
Chapter 4 • Table Control 153
Input/
Output Name Type Description
FillTableCellRange Function
The FillTableCellRange function sets to the same value the value of all the cells
in the cell range specified. All cells must be of the same cell type in the cell
range. Its prototype is shown here and its arguments explained in Table 4–4.
FileToArray Function
The FileToArray function converts a data file to an array. Its prototype is
shown here and its arguments explained in Table 4–5.
Input/
Output Name Type Description
Input/
Output Name Type Description
■ VAL_CHAR—character
■ VAL_SHORT_INTEGER—short integer
■ VAL_INTEGER—integer
■ VAL_DOUBLE—double
■ VAL_UNSIGNED_SHORT_INTEGER—
unsigned short integer
■ VAL_UNSIGNED_INTEGER—
unsigned integer
■ VAL_UNSIGNED_CHAR—unsigned
character
■ VAL_GROUPS_TOGETHER. All
elements of first data group are
followed by all elements from the
second data group, and so on.
■ VAL_DATA_MULTIPLEXED. First
elements of all data groups are stored
together, followed by second
elements of all data groups, and so on.
■ VAL_GROUPS_AS_COLUMNS
■ VAL_GROUPS_AS_ROWS
■ VAL_ASCII
■ VAL_BINARY
GetActiveTableCell Function
The GetActiveTableCell function returns the point structure of the active
(selected) cell of the table control. Its prototype is shown here and its argu-
ments explained in Table 4–6.
GetBitmapFromFile Function
The GetBitmapFromFile function reads the bitmap file and converts it to a
bitmap image. Its prototype is shown here and its arguments explained in
Table 4–7.
GetNumTableRows Function
The GetNumTableRows function obtains the number of rows in the table con-
trol. Its prototype is shown here and its arguments explained in Table 4–8.
Input/
Output Name Type Description
Input/
Output Name Type Description
Input/
Output Name Type Description
GetTableCellFromVal Function
The GetTableCellFromVal function returns the first cell in the cell range of a
table control with a value matching the value specified. Its prototype is
shown here and its arguments explained in Table 4–9.
Input/
Output Name Type Description
■ VAL_CELL_NUMERIC 0
■ VAL_CELL_STRING 1
GetTableCellVal Function
The GetTableCellVal function obtains the current value of the cell selected. Its
prototype is shown here and its arguments explained in Table 4–10.
HideBuiltInCtrlMenuItem Function
The HideBuiltInCtrlMenuItem function hides the built-in menu item from the
table control menu. Its prototype is shown here and its arguments explained
in Table 4–11.
InsertTableColumns Function
The InsertTableColumns function inserts a new column on the table control at
the column location specified. Its prototype is shown here and its arguments
explained in Table 4–12.
InsertTableRows Function
The InsertTableRows function inserts a new row on the table control at the
row location specified. Its prototype is shown here and its arguments ex-
plained in Table 4–13.
Input/
Output Name Type Description
Input panel
Handle integer panel handle loaded in memory
Input/
Output Name Type Description
Input/
Output Name Type Description
■ VAL_CELL_NUMERIC—for cell to
hold numeric values
■ VAL_CELL_STRING—for cell to hold
text
■ VAL_CELL_PICTURE—for cell to
hold images
■ VAL_USE_MASTER_CELL_TYPE—to
use the default cell types for each column
MakePoint Function
The MakePoint function creates a Point structure using the x and y coordi-
nates specified for the point. For a table control the x and y coordinates of
the cell are used. Its prototype is shown here and its arguments explained in
Table 4–14.
Input/
Output Name Type Description
■ VAL_CELL_NUMERIC—for cell to
hold numeric values
■ VAL_CELL_STRING—for cell to hold
text
■ VAL_CELL_PICTURE—for cell to
hold images
■ VAL_USE_MASTER_CELL_TYPE—
to use the default cell types for each
column
Input/
Output Name Type Description
MakeRect Function
The MakeRect function creates a Rect structure using the x and y coordinates
of one corner of the rectangle and the width of the rectangle. Its prototype is
shown here and its arguments explained in Table 4–15.
typedef struct
{
int top;
int left;
int height;
int width;
} Rect;
For instance, if the cell range selected were as shown in Figure 4–24, the
rectangle coordinates would be
range.top = 2;
range.left = 3;
range.height = 3;
range.width = 2;
Input/
Output Name Type Description
1 2 3 4 5
1 left
2 top
3 height
4
5 width
6
Figure 4–24
Example Cell Range
■ To select all the rows and columns in the table control, use the macro
VAL_TABLE_ENTIRE_RANGE. This is equivalent to calling the function
MakeRect(1,1,,-1,-1).
■ To select the entire row of a table control, use VAL_TABLE_ROW_
RANGE(r), where r is the one-based row number of the row selected.
■ To select all the cells in the column, select VAL_TABLE_COLUMN_
RANGE(c), where c is the one-based column number of the column
selected.
NewCtrlMenuItem Function
The NewCtrlMenuItem function creates a new menu item on menu for the table
control. Its prototype is shown here and its arguments explained in Table 4–16.
Input/
Output Name Type Description
■ VAL_GOTO -2
■ VAL_SEARCH -3
■ VAL_SORT -4
void CVICALLBACK
FunctionName (int
panelHandle, int controlID,
int MenuItemID, void *
callbackData);
SetActiveTableCell Function
The SetActiveTableCell function sets the cell specified by the Point structure
as the active cell. Its prototype is shown here and its arguments explained in
Table 4–17.
SetTableCellAttribute Function
The SetTableCellAttribute function sets the attribute of the cell specified. Its
prototype is shown here and its arguments explained in Table 4–18.
SetTableCellVal Function
The SetTableCellVal function sets the value specified on the table control cell se-
lected. Its prototype is shown here and its arguments explained in Table 4–19.
Input/
Output Name Type Description
Input/
Output Name Type Description
cell Point Point structure for the cell for which you
want to set the attribute
Input/
Output Name Type Description
value any type specify the cell value you want to set
SetTableCellRangeVals Function
The SetTableCellRangeVals function replaces the values of a table control cell
range by the values in a specified array. All cells must be of the same cell
type in the cell range. Its prototype is shown here and its arguments ex-
plained in Table 4–20.
Input/
Output Name Type Description
SetTableCellRangeAttribute Function
The SetTableCellRangeAttribute function sets the attribute for a range of specified
cells. Its prototype is shown here and its arguments explained in Table 4–21.
SetTableColumnAttribute Function
The SetTableColumnAttribute function sets the attribute of a table column. Its
prototype is shown here and its arguments explained in Table 4–22.
Input/
Output Name Type Description
Input/
Output Name Type Description
SetTableRowAttribute Function
The SetTableRowAttribute function sets the attribute of a table row. Its proto-
type is shown here and its arguments explained in Table 4–23.
ShowBuiltInCtrlMenuItem Function
The ShowBuiltInCtrlMenuItem function makes a built-in pop-up menu item
visible on the table control. The menu item can be made visible only if you
previously hid the menu item by calling HideBuiltInCtrlMenuItem. Its proto-
type is shown here and its arguments explained in Table 4–24.
Input/
Output Name Type Description
Input/
Output Name Type Description
■ VAL_GOTO -2
■ VAL_SEARCH -3
■ VAL_SORT -4
(continued)
172 Chapter 4 • Table Control
■ VAL_GOTO -2
■ VAL_SEARCH -3
■ VAL_SORT -4
SortTableCells Function
The SortTableCells function sorts a group of specified cells in a table control.
Its prototype is shown here and its arguments explained in Table 4–25.
Input/
Output Name Type Description
Input panel
Handle integer panel handle loaded in memory
(continued)
Chapter 4 • Table Control 173
■ VAL_ROW_MAJOR
■ VAL_COLUMN_MAJOR
Introduction
The VXIbus (VMEbus eXtensions for Instrumentation) standard for
instruments-on-a-card systems was developed to accommodate the test
equipment industry’s need to reduce the physical size and cost of rack-
mounted equipment, increase performance, and use more precise timing
and synchronization between instruments. The instrumentation industry
wanted an open architecture for all instruments, enabling them to use the
best techniques of both General-Purpose Interface Bus (GPIB) and plug-in
Data Acquisition (DAQ) boards.
VXIbus consists of a mainframe chassis with modular instruments on a
board (also called modules) that plug into chassis slots. VXIbus defines a
standard communication protocol to devices using American Standard
Code for Information Interchange (ASCII) commands to control instru-
ments, similar to GPIB.
The VXIbus standard is an extension of the VMEbus (VERSAbus Modu-
lar Eurocard), standard, which uses the same backplane connectors as the
VME. VMEbus is a backplane standard (IEEE 1014) for many electronic plat-
forms. This standard defines the electrical and mechanical backplane charac-
teristics to work with equipment developed by different manufacturers.
VXIbus includes additional signals from the VMEbus specification. This
standard adds two more board sizes and additional connectors on the board
using different board widths. These are explained in the section VXI Chassis,
Modules, and Connectors below.
Short History
In 1970, Motorola, along with a number of other companies, developed the
VMEbus as a backplane standard to communicate with instruments using
different electronic platforms. At that time the instrument manufacturers
wrote the drivers for their instruments, which did not conform to any estab-
lished industry standards.
In 1987, the VXIbus Systems Alliance (or VXIbus Consortium, for short)
was formed to create a standard protocol for instrumentation encompassing
both hardware and software. The VXIbus standard was adopted by IEEE in
March 1993 and became known as IEEE 1155. The VXIbus Consortium was
founded in September 1993 and comprised of companies such as National
Chapter 5 • VXI Communication Using VISA 177
Figure 5–1
13-Slot VXI Chassis with Plug-in Modules
(Copyright National Instruments)
The VMEbus and VXIbus boards can have one to three connectors, de-
pending on the size of the boards. The board sizes and the number of con-
nectors are shown in Figure 5–2. Each connector has three rows of 32
sockets. The board connector is a male connector known as the P (plug) con-
nector. The board connector is inserted into the female backplane connector
on the mainframe, called the J (jack) connector.
The VMEbus mainframe usually houses 20 slots using a 0.8-inch board
width for each module. To reduce radiation between the boards, VXIbus in-
creased the board width to 1.2 inches to allow for additional space to enclose
the boards in a metal case and connecting the metal case to the backplane
ground for better shielding. The increased board width resulted in the VXIbus
mainframe having only 13 slots for the boards.
Figure 5–2
VXI Module Sizes and Connectors
(Copyright National Instruments)
backplane. This configuration offers the smallest size and the highest
performance.
■ VXI Mainframe Linked Through GPIB. The GPIB-VXI interface mod-
ule is installed inside the VXI mainframe and the GPIB interface card
on the PC. These are linked together by a GPIB interface cable. The
GPIB-VXI interface board translates the GPIB messages and data.
■ High-Speed MXIbus Link. The VXI backplane is controlled using a
highspeed MXIbus, (Multisystem eXtension Interface bus), linked
from an external computer to a VXI-MXI extender in Slot 0 of the VXI
mainframe. The system performance is equivalent to using the em-
bedded computer connected to the VXI platform. This configuration
gives you the flexibility of choosing your own external computer (see
Figure 5–3).
If there are not enough slots available on one mainframe, you can add ad-
ditional mainframes, since in a VXI system there are no limitations on the
number of mainframes that you can add. Figure 5–4 shows one of the ways in
which you can connect multiple VXI chassis using the MXIbus and VXI-MXI
extender boards.
180 Chapter 5 • VXI Communication Using VISA
Figure 5–3
PC Using MXI to Control Two-VXIbus System
(Copyright National Instruments)
Figure 5–4
VXI-MXI Used for Connecting Multiple VXI Mainframes
(Copyright National Instruments)
Chapter 5 • VXI Communication Using VISA 181
1 1 1 1 1 1 9 8 7 6 5 4 3 2 1 0
5 4 3 2 1 0
Write RESERVED [Logical Address]
Address
Space
Device
Class
Manufacturer ID Code
Read
Figure 5–6
ID/Logical Address Register Bit Allocation
184 Chapter 5 • VXI Communication Using VISA
Bit Bit
13 12 Address Space Used
1 0 reserved
1 1 A16 only
1 1 1 1 1 1 9 8 7 6 5 4 3 2 1 0
5 4 3 2 1 0
Write
RESERVED
Required
Read
Memory/ Model Code
Model Code
Figure 5–7
Device Type Register Bit Allocation
1. Obtain the decimal value for bits 12–15 in this register (n).
2. If the A24 address space is used, the memory size requested is 223-n.
3. If the A32 address space is used, the memory size requested is 231-n.
You can determine the address space by decoding bits 12 and 13 in the
ID/Logical Address Register (see Figure 5–6 and Table 5–1).
The lower 12 bits of the Device Type Register in the read mode describe
the Model Code of the VXI device. If the device does not require any
memory in A24 and A32 address space, indicated by bits 12 and 13,
both set in the ID/Logical Address Register, all 16 bits in the Device
Type Register are used for defining the Model Code of the device. Note
that the Device Type Register is different from the Device Class obtained
from the ID/Logical Address Register (Figure 5–6). The Device Class is
explained in the section VXI Device Classes below.
Chapter 5 • VXI Communication Using VISA 185
1 1 1 1 1 1 9 8 7 6 5 4 3 2 1 0
5 4 3 2 1 0
A24/A32
Sysfail
Inhibit
Write
Rese t
Enable
Device Dependent
A24/A32
Dependent
Device Dependent
MODID
Ready
Device
Active
Read
Pass
Figure 5–8
Status/Control Register Bit Allocation
186 Chapter 5 • VXI Communication Using VISA
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Write
A24/A32 Offset
Read
A24/A32 Offset
Figure 5–9
A24/A32 Offset Register Bit Allocation
Space (bits 12 and 13). The Resource Manager system startup assigns
and writes the base address of the onboard memory of the device in the
A24 or A32 address space. In the read mode this register returns the
base address of either the A24 or A32 address space of the device’s on-
board memory.
1 1 Register-Based
1 0 Message-Based
0 0 Memory
0 1 Extended
Chapter 5 • VXI Communication Using VISA 187
These registers are shown in Figure 5–5 and are located at offset 08 hex
through 0E hex. The functionalities of these registers are explained below.
Resource Manager
The Resource Manager resides on the VXIbus embedded controller or an ex-
ternal computer controlling the VXIbus. The Resource Manager runs the
Resman algorithm using the resman.exe file. Resman.exe is installed auto-
matically on a computer when the NI-VXI software is installed and sets up
the configuration registers of the devices and the system resources at startup
and initiates normal operations.
The Resource Manager can reside physically in any slot in the VXI chassis
but must have a logical address of 0. At power-on the VXIbus system first
operates in the configuration state in which the Resource Manager config-
ures the devices, then transitions to an operational state in which the normal
operation of the device can begin. The Resource Manager is used only dur-
ing startup and is not used for controlling the VXIbus system after the
startup operation is complete.
190 Chapter 5 • VXI Communication Using VISA
There are a few caveats about running Resman. The VXI controller must be
initialized before running Resman. This is done automatically when National
Instruments VXI driver software is installed. You must run Resman every
time you cycle power on the mainframe to reinitialize the system. This is be-
cause the Resource Manager runs only once on power-up. Note that if you
need to run the Resource Manager again, the message-based devices do not
respond to most of the word serial configuration commands after receiving the
Begin Normal Operation command. To run the Resource Manager again you
would need to power cycle on the VXI mainframe(s) or send the system reset
(SYSRESET*) command to set the devices to their configuration state. This is
accomplished through the VISA function viAssertUtilSignal (if you are using
CVI 6.0 or later versions) or by using the NI-VXI function AssertSysReset (for
Chapter 5 • VXI Communication Using VISA 191
CVI versions 5.5 and earlier). Sending the system reset from either of these
functions is equivalent to cycling power on the VXI system, as it asserts the
Sysreset line on the controller specified.
Let us now see how each of these steps is performed using the VISA library
functions.
Step 1 calls for establishing a session with the VISA Default Resource Man-
ager using the VISA library function viOpenDefaultRM(&DefaultRM). The
VISA Default Resource Manager initializes the VISA system and can search
for available resources or open sessions to them. Opening a session means es-
tablishing a communication link to the VISA Default Resource Manager or the
device(s). Note that the VISA Default Resource Manager is different from the
VXI Resource Manager. The VXI Resource Manager executes Resman when
the VXI system is turned on and therefore must be run before VISA. In VXI
systems, the VISA Default Resource Manager looks at the resman.tbl cre-
ated by the Resman utility to obtain the instruments available on the system.
The viOpenDefaultRM(&DefaultRM) function returns a resource manager han-
dle, DefaultRM, that identifies this session uniquely. This argument will be
used in the viOpen and viClose library functions when closing the session with
the VISA Default Resource Manager.
Step 2 is to open a communication channel to the device using the func-
tion viOpen. This function has a form similar to
Interface Type[board]::Address::Resource
The Instrument Descriptor syntax is shown in Table 5–3. Interface Type in the
table shows the keywords that are used to communicate with the various inter-
faces. The items shown in parentheses in Table 5–3 are optional parameters.
The board index is the board number to which the device is connected. The
board index is used if more than one interface board is present.
Chapter 5 • VXI Communication Using VISA 193
Interface
Type Syntax
As shown in Table 5–3, the following VISA resource types are supported:
INSTR, MEMACC, INTFC, BACKPLANE, SERVANT, and SOCKET. Two of the
most commonly used resource types are INSTR and MEMACC.
A VISA Instrument Control (INSTR) Resource lets the controller interact
with the device to write and read data from the device, triggering and han-
dling service requests, resetting and initializing the device, obtaining the de-
vice status, transferring large blocks of data, accessing the device registers,
and other functionalities to communicate with the device.
A VISA Memory Access (MEMACC) Resource is used for accessing the
entire memory range for the address space specified. This is used for access-
ing device registers for multiple devices. This resource allows for moving
large blocks of data between addresses using the absolute address within
the address space specified.
For a description and functionality of other VISA resource types, see VISA
Resource Types in Chapter 2 of the NI-VISA Programmer’s Reference Manual.
As an example, to communicate with a device located at logical address
10, connected to the VXI interface VXI0, use the following as the Instrument
Descriptor:
VXI0::10::INSTR
The next argument in the viOpen function is the Access Mode. The Access
Mode argument can consist of VI_EXCLUSIVE_LOCK, VI_LOAD_CONFIG, or
VI_NULL. VI_EXCLUSIVE_LOCK is used for locking the resource before the
operation returns. If the resource cannot be locked, the operation waits up to
the time specified in the Timeout argument (the next argument in the viOpen
function) before returning an error. When VI_EXCLUSIVE_LOCK is used in
this argument, any external user-defined settings will be used rather than the
VISA-specified defaults. VI_LOAD_CONFIG is used for any external user-
defined settings rather than the VISA-specified defaults. If there are no exter-
nal settings, the operation will use the VISA defaults and return VI_WARN_
CONFIG_NLOADED. Use VI_NULL if you are not using these features.
The last argument of this function is InstrumentHandle, which returns
the communication channel to the device. This argument is used to commu-
nicate with the device selected and is used in all subsequent function calls.
There are a few differences between communicating with message-based
devices and a register-based device. Message-based devices communicate
using the word serial protocol, as mentioned above, whereas register-based
devices write and read 16-bit values in the A16, A24, or A32 address space.
These address spaces were explained in the section VXI Address Space and
Configuration Registers above.
Chapter 5 • VXI Communication Using VISA 195
As in viWrite function, the first argument is the handle you obtained from
the viOpen function to open a communication channel to the device. You
specify the number of bytes to read in the argument NumberOfBytes-
ToRead. BytesTransferred tells you the actual number of bytes that
were read. Again, you can use VI_NULL for this argument if you do not
need this value.
To write to or read from a register-based device or the configuration regis-
ters of message-based devices, the register access functions are used. VISA
allows two ways in which you can access register-based devices: high-level
access (HLA) operations and low-level access (LLA) operations. The HLA
operations use the arguments in the VISA functions to perform the neces-
sary steps to set up the hardware, access the address space, perform the
write or read to the register, detect errors, and perform error handling. All
these activities are performed through a single HLA function. When using
LLA operations, you have to perform the same activities as HLA through
multiple function calls. The HLA functions are easier to implement in an ap-
plication. The LLA operations take longer to create an application, but result
in faster communication than when the HLA functions are used. In this
chapter we discuss the HLA functions only. Refer to the NI-VISA User Man-
ual for an explanation of LLA functions and implementation.
196 Chapter 5 • VXI Communication Using VISA
Using the HLA functions to write to a register-based device, you can use
the viOut8, viOut16, or viOut32 function, depending on whether you are writ-
ing to an 8-, 16-, or 32-bit register. The generic form of the viOut16 function is
shown here; the 8- and 32-bit versions use similar function arguments.
As in the viWrite function, the first argument is the handle you obtain
from the viOpen function to open a communication channel to the device.
The AddressSpace is the VXI address space you want to access. It can be
A16, A24, or A32 space. The next argument is Offset, which refers to the
memory offset from the base address of the device. The use of this argument
requires some explanation. Logical addresses in A16 space start at offset
0xC000 (see Figure 5–5). The base address of a device at logical address 2, for
example, is computed as follows:
since there are 0x40 (64 decimal) address registers in each configuration space
of a device. This address calculation is performed automatically by the function
since it knows which device you are talking to from the InstrumentHandle
argument. Suppose you want to refer to the Status/Control Register device at
offset 4; its address would be
All you need to do is to supply the Offset for the Status/Control Register
in the viOut function and the correct register is referenced. The last argument
in the viOut function is ValueToWrite and is the data you want to write to
this register.
Step 4 is to read from a register-based device. You can use the viIn8,
viIn16, or viIn32 function, depending on whether you are reading to an 8-,
16-, or 32-bit register. The generic form of the viIn16 function is shown here;
the 8- and 32-bit versions use similar arguments.
The arguments used in this function are similar to those defined for the
viOut16 function, except that the data received from the device is read in the
buffer ReadBuffer.
Chapter 5 • VXI Communication Using VISA 197
VISA Project
Some of the basics of communicating using VISA were shown in the section
above. Project5.prj will show you how to set up a communication and
how to write and read data to/from a message-based VXI device.
This project demonstrates communicating with a Function/Arbitrary
Waveform Generator VXI device. The code is written to work with the
Hewlett-Packard (now part of Agilent Technologies) E1441A Arbitrary
Waveform Generator VXI module. For simplicity, in this book I refer to the
Arbitrary Waveform Generator as the function generator. Let us examine the
GUI for this project, shown in Figure 5–10. Using this GUI you will be able
to configure the function generator to output the selected type of waveform
and the frequency from the Waveform Shape box, with the peak-to-peak
voltage specified set from the Amplitude box. You can set the output im-
pedance to either 50 ohms or open-circuit by selecting from the Impedance
switch, and also apply an offset DC voltage. After you have made the selec-
tion, you can click on the CONFIGURE command button to send the selec-
tions to the function generator and configure the function generator.
Echoing the string back from the device and displaying it on the text box on
the GUI verifies that the string was sent correctly to the function generator.
If you want to find all the resources available on your VXI system, click on
the FIND RESOURCES command button. All the devices with their logical
addresses will be displayed on the text box.
Let us look at the code and the VISA functions used in this project.
198 Chapter 5 • VXI Communication Using VISA
Figure 5–10
Arbitrary Waveform Generator GUI
1 #include <utility.h>
2 #include <formatio.h>
3 #include <userint.h>
4 #include <ansi_c.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <visa.h>
9 #include "project5.h"
10
11 #define BUFFER_LEN 256 //Buffer Length
12
13 static int AWGPanelHandle;
14 int DriverIndex;
15 short int ImpedanceIndex;
16
17 ViStatus status = VI_SUCCESS;
18 ViSession InstrHandle, ResourceManager;
19 ViChar buffer[BUFFER_LEN], bytes[BUFFER_LEN], errStr[BUFFER_LEN];
20
21 unsigned char read_buf[BUFFER_LEN], cmdString[BUFFER_LEN];
22 ViReal64 Impedance;
23
24 int SetupCommunication(void);
25
26 int main()
27 {
28 AWGPanelHandle =LoadPanel(0, "project5.uir", AWG_PNL);
29 DisplayPanel(AWGPanelHandle);
30 //Open VISA Default Resource Manager
31 status = viOpenDefaultRM(&ResourceManager);
32 if (status < VI_SUCCESS)
33 {
34 sprintf (buffer, "Error Opening Resource Manager...Exiting Program");
35 InsertTextBoxLine (AWGPanelHandle, AWG_PNL_DISP, -1, buffer);
36
37 return -1;
38 }
39 RunUserInterface();
40 } //main
Figure 5–11
project5 Header and main Function Listing
18 the ViSession data type is defined for sessions opened with the VISA
Default Resource Manager or with a VISA device. The ResourceManager
handle is used at line 31 to identify the session uniquely. Recall that the first
call when opening a session with VISA is to the viOpenDefaultRM function
and is therefore included in the main function. It cannot be emphasized
enough that whenever you make a call to any VISA function, you must check
the function’s return status for possible errors. In case there is a problem with
the function call, you will be notified of the error immediately. VISA status
codes are 32-bit integers in hexadecimal that can indicate possible errors or
warnings or indicate if the operation completed successfully. The status
codes are listed in Appendix B of the NI-VISA Programmer Reference Manual.
Between lines 32 and 37, the value returned from the resource manager is
checked and the error (if any) displayed in the text box. If an error is found,
the Default Resource Manager is closed and the program terminated.
Figure 5–12
FindResourcesCB Function Listing
202 Chapter 5 • VXI Communication Using VISA
Figure 5–13
Expression List in viFindRsrc Function
Figure 5–14
SetupCommunication Function Listing
The VISA library function viSetAttribute at line 15 is used for setting the
attributes of the communication channel. There are numerous attributes you
can set by bringing up the function panel and clicking on the Attribute
Name field (see Figure 5–15). Here we are selecting the timeout attribute
and setting the timeout value to 5 seconds. The timeout value is entered in
milliseconds as the last argument of this function. It is necessary to set this
attribute for a message-based device to prompt you in case the device
“hangs up.”
204 Chapter 5 • VXI Communication Using VISA
Figure 5–15
Attributes in viSetAttribute Function Panel
The VISA library function viStatusDesc at line 18 takes the VISA status
code and converts it to a meaningful error message. In this program, the
error string is displayed on a message pop-up panel whenever there is a
communication error.
To send a string to a message-based device, you use the viWrite library
function. The reply from a message-based device is obtained in the string re-
turned by the viRead function. These functions are shown at lines 23–25.
The first argument of viWrite function is InstrHandle, the instrument
handle that was obtained from viOpen function. This identifies the device to
which you want to send the string message. At line 23 the string containing
the reset command (“*RST”) is sent to the device and the device identifica-
tion (“*IDN?") is requested at line 24 in the second argument of this func-
tion. These strings are standard IEEE 488.2 commands that are acceptable to
all VXI message-based devices.
Chapter 5 • VXI Communication Using VISA 205
The viRead function receives the string returned in read_buf and con-
tains the identification information for this device.
As mentioned above in the section Basics of Programming with VISA, to
write and read to a register-based device you use the viIn and viOut library
functions. This program is communicating with a message-based device,
and therefore functions relevant to such a device will be explained only for
this project.
Figure 5–16
ConfigAWGCB Function Listing (continued)
206 Chapter 5 • VXI Communication Using VISA
18 {
19 GetCtrlVal(AWGPanelHandle,AWG_PNL_AMP_50_OHMS, &Amp);
20 GetCtrlVal(AWGPanelHandle,AWG_PNL_DC_50HMS, &DC_Offset);
21
22 Fmt(cmdString, "%s<OUTP:LOAD 50"); //Set impedance to 50 ohms
23 status = viWrite (InstrHandle, cmdString, NumFmtdBytes(), VI_NULL);
24 Fmt(cmdString, "%s<OUTP:LOAD?"); //create command string
25 status = viWrite (InstrHandle, cmdString, NumFmtdBytes(), VI_NULL);
26 status = viRead (InstrHandle, imp_buf,BUFFER_LEN, VI_NULL);
27 Fmt(impedance, "%s<Impedance = %s\n", imp_buf);
28 InsertTextBoxLine (AWGPanelHandle, AWG_PNL_DISP, -1, impedance);
29
30 }
31 else //Open circuit
32 {
33 GetCtrlVal(AWGPanelHandle,AWG_PNL_AMP_OPEN_OHMS, &Amp);
34 GetCtrlVal(AWGPanelHandle,AWG_PNL_OPEN_DC, &DC_Offset);
35
36 Fmt(cmdString, "%s<OUTP:LOAD INF"); //Set impedance to OPEN
37 status = viWrite (InstrHandle, cmdString, NumFmtdBytes(), VI_NULL);
38 Fmt(cmdString, "%s<OUTP:LOAD?"); //read back configured impedance
39 status = viWrite (InstrHandle, cmdString, NumFmtdBytes(), VI_NULL);
40 status = viRead (InstrHandle, imp_buf,BUFFER_LEN, VI_NULL);
41 Fmt(impedance, "%s<Impedance = %s\n", imp_buf);
42 InsertTextBoxLine (AWGPanelHandle, AWG_PNL_DISP, -1, impedance);
43
44 }
45
46 //Select waveform
47 GetCtrlIndex(AWGPanelHandle,AWG_PNL_WAVE_SHAPE, &WaveIndex);
48 switch(WaveIndex)
49 {
50 case 0:
51 Fmt(cmdString, "%s<APPL:SIN %f, %f VPP, %f V",
52 frequency, Amp, DC_Offset);
53 status = viWrite (InstrHandle, cmdString, NumFmtdBytes(), VI_NULL);
54
55 Fmt(cmdString, "%s<APPL?"); //read back configuration
56 status = viWrite (InstrHandle, cmdString, NumFmtdBytes(), VI_NULL);
57
58 status = viRead (InstrHandle, read_buf,BUFFER_LEN, VI_NULL);
59 CopyString(Waveform, 0, "Sine",0, -1);
60 break;
61 case 1:
62 Fmt(cmdString, "%s<APPL:SQU %f, %f, %f ",
63 frequency, Amp, DC_Offset);
64 status = viWrite (InstrHandle, cmdString, NumFmtdBytes(), VI_NULL);
65
66 Fmt(cmdString, "%s<APPL?"); //read back configuration
67 status = viWrite (InstrHandle, cmdString, NumFmtdBytes(), VI_NULL);
68
69 status = viRead (InstrHandle, read_buf,BUFFER_LEN, VI_NULL);
Figure 5–16
ConfigAWGCB Function Listing (continued)
Chapter 5 • VXI Communication Using VISA 207
Figure 5–16
ConfigAWGCB Function Listing (continued)
208 Chapter 5 • VXI Communication Using VISA
Figure 5–16
ConfigAWGCB Function Listing (continued)
shown between lines 14 and 42. Notice that throughout this function we are
communicating with the device using the Standard Commands for Program-
mable Instrumentation (SCPI). SCPI are basically strings in a hierarchical tree
structure using a standard vocabulary to command and control the devices.
An introduction to SCPI is given in the book LabWindows/CVI Programming
for Beginners, but for instrument-specific communications, refer to the in-
strument’s User’s Manual. In the ConfigAWGCB function, the commands
specific to the function generator are used and are explained in the source
code listing.
At line 47 the waveform index selected is obtained and the SCPI com-
mand(s) is/are used to send the frequency, amplitude, and DC offset to the
function generator. For verification purposes the command(s) sent to the
function generator are read back from the function generator using the
“APPL?” command and displayed in the text box on the GUI.
When you exit the program, be sure first to close the communication
channel to the device and then the channel to the VISA Default Resource
Manager using the respective handles in the library function viClose. This
is shown in the source code listing of the ExitAWGCB callback function in
Figure 5–17.
Chapter 5 • VXI Communication Using VISA 209
//Exit device
int CVICALLBACK ExitAWGCB (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event)
{
case EVENT_COMMIT:
DiscardPanel(AWGPanelHandle);
viClose(InstrHandle);
viClose(ResourceManager);
QuitUserInterface(0);
break;
}
return 0;
}//ExitAWGCB
Figure 5–17
ExitAWGCB Function Listing
Summary
The aim of this chapter was to explain the hardware and software features of
the VXI system. This chapter gave you the basic features of VXI devices. You
were shown the differences between the various types of VXI devices and
how to communicate with them using VISA functions. By means of the pro-
ject and with the appropriate hardware connected to your computer, you
were able to send data to and receive data from the device. A short introduc-
tion to VISA was given here. Due to the vastness of VISA functionalities, all
the features could not be mentioned in this chapter. If you are interested in
learning its advanced features, refer to the On-line manuals.
AssertSysReset Function
The AssertSysReset function asserts the Sysreset line to the controller specified
on the VXI system. Its prototype is shown here and its arguments explained
in Table 5–4.
viAssertUtilSignal Function
The viAssertUtilSignal function asserts or deasserts the utility bus signal spec-
ified. Its prototype is shown here and its arguments explained in Table 5–5.
Input/
Output Name Type Description
0 successful
–1 unsupported function
–2 invalid controller
Chapter 5 • VXI Communication Using VISA 211
Input/
Output Name Type Description
viClose Function
The viClose function closes a communication channel to a resource. Its proto-
type is shown here and its arguments explained in Table 5–6.
Input/
Output Name Type Description
viFindNext Function
The viFindNext function finds the instrument descriptor of the next resource.
Its prototype is shown here and its arguments explained in Table 5–7.
viFindRsrc Function
The viFindRsrc function finds a list of matching instrument descriptors avail-
able on the system. Its prototype is shown here and its arguments explained
in Table 5–8.
viIn16 Function
The viIn16 function reads a 16-bit value from the A16, A24, or A32 address
space for register-based devices. Its prototype is shown here and its argu-
ments explained in Table 5–9.
viOpen Function
The viOpen function opens a communication channel to a device. Its proto-
type is shown here and its arguments explained in Table 5–10.
Input/
Output Name Type Description
Input/
Output Name Type Description
Input/
Output Name Type Description
■ VI_A16_SPACE
■ VI_A24_SPACE
■ VI_A32_SPACE
Input/
Output Name Type Description
(continued)
Chapter 5 • VXI Communication Using VISA 215
viOpenDefaultRM Function
The viOpenDefaultRM function opens a communication channel to the VISA
Default Resource Manager. Its prototype is shown here and its arguments
explained in Table 5–11.
viOut16 Function
The viOut16 function writes a 16-bit value to the A16, A24, or A32 address
space for register-based devices. Its prototype is shown here and its argu-
ments explained in Table 5–12.
viRead Function
The viRead function reads the data from the device specified. Its prototype is
shown here and its arguments explained in Table 5–13.
Input/
Output Name Type Description
Input/
Output Name Type Description
■ VI_A16_SPACE
■ VI_A2 4_SPACE
■ VI_A32_SPACE
viSetAttribute Function
The viSetAttribute function sets a specified attribute for the object given. Its
prototype is shown here and its arguments explained in Table 5–14.
Input/
Output Name Type Description
Output buffer unsigned buffer to read the data from the device
char[ ]
Input/
Output Name Type Description
viStatusDesc Function
The viStatusDesc function converts the status code to a string message. Its
prototype is shown here and its arguments explained in Table 5–15.
Input/
Output Name Type Description
viWrite Function
The viWrite function writes the data to the device specified. Its prototype is
shown here and its arguments explained in Table 5–16.
Input/
Output Name Type Description
This chapter introduces you to some of the basic hardware and software fea-
tures of data acquisition. You are introduced to the different configurations
in which the data acquisition can be performed by means of components of a
multifunction input/output DAQ (data acquisition) board. Signal condition-
ing is discussed and the various analog input/output parameters explained.
You are shown how to select the appropriate DAQ board using the DAQ
Designer tool and to install and set up the DAQ board. The use of the DAQ
Channel Wizard to configure and verify operations of DAQ channels is ex-
plained. Finally, the DAQ library functions for analog input/output, digital
input/output, and counter applications are explained by means of code
fragments.
220 Chapter 6 • Data Acquisition
Introduction
DAQ is a process by which a real-world physical phenomenon is converted
into an electrical signal by means of a transducer/sensor using data acquisi-
tion hardware and software. A transducer/sensor is a device that converts
physical phenomena (such as temperature, pressure, strain, light, motion,
flow, or any other measurable entity) into a proportional electrical stimulus.
DAQ hardware and software are used to acquire raw data from transduc-
ers/sensors connected to the DAQ system. The DAQ software acquires the
data and sends it on your computer. The DAQ system consists of transduc-
ers, a DAQ board, and optional signal conditioning devices. Signal condi-
tioning devices are discussed in the section Signal Conditioning.
To acquire data, you can use the DAQ board in various configurations.
Figure 6–1 shows the plug-in DAQ board residing inside the computer. A
single DAQ board receives the multiplexed and conditioned signals from
the Signal Conditioning eXtensions for Instrumentation (SCXI) modules.
If you are using a laptop computer, you can use a PCMCIA DAQ card, as
shown in Figure 6–2.
Figure 6–1
Plug-in DAQ Board Configuration (Copyright National Instruments)
Chapter 6 • Data Acquisition 221
Figure 6–2
PCMCIA DAQ Board Configuration (Copyright National Instruments)
To acquire data from a device located a distance from your computer, you
can use the serial, parallel, USB, or Ethernet interface to connect to a remote
DAQ board. The setup you use can be similar to that shown in Figure 6–3
using a remote SCXI chassis and SCXI modules. One serial bus, RS-485, al-
lows you to use up to 31 SCXI chassis per serial port at distances of up to
1200 meters from your computer.
Figure 6–3
Remote DAQ Board Configuration (Copyright National Instruments)
222 Chapter 6 • Data Acquisition
Figure 6–4
Multifunction DAQ Board Block Diagram (Copyright National Instruments)
Chapter 6 • Data Acquisition 223
The analog multiplexer is a switch that connects one or more of the input
channels to the instrumentation amplifier. During data acquisition from sev-
eral channels the multiplexer switches the channels in sequence to connect
to the instrumentation amplifier.
The instrumentation amplifier applies gain to the input voltage to keep it
within the ADC range. The gain is determined by the CVI function and is
applied according to the input signal limits.
The sample-and-hold circuitry ensures that the input voltage does not fluc-
tuate during analog-to-digital conversion. The sample-and-hold circuitry ac-
complishes this by holding the analog voltage from the instrumentation
amplifier and inputting it to the ADC as a steady unchanging input.
The DAC is used to convert the digital values into analog signals that can
be output from the DAQ board.
Digital I/O is discussed in the section Digital Input/Output.
The Counter/Timer circuitry on the DAQ board is used for counting pulses,
measuring pulse widths, pulse transition frequency, and for generating tim-
ing signals and pulse trains.
The RTSI bus interface on the DAQ card is a National Instruments inno-
vation used to route timing and trigger signals between multiple functions
on one DAQ board or between two or more boards. The RTSI is used to syn-
chronize A/D conversions, D/A conversions, digital inputs, digital outputs,
and counter/timer operations on multiple boards. This is useful when you
want to use two boards to capture data simultaneously or use the third
board to generate an output pattern synchronized with the sampling rate of
the inputs.
Signal Conditioning
At times, signals produced by the transducers/sensors may need to be con-
ditioned before being input to the DAQ board. Some form of signal condi-
tion device(s) is used to clean up the signal. Signal conditioning is most
appropriate under the following situations:
■ When you want to multiplex a large number of channels (more than are
supported by your DAQ board)
■ When you are using a mix of input/output (I/O) or transducer types
■ When operating in a noisy environment
224 Chapter 6 • Data Acquisition
The basic specifications for DAQ products consist of the sampling rate,
resolution, and input range. Sampling rate refers to the maximum rate at
which analog-to-digital (A/D) conversions take place. To obtain an accurate
representation of the input signal, a faster scan rate must be used, allowing
you to acquire more points in a given time frame. The Nyquist theorem
states that you must sample at twice the frequency component of the signal
to prevent aliasing. Aliasing refers to the distortion that appears in the digi-
tized signal that makes it appear to have an incorrect frequency. Depending
on your application, sampling at a rate five to 10 times the highest frequency
of a signal is recommended for an accurate representation of the waveform.
Resolution is the number of bits that an analog-to-digital converter (ADC)
uses to convert an analog signal. High resolution causes the voltage range to
be divided into more divisions, thus making it possible to detect a smaller
voltage change. This is made clear by looking at the example in Figure 6–5,
which shows a sine wave and its corresponding digital image using a 3-bit
converter. As you notice in this figure, the 10-volt range is divided into 23 or 8
divisions, represented by the binary code 000 through 111. The digitized
waveform from the 3-bit ADC is not an accurate representation of the original
226 Chapter 6 • Data Acquisition
signal since the resolution is not high enough. This is shown in the bottom
part of the figure. Using a 16-bit converter will divide the voltage range into 216
or 65,536 divisions, causing a higher resolution and more accurate representa-
tion of the analog waveform, as shown on the bottom right of Figure 6–5.
It is often required to provide stimuli to the DAQ system from the analog
output circuitry. Settling time, slew rate, and resolution of the DAC deter-
mine the quality of the output signal produced. Settling time is the time re-
quired for the output to stabilize to within a specified accuracy. Slew rate is
the maximum rate of change that the DAC can produce on the output signal.
A DAC with a short settling time and a high slew rate will change the out-
put to a new voltage level within a short time, making it possible to generate
high-frequency signals. The output resolution is similar to the input resolu-
tion discussed above.
Figure 6–5
Resolution Example Using 3- and 16-bit ADC (Copyright National
Instruments)
Chapter 6 • Data Acquisition 227
This change in voltage represents 1 LSB (least significant bit) of the digital
value and is called the code width. If, for example, you are using a 12-bit DAQ
board with a 0- to 10-volt input range and a gain of 10, the smallest detectable
change (code width) will be calculated as follows using the equation above:
Now if the range were changed to –10 to 10 volts using the same DAQ
board attributes as above, the smallest detectable change would become
since the voltage range is 20 (–10 volts to +10 volts) in this case. By changing
the range and the gain, you can adjust the value for the smallest detectable
change in your application.
Figure 6–6
DAQ Designer Query Screen
Figure 6–7
NI-DAQ Installation
When the installation is complete, you are prompted to the Configure Mea-
surement and Automation System. Accept this option to bring up the Mea-
surement & Automation Explorer (MAX) window, as shown in Figure 6–8.
Your installation screens may look different, depending on the NI-DAQ ver-
sion you are using.
To confirm that your device is installed properly, click on the Devices
and Interfaces folder to see the device name in this folder. If at any time
you want to reconfigure or test the device, you can double-click on the Mea-
surement & Automation icon on your Windows desktop to run this utility.
Depending on the NI-DAQ version installed, your MAX window may look
different but as a minimum will consist of the following folders: Data
Neighborhood, Devices and Interfaces, IVI Instruments, and Scales.
In earlier versions of NI-DAQ, the Software folder is not included.
The Data Neighborhood folder includes the DAQ Channel Wizard
found in previous NI-DAQ versions. The DAQ Channel Wizard is explained
in the section Using the DAQ Channel Wizard.
Double-clicking on the Devices and Interfaces folder gives a list of
National Instruments devices with the device number shown in parentheses
(see Figure 6–8). This device number in used in the CVI function when refer-
ring to the board to perform the DAQ operations. Here the PCI-MIO-16E-4
board is installed as device 1. Devices will not be installed automatically if you
are using Windows NT, PCMCIA, and non-PnP (Legacy board) AT devices.
230 Chapter 6 • Data Acquisition
Figure 6–8
Measurement & Automation Explorer (MAX) Window
For the non-PnP (non-Plug&Play) board you must configure the board manu-
ally using the Add New Hardware option under Control Panel in Windows.
For more information on installing and configuring DAQ devices in Windows
NT, see the NI-DAQ release notes or the DAQ Troubleshooting Wizard on the
National Instruments Web site.
Double clicking on the Software folder shows a list of installed software
from where you can view, launch, or install the latest versions of the soft-
ware. You are shown how to accomplish this by the help available in the
right half of the MAX window shown in Figure 6–9. Again, your display
screens may look different depending on the DAQ version being used.
To configure and test the board, right-click on the PCI-MIO-16-E4 de-
vice in the Devices and Interfaces folder, and select Properties from
the menu. The Configuring Device window is displayed (Figure 6–10).
Under the System tab in the Configuring Device window, the configura-
tion for Memory Range, Interrupt Request, and Direct Memory Access as-
signed to the board from the Windows registry are displayed.
Chapter 6 • Data Acquisition 231
Figure 6–9
MAX Window with Software Installed
Figure 6–10
Devices and Interfaces Configuration: System Tab
232 Chapter 6 • Data Acquisition
Selecting the AI (Analog Input) tab, the options shown in Figure 6–11 are
displayed. In this window you can set Polarity/Range and Mode for the
board’s operation from the pull-down menu. You can select Polarity/Range
to obtain the desired precision, as explained in the section Range, Gain, and
Code Width above. The Modes for the DAQ board were explained in the sec-
tion Analog Input/Output Parameters.
The AO (Analog Output) tab allows you to set the Polarity of the analog
output channels (see Figure 6–12). You have an option to choose be-
tween Unipolar, Bipolar, Unipolar External Reference, or Bipolar Exter-
nal Reference.
Figure 6–11
Devices and Interfaces Configuration: AI Tab
Chapter 6 • Data Acquisition 233
Figure 6–12
Devices and Interfaces Configuration: AO Tab
You can select the accessories attached to the DAQ board (if any) by click-
ing on the Accessory tab and selecting from among the accessories shown in
the pull-down menu (see Figure 6–13).
The last tab, OPC, sets the analog input recalibration period in seconds
that is used with the NI-DAQ OPC server. If you are not using the OPC
server, you can ignore this setting, since it is disabled by default.
The Test Resources button on the System window (see Figure 6–10) will
test the system resources assigned to the DAQ board. A pop-up window dis-
playing the message “The device has passed the test” will appear if the
board is configured properly. Select OK to return to the System tab.
To test the individual functions of the DAQ board, select Run Test Panels…
from the System window. Figure 6–14 shows the Analog Input test for the
transducer connected on channel 0.
When you select the Analog Output tab on the Test Panel window, Fig-
ure 6–15 is displayed. In this window you can either set a single voltage or a
sine wave, or set the output voltage on one of the DAQ board’s analog out-
put channels in the Channel Selection: dialog box. The output selected will
be displayed continuously on the Test Panel window.
234 Chapter 6 • Data Acquisition
Figure 6–13
Devices and Interfaces Configuration: Accessory Tab
Figure 6–14
Run Test Panel: Analog Input Window
Chapter 6 • Data Acquisition 235
Figure 6–15
Run Test Panel: Analog Output Window
When the Counter I/O tab on the Test Panel window is selected, the
Counter I/O window is displayed (Figure 6–16) and is used for testing
the counter timers on the DAQ board. Select Simple Event Counting in
the Counter Mode dialog box, leave the counter to test in the Counter:
dialog box to GPCTR0, and select Start. The Counter Value: box will be
updated continuously and the GPCTR0 LED will be enabled in the
Counter Status subpanel. To stop the counter test, click on the Reset
command button. Test similarly for other counters by selecting from the
Counter: dialog box.
The Digital I/O tab on the Test Panel window is used for testing the digi-
tal lines on the DAQ board. To test these lines, check the Output radio but-
tons for the lines selected as output lines (see Figure 6–17, where lines 0–3
are output lines) and notice that the LEDs are turned off on the panel. To test
these lines, check on the Logic Level boxes for the Output lines and read the
logic on these lines using a voltmeter, oscilloscope, or LEDs connected to
these lines. Select the Close button to return to the board’s configuration
screen.
236 Chapter 6 • Data Acquisition
Figure 6–16
Run Test Panel: Counter I/O Window
Figure 6–17
Run Test Panel: Digital I/O Window
Chapter 6 • Data Acquisition 237
If you have SCXI hardware installed on your system, you would need to
configure it also. The SCXI installed will appear as a folder under the Devices
and Interfaces folder in the MAX window (not shown in Figure 6–8).
When you click on the SCXI chassis folder, the right half of the window dis-
plays the modules in the SCXI chassis with the Chassis Address and Chassis
Identification. Right-click on the SCXI Chassis in the left half of the window,
and select Properties from the pull-down menu. The Configuring SCXI win-
dow is displayed, from where you can set the Chassis ID and the Chassis Ad-
dress. To configure the modules in the SCXI chassis, right-click on each module
in the right-half window one at a time and select Properties. The window to
configure the SCXI module is displayed from where you can set the operating
mode, DAQ board to control the SCXI chassis, channel gains, and filters (if any
are used). You can also select the accessory connected (if any).
The Data Neighborhood folder contains the DAQ Channel Wizard to cre-
ate aliases for your signals connected to the channels on your DAQ board. The
IVI Instruments folder shown in Figure 6–18 contains the Logical Name
Wizard and the Interchangeable Virtual Instruments (IVI) logical names. The
right half of the window contains a description of the items selected. The
Scales folder contains a wizard to customize the scales for your channel con-
figurations. The purpose of the Scales folder is given in the next section.
Figure 6–18
MAX Window: IVI Instruments
238 Chapter 6 • Data Acquisition
Figure 6–19
DAQ Channel Wizard: Create New Window
Chapter 6 • Data Acquisition 239
Highlight the Virtual Channel option in the Create New… window and
select the Finish button. This will bring up a Create New Channel window
(Figure 6–20) from where you can create an alias channel name and config-
ure either an Analog Input, Analog Output, or Digital I/O channel.
An example of setting up an analog input channel is given below. Select
Analog Input from the pull-down menu in Figure 6–20 and click on Next>.
This will bring up a dialog window (Figure 6–21) where you can enter the
Channel Name and Description. Enter Temp_Sensor0 in this box. Type a
brief description of the purpose of this channel in the Channel Description
box. After this channel is configured, you can refer to it in your software by
its alias name (Temp_Sensor0).
Select Next> to display Figure 6–22, from where you can select the type of
sensor or measurement from the pull-down menu list. Select Voltage from
the pull-down list box and a new window will be displayed (figure not
shown) with your choice. Also, be sure to check the box next to This will be
a temperature measurement if you are measuring temperature using this
channel, as in this example.
In the next window (not shown) you define the Units and Range of the
temperature sensor. When you select Next> from this window, Figure 6–23
is displayed, where you define the signal’s scaling.
Figure 6–20
DAQ Channel Wizard: Create New Channel Window
240 Chapter 6 • Data Acquisition
Figure 6–21
DAQ Channel Wizard: Channel Name and Description Window
Figure 6–22
DAQ Channel Wizard: Type of Sensor or Measurement Window
Chapter 6 • Data Acquisition 241
Figure 6–23
DAQ Channel Wizard: Signal Scaling Choices Window
If you are using your own scaling, select New Custom Scale… and a win-
dow will be displayed asking you to input the Scale Name, Scale Descrip-
tion, and Scale Type. Enter the relevant information as shown in Figure 6–24
and click on Scale Type. You have a choice of Linear, Polynomial, or Table
scales. In this case, since you are using a temperature sensor, select Linear
Scale. For a description and meaning of the different types of scales and
other information about the Measurement & Automation Explorer, select
Help>>Help Topics in the Measurement & Automation Explorer menu.
From there you can navigate to the appropriate topic.
When you select Next> in Figure 6–24 you are asked to enter the values
for the linear scale values. The scaling factor for the temperature sensor is to
multiply the voltage reading by 100 to obtain the degrees. Therefore, enter
100.0 for the m value in Figure 6–25. Since there is no offset, leave b as 0.
Click Next> to verify that the scale is configured correctly. A linear plot with
the scaling factors you selected will be shown as in Figure 6–26.
When Finish is selected in Figure 6–26, a window showing the scale’s
name just created (TempScale in this example) with scale values selected is
displayed. Note that this scale name is also displayed when you select the
Scales folder in the Data Neighborhood window.
242 Chapter 6 • Data Acquisition
Figure 6–24
DAQ Channel Wizard: Create New Custom Scale Window
Figure 6–25
DAQ Channel Wizard: Scale Coefficient Window
Chapter 6 • Data Acquisition 243
Figure 6–26
DAQ Channel Wizard: Verify Scale Window
Select Next> from the window showing the scale information; Figure 6–27
is displayed with the DAQ hardware settings. Select the appropriate values
in the dialog boxes for this channel.
The Finish button configures the channel that is now visible in the Data
Neighborhood window. Similarly, you can define and configure other channels
on your DAQ board. When configured, these will appear in the Data Neighbor-
hood window. Figure 6–28 shows the three channels configured with their alias
names: Temp_Sensor0, SineWave_Ch1, and SquareWaveCh2 for channels 0,
1, and 2, respectively, with their settings in the window on the right.
To view the configuration of an individual channel, right-click on the
channel name in the Data Neighborhood window (Figure 6–28) and select
Properties from the pull-down menu. Figure 6–29 gives the related configu-
ration values for the channel selected.
Before you run your application, you may want to test the individual chan-
nels with the appropriate signals connected. Connect the signal to that chan-
nel, right-click on the channel name in the Data Neighborhood window, and
select Test. A test window will display the signal waveform on the channel
selected. Figure 6–30 is the waveform for a square-wave input connected to
244 Chapter 6 • Data Acquisition
Figure 6–27
DAQ Channel Wizard: Hardware Settings
Figure 6–28
Data Neighborhood: Created Channels
Chapter 6 • Data Acquisition 245
analog input channel 2. This test will give you confidence that your channel
is configured and you can measure the signal correctly.
Figure 6–29
Channel Configuration Window
Figure 6–30
DAQ Channel Wizard: Test Panel
246 Chapter 6 • Data Acquisition
The scale names created appear in the Scales folder in the MAX window
(see Figure 6–31). When you right-click on the scale name that you created,
you have a choice of Delete and Properties… from the pull-down menu. Se-
lecting the Properties… menu item will display the current scale settings
that can be modified from the window displayed.
Hardware Configurations
There are three parameters that must be set up on the DAQ board: Base I/O
Address, Interrupt Level, and Direct Memory Access (DMA). On Plug&Play
DAQ boards, these parameters are configured from the software. On non-
Plug&Play DAQ boards, the configuration is done through jumpers and dip-
switches provided that there is no conflict with the hardware. If you make a
change to the jumper settings on the board, you must change the software
configuration accordingly.
Figure 6–31
DAQ Channel Wizard: Scales Window
Chapter 6 • Data Acquisition 247
■ Base I/O Address. Base I/O Address settings are used to determine
where in the computer’s I/O space the board’s registers reside. The
DAQ board uses these registers to communicate with the computer.
The DAQ driver software writes to the configuration registers to con-
figure the board and reads from the data registers on board to obtain
the board’ s status and data.
■ Interrupt Level. Interrupt Level is a means of informing the processor
of the priority with which it must handle the interrupt request from the
DAQ board. Each interrupt-generating device is assigned a different in-
terrupt level in order for the processor to decide uniquely when to han-
dle the interrupt in order to avoid conflicts.
■ Direct Memory Access (DMA). The DAQ board can communicate with
the computer through DMA. DMA increases the data throughput by
transferring the data directly from the peripheral to the computer mem-
ory, bypassing the processor. DMA is genrally used when high-speed
data transfer is required.
If at any later time you want to set up NI-DAQ, obtain On-line Help, or
access the DAQ documentations, you can do so from the Windows Start
menu and follow the path shown in Figure 6–32.
Figure 6–32
NI-DAQ Setup Path
248 Chapter 6 • Data Acquisition
Analog Input
To access the Analog Input Easy I/O DAQ library functions, select Library>>
Easy I/O for DAQ>>Analog Input.
Let us look at the fundamental steps involved in data acquisition using
the library functions when sampling analog input channels:
1. Identify the channel(s) you wish to acquire the data from, and the data
type to be created. This is accomplished by using the nidaqAICreateTask
library function. This function returns a unique identifier called the task
identifier associated with the data acquisition task. This task identifier
is used in subsequent function calls to identify the DAQ board, chan-
nel(s) and the type of analog input task.
2. Call the nidaqAIStart library function to start acquiring the data from
the channel(s) using the task identifier created in the nidaqAICreateTask
library function.
3. Retrieve analog input data from the channel(s) selected by calling the
nidaqAIRead library function. In this function you can specify a subset of
channels to retrieve data from selected channels if you are scanning
multiple channels. In this function you also specify the number of scans
to acquire. A scan is one sample from each channel in multichannel
data acquisition.
Chapter 6 • Data Acquisition 249
You will see how these steps are accomplished by looking at a simple data
acquisition project. Load and run project6-1 to bring up the GUI shown
in Figure 6–33. This GUI is shown with the channel selection options in the
Channel String ring control.
The data acquisition library functions in the source code (Figure 6–34) are
annotated with the step numbers shown above.
When you select the START command button the StartAcquisitionCB
function at line 27 is invoked. At line 40 the nidaqAICreateTask library func-
tion is called and is repeated here for your convenience.
Figure 6–33
Analog Input Example GUI for project6-1
250 Chapter 6 • Data Acquisition
1 #include <utility.h>
2 #include <cvirte.h>
3 #include <userint.h>
4 #include <easyio.h>
5 #include <ansi_c.h>
6 #include "project6-1.h"
7
8 static int DAQHandle;
9 long TaskID, daq_error, NumOfChannels;
10 char *ErrorString, Channel_Selected[100];
11 static double AcquiredData[2000];
12 int StartFlag=0;
13
14 int main (int argc, char *argv[ ])
15 {
16 if (InitCVIRTE (0, argv, 0) == 0)
17 return -1; /* out of memory */
18 if ((DAQHandle = LoadPanel (0, "project6-1.uir", PANEL)) < 0)
19 return -1;
20 DisplayPanel (DAQHandle);
21 RunUserInterface ();
22 DiscardPanel (DAQHandle);
23 return 0;
24 } //main
25
26 //Invoked from START command button
27 int CVICALLBACK StartAcquisitionCB (int panel, int control, int event,
28 void *callbackData, int eventData1, int eventData2)
29 {
30
31
32 switch (event)
33 {
34 case EVENT_COMMIT:
35 //Obtain the channel string from the control box
36 GetCtrlVal (DAQHandle, PANEL_CHL_STR, Channel_Selected);
37 ClearStripChart (DAQHandle, PANEL_STRIP_CHART); //Clear the strip chart
38
39 //Step 1 - Create data acquisition task
40 daq_error = nidaqAICreateTask (Channel_Selected, kNidaqPointByPoint,
41 &NumOfChannels, &TaskID);
42 if ( daq_error !=0)
43 {
44 ErrorString = nidaqGetErrorString (TaskID, daq_error);
45 InsertTextBoxLine (DAQHandle, PANEL_ERROR_BOX, -1, ErrorString);
46 }
47
48 //Step 2 - Start data acquisition
49 daq_error=nidaqAIStart(TaskID);
50 if ( daq_error !=0)
51 {
Figure 6–34
Source Code Listing for project6-1 (continued)
Chapter 6 • Data Acquisition 251
Figure 6–34
Source Code Listing for project 6-1 (continued)
252 Chapter 6 • Data Acquisition
103 {
104 ErrorString = nidaqGetErrorString (TaskID, daq_error);
105 InsertTextBoxLine (DAQHandle, PANEL_ERROR_BOX, -1, ErrorString);
106 }
107 daq_error =nidaqAIDestroyTask (TaskID);
108 if ( daq_error !=0)
109 {
110 ErrorString = nidaqGetErrorString (TaskID, daq_error);
111 InsertTextBoxLine (DAQHandle, PANEL_ERROR_BOX, -1, ErrorString);
112 }
113
114 StartFlag=0; //Stop timer - disable flag
115 break;
116 }
117 return 0;
118 }
119
120 //Invoked from QUIT command button
121 int CVICALLBACK QuitAcquisitionCB (int panel, int control, int event,
122 void *callbackData, int eventData1, int eventData2)
123 {
124 switch (event)
125 {
126 case EVENT_COMMIT:
127 /*Stop data acquisition either in this function
128 or in "Stop Acquisition CB" function. If you try
129 to stop a task that is already stopped, a
130 library error occurs.*/
131
132
133
134
135 //Step 6 - Relinquish the resources
136 daq_error =nidaqAIDestroyTask (TaskID);
137 if ( daq_error !=0)
138 {
139 ErrorString = nidaqGetErrorString (TaskID, daq_error);
140 InsertTextBoxLine (DAQHandle, PANEL_ERROR_BOX, -1, ErrorString);
141 }
142 StartFlag=0; //Stop timer - disable flag
143 QuitUserInterface (0);
144 break;
145 }
146 return 0;
147 } //QuitAcquisitionCB
Figure 6–34
Source Code Listing for project6-1 (continued)
The arguments for the nidaqAICreateTask function are explained. The first
argument, ChannelSelected of nidaqAICreateTask, is a string called the
channel path that specifies the channel(s) from where you want to acquire the
Chapter 6 • Data Acquisition 253
data. There are two ways in which you can specify the channel paths: using
the channel name aliases set up by the Data Channel Wizard as explained
above in the section Using the DAQ Channel Wizard or by using the NI-DAQ
syntax. The channel path in this example is obtained from the Channel
String ring control (Figure 6–31). The first list item in the Channel String
ring control is
"daq::1!(1)"
Let us examine what this syntax means and how it is structured. The
channel path always starts with “daq::”, followed by the device number,
which in this case is “1,” followed by “!”. The character “!” is a separator
between the strings, followed by the channel number in parentheses, “(1)”
in this example.
You can also specify the channel path as a range. For example, if you
wanted to acquire data from channels 1–3, on device 1 you could use the NI-
DAQ syntax as follows:
"daq::1!(1:3)"
In addition, the channel numbers you may want to acquire data from may
not be contiguous. For example, to acquire data from channels 1, 2, 3, and 8,
the NI-DAQ syntax will be as follows:
"daq::1!(1:3,8)"
The NI-DAQ syntax used to acquire data using the SCXI chassis, the mod-
ule number in the SCXI chassis, and the channel number is of the form
"daq::1!(ob#!sc#!md#!ch#)"
where
"daq::1!(ob0!sc1!md2!ch2)"
would acquire data from SCXI channel 2 from the module in slot 2 of SCXI
chassis 1, that is sent to channel 0 of the onboard DAQ (device 1).
254 Chapter 6 • Data Acquisition
In this example we are capturing the data point by point using the re-
served word nidaqPointByPoint.
The third argument, NumOfChannels, returns the number of channels in
the channel path argument. You may use this information in your application
to set up the number of channels to plot on the strip chart, for example.
The last argument of this function is the task identifier. This identifier is
used in subsequent function calls when referring to the task created with the
configuration in nidaqAICreateTask.
Each NI-DAQ library function returns a status code to indicate
whether the function has performed successfully. In this example the
status code is returned in the variable nidaq_error. As always, you
must check for errors whenever making a call to the library functions.
When the status code returns the value 0, it implies that there are no
errors or warnings. Warnings are indicated by the status code being a
positive number and errors by a negative value. You can get a detailed
listing of status codes from the desktop by selecting Start>>Programs>>
National Instruments>>Ni-DAQ>>NI DAQ Help, selecting the Contents
tab, and clicking on Status Codes.
A better way to obtain the meaning of the status code(s) is to let your ap-
plication decipher the status code(s) using the NI-DAQ library function
nidaqGetErrorString, which gives a text description of the status code. This
function is shown on line 44 and is repeated here.
This function takes the task identifier as the first argument and the status
code is the second argument. This function returns the description of the sta-
tus code in the string ErrorString. In this program the ErrorString is
displayed in the text box on the GUI.
Chapter 6 • Data Acquisition 255
The library function nidaqAIStart at line 49 starts the data acquisition for
the channel(s) specified by the task identifier created in the library func-
tion nidaqAICreateTask. This function consists of the task identifier as the
only argument.
Data is obtained from the DAQ card using the nidaqRead library function
at line 79, called by the TimerTickCallback function. The TimerTickCallback
function reads the data at the rate specified in the timer control. The argu-
ments of the nidaqRead library function are as follows:
The first argument of this function is the task identifier that was created
using the function nidaqAICreateTask. The second argument is the channel
path, as explained above for the nidaqAICreateTask function argument. This
channel path can be a list of one or more of the channels specified in the
nidaqAICreateTask function, or an empty string (“”) can be used to specify all
channels in the task. The third argument is the number of scans to acquire
(one in this case). The fourth argument is the maximum time in seconds to
wait for the data before the function returns a timeout error. As shown in
this example, “-1.0” is the default argument value and is used to let the
function calculate the timeout based on the acquisition rate and the number
of scans. You can disable the time limit by entering a “-2.0” for this argu-
ment. The last argument of this function contains the data acquired in the
array AcquiredData. This array contains the data acquired from the chan-
nel(s) specified in the channel path. If you had created the channel path
using the DAQ Channel Wizard, the data is the units of channel that you
had specified in the DAQ Channel Wizard. If you are using the NI-DAQ
syntax, all the data is in volts. At line 88 the AcquiredData is plotted on the
strip chart using the PlotStripChart library function.
When you select the QUIT command button, the QuitAcquisitionCB func-
tion is called to stop data acquisition, relinquish the resources being used,
and stop event processing from the user interface. The nidaqAIStop library
function at line 101 stops data acquisition for the task specified as the argu-
ment in this function. The nidaqAIDestroyTask library function at lines 107
and 136 contains the task identifier for which you want to relinquish the re-
sources. After calling this function, the task identifier is no longer valid and
cannot be used until you create the task using the nidaqAICreateTask library
function again. The StopAcquisitionCB function stops data acquisition with-
out exiting the program.
256 Chapter 6 • Data Acquisition
Figure 6–35
project6-1 Sample Run
Chapter 6 • Data Acquisition 257
Figure 6–36
project6-2 Sample Run
The code segment that is executed when Scans is selected from the Mode
binary switch on the GUI is shown in Figure 6–37.
The nidaqAIScanOp function, called at line 11, is
Figure 6–37
project6-2 Code Segment
you can later change the data to group by channel using the GroupByChannel
library function.
Looking at the arguments of nidaqAIScanOp, the ActualRate argument
returns the actual scan rate (in seconds per second) for data acquisition and
could be different from the ScanRate. The waveform data from the selected
channel(s) is returned in the data array ScanData, which is ordered as spec-
ified by the fillmode. The values for the channel will be in the units of the
channel if the channel string used was referencing a channel created using
the DAQ Channel Wizard. The values will be in volts if the channel string
uses the NI-DAQ syntax, as in this case.
Analog Output
Multifunction input/output DAQ boards contain digital-to-analog converters
(DACs) to convert digital values to analog values. This functionality generates
outputs that you can send to the analog output channel(s) of the DAQ board
and to the devices connected to these channel(s). To do so, you use the DAQ li-
brary functions. To access the Analog Output Easy I/O DAQ library functions,
select Library>>Easy I/O for DAQ>>Analog Output. The four analog output
library functions are displayed in the function tree panel: AOUpdateChannel,
AOUpdateChannels, AOGenerateWaveforms, and AOClearWaveforms. Below we
look at the purpose of these library functions and how they are used.
short deviceNumber=1;
double voltage =3.6:
.
.
.
.
AOUpdateChannel( deviceNumber, "2", voltage);
short deviceNumber=1;
double voltage[3] ={1.1, 2.1,.8};
.
.
.
short deviceNumber=1;
double updatesSecond = 5.0; //Number of updates per second
int updatesChannel =9; //Number of D/A conversion that
//comprises a waveform
int iterations =0; //Generate waveform continuously
double waveform[ ] ={1.1,1.2,1.4,2.1,2.2,2.4,4.1,4.2,4.4};
unsigned long taskID; //Used in subsequent function calls
.
.
.
.
AOGenerateWaveforms( deviceNumber, "0,2,4", updatesSecond,
updatesChannel, iterations, waveform, &taskID);
.
.
.
.
Here each waveform contains nine elements from the waveform array.
■ AOClearWaveforms. The AOClearWaveforms function clears the wave-
form generated by AOGenerateWaveforms when you pass a 0 for the it-
erations argument in AOGenerateWaveforms to generate the waveform
continuously.
Digital Input/Output
The Digital I/O of a DAQ board contains several digital lines for sensing and
controlling multiple digital signals. The digital I/O circuitry on the DAQ
board is used for reading and writing data to peripheral equipment, control-
ling processes, and sending test patterns. The number of digital lines avail-
able, the rate at which these lines can send and receive data, and the drive
capability of the lines all determine how you can use this feature of the DAQ
card. Several digital I/O lines are grouped into a port (four lines comprise a
port on the MIO board). The digital I/O port can be configured to read data
from or write data to the entire port or from single digital lines within a port.
You can set the configuration of the port through CVI as input or an output
port using the DAQ library function DIG_Prt_Config. Some boards, such as
MIO E-series, 6533 family, 6602 family, and TIO-10, allow you to configure
each digital line individually as an input or output using the DAQ library
function DIG_Line_Config. In other boards all digital lines within the same
port must be configured as either input or output.
When the port is configured as an input port, reading the port returns the
values of the digital lines as logical high or low. When configured as an out-
put port, writing to the port sets each digital line of the port to the corre-
sponding digital logical high or low value, enabling you to send data to an
external device through these lines. The digital circuitry of the DAQ board
can input and output digital signals using transistor-transistor (TTL) logic.
The TTL signal is considered logical low if the voltage is between 0 and 0.8
volt and logical high if the voltage lies between 2.0 and 5.5 volts.
There are two categories of digital applications: immediate and timed. Imme-
diate digital I/O instantaneously updates or reads a line or port when a call to
the digital library function is made. In timed digital I/O, external signals are used
to control or handshake the data transfers. This ensures that the DAQ board
and the instrument are ready to transfer data before starting the operation.
262 Chapter 6 • Data Acquisition
To access digital input/output functions from the easy I/O DAQ library
functions, select Library>>Easy I/O for DAQ>>Digital Input/Output….
You will see four digital output library functions in the displayed function
tree panel: ReadFromDigitalLine, ReadFromDigitalPort, WriteToDigitalLine, and
WriteToDigitalPort. The purpose of these library functions is shown by
means of code fragments.
short device=1;
char PortNumber = "1"; //Port Number on the DAQ
short line =3; //Line number in the port
short PortWidth = 4; //Number of lines in a port
long Configure=1; // 1=Always configure; 0 = Only if necessary
unsigned long LineState=1; //State of digital line
short device=1;
char PortNumber = "2"; //Port Number on the DAQ
short PortWidth = 4; //Number of lines in a port
long Configure=1; // 1=Always configure; 0 = Only if necessary
unsigned long WritePattern =5; //Pattern to write "0101"
Counter Fundamentals
Counters on the DAQ board provide the means to manipulate and coordi-
nate various timing parameters and events. A counter is a device that counts
digital signal transitions or generates various types of timing signals. A
counter event is any TTL rising or falling edge that occurs at the SOURCE
input of the counter. The inputs and outputs of the counter are shown in
Figure 6–38.
264 Chapter 6 • Data Acquisition
GATE OUT
Count
Register
SOURCE
(CLK)
Figure 6–38
Typical Counter
Chapter 6 • Data Acquisition 265
Rise Fall
Time Time
+5 V
0V Minimum
Pulse Width
Figure 6–39
Counter Signal Characteristics
Counter Applications
In this section we look at some common counter applications. The counter
applications discussed are event counting and timing, pulse generation,
pulse width or period measurement, and frequency measurement. To access
the Counter Easy I/O DAQ library functions, select Library>>Easy I/O for
DAQ>>Counter/Timer… .
266 Chapter 6 • Data Acquisition
Figure 6–40
CounterEventOrTimeConfig Code Fragment
Chapter 6 • Data Acquisition 267
The taskID is the last argument for this function and is the identifier
number assigned to this counter operation. It is used in subsequent function
calls when referring to the operation.
After you have configured the counter, you start the counting operation
by calling the library function CounterStart with the taskID as its argument,
as shown on line 19. The taskID is created by the CounterEventOrTimeConfig
function. The CounterStart function is valid only for DAQ-STC and Am9513
counters.
The internal Count Register of the counter is read when the CounterRead
function is called, as shown on line 25. In your application you may want to
obtain this count continuously or only after a certain criterion has been met,
such as when the counter reaches the TC value. This function takes the
taskID as the first argument, returns the count value from the internal
Count Register, and sets the overflow flag if the terminal count is exceeded.
This function is valid only for DAQ-STC and Am9513 counters.
The CounterStop function at line 32 stops the counting operation. This
function is valid only for DAQ-STC and Am9513 counters.
Pulse Generation
You can use the counter to generate either a single pulse or continuous pulses
(called a pulse train) on the OUT pin of a counter. Before explaining the li-
brary functions used for generating pulses, some terms need to be explained.
The duty cycle of a pulse is defined as
or equivalently,
Phase 1 Phase 2
/Delay /Width
Figure 6–41
Pulse Duty Cycle
The pulse polarity determines whether the pulse is high or low. The pulse
polarity is high/low if the phase 2 of the pulse is high/low. The high and
low pulse polarities are shown in Figure 6–42.
To configure a counter to generate a continuous TTL pulse train on its
OUT pin with a specified frequency, duty cycle, gate mode, and pulse polar-
ity, use the easy I/O DAQ library function ContinuousPulseGenConfig. The
code fragment in Figure 6–43 shows how this function may be used in your
application.
Figure 6–42
Pulse Polarity
270 Chapter 6 • Data Acquisition
Figure 6–43
ContinuousPulseGenConfig Code Fragment
the counter’s OUT pin with specified pulse delay, pulse width, and pulse
polarity. You can indicate the timebase source as internal or external to spec-
ify the signal used by the counter to count. The code fragment shown in Fig-
ure 6–44 demonstrates how this function can be used in your application.
The first and second arguments in the DelayedPulseGenConfig function are
the device number and the counter string, respectively, used for this opera-
tion, as seen above. The third argument is pulseDelay, the desired value of
the delay (Phase 1) (see Figure 6–41). The units for this argument are sec-
onds if timebaseSource is USE_INTERNAL_TIMEBASE and cycles if
timebaseSource is USE_COUNTER_SOURCE. The pulseWidth argument
is the desired pulse width (Phase 2) (Figure 6–42). Again, the units for this
argument are seconds if timebaseSource is USE_INTERNAL_TIMEBASE
and cycles if timebaseSource is USE_COUNTER_SOURCE. The next argu-
ment (USE_INTERNAL_TIMEBASE) is the timebase source and defines
whether an internal or external signal will be used for the delay and width
duration. You have the option of using either USE_INTERNAL_TIMEBASE
or USE_COUNTER_SOURCE. When you select USE_INTERNAL_TIMEBASE,
the onboard clock is used and the delay and pulse width are timed in sec-
onds. When USE_COUNTER_SOURCE is selected, you must connect the time-
base signal to the counter SOURCE pin, and the delay and pulse width are
timed in cycles of the external timebase signal. UNGATED_SOFTWARE_START
Figure 6–44
DelayedPulseGenConfig Code Fragment
272 Chapter 6 • Data Acquisition
and pulsePolarity arguments are the same as explained above for the
ContinuousPulseGenConfig function. This function returns values for the ac-
tual delay and actual pulse width that may be different from the values
specified, due to hardware limitations. The task identifier (taskID) is ob-
tained from CounterEventOrTimeConfig as explained above.
Pulse Measurement
Counters can be used to measure the pulse width or the period of a pulse or
pulse train. The Easy I/O for DAQ library function PulseWidthOrPeriodMeas-
Config configures the specified counter to measure the pulse width or period
of the TTL signal connected to the GATE pin of the counter. You can mea-
sure the pulse width or period by counting the number of cycles of the time-
base specified. The timebase can be either internal or external. The
PulseWidthOrPeriodMeasConfig function prototype is shown below and its ar-
guments explained.
The first two arguments of this function are the same as explained previ-
ously. In the typeOfMeasurement argument, you specify the type of pulse
width or period measurement you want to make. You can select from the
following options:
Frequency Measurement
Counters can be used to measure the frequency of an unknown pulse train
connected to the SOURCE pin of the counter. This is achieved by counting
the rising edges of the signal during a specified period of time. A pulse con-
nected to the GATE pin of the counter controls the time period specified. To
measure the frequency, you must connect the counter’s GATE pin to the
OUT pin of the second counter, referred to as “counter-1” or to an external
source of known pulse width. The CounterMeasureFrequency function config-
ures one counter, counter-1, to generate a pulse to the GATE of a second
counter, the event counter. The event counter counts the transition events on
the source signal and calculates the frequency of the source signal by divid-
ing the events counted by the pulse width of the pulse counter-1 sent to the
GATE of the event counter.
For example, if you have the pulse train of unknown frequency connected
to the SOURCE pin of counter-1, the OUT pin of counter-0 must be con-
nected to the GATE pin of counter-1. To calculate the pulse train frequency,
divide the pulse count by the gating period of the known pulse connected to
the GATE pin of counter-1.
A list of counters and counter-1 is shown in the CounterMeasureFrequency
function panel for both Am9513 and DAQ-STC counters. The CounterMeasure-
Frequency function prototype is shown below and its arguments explained.
The device and counterString are the board number and counter
string, respectively, that receive the pulse train. counterSize for the DAQ-
STC counter is 24 bits, and for the Am9513 counter could be 16 bits if one
counter is used or 32 bits if two counters are used. gateWidthSampleTime
is the width in seconds of the pulse used to gate the signal. MaxDelayBe-
foreGate is the maximum expected delay between the time the function is
called and the start of the gating pulse. A timeout error occurs if the gate sig-
nal does not start within this time. Counter1GateMode is the gate mode for
counter-1. The options for the gate mode for this function are the same as those
for CounterEventOrTimeConfig shown above.
actualGateWidth is the length in seconds of the gating pulse that is re-
turned from the hardware. It may differ from the gateWidthSampleTime
value specified. An Overflow value of 1 indicates counter overflow. A 0
value indicates normal operation. A Valid argument value of 1 indicates
that there was no counter overflow and the operation was completed suc-
cessfully. If the time limit expires during the function call, the timeout
value is set to 1. It is possible for a timeout and a valid measurement to occur
at the same time. A timeout does not produce a function error. The last argu-
ment returns the value of frequency of the pulse train connected to the
SOURCE pin of the counter.
Summary
This chapter introduced you to some of the basic hardware and software
features of data acquisition. You saw the basic MIO DAQ board hardware
architecture and how to select a DAQ board appropriate for your applica-
tion, install it, configure it, and acquire data using the various components
of the DAQ board. You were introduced to some of the easy I/O DAQ li-
brary functions and their use, demonstrated by means of code fragments.
Data acquisition is a vast topic, but here we only touched on the basics to get
you started. As you start to write sophisticated data acquisition applications,
you can look into the sample programs that are included in the samples
folder included with CVI and experiment with some of the more elaborate
DAQ library functions.
Chapter 6 • Data Acquisition 275
AOClearWaveforms Function
The AOClearWaveforms function clears the waveforms generated by AO-
GenerateWaveforms when you pass 0 for the iterations argument in
AOGenerateWaveforms. The prototype for AOClearWaveforms is shown
below and its arguments explained in Table 6–1.
AOUpdateChannel Function
The AOUpdateChannel function applies the specified voltage to a single ana-
log output channel. Its prototype is shown below and its arguments ex-
plained in Table 6–2.
Input/
Output Name Type Description
Input/
Output Name Type Description
AOUpdateChannels Function
The AOUpdateChannels function applies the specified voltage to analog out-
put channels specified in the channel string. Its prototype is shown below
and its arguments explained in Table 6–3.
AOGenerateWaveforms Function
The AOGenerateWaveforms function generates a timed waveform of the volt-
age data on the analog output channels specified. Its prototype is shown
below and its arguments explained in Table 6–4.
Input/
Output Name Type Description
Input/
Output Name Type Description
(continued)
278 Chapter 6 • Data Acquisition
ContinuousPulseGenConfig Function
The ContinuousPulseGenConfig function configures a counter to generate a
continuous TTL pulse train on its OUT pin. Its prototype is shown below
and its arguments explained in Table 6–5.
CounterEventOrTimeConfig Function
The CounterEventOrTimeConfig function configures one or two counters to
count edges in the signal on the counter SOURCE pin specified or the num-
ber of cycles of an internal timebase signal. Its prototype is shown below and
its arguments explained in Table 6–6.
Input/
Output Name Type Description
Input/
Output Name Type Description
(continued)
280 Chapter 6 • Data Acquisition
■ COUNT_UNTIL_TC
■ COUNT_CONTINUOUSLY
■ COUNT_ON_RISING_EDGE
■ COUNT_ON_FALLING_EDGE
CounterMeasureFrequency Function
The CounterMeasureFrequency function measures the frequency of a TTL sig-
nal on the counter SOURCE pin specified by counting the rising edges of the
signal during a certain time. Its prototype is shown below and its arguments
explained in Table 6–7.
CounterRead Function
The CounterRead function reads the counter identified by the task identifier.
This function is used for DAQ-STC and Am9513 counters only. Its prototype
is shown below and its arguments explained in Table 6–8.
CounterStart Function
The CounterStart function starts the counter identified by the task identifier.
This function is used for DAQ-STC and Am9513 counters only. Its prototype
is shown below and its arguments explained in Table 6–9.
CounterStop Function
The CounterStop function stops the counter identified by the task identifier.
This function is used for DAQ-STC and Am9513 counters only. Its prototype
is shown below and its arguments explained in Table 6–10.
Input/
Output Name Type Description
Input/
Output Name Type Description
Input/
Output Name Type Description
Input/
Output Name Type Description
DelayedPulseGenConfig Function
The DelayedPulseGenConfig function configures a counter to generate a de-
layed TTL pulse train or triggered pulse train on its OUT pin. Its prototype
is shown below and its arguments explained in Table 6–11.
DIG_Line_Config Function
The DIG_Line_Config function configures the specified line for input or out-
put. This function is supported by DIO-32HS, PC-TIO-10, and MIO E-series
boards only. Its prototype is shown below and its arguments explained in
Table 6–12.
DIG_Prt_Config Function
The DIG_Prt_Config function configures the specified port for input, output,
or bidirectional. This function is used on all boards that support digital I/O.
Its prototype is shown below and its arguments explained in Table 6–13.
Input/
Output Name Type Description
(continued)
286 Chapter 6 • Data Acquisition
Input/
Output Name Type Description
0 input
1 output
GroupByChannel Function
The GroupByChannel function reorders an array of data from group by scan
mode into grouped by channel mode. Its prototype is shown below and its
arguments explained in Table 6–14.
Chapter 6 • Data Acquisition 287
Input/
Output Name Type Description
■ DIO-24
■ DIO-96
■ Lab and 1200 series boards
■ AT-MIO-16DE-10
■ AT-MIO-16D
0 input
1 output
2 bidirectional
Input/
Output Name Type Description
nidaqAICreateTask Function
The nidaqAICreateTask function creates an analog input task. Its prototype is
shown below and its arguments explained in Table 6–15.
nidaqAIDestroyTask Function
The nidaqAIDestroyTask function destroys the task, making the task identifier
number invalid for use in other function calls. Its prototype is shown below
and its arguments explained in Table 6–16.
Input/
Output Name Type Description
kNidaqPointByPoint
kNidaqWaveformCapture
Input/
Output Name Type Description
nidaqAIRead Function
The nidaqAIRead function retrieves the analog input data from the analog
input storage buffer. Its prototype is shown below and its arguments ex-
plained in Table 6–17.
nidaqAIScanOp Function
The nidaqAIScanOp function acquires a finite number of scans from analog
input channels. Its prototype is shown below and its arguments explained in
Table 6–18.
Input/
Output Name Type Description
Input/
Output Name Type Description
■ kNidaqGroupByChannel—group
by channels
■ kNidaqGroupByScan—group by
scans
nidaqAISinglePointOp Function
The nidaqAISinglePointOp function acquires a single value from an analog
input channel. Its prototype is shown below and its arguments explained in
Table 6–19.
292 Chapter 6 • Data Acquisition
Input/
Output Name Type Description
nidaqAISingleScanOp Function
The nidaqAISingleScanOp function retrieves a single scan of values from ana-
log input channels. Its prototype is shown below and its arguments ex-
plained in Table 6–20.
nidaqAIStart Function
The nidaqAIStart function starts data acquisition on the analog input task
identifier specified. Its prototype is shown below and its arguments ex-
plained in Table 6–21.
Input/
Output Name Type Description
Input/
Output Name Type Description
nidaqAIStop Function
The nidaqAIStop function stops data acquisition on the analog input task
identifier specified. Its prototype is shown below and its arguments ex-
plained in Table 6–22.
Input/
Output Name Type Description
nidaqGetErrorString Function
The nidaqGetErrorString function returns the string with a description of the
error code. Its prototype is shown below and its arguments explained in
Table 6–23.
PulseWidthOrPeriodMeasConfig Function
The PulseWidthOrPeriodMeasConfig function configures the counter specified
to measure the pulse width or period of a TTL signal connected to its GATE
pin. This function is used with DAQ-STC and Am9513 counters only. Its
prototype is shown below and its arguments explained in Table 6–24.
Input/
Output Name Type Description
Input/
Output Name Type Description
ReadFromDigitalLine Function
The ReadFromDigitalLine function reads the logical state of digital line on a
port that is configured as input. Its prototype is shown below and its argu-
ments explained in Table 6–25.
Input/
Output Name Type Description
ReadFromDigitalPort Function
The ReadFromDigitalPort function reads the digital port that is configured as
input. Its prototype is shown below and its arguments explained in Table 6–26.
Input/
Output Name Type Description
Output pattern unsigned data read from the specified digital port
long*
WriteToDigitalLine Function
The WriteToDigitalLine function writes the logical state of a digital line on a
port that is configured as output. Its prototype is shown below and its argu-
ments explained in Table 6–27.
Input/
Output Name Type Description
WriteToDigitalPort Function
The WriteToDigitalPort function writes a digital pattern to the digital port
that is configured as output. Its prototype is shown below and its arguments
explained in Table 6–28.
Input/
Output Name Type Description
This chapter will show you how to create a function tree and include classes
and functions to the function tree. You will see how to create a function
panel using various types of function panel controls and adding help text to
the function panel and the controls. In this chapter you are stepped through
creating a function tree with two function panels using algebraic equations.
These functions are tested using the Interactive Execution Window (IW).
You are introduced to the various types of controls that you can use on func-
tion panels and shown how to interchange control types with ease.
302 Chapter 7 • Creating and Using Function Panels
Figure 7–1
Sample Function Panel
Chapter 7 • Creating and Using Function Panels 303
After you have entered the data in the function panel template, you can
insert the function with the specified arguments into your source code at the
location of the cursor by selecting Code>>Insert Function Call (shortcut is
<Ctrl –I>) from the function panel. The same can be accomplished by click-
ing on the Insert Function Call icon on the function panel toolbar.
The Insert Function Call icon is similar to selecting Code>> Insert Function
Call from the function panel menu.
If you want to test the function before inserting it in your code, you can
run and test it by executing the Interactive Execution Window by selecting
the Code>>Run Function Panel from the function panel. Click on the Run
Function Panel icon on the function panel toolbar.
You can access the library function panel or the instrument driver by se-
lecting the Library menu or the Instrument menu, respectively. You can
choose a function panel by selecting from the Select Function Panel, a sam-
ple of which is shown in Figure 7–2.
The functions are grouped as a hierarchy in a multilevel structure called a
function tree. In a function tree the functions are arranged into various classes,
by grouping the functions that perform similar kinds of operations together.
For example, all the functions that perform the operations related to panels
are in one class, pop-up panel functions in another, menu control operations
in another, and so on. When you select the class from the Select Function
Panel, you can traverse through the list of classes until you find the function
panel you need. The Select Function Panel gives you a choice to view the
functions in a different format. You can check the Flatten box on the bottom
of the Select Function Panel (Figure 7–2) to see a list of all function panels in
the library selected. You can also view the function panels in alphabetical
order by checking the Alphabetize box in Figure 7–2.
304 Chapter 7 • Creating and Using Function Panels
Figure 7–2
Sample Select Function Panel
To view the function panel from your source code, move the cursor over
the function and select View>>Recall Function Panel or (<Ctrl-P>). The
function panel containing the arguments specified will be displayed. You
can change the argument in the function panel and reinsert it into the source
code if you desire. You can always enter the function by typing it directly
into the source code.
Figure 7–3
Blank Function Tree Editor Window
Select Create>> Instrument from the Function Tree Editor to display Fig-
ure 7–4. In the Name: box, enter the name you would use for the function tree
(up to 40 characters long). In this example, type the name as MyFunctions.
CVI automatically adds a prefix (up to eight characters) to all the function
names that you include in the Prefix: box. This prefix helps you identify all
functions related to a certain instrument or function group. CVI adds an un-
derscore character as a separator between the prefix and the function name.
Enter my as the prefix in the Prefix: box without the underscore character.
Click on the OK command button.
A Function Tree Editor window with the function tree name is created as
shown in Figure 7–5. To create a function class from the Function Tree Edi-
tor menu, select Create>>Class and a Create Class Node dialog box ap-
pears. Enter the name in the Name: box as Algebraic Functions. This is
the class name you will use for the function panels that are created here.
When you click OK on the Create Class Node box, this name is added to the
Function Tree Editor window below MyFunctions.
306 Chapter 7 • Creating and Using Function Panels
Figure 7–4
Create Instrument Node Window
Figure 7–5
MyFunctions Function Tree Window
Chapter 7 • Creating and Using Function Panels 307
Figure 7–6
Create Function Panel Window Node Window
308 Chapter 7 • Creating and Using Function Panels
Figure 7–7
Complete Function Tree Window
Figure 7–8
Blank Function Panel
The my_SolveQuadratic function will require three input control boxes to re-
ceive the coefficients of the quadratic equation, and the two roots calculated
for the quadratic equation will be placed in the output control box. The func-
tion operation status is sent to the return value control box.
Before creating these controls on the function panel, let us understand the
purpose of these controls. The input control receives the values that you
input to the function. You can assign a default value to this control which
appears when the function initially loads. You will see how this is done
when you create this control on the function panel. The output control re-
ceives the value calculated by the function. The output control is included as
a formal parameter in the function argument list. The return value control is
usually the result of the function operation that appears on the left side of
the function call.
310 Chapter 7 • Creating and Using Function Panels
We are now ready to add the controls for the function arguments on the
function panel for my_SolveQuadratic function. To create an input control on
the function panel, select Create>>Input… and a Create Input Control dia-
log box will appear (see Figure 7–9). Alternatively, you can also click on the
Create Input… icon on the function panel toolbar.
The Create Input… icon is similar to selecting Create>> Input… from the
function panel menu.
In the Create Input Control dialog box, Control Label: is the label that you
want to appear for this control. Enter First Coefficient in this box. The
Parameter Position: is the location of the control value in the function argu-
ment list. Leave this value as 1 since you will be using this value as the first ar-
gument in the function. When you click on the Data Type: control box you get
a list of all the data types available. Set the Data Type: to double. The Default
Figure 7–9
Create Input Control Dialog Box
Chapter 7 • Creating and Using Function Panels 311
Value: control box is the value that is displayed when the function panel first
loads. Enter the value 1.0 in this box. The Control Width: is the width of this
control in pixels. The range for this control is between 24 and 2048, with a de-
fault value of 96. Leave this control set to its default value. Once you have
made the selections, click OK and the input control box will appear on the top
left side of the function panel. You can use the mouse to drag and drop it to a
different location on the function panel if you wish.
Similarly add two more input controls with Control Labels Second Co-
efficient and Third Coefficient. The Parameter Position will incre-
ment to the next-higher number automatically when you select this control.
Set the remaining parameters the same as for First Coefficient. The
function panel will now look like Figure 7–10.
Let us now add the two output controls to the function panel. These controls
will receive the roots of the quadratic equation. Select Create>>Output… to dis-
play the Create Output Control dialog box as shown in Figure 7–11. Alterna-
tively, you can click on the Create Output… icon on the function panel toolbar.
Figure 7–10
Function Panel with Input Control Boxes
312 Chapter 7 • Creating and Using Function Panels
Figure 7–11
Create Output Control Dialog Box
Enter Root1 in the Control Label: dialog box, and select double from the
Data Type: dialog box. Leave the Default Value: dialog box blank. Display
Format: is the format in which the output control displays the output values.
You have a choice to display integers, longs, shorts, and characters in decimal,
hexadecimal, octal, or ASCII. The doubles and floats can be displayed in either
scientific or floating-point notation. Select Floating Point for this dialog box
and then select OK. The output control will be added to the function panel.
Drag it to a position below the First Coefficient input control on the panel.
Create a second output control and enter Root2 in the Control Label: dia-
log box. Leave the rest of the parameters the same as the Root1 control.
Chapter 7 • Creating and Using Function Panels 313
Figure 7–12
Create Return Value Control Dialog Box
Figure 7–13
my_SolveQuadratic Function Panel
Figure 7–14
my_Factor Function Panel
Chapter 7 • Creating and Using Function Panels 315
Figure 7–15
MyFunctions Help Window
Before we leave the topic of creating the function panel, let us add help
text to the function panel and its controls. Help text serves to define the
function, its prototype, and the function arguments adequately. To add help
to MyFunctions, open the function panel using the File>>Open>>Function
Panel [*.fp] from the Project window and select MyFunctions.fp. The
function tree window will be displayed. Highlight MyFunctions and select
Edit>>Edit Help from the menu. A blank window will be displayed in
which you can enter the help text to explain the purpose of the functions in
this function tree. Type in the help text in this window for MyFunctions.
This may look similar to Figure 7–15.
To add help text to the class node, highlight Algebraic Functions from the
function tree and select Edit>>Edit Help from the menu. Enter the help text
that will describe the functions in this class. An example of this is shown in
Figure 7–16. Save by selecting Save .FP File from the File menu.
316 Chapter 7 • Creating and Using Function Panels
Figure 7–16
MyFunctions Class Help Window
It is advisable to add help text to the function panels and controls that you
have created to enable the user to understand the purpose of the function
and the use of the controls placed on the panel. To add help text to the func-
tion panel, double-click the function name in the function tree to bring up its
function panel. For CVI version 5.5 and earlier, right-click on the panel win-
dow or the control to open a Help Editor window for the function or the
control and type in the help information. For CVI versions following 5.5,
when you right-click on the panel window, you get a context menu, from
where you select the Function Help menu item to open the Help Editor
window. Enter help text for the function. To add help information for the
control, right-click on the control to get a context menu, from where you se-
lect the Control Help menu item to open the Help Editor window.
After you have completed the function panels, you need to create the
header file and the source code file for these functions. Open a blank header
file by selecting File>>New>>Include (*.h)… from the project window and
type the prototypes for the two functions created above. The header file for
these two functions is shown in Figure 7–17. Save the file as MyFunctions.h.
Chapter 7 • Creating and Using Function Panels 317
#include <cvidef.h>
Figure 7–17
MyFunctions Header File
That is CVI’s calling convention for library and DLL functions. You can also
generate the header file for the functions from the Function Tree Editor by
opening MyFunctions.fp from the File menu of the project window and
selecting Options>>Generate Function Prototypes from the Function Tree
Editor.
You can now write the source code for the functions by creating a new file,
MyFunctions.c. The listing for MyFunctions.c is shown in Figure 7–18.
Note that you can also generate the “skeleton” source code automatically for
a single panel function or for the entire driver by selecting Tools>>Generate
New Source For Function Tree from the Function Tree Editor.
The formula used to find the roots of the quadratic equation
ax 2 + bx + c = 0
is
–b± b2–4ac
x= 2a
This formula is not accurate and you may get a round-off error when ac is
very small compared to b2. To use a more accurate formula, refer to the book
Numerical Recipes in C: The Art of Scientific Computing. If you desire, you can
use the more accurate formula from the book in your source code here. In the
function my_SolveQuadratic, the formula shown above is used to calculate the
roots of the quadratic equation, outputting the roots in the variables root1
and root2 of your program. These roots are displayed in the function panel
output control boxes when you run the IW, as you will see in the next section.
Notice that in the source code there is error checking to determine if the first
coefficient is a nonzero value. If a zero value is entered for this coefficient, the
318 Chapter 7 • Creating and Using Function Panels
/******************************************************
*****************************************************/
#include <ansi_c.h>
#include "MyFunctions.h"
} //my_SolveQuadratic
//Factorial calculations
int CVIFUNC my_Factor (unsigned int number, double *factorial)
{
int status=0, i;
double result;
//Factorial of 0 is 1
if (number == 0)
{
*factorial =1;
return status=0;
}
//Number is too large
else if (number > 170 )
Figure 7–18
MyFunctions Source Code File (continued)
Chapter 7 • Creating and Using Function Panels 319
return status=-1;
else
{ //Number is in valid range
result =1;
for ( i=1; i<=number; i++)
result = result *i;
*factorial=result;
return status =0;
}
}//my_Factor
Figure 7–18
MyFunctions Source Code File (continued)
equation is not a quadratic equation and the function returns a value –1. The
function returns a value -2 if the expression b2 – 4ac is negative in the qua-
dratic equation formula, since the square root of a negative value is not a real
number. If the operation is successful, the function returns a value zero.
The function my_Factor calculates the factorial value for an unsigned inte-
ger entered in the first argument of the function. To prevent overflow, spec-
ify a number less than 170. Entering a number greater than 170 would
cause the function to return a –1.
The status codes for these functions are entered in the help description for
the status control boxes on the function panel. You can view the description
by right-clicking on the status control box on the function panels.
x 2 –5x+6=0
Enter a 1.0 in the First Coefficient control box, -5.0 in the Second Coef-
ficient control box, and 6.0 in the Third Coefficient control box. Click on
320 Chapter 7 • Creating and Using Function Panels
the Run Function Panel icon on the function panel toolbar. CVI creates tem-
porary variables for Root1, Root2, and the status control boxes and displays
the values calculated below these controls, as you can see in Figure 7–19. The
status value is 0 if the operation is successful. You can experiment with this
function panel by inserting different valid and erroneous values in the input
control boxes and verifying the results calculated and the return status.
Similarly, bring up the Factor function panel from the function panel. To
test this function from the IW, enter 6 in the Number control box and click
on the Run icon. Again, CVI will create temporary variables for Factorial
and status controls and display the results below these control boxes, as
shown in Figure 7–20.
Once you know that the functions you created are working correctly, you
can create an object file of the source code for future use. To create an object
file, open MyFunctions.c and from the Source Editor select Options >>
Create Object File.... A dialog box will pop up giving you the choice of se-
lecting either Generate object file for current compatibility mode or Gen-
erate object file for all compilers. Select the option you want for your
application. When you click on OK in the dialog box, the object file will be
created as MyFunctions.obj. When you want to use these functions, be
Figure 7–19
Testing my_SolveQuadratic Function Panel Using IW
Chapter 7 • Creating and Using Function Panels 321
Figure 7–20
Testing my_Factor Function Panel Using IW
Numeric Control
A numeric control is an input control in which you can change the values
by clicking the up and down arrows located on the left side of the numeric
control or use the <up> and <down> arrows on the keyboard. The numeric
control is shown in Figure 7–21. To create the numeric control, select
322 Chapter 7 • Creating and Using Function Panels
Control Label: allows you to specify a label you assign to this control that
appears above the numeric control. The Parameter Position: is the location
of this argument in the function argument list. When you click on the Data
Type: control, you will see a pull-down menu from which you can choose
one of the following data types:
int
short
char
unsigned int
unsigned short
unsigned char
double
float
Display Format: is the same as that for Create Output Control in Fig-
ure 7–11. When either double or float is selected as the Data Type:, the
Precision: dialog box is enabled. Here you set the number of digits to be
displayed to the right of the decimal point.
Selecting the Value Set… command button brings up the Edit Value Set di-
alog box shown in Figure 7–23. In this dialog box you enter the Minimum: and
Maximum: values for the numeric control. In the Inc Value: dialog box, enter
Figure 7–21
Numeric Control
Chapter 7 • Creating and Using Function Panels 323
Figure 7–22
Create Numeric Control Dialog Box
the number by which you want the value to increment/decrement on the nu-
meric control when you click on the up/down arrows of the numeric control.
Slide Control
Slide control, an input control, is shown in Figure 7–24. This control specifies
a parameter value depending on the position of the marker on the slide con-
trol. To create this control, select Create>>Slide… or click on the Create
Slide… icon on the function panel toolbar and enter your selections in the
Edit Slide Control dialog box shown in Figure 7–25.
The Create Slide… icon is similar to selecting Create>> Slide… from the
function panel menu.
Figure 7–23
Edit Value Set Dialog Box
324 Chapter 7 • Creating and Using Function Panels
Figure 7–24
Slide Control
Figure 7–25
Edit Slide Control Dialog Box
The Control Label:, Parameter Position:, and Data Type: dialog boxes are
the same as those you have seen for the other controls above. Default Value:
is the position of the slide marker when the function panel is first loaded.
You can click on the ring up/down arrows to find the default value after
you have entered the label in the Edit Label/Value Pairs… list box. When
you select the Label/Value Pairs… command button, Figure 7–26 is dis-
played where you enter the Label: and Value: pair in the list box. Selecting
OK will return you to the Edit Slide Control dialog box. Selecting OK again
will create the control on the function panel.
Binary Control
Binary control is an input control that can take one of two values, depending
on the switch being in the up or the down position (see Figure 7–27). This
control is created when you select Create>>Binary… or when you click on
the Create Binary… icon on the function panel toolbar and enter your selec-
tions in the Create Binary Control dialog box shown in Figure 7–28.
Chapter 7 • Creating and Using Function Panels 325
Figure 7–26
Slide Control Label/Value Pairs… Box
Figure 7–27
Binary Control
Figure 7–28
Create Binary Control Dialog Box
The Control Label:, Parameter Position:, and Data Type: dialog boxes are
the same as those you have seen for the other controls above. In the Default
Value: dialog box you have a choice of setting it to either On or Off. When
you select the On/Off Settings… command button from the Create Binary
Control dialog box, Figure 7–29 is displayed, in which you can set the label
for the two control states and their associated values. The ON Text: refers to
the upper position of the binary switch, and the OFF Text: to the lower posi-
tion. In the ON Value: and OFF Value: boxes you can enter a value, a con-
stant name, or a valid C expression to associate with these switch positions.
Ring Control
The ring control allows you to select one item at a time from among the options
in the pull-down list. This ring control is shown in Figure 7–30. Ring control is
created when you select Create>>Ring… or when you click on the Create
Ring icon on the function panel toolbar and enter the data in the Create Ring
Control dialog box shown in Figure 7–31.
The Create Ring… icon is similar to selecting Create>> Ring… from the
function panel menu.
The Control Label:, Parameter Position:, and Data Type: dialog boxes are
the same as those you have seen for the controls above. The Default Value:
is the position of the ring control when the function panel is first loaded.
Figure 7–29
Edit On/Off Settings Dialog Box
Chapter 7 • Creating and Using Function Panels 327
Figure 7–30
Ring Control
Figure 7–31
Create Ring Control Dialog Box
Select the Label/Value Pairs… command button from the Create Ring Con-
trol to create a list and assign a value to the labels in the list. A figure similar to
the Edit Label/Value Pairs for the slide control dialog box (Figure 7–26) will be
displayed. You can enter the appropriate label/value pairs in the list box.
Global Variable
The global variable control displays the value of the global variable defined
in your CVI source code when the function panel is operated. The global
variable control is shown in Figure 7–32. The global variable control is cre-
ated when you select Create>>Global Variable… from the function panel
menu or click on the Create Global Variable… icon on the toolbar and
enter data in the Edit Create Global Variable Control dialog box shown in
Figure 7–33.
In the Global Variable Name: dialog box, enter the name of the global
variable whose contents you would like to monitor on the panel.
328 Chapter 7 • Creating and Using Function Panels
Figure 7–32
Global Variable Control
Figure 7–33
Edit Global Variable Control Dialog Box
Message Control
The message control is used to display a text message on the function panel.
The purpose of this control is to provide information to the user while the
function panel is opened. It may be useful in instances when you want to
alert the user to the limitations of this function. The message control looks
similar to Figure 7–34, containing the text that you entered in the message
control. You can create a message control by selecting Create>>Message…
from the function panel menu or Create Message… icon on the toolbar.
Enter your message in the Message Text: box in the Create Message Control
dialog box shown in Figure 7–35.
Chapter 7 • Creating and Using Function Panels 329
Figure 7–34
Message Control
Figure 7–35
Create Message Control Dialog Box
Before we leave the topic of the function panel, you should know that
you have an option to change the control type on the function easily to a
different control type. For example, if you have a slide control on the
panel and later wanted to change it to a ring control with the same
label/pair values, you do not have to delete the slide control and create a
new ring control and reenter the data. An easier way to do this is to high-
light the slide control on the function panel (for example) and select
Edit>>Change Control Type. A Change Input Control Type selection
box (Figure 7–36) will appear. Highlight the control that you want to
change to (Ring in this example) and select OK. A new ring control will
be placed on the function panel with the same label/pair values as those
of the slide control replaced.
330 Chapter 7 • Creating and Using Function Panels
Figure 7–36
Change Input Control Type Selection Box
Summary
The creation and purpose of the function tree and the function panel were
explained. You were introduced to the creation of nine different types of
controls that can be used on the function panel. You were shown how to add
help information to the function panel and the controls to make your func-
tion panels more useful to the user. You learned how to create the header,
the source code file, and the object file for the functions and test them using
the IW. You saw how you could switch from one control to another by the
use of a function panel command.
8
CREATING INSTRUMENT DRIVERS
Chapter Highlights
■ Introduction
■ Creating an Instrument Driver
■ Generating Driver Files Review
■ Using the Attribute Editor
■ Editing High-Level Instrument Driver Functions
■ Deleting High-Level Instrument Driver Functions
■ Adding High-Level Instrument Driver Functions
■ Creating Instrument Driver Documentation
■ Testing the Instrument Driver
■ Summary
Introduction
Instrument drivers are collections of high-level reusable routines that per-
form the useful functionality of communicating with a physical instrument.
Instrument drivers may not be limited to an instrument device only. A nonin-
strument driver such as a software utility that performs a certain specific task
can also be packaged as an instrument driver. You saw an example of the
software utility instrument driver legend.fp used in project2-2.prj in
Chapter 2, Plotting on Graph Controls. For communicating with a physical in-
strument the high-level routines are grouped so that they can be used for the
purpose of communicating with hardware, to perform low-level functions to
send and retrieve useful information to/from the hardware. The instrument
drivers usually communicate to a physical instrument via the GPIB, VXI, or
serial interface. When using high-level instrument driver routines the user
does not have to be aware of the communication protocol of the instrument
since it is implemented by low-level communication routines in the instru-
ment driver. The instrument driver saves the user time by using the already
created generic instrument driver functions in his/her applications. Instru-
ment drivers consist of graphical function panels that facilitate using the in-
strument driver functions from where the user can select and enter the
appropriate information in the function panel to activate a particular instru-
ment driver task. Function panels were introduced in Chapter 7, Creating and
Using Function Panels.
There are two types of instrument driver architectures: VXIplug&play and
Interchangeable Virtual Instruments (IVI). The VXIplug&play architecture
uses Virtual Instrumentation Software Architecture (VISA), which uses stan-
dard data types to define the arguments of the instrument driver functions.
Using this feature makes the instrument driver portable between different
operating systems and programming languages. All communication with
the instruments is performed using VISA. You saw the features of VISA in
Chapter 5, VXI Communication Using VISA. Instrument drivers using the IVI
architecture are an enhancement of the VXIplug&play model, which also
uses VISA but allows for higher performance and instrument simulation.
VXIplug&play uses direct instrument I/O to query and modify instrument
settings, whereas IVI drivers do the same through attributes.
The IVI Foundation, created by National Instruments together with several
other companies in 1998, established standards for the IVI instrument driver.
The IVI architecture consists of an IVI engine that works in conjunction with
Chapter 8 • Creating Instrument Drivers 333
the instrument driver to control the reading and writing of instrument settings
to and from the instrument as attributes. An attribute represents an engine set-
ting or a driver option. The IVI engine checks these settings for valid range
values in the range tables for each instrument attribute when communicating
with the instrument (if the range checking attribute is enabled). If the value is
within the valid range in the range table, the instrument driver generates the
callback function to update the instrument attribute by sending a command
string to the instrument. If the value is outside the range table, the instrument
driver returns an error code. If the instrument driver query status is enabled,
the check status callback function reads the status register of the instrument
for error conditions. Similarly, if state caching and simulation are enabled, ap-
propriate callback functions are invoked to implement these conditions. Once
you have debugged the instrument driver functions you can disable range
and status checking to speed your application.
For more features of the IVI instrument drivers, see Chapter 2, IVI Architec-
ture Overview of LabWindows/CVI Instrument Driver Developers Guide. Some of
the main features of IVI instrument drivers are:
You will now step through creating an instrument driver. Following are
the steps recommended for creating IVI instrument drivers.
1. Create the instrument driver files using the Instrument Driver Devel-
opment Wizard.
2. Edit the instrument driver attributes and modify the write and read
callback functions (if necessary).
3. Edit the high-level instrument driver functions (if necessary).
4. Delete the high-level instrument driver functions not used by the in-
strument (if necessary).
5. Add new attributes and functions (if necessary).
6. Create the instrument driver documentation and Windows Help files.
7. Test the instrument driver.
You will see how these steps are implemented in the following sections.
■ An instrument driver source (.c) file, containing the source code for
the driver functions
■ An instrument driver include (.h) file, containing function declara-
tions, constant definitions, and external declarations of global variables
■ A (.sub) file that contains the instrument driver attributes and their
possible values, whose contents you can view when you use certain in-
strument driver function panels and modify using the Attribute Editor
(created only for instrument drivers using the attribute model, e.g., IVI
drivers). The Attribute Editor is explained below in the section Using
the Attribute Editor.
The files created by the wizard use the driver name as the base name, with
the appropriate file extensions shown above. The driver name is the instru-
ment prefix that you assign when you create the instrument driver, as you
will see later in this section.
Let us go through the procedure to create the instrument driver for a
Triple Output DC Power Supply, E3661A. (Hewlett-Packard manufactured
this power supply, but it is now sold by Agilent Technologies.) Start CVI
and from the Project window, select the Tools>>Create IVI Instrument Dri-
ver to launch the Instrument Driver Development Wizard. A Welcome
window is displayed, as shown in Figure 8–1.
Figure 8–1
Instrument Driver Development Wizard: Welcome Window
336 Chapter 8 • Creating Instrument Drivers
Figure 8–2
Instrument Driver Development Wizard: Select an Instrument Driver
Chapter 8 • Creating Instrument Drivers 337
and attributes for the instruments shown in the Type of Instrument list box de-
pending on the I/O Interface selected. When you select any of the class tem-
plates, the Instrument Driver Development Wizard generates the skeleton
driver files with functions and attributes that VXIplug&play and IVI require.
You should use the General Purpose class template (shown at the top of this
list box) only when there are no predefined instrument class templates for your
instrument. The other class templates are to be used with the appropriate in-
struments shown in the list. Here we will be creating an instrument driver for a
DC Power Supply.
Select DC Power Supply in the Type of Instrument list box and click on
Next> command button to display the General Information dialog window
(Figure 8–3). In the Instrument Name dialog box, enter the name of the in-
strument for which you are developing the driver. Enter Triple Output DC
Power Supply. This name will be used to identify your instrument driver
and will appear in the function panel tree and on the Instrument menu when
you load the instrument driver from the Project window. Enter E3631A in
the Instrument Prefix dialog box. The Instrument Prefix must have eight
characters or less. This prefix will be used for the entire instrument driver
files and appended to all driver functions to identify them uniquely. In this
example the files that comprise the instrument driver (when generated)
Figure 8–3
Instrument Driver Development Wizard: General Information Window
338 Chapter 8 • Creating Instrument Drivers
Figure 8–4
Instrument Driver Development Wizard: General Command Strings Window
Chapter 8 • Creating Instrument Drivers 339
you can enter them in the dialog box separated by commas. If you wish, you
can also use the channel names from the front panel of your instrument for
better comprehension when referencing the channels in the driver functions.
Enter 1,2,3 in the Channel List String dialog box since this DC power sup-
ply consists of three outputs (+6V, +25V, and –25V) that are referenced using
these channel numbers. “1” selects the +6V output, “2” selects the +25V out-
put, and “3” selects the –25V output for this power supply.
Click on the Next> command button and Figure 8–5, the Standard Opera-
tions dialog window, is displayed.
The Standard Operations dialog window allows you to select the stan-
dard operations of your instrument. E3631A DC power supply supports all
the standard operations shown in this window; therefore, you need to put
check mark in all the boxes. The command string your instrument requires
to trigger these operations will be entered in the next few dialog windows.
Click on the Next> command button to bring up Figure 8–6, the ID Query
dialog window. Enter *IDN? (default value) in the ID Query Command dialog
box to obtain the instrument’s identification string. In the Expected ID Query
Response dialog box, enter the following instrument identification string:
HEWLETT-PACKARD,E3631A,0,1.4-5.0-1.0
Figure 8–5
Instrument Driver Development Wizard: Standard Operations Window
340 Chapter 8 • Creating Instrument Drivers
Figure 8–6
Instrument Driver Development Wizard: ID Query Window
You obtain the instrument identification string from the instrument user’s
manual. The driver uses this string to compare the output received from the
instrument to determine if it is communicating with the correct instrument.
Click the Next> command button to display Figure 8–7. Enter *RST (de-
fault string) in the Reset Command dialog box. This command resets the in-
strument to its power-on state.
Click on Next> to display the Self Test dialog window, shown in Fig-
ure 8–8. Enter TST? (default string) in the Self-Test Command dialog
box to perform its internal self-test and return the pass/fail result. In the
Self-Test Response Contents control box you can select the instrument’s
response contents to return the results of the self-test. Some instruments
return just a pass or fail code as “0” or “1”, while others return a message,
and others return a code and a message. If your instrument uses none of
these, you have a choice of selecting Custom from the pull-down menu to
create the appropriate return output. This power supply returns a code
only; therefore, select Self-Test Code from this control box. Depending on
your selection, the Format String indicator box automatically displays the
appropriate string format that VISA uses to interpret the instrument’s re-
sponse in the Format Choices and Format String dialog boxes.
Chapter 8 • Creating Instrument Drivers 341
Figure 8–7
Instrument Driver Development Wizard: Reset Command Window
Figure 8–8
Instrument Driver Development Wizard: Self-Test Window
342 Chapter 8 • Creating Instrument Drivers
When you click on the Next> command button, the Error Query dialog
window is displayed (Figure 8–9). The Error Query Command string for
this instrument is :SYST:ERR?. This command string reads an error from the
instrument’s error queue. The Error Query Response Contents pull-down
box allows you to select the format of your instrument response to the error
messages. When you check on this box, you have a choice of Error Code,
Error Message, Error Code and Message, or Custom. Select the appropriate
format as indicated in your instrument’s user’s manual. For E3631A the
error code and a message are returned in the response buffer using the VISA
string format indicated in the Format String box. Select Error Code and
Message from the Error Query Response Contents box. The Format
Choices are set automatically to the correct string format based on the selec-
tion you make in the Error Query Response Contents box.
Click on the Next> command button to display the Revision dialog win-
dow shown in Figure 8–10. To obtain the firmware revision of the instru-
ment, enter *IDN? (default string) in the Revision Command dialog box.
Select the Format Choices as shown in Figure 8–10. The Format String indi-
cator box gives the format string for VISA to interpret the instrument’s re-
sponse. This format string ignores everything up to the third comma. The
remainder of the response is read up to the linefeed to indicate the firmware
revision returned by the instrument.
Figure 8–9
Instrument Driver Development Wizard: Error Query Window
Chapter 8 • Creating Instrument Drivers 343
Figure 8–10
Instrument Driver Development Wizard: Revision Window
Click on the Next> command button. The Test dialog window is dis-
played as in Figure 8–11. The dialog window shown here is for CVI version
5.5. For later CVI versions a Resource Descriptor combo box where the user
can enter any input replaces the GPIB Address box. Here we create the in-
strument driver using the GPIB Address control box. In the GPIB Address
control box, enter the GPIB address as displayed on your instrument’s front
panel at power-on or obtain this address from the user’s manual. In the
Reset Delay(s) control box enter the number of seconds to delay after per-
forming the instrument reset. In the Self Test Delay(s) control box enter the
time taken by this power supply to perform the self-test. Before you run the
test you need to have your instrument powered-on and connected to the in-
terface you selected in Figure 8–2 (GPIB, in this case). Click on the Run Tests
command button to test your instrument.
After the instrument has completed running the tests, the Test Results
window is displayed (Figure 8–12), indicating the test operations and the re-
sults of these operations. Be sure that there are no errors and that all the re-
sponses are valid. After viewing the test results, select the Done command
button to return to the previous window. If you found errors in the test run,
click on the <Back command button to return to the appropriate window to
344 Chapter 8 • Creating Instrument Drivers
Figure 8–11
Instrument Driver Development Wizard: Test Window
Figure 8–12
Instrument Driver Development Wizard: Test Results Window
Chapter 8 • Creating Instrument Drivers 345
enter the correct information. Return to the Test window to rerun the tests
and verify the test results.
When you are satisfied with the results, click on the Next> command button
in the Test window. Using the information you provided, the wizard generates
the instrument driver files. Figure 8–13 is displayed, indicating that the driver
files have been generated successfully. As mentioned earlier, the following in-
strument driver files are created in the Target Directory that you specified in
Figure 8–3: E3631A.c, E3631A.h, E3631A.fp, and E3631A.sub. These in-
strument driver files will implement all the required IVI and VXIplug&play
functions shown below.
The VXIplug&play standard requires the following seven functions to be
implemented by each instrument driver.
Prefix_init
Prefix_close
Prefix_reset
Prefix_self_test
Prefix_revision_query
Prefix_error_query
Prefix_error_message
Figure 8–13
Instrument Driver Development Wizard: Finish Window
346 Chapter 8 • Creating Instrument Drivers
Prefix appended to the function name is the instrument prefix for the instru-
ment driver that you specified in the wizard (Figure 8–3); for this instrument
driver, they are E3661A_init, E3661A_close, ....
The IVI standard calls for the following additional functions:
Prefix_InitWithOptions
Prefix_IviInit
Prefix_IviClose
Prefix_LockSession
Prefix_UnlockSession
Prefix_GetErrorInfo
Prefix_ClearErrorInfo
Prefix_SetAttribute<type>
Prefix_GetAttribute<type>
Prefix_InvalidateAllAttributes
Prefix_GetNextCoercionRecord
Prefix_ReadInstrData
Prefix_WriteInstrData
Initialize Functions
Initialize functions allow you to initialize the software before you communi-
cate with the instrument. There are two functions, Prefix_init and Prefix_
InitWithOptions, that can initialize an IVI instrument driver session. When
you initialize an IVI session, the IVI engine creates a data structure to store
all the information for this session. Using the initialization functions, you
have a choice of performing an ID query and sending a reset to the instru-
ment identified in the resource name of the function argument. Resource name
is a string used to identify the instrument with the hardware interface and
the address. This is the same as the Instrument Descriptor discussed in the
section Basics of Programming with VISA in Chapter 5, VXI Communication
Using VISA. The resource name for this instrument driver is GPIB::5
::INSTR. Both these initialization functions return the handle of the initial-
ized session that identifies the session uniquely and is used in subsequent
function calls. The Prefix_InitWithOptions has an additional string argument
allowing you to set the following options: simulation mode, range checking,
state-caching mechanism, and status checking.
348 Chapter 8 • Creating Instrument Drivers
Figure 8–14
Power Supply Function Panel Tree
Configuration Functions
Configuration Functions are used to perform certain instrument operations.
The number and type of configuration functions and subclasses depend on
the instrument driver class template used to create the instrument driver.
This class contains functions to configure the various instrument settings.
This class may include setting the output of the instrument, configuring the
Chapter 8 • Creating Instrument Drivers 349
triggering system of the instrument, or to query, modify, and validate the in-
dividual attributes of the instrument using the Prefix_GetAttribute, Prefix_Set-
Attribute, and Prefix_CheckAttribute functions for each of the instrument
driver attributes data types. These functions, in turn, call the IVI library func-
tions Ivi_GetAttribute, Ivi_SetAttribute, and Ivi_CheckAttribute. For a descrip-
tion of the IVI library functions, see the On-line Help.
Action/Status Functions
Action/Status Functions are used for initiating and aborting the instrument
operations and to obtain the current or pending status of the instrument.
Utility Functions
Utility Functions consist of a variety of functions that are used to perform on
the instrument. These functions are: sending a reset, obtaining the revision
query from the instrument’s firmware, obtaining instrument-specific error
information, and translating the error code received from the instrument to
a user-readable form. These functions also include getting and clearing the
error information, getting the next coercion record from the IVI engine, in-
validating the state of all attributes, locking/unlocking the instrument from
interference from other execution threads, and reading and writing data to
the instrument I/O directly.
Close Function
The close function is used to close the instrument driver session and deallo-
cate the system resources.
Source File
The instrument driver Source File consists of code for the functions generated
by the wizard and is grouped in logical categories for easy navigation in the
350 Chapter 8 • Creating Instrument Drivers
source code. The section at the top of the instrument driver source file has
suggestions on how to modify the code inside the function body. Read these
suggestions, as you will need them to modify the various instrument driver
functions.
Include File
The Include File contains the defined constant and constant names for the at-
tributes and attribute values used by the instrument driver. This file also in-
cludes the function prototypes used in the instrument driver source file. You
need to change this file only when you add, delete, or modify functions in
your driver or add new attribute values. In the sections Deleting High-Level
Instrument Driver Functions and Adding High-Level Instrument Driver Func-
tions we explain how to make these changes.
.sub File
The .sub File has information about instrument driver attributes and their
values. You can view this information using the SetAttribute or GetAttribute
function panels. To do so, bring up the function panel for one of these func-
tions in the Configuration Functions class in your driver and click on the At-
tribute ID control on the function panel. The Select Attribute Constant
dialog window is displayed in Figure 8–15. To view the values of the attrib-
utes, select the attribute in the Attributes: list box, and the possible values of
the attributes are displayed in Attributes help: list box in the lower half of
the dialog window. National Instruments does not recommend editing this
file directly. It should be edited using the Attribute Editor only.
You can modify the .sub file by using the Attribute Editor that is ex-
plained in the next section.
Figure 8–15
Select Attribute Constant Dialog Window
Figure 8–16
Instrument Driver Development Wizard: Edit Driver Attributes Window
Chapter 8 • Creating Instrument Drivers 353
Figure 8–17
Attribute Editor: Edit Attribute Window
354 Chapter 8 • Creating Instrument Drivers
Figure 8–18
Attribute Editor: Edit Group Window
The attributes can be moved up and down in the list box by the Move Up
and Move Down command buttons.
To indent the attributes left or right in the list box to enhance grouping
and readability, use the Move Left or Move Right command buttons.
To edit an attribute, select the attribute and click on the Edit... command
button. You can also edit an attribute by double clicking on the attribute or
pressing <Enter> on the attribute. The Edit Attribute dialog window is dis-
played (Figure 8–17), from where you can edit the attribute information.
You can similarly edit a group label by highlighting the group label and click-
ing on the Edit... command button (Figure 8–16), pressing <Enter>, or double-
clicking on the group label. The Edit Group dialog window is displayed as
shown in Figure 8–18. Here you can change the displayed information.
The Range Tables… command button (Figure 8–16) is used to display a
list of range tables in the driver source file in the Range Tables dialog win-
dow. You can add a new range table, edit an existing range table, and cut,
copy, and paste the range table names in the list box. Refer to the section
Adding and Editing Range Tables in Chapter 4, IVI Architecture Overview of Lab-
Windows/CVI Instrument Driver Developers Guide, for a description of how to
edit the range tables.
Use the Expand/Collapse command button (Figure 8–16) to expand or
contract the attribute selected. You can also expand or contract the at-
tribute by selecting the attribute and pressing <Space bar>. Expanding at-
tribute results in a list of different types of attribute callback functions
appearing under the attribute name. Some of the attribute callback types
have a check mark next to them, indicating that the Attribute Editor found
the name of a callback function in the Ivi_AddAttribute for the attribute or
in a call to a function that references the attribute. The Ivi_AddAttribute
Chapter 8 • Creating Instrument Drivers 355
function creates a new attribute of the type specified for an instrument ses-
sion. You can disassociate a callback function from the attribute by remov-
ing the check mark. To do so, click on the check mark or press the <Space
bar>. If you add the check mark to associate a callback type with the at-
tribute that did not have a check mark initially, the Attribute Editor will
associate a default callback function name with the attribute. When you se-
lect the Apply command button in the Attribute Editor dialog window
(Figure 8–16), the Attribute Editor inserts the skeleton code for the new
callback function in the driver’s source file.
You can jump to the callback function body in the instrument driver’s
source code by selecting the callback function in the Instrument Attributes:
list box and clicking Go To Callback Source command button. This opera-
tion will close the Attribute Editor dialog window; therefore, the Attribute
Editor prompts you to save the changes before proceeding. The Go To Call-
back Source command button is enabled when you select the callback func-
tion for a certain attribute in the Instrument Attributes: list box; otherwise,
it remains disabled.
Highlight the attribute and select Go To Range Table Source command
button to go to a range table in the driver source file. This command but-
ton will be enabled only if the selected attribute has an associated range
table. Again, this operation will close the Attribute Editor dialog window;
therefore, the Attribute Editor prompts you to save the changes before
proceeding.
If you want to add class attributes that you had previously deleted or a
new version of class definition contains additional attributes, click on the
Add Class Attributes command button. The Attribute Editor searches the
header file for the #include statement for a class driver header file. If the
appropriate #include statement is not found, the Add Class Attribute
command button appears dimmed; otherwise, the Attribute Editor creates a
list of class attributes currently not in the list box using the predefined in-
strument template for the class that you selected in Figure 8–2. If there is no
new class attribute to be included, a pop-up panel displays a message to that
effect.
The Apply command button is used to update the instrument driver files
with the changes made in the Attribute Editor.
Note that the Inherent IVI Attributes group listed in the Instrument At-
tributes: list box (Figure 8–16) consists of the attributes common to all IVI in-
strument drivers that are called inherent attributes. You cannot edit, expand,
cut, or copy an inherent attribute.
356 Chapter 8 • Creating Instrument Drivers
Figure 8–19
Function Tree Editor Context Menu
Chapter 8 • Creating Instrument Drivers 357
To modify the source code for this function, go to the function body in the
source code by selecting the Go To Definition menu item on the context
menu. The source code for E3631A_error_message function appears as shown
in Figure 8–20.
Notice that the section marked between “=CHANGE:” and “END=
CHANGE=” within comments between lines 17 and 22 has recommenda-
tions with sample source code. You need to modify the source code between
1 /*****************************************************************************
2 * Function: E3631A_error_message
3 * Purpose: This function translates the error codes returned by this
4 * instrument driver into user-readable strings.
5 *
6 * Note: The caller can pass VI_NULL for the vi parameter. This
7 * is useful if one of the init functions fail.
8 *****************************************************************************/
9 ViStatus _VI_FUNC E3631A_error_message (ViSession vi, ViStatus errorCode,
10 ViChar errorMessage[256])
11 {
12 ViStatus error = VI_SUCCESS;
13
14 static IviStringValueTable errorTable =
15 {
16
17 /*=CHANGE:===============================================================*
18 Insert instrument driver specific error codes here. Example:
19
20 {E3631A_ERROR_TOO_MANY_SAMPLES, "Sample Count cannot exceed 512."},
21
22 *==========================================================END=CHANGE=*/
23 IVIDCPWR_ERROR_CODES_AND_MSGS,
24 {VI_NULL, VI_NULL}
25 };
26
27 if (vi)
28 Ivi_LockSession(vi, VI_NULL);
29
30 /* all VISA and IVI error codes are handled as well as codes in the table */
31 if (errorMessage == VI_NULL)
32 viCheckParm( IVI_ERROR_INVALID_PARAMETER, 3, "Null address for Error Message");
33
34 checkErr( Ivi_GetSpecificDriverStatusDesc(vi, errorCode, errorMessage, errorTable));
35
36 Error:
37 if (vi)
38 Ivi_UnlockSession(vi, VI_NULL);
39 return error;
40 }
Figure 8–20
E3631A_error_message Driver Created Source Code
358 Chapter 8 • Creating Instrument Drivers
the comments per modification instructions. After you have made the
changes to the source code, remove the “=CHANGE:” and “END=
CHANGE=” comment lines and the modification instructions. Your source
code should now look like as in Figure 8–21.
You can similarly modify the remaining functions in the source file by
doing a search on “=CHANGE:” and editing the code according to the in-
structions given.
/*****************************************************************************
* Function: E3631A_error_message
* Purpose: This function translates the error codes returned by this
* instrument driver into user-readable strings.
*
* Note: The caller can pass VI_NULL for the vi parameter. This
* is useful if one of the init functions fail.
*****************************************************************************/
ViStatus _VI_FUNC E3631A _error_message (ViSession vi, ViStatus errorCode,
ViChar errorMessage[256])
{
ViStatus error = VI_SUCCESS;
if (vi)
Ivi_LockSession(vi, VI_NULL);
/* all VISA and IVI error codes are handled as well as codes in the table */
if (errorMessage == VI_NULL)
viCheckParm( IVI_ERROR_INVALID_PARAMETER, 3, "Null address for Error Message");
Error:
if (vi)
Ivi_UnlockSession(vi, VI_NULL);
return error;
}
Figure 8–21
E3631A_error_message Modified Source Code
Chapter 8 • Creating Instrument Drivers 359
1. In the function tree, right-click on the function that you want to delete.
This will display the context menu (Figure 8–19). Select Go To Declara-
tion menu item. This will take you to the function declaration in the in-
strument’s header (.h) file.
2. Delete the declaration.
3. Right-click anywhere in the header file to bring up the context menu.
Select the Edit Function Tree menu item from the context menu to go
back to the function tree.
4. Right-click on the same function that you selected in step 1. The context
menu is displayed. Select the Go To Definition menu item from the
context menu to jump to the function definition in the instrument dri-
ver’s source file.
5. Delete the entire function code.
6. Right-click anywhere in the source file to bring up the context menu.
Select the Edit Function Tree menu item from the context menu to re-
turn to the function tree.
7. To delete the function name from the function panel, select Edit>>Cut.
8. Repeat steps 1 through 7 to delete all the functions one at a time. If you
wish, you can also make all the edits in each file at the same time.
Figure 8–22
Generate Documentation Dialog Window
362 Chapter 8 • Creating Instrument Drivers
Figure 8–23
Generate Windows Help Window
Chapter 8 • Creating Instrument Drivers 363
verify that there are no errors. In the CVI project, add an E3631A.fp,
E3631A.c, or E3631A.lib file. Recall that you can create the .lib file from
the Project window by setting the Target Type to Static Library in the Build
menu. Give the project the same base name of the .lib file you are creating
(E3631A). In the source file of your application, add the include file E3631A.h.
You should also create a standalone application implementing all the settings
of the instrument driver functions and verify that all the functions are executed
without any errors.
An intuitive exercise would be to create the front panel (soft panel) of the
instrument with all the controls on the physical instrument (if the instru-
ment has a front panel). When you operate the controls from the “soft
panel,” the instrument connected should respond using the driver software.
This would be similar to operating the instrument manually by using the
controls on the instrument’s front panel.
Summary
In this chapter you obtained a taste of creating instrument drivers. You were
stepped through the mechanics of creating an instrument driver for the
power supply and shown how to modify the source code and the driver at-
tributes. Creating instrument drivers is a vast topic and is covered in the
LabWindows/CVI Instrument Driver Developers Guide manual. To fully under-
stand this topic you need to familiarize yourself by reading this manual and
practice creating instrument drivers for your instrument(s). As you create
the instrument drivers, you will need to understand the IVI library functions
given in On-line Help.
This page intentionally left blank
9
OPENGL
Chapter Highlights
■ Introduction
■ OpenGL Project
■ Source Code Analysis
■ OpenGL Properties Panel
■ Summary
■ Library Function Prototypes and Definitions
Introduction
OpenGL (“GL” stands for Graphics Libraries) is a collection of software li-
braries that interact with the graphics hardware of your computer to render
color images of moving two-and three-dimensional objects at high speeds. It
is a cross-platform standard that works on Windows, MacOS, Linux, and
UNIX operating systems. OpenGL (OGL) was developed in 1992 by Silicon
Graphics (SGI) and its standard maintained and updated by the OpenGL Ar-
chitecture Review Board (ARB). The OpenGL ARB comprises of a consortium
of leading computer graphics companies, such as 3Dlabs, Compaq, Evans &
Sutherland, Hewlett-Packard, IBM, Intel, Intergraph, NVIDIA, and SGI.
Some of the basics of OpenGL and definition of the terms used in
OpenGL are noted here. OpenGL interface consists of about 250 library
functions (approximately 200 functions are part of the core OpenGL library
and another 50 belong to the OpenGL Utility Library [GLU]). These func-
tions allow you to specify the objects (models) and operations to render inter-
active graphical images. Rendering is the process by which a computer
creates images from models. To build an OpenGL model, you use a small set
of geometric primitives—points, line segments, and polygons to draw into a
framebuffer with a specified mode that can be set and changed indepen-
dently. The purpose of a framebuffer is to hold all the information that a
graphic display needs to control the color and intensity of the pixels. A pixel
(picture element) is defined as the smallest element that can be displayed on
the screen and is a set of a number of bits defining the attributes of the pixel.
Geometric primitives are drawn with one or more vertices. A vertex can be
a point or an intersection of two line segments. Starting with the vertices,
you can build a line segment, a triangle, a polygon, or a combination of other
complex geometric objects. Each vertex datum consists of positional coordi-
nates, colors, normal vector (normal), and texture coordinates that are trans-
mitted using the OpenGL library functions. A normal vector is a vector
pointing in a direction perpendicular to the surface. Texture coordinates are
used for assigning texel (texture element) in the texture map to a particular
vertex of the object. Applying a texture map to a primitive gives that object a
more realistic look.
OpenGL is designed to work on different windowing and operating sys-
tems, and therefore there are no commands implicit to OpenGL to control the
opening of a window or to receive commands from the keyboard or mouse.
The OpenGL Utility Kit (GLUT) is as a set of library functions written to
bridge this gap. GLUT is used for opening windows and receiving inputs
Chapter 9 • OpenGL 367
OpenGL Project
project9.prj uses the CVI’s OpenGL instrument driver and shows you
some of the CVI’s OpenGL library functions for controlling and plotting data
on the OpenGL control. To use the OpenGL library functions, you need to
add the OpenGL 3D Plotting Control instrument driver (cviogl.fp) to
your project. This file is located in the toolslib\custctrl folder, but for
convenience has been copied to the Chapter9_Proj folder. When you run
project9.prj, the data is loaded from the file you select from the ring con-
trol on the GUI and plotted on the OpenGL control. By using the keyboard
and the mouse, you will be able to rotate, pan, and zoom the data plotted to
view various orientations of your plot.
Load and run project9.prj to display the GUI showed in Figure 9–1.
Let us look at some of the controls on this GUI. When you click on the Select
File to Plot ring control, names of data files that contain the data are dis-
played and the data plotted on the DATA PLOT control. For example, these
data files may contain data that you may have acquired from a data acquisi-
tion source, a mathematical model that you are trying to analyze, or from
some other data that you are trying to view in three dimensions using
OpenGL. The data is plotted using the colors that correspond to the magni-
tude of data. This color representation is shown by means of a color map on
Color Map control during execution. The control labeled DATA PLOT is a
picture control that you create by selecting Create>>Picture from the User
Interface Editor. This picture control is converted to an OpenGL control
programmatically, as you will see later.
368 Chapter 9 • OpenGL
Figure 9–1
project9 GUI
When you select a data file, a figure similar to Figure 9–2 is displayed
with the data plotted on the DATA PLOT control.
You can view this plot using various orientations. To rotate the plot, hold
down the left mouse button and move the mouse over the data plotted. To
zoom in or zoom out, hold the <Ctrl> key down on the keyboard and with
the left mouse button pushed down, move the mouse on the DATA PLOT
control toward you to zoom in and away from you to zoom out. To pan the
plot, hold down the <Shift> key, and with the left mouse button pushed
down, move the mouse in the direction you want to move the plot. To view
the instructions mentioned above for using OpenGL controls, click on the
HELP command button to display Figure 9–3.
Experiment with the data plotted by rotating, zooming, and panning, and
notice how convenient it is to view the plot from various angles. After you
have selected a view of your data, you can print it or send it to a file by se-
lecting the PRINT command button.
Chapter 9 • OpenGL 369
Figure 9–2
project9 Data Plot
Figure 9–3
project9 Using OpenGL Controls Help Panel
370 Chapter 9 • OpenGL
1 #include <userint.h>
2 #include <ansi_c.h>
3 #include "project9.h"
4 #include "cviogl.h"
5 #include <formatio.h>
6
7 #define POINTS_X 21
8 #define POINTS_Y 21
9
10 #define PI 3.1415927
11
12 static int OGLPanelHandle;
13 static int OGLControl_ID;
14 static int SetOGLAttributes(void);
15 static int PlotOGLData(void);
16 static char buf[256];
17 double ReadArray[ POINTS_Y][ POINTS_X];
18 char FileName[MAX_FILENAME_LEN];
19 static ColorMapEntry MapColor[5];
20
21 //Function prototypes
22 void CreateColorMap (int lowColor, int MediumLow, int medColor,int MediumHigh, int highColor);
23 int CreateColorScale (void);
24
25 //Help Message
26 #define HELP_MSG "\
27 \n\
28 \n\
29 Position the mouse on the OGL control.\n\
30 The following buttons and keys are used to control the OGL plot:\n\
31 \n\
32 To Rotate - Hold the left mouse button and move the OGL object \n\
33 To Zoom In - Hold the Ctrl key, and move the mouse closer while holding the left mouse button \n\
Figure 9–4
project9 Header and main Function Listing (continued)
Chapter 9 • OpenGL 371
34 To Zoom Out - Hold the Ctrl key, and move the mouse further while holding the left mouse
35 button\n\
36 To Pan - Hold the Shift key, and move the mouse while holding the mouse button \n\
37 \n\
38 To view and change the OGL properties, right-click on the OGL control. \n\
39 \n\
40 "
41 //Program entry point
42 int main (int argc, char *argv[])
43 {
44 int error = 0;
45 if (InitCVIRTE (0, argv, 0) == 0) /* Initialize CVI libraries */
46 return -1; /* out of memory */
47
48
49
50 if ((OGLPanelHandle = LoadPanel (0, "project9.uir", OGLPANEL)) < 0)
51 return -1;
52
53 // Convert to OpenGL control
54 OGLControl_ID = OGLConvertCtrl(OGLPanelHandle,OGLPANEL_OGL_CTRL);
55 if (OGLControl_ID<0)
56 {
57 OGLGetErrorString (OGLControl_ID, buf, 255);
58 MessagePopup("OGLConvertCtrl Error", buf);
59 goto Error;
60 }
61
62 DisplayPanel (OGLPanelHandle);
63 //Setup CVIOGL control
64 SetOGLAttributes();
65 RunUserInterface();
66
67 //Discard CVIOGL control
68 OGLDiscardCtrl(OGLPanelHandle,OGLControl_ID);
69 return 0;
70
71 Error :
72 //Discard CVIOGL control
73 OGLDiscardCtrl(OGLPanelHandle,OGLControl_ID);
74 DiscardPanel(OGLPanelHandle);
75 return error;
76 }//main
Figure 9–4
project9 Header and main Function Listing (continued)
Lines 26–40 list the help message that is displayed on a pop-up panel (Fig-
ure 9–3) when you click on the HELP command button (Figure 9–1). The
help message explains how to manipulate the OpenGL plot using the key-
board and the mouse buttons.
372 Chapter 9 • OpenGL
//Select the data file, set the attributes, and plot on the OGL control
int CVICALLBACK LoadPlotCB (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
int Index;
switch (event)
{
case EVENT_COMMIT:
//Get filename from ring control
GetCtrlIndex (OGLPanelHandle, OGLPANEL_LOAD, &Index);
GetLabelFromIndex (OGLPanelHandle,OGLPANEL_LOAD , Index,
FileName );
//Plot OGL using selected file data
PlotOGLData();
break;
}
return 0;
} //LoadPlotCB
Figure 9–5
LoadPlotCB Source Listing
This callback function obtains the name of the data file selected from the
ring control and plots the data contained in this file by calling the user-defined
function PlotOGLData.
Figure 9–6
SetOGLAttributes Source Listing
Chapter 9 • OpenGL 375
the viewing volume does not change from one end of the scene to the other
end. The actual size of the objects and angles between them is maintained. In
a perspective projection, the view of a scene is what is more visible to a human
eye (or camera) in real life, where closer objects appear to be larger than
those farther away. At line 17 the projection is set to perspective projection
using the attribute value as OGLVAL_PERSPECTIVE.
The attributes OGLATTR_XNAME_VISIBLE, OGLATTR_YNAME_VISIBLE and
OGLATTR_ZNAME_VISIBLE at lines 21–23 specify whether the axes names are
displayed. Lines 24–26 display the text names for the X-axis, Y-axis, and Z-axis
as will appear on the OpenGL control when the data is plotted. The attributes
specified for this are OGLATTR_XNAME, OGLATTR_YNAME, and OGLATTR_
ZNAME, respectively. The attributes OGLATTR_XLABEL_VISIBLE, OGLATTR_
YLABEL_VISIBLE, and OGLATTR_ZLABEL_VISIBLE at lines 27–29 make the
names visible for the X-axis, Y-axis, and Z-axis, respectively.
At lines 33–36 the attribute OGLATTR_XY_GRID_COLOR for the XY plane grid
color is set to light gray and displayed using the attribute OGLATTR_XY_GRID_
VISIBLE. If you wish, you can create a color of your choice by using the Make-
Color library function. Similarly, at lines 38–46 you are setting the grid color at-
tribute for the YZ and XZ planes and making these grids visible.
Plotting Data
After you have set the OpenGL attributes, you need to plot the data using
the PlotOGLData function whose listing is shown in Figure 9–7. Before you
plot the data, you need to set up the various coordinates and plotting attrib-
utes. The starting point for the Z-axis plot area’s coordinated system is set to
0.0 at line 10 using the attribute OGLATTR_PLOTAREA_ZSTART. The plot
area coordinate system defines the space where plotting occurs.
At lines 12 and 13 the Z-axis size for the plot area’s coordinate system is
specified using the attribute OGLATTR_PLOTAREA_ZSIZE. You have to experi-
ment with this value to proportionate your plot to lie within the OpenGL con-
trol. Too big a value will make the top part of the Z-axis scale lie outside the
control region, and too small a value will not give you sufficient resolution on
the Z-axis.
At lines 14 and 15 if you set the attribute OGLATTR_VIEW_AUTO_DISTANCE
to a value 1, it specifies that the view distance must be set automatically, ignor-
ing the value of OGLATTR_VIEW_DISTANCE (line 16). Otherwise, setting the
value to 0 signifies not to set the view distance automatically, but instead, to
use the value indicated for this attribute (OGLATTR_VIEW_DISTANCE), which
in this case is 2.5. OGLATTR_VIEW_DISTANCE was explained above in the sec-
tion Setting OpenGL Attributes.
Chapter 9 • OpenGL 377
Figure 9–7
PlotOGLData Source Listing (continued)
378 Chapter 9 • OpenGL
Figure 9–7
PlotOGLData Source Listing (continued)
ReadArray[POINTS_Y][POINTS_X]
Chapter 9 • OpenGL 379
where POINTS_X is the size of the row dimension of the array, and
POINTS_Y is the size of the column dimension of the array. These are speci-
fied in the arguments of the OGLPlot3DUniform library function, which is
called at line 51 to create a uniform three-dimensional plot of the data on the
OpenGL control.
It is more meaningful to display the plotted values in color in a way that
each color represents a certain magnitude value of data. This is achieved by
calling the user-defined function CreateColorMap at line 36, which assigns the
color to the data plotted. We will see how this is accomplished in the section
Creating a Color Map below. To associate the color to the magnitude of the
data value, it is necessary to show the color representation of the data plot-
ted by means of a color mapping scale. This is displayed as an intensity plot
on the graph control labeled Color Map (Figure 9–1).
The X_Gain, Y_Gain arguments and X_Offset, Y_Offset arguments
used in the OGLPlot3DUniform library function at lines 51–53 are used to
specify the gain and offset applied to the x and y index values of ReadArray.
The default values of the gain are 1.0, and for the offsets are 0. If the gains and
offsets are used, the value of ReadArray[y][x] is the z-axis value, located
on the graph at
Before you can plot data, you need to set up the color scheme for your
data plot. The OGLSetPlotColorScheme library function at lines 55 and 56 de-
termines the color scheme used and the color assigned to the data values in
the array MapColor. The values for this array are set in the function Create-
ColorMap, as explained below in the section Creating a Color Map. You have a
choice of the following color schemes:
In this project Color Map is used for the color scheme. Note that instead
of using the OGLSetPlotColorScheme function, you can also assign the color
scheme in the library function OGLSetPlotAttribute using the OGLATTR_
COLOR_SCHEME attribute and selecting one of the color schemes above.
Lines 59–69 set up the various plot attributes. These attributes decide the
appearance of your plotted data. You can set the point attributes, wire attrib-
utes, and surface attributes. Let us digress for a moment and explain these
plot attributes.
The point attributes can specify the size of the point used for plotting,
whether the points are smooth or not, and the RGB color of the point.
In OpenGL all the objects in a scene (or plot) are made of wires. Each line
of wire corresponds to an edge of a primitive (typically, a side of a polygon).
Wireframe is an object that consists of line segments only. The wire attributes
specify the wireframe model features, such as the style of wire used (solid,
dash, dot, dash-dot, and dash-dot-dot), the wire used to draw: smooth or
otherwise, and the RGB color of the wire.
The surface attributes are used to specify the surface style. You can choose
from the following surface styles: none, in which no surface is displayed;
smooth; or flat. You can also set the RGB color of the surface, the surface’s
opaqueness or transparency, the specular reflectance of the material, and the
surface shininess. Specular reflectance is the effect the material has on the re-
flected light, which is also dependent on the position of viewer. Shiny mate-
rials such as glass or high-gloss finishes have high specular reflectance,
while objects like cork or carpets have low specular reflectance.
Examining the source code again, the surface style attribute,
OGLATTR_SURFACE_STYLE, at lines 59 and 60 is set to OGLVAL_SMOOTH for
a smooth surface plot. At lines 61 and 62, the specular reflectance factor is set
using the attribute OGLATTR_SURFACE_SPECULAR_FACTOR. The range of
specular reflectance factor is between 0.0 to 1.0. The surface shininess is
specified at lines 63 and 64 by assigning a value for the attribute
OGLATTR_SURFACE_SHININESS. The range of shininess is between 0 (no
shine) to OGL_MAX_SURFACE_SHININESS (maximum shininess has a value
of 128). For an object to appear shiny, the OGLATTR_SURFACE_SPECULAR_
FACTOR must be a nonzero value. You have to experiment with the attrib-
utes OGLATTR_SURFACE_SPECULAR_FACTOR and OGLATTR_SURFACE_
SHININESS to obtain the desired shininess for your object.
The wire style and color is specified at lines 66–69 using the attributes
OGLATTR_WIRE_STYLE and OGLATTR_WIRE_COLOR, respectively. The wire
Chapter 9 • OpenGL 381
styles were discussed above and you can choose from among the following
values: OGLVAL_NONE, OGLVAL_SOLID, OGLVAL_DASH, OGLVAL_DOT,
OGLVAL_DASH_DOT, and OGLVAL_DASH_DOT_DOT. The wire color is set to
black here. You can also use any color by setting the RGB values in the li-
brary function MakeColor, as indicated above.
The settings and changes only take effect when the library function OGL-
RefreshGraph is called at line 72 to refresh an OpenGL control. Note that to re-
fresh the control, this function must be called in the same thread in which the
control was created; otherwise you will get OGLErrorInvalidThread error.
Figure 9–8
CreateColorMap Source Listing
382 Chapter 9 • OpenGL
double ColorMapArray[5][2];
int NumberOfXpoints, NumberOfYpoints, NumberOfColors,
InterpolateColors,InterpolatePixels ;
ColorMapArray[0][0] = -10.0;
ColorMapArray[0][1] = -10.0;
ColorMapArray[1][0] = -5.0;
ColorMapArray[1][1] = -5.0;
ColorMapArray[2][0] = 0.0;
ColorMapArray[2][1] = 0.0;
ColorMapArray[3][0] = 5.0;
ColorMapArray[3][1] = 5.0;
ColorMapArray[4][0] = 10.0;
ColorMapArray[4][1] = 10.0;
Figure 9–9
CreateColorScale Source Listing
Chapter 9 • OpenGL 383
Figure 9–10
PrintCB Source Listing
Lines 11–20 determine the location of the copied image (file or printer). If
you select a file, a pop-up panel will ask you to enter the file name, and the
bitmap image is saved to this file in your default project folder. Otherwise,
the Windows Print dialog window appears where you can select the printer
and the printer options to send the image to the printer.
The User Interface Library function PrintPanel at lines 14 and 19 is used to
print the panel selected. At line 14, the second argument in this function is
an empty string indicating that no destination file is specified for the output,
and therefore the output is sent to the printer. The PrintPanel function at line
19 sends the output to the file name specified in the second argument.
Summary
In this chapter you were given a taste of the concepts and terms used in
OpenGL. The purpose of this chapter was to show how you could use
OpenGL from CVI. You learned how to use the various functions in CVI’s
OpenGL Library to control and plot data. The attributes of the library func-
tions used in the project were explained, although there are many attributes
that could not be covered here. To gain an understanding of the attributes
available for a function, you need to bring up the function panel and look at
a description and the values available for that attribute.
386 Chapter 9 • OpenGL
Figure 9–11
OpenGL Control Properties Panel
OGLConvertCtrl Function
The OGLConvertCtrl function converts an existing picture control into an
OpenGL control and returns the identifier for the converted control. Its pro-
totype is shown below and its arguments explained in Table 9–1.
Input/
Output Name Type Description
OGLDeletePlot Function
The OGLDeletePlot function deletes the specified plot. Its prototype is shown
below and its arguments explained in Table 9–2.
Input/
Output Name Type Description
1 Yes
0 No
OGLDiscardCtrl Function
The OGLDiscardCtrl function removes an OpenGL control from the panel
and memory. The plots on the control are also deleted. Its prototype is
shown below and its arguments explained in Table 9–3.
OGLGetCtrlAttribute Function
The OGLGetCtrlAttribute function obtains the value of an OpenGL control
attribute for the control specified. Its prototype is shown below and its argu-
ments explained in Table 9–4.
OGLGetErrorString Function
The OGLGetErrorString function retrieves a text string from the error codes
of the OpenGL instrument driver and the User Interface Library functions.
Its prototype is shown below and its arguments explained in Table 9–5.
Input/
Output Name Type Description
Input/
Output Name Type Description
Input/
Output Name Type Description
OGLPlot3DUniform Function
The OGLPlot3DUniform function creates a three-dimensional plot on the
OpenGL control specified. Its prototype is shown below and its arguments
explained in Table 9–6.
Input/
Output Name Type Description
■ character
■ short integer
■ integer
■ float
■ double-precision
■ unsigned short integer
■ unsigned integer
■ unsigned character
(continued)
Chapter 9 • OpenGL 391
OGLPropertiesPopup Function
The OGLPropertiesPopup function displays the OpenGL properties panel and
allows you to modify the control and plot attributes. Its prototype is shown
below and its arguments explained in Table 9–7.
OGLRefreshGraph Function
The OGLRefreshGraph function refreshes an OpenGL control. Its prototype is
shown below and its arguments explained in Table 9–8.
Input/
Output Name Type Description
Input/
Output Name Type Description
OGLSetCtrlAttribute Function
The OGLSetCtrlAttribute function sets the value of an OpenGL control at-
tribute for the control specified. Its prototype is shown below and its argu-
ments explained in Table 9–9.
Input/
Output Name Type Description
OGLSetPlotAttribute Function
The OGLSetPlotAttribute function sets the value of an OpenGL plot attribute
for the control specified. Its prototype is shown below and its arguments ex-
plained in Table 9–10.
OGLSetPlotColorScheme Function
The OGLSetPlotColorScheme function sets the color scheme to be used when
the plot is drawn on an OpenGL control. This function also sets the data that
may be required for each of those color schemes. Its prototype is shown
below and its arguments explained in Table 9–11.
PlotIntensity Function
The PlotIntensity function plots a solid rectangle on a graph control. The plot
consists of pixels whose colors correspond to the magnitude of the data val-
ues in a two-dimensional array. The coordinates of the plot are represented
by the locations of the data values in the array. Its prototype is shown below
and its arguments explained in Table 9–12.
Input/
Output Name Type Description
Input/
Output Name Type Description
■ None
■ Shaded
■ Gray Scale
■ Color Spectrum
■ Color
■ Color Array
(continued)
Chapter 9 • OpenGL 395
Input/
Output Name Type Description
(continued)
396 Chapter 9 • OpenGL
■ double
■ float
■ integer
■ unsigned integer
■ short integer
■ unsigned short integer
■ character
■ unsigned character
PrintPanel Function
The PrintPanel function prints the panel selected to the file or printer speci-
fied. Its prototype is shown below and its arguments explained in Table 9–13.
Input/
Output Name Type Description
SetWaitCursor Function
The SetWaitCursor function specifies the state of the wait cursor. When en-
abled, all other cursor styles are overridden to display the wait cursor. Its
prototype is shown below and its arguments explained in Table 9–14.
Input/
Output Name Type Description
Deitel, H. M., and Deitel, P. J., C How to Program. Upper Saddle River, NJ:
Prentice Hall, 1994.
Eckel, B., Thinking in C++. Upper Saddle River, NJ: Prentice Hall, 2000.
Edward, H., Building an Interactive Web Page with DataSocket. National Instru-
ments Corporation (Application Note 127).
Hewlett-Packard Company. HP 3631A Triple Output DC Power Supply, User’s
Guide. Dallas, TX: Hewlett-Packard, April 1998 [Part Number E3631-90002].
Khalid, S. F., LabWindows/CVI Programming for Beginners. Upper Saddle
River, NJ: Prentice Hall, 2000.
National Instruments Corporation. DAQ Hardware Overview Guide. Austin,
TX: National Instruments, January 2000 [Part Number 370097A-01].
National Instruments Corporation. Getting Started with LabWindows/CVI.
Austin, TX: National Instruments, 1999 [Part Number 320680E-01].
National Instruments Corporation. Hot Technologies for Measurements.
Austin, TX: National Instruments, 2000 [Part Number 350656A-01]
400 Bibliography
A AdvProject folder, 2
Agilent Technologies, 335
A/D, 223 alias channel name
Accessing the DataSocket Server, 99–104 creating, 239
Accessory tab, 233 aliasing, 225
ActiveX, 122 Am913, 281
container Am9513, 268, 273
DataSocket, 98 counter size, 267, 274
control Am9513 MIO
DataSocket, 98 counter numbers, 267
ADC, 222 Am9513A System Timing Controller, 264
Adding High-Level Instrument Driver Functions, American Standard Code for Information Inter-
359–60 change. See ASCII
address bus analog input
decoding, 181 configure, 239
purpose of, 181 Analog Input Functions, 248–59
widths, 181 analog input signals, 222
402 Index
DAQ Channel Wizard, 219, 229, 237, 238, 255, 259 DataSocket object
DAQ Designer, 227 configurations, 83
DAQ Designer Tool, 219 AutoUpdate mode, 84
DAQ drivers, 228 non-AutoUpdate mode, 84
DAQ Library Functions DataSocket Server, 77, 78, 79, 82, 89
types of, 248 communication, 77
DAQ system DataSocket Server Manager
consists of, 220 configuring, 99
DAQ Troubleshooting Wizard, 230 path, 99
DAQ-STC, 265, 267, 268, 273, 281, 294. See also Permissions Groups, 101
Data Acquisition System Timing Controller Predefined Data Items, 102
counter numbers, 267 Server Settings, 100
counter size, 267, 274 settings, 78
Data Acquisition. See DAQ what is, 99
fundamental steps, 248 window, 99
Data Acquisition Board Architecture, 222–23 DataSocket Server Manager Configurations, 99–104
Data Acquisition Overview, 220–22 DDE, 76
Data Acquisition System Timing Controller, 265 Default Resource Manager, 200
data bus Default Setup Command
width, 181 dialog box, 338
Data Neighborhood, 238 DelayedPulseGenConfig, 270, 271, 284
Data Neighborhood folder, 229, 237 DeleteGraphPlot, 21, 24, 41
DataSocket DeleteTableRows, 138, 152
access method, 77 Deleting High-Level Instrument Driver
communicates with, 77 Functions, 359
data socket transfer protocol, 77 Device Class. See VXI Device Classes
data transfer rate, 78 device number, 229
file scheme, 77 Devices and Interfaces folder, 229, 230
file size limitations, 78 differential, 225
file transfer protocol, 77 DIG_Line_Config, 261, 284
Overview, 76–77 DIG_Prt_Config, 261, 284
publisher, 77 digital applications
streaming data, 76 categories of, 261
subscriber, 77 Digital I/O, 261
technology, 75 configure, 239
what is, 76 digital I/O port
DataSocket Applications, 97–99 configuration, 261
DataSocket Data file format, 77, 89 Digital I/O tab, 235
DataSocket Data Files, 77–78 Digital Input/Output Functions, 261–63
Index 405
E Auto Scale, 39
Axis Name, 38
E1441A Arbitrary Waveform Generator, 197 dialog box, 38
E3631A.doc, 361 Display Format, 39
E3631A.hlp, 362 Divisions, 38
E3631A_error_message Eng. Units, 39
listing, 357 Gain, 38
Easy I/O for DAQ library functions Log Scale, 39
analog input functions, 248 Loose Fit, 39
406 Index
Edit Graph dialog box, (continued) Editing High-Level Instrument Driver Functions,
Loose Fit Units, 39 356–58
Mark Origin, 40 encrypted hyper text transfer protocol, 77
Maximum, 38 Error Query
Minimum, 38 dialog window, 342
Offset, 38 Error Query Response Contents
Padding, 39 pull-down box, 342
Precisions, 38 Ethernet, 78, 221
Reverse Axis, 39 Event Counting and Timing, 266–68
Show Grid, 39 Expected ID Query Response
Show Lables, 39 dialog box, 339
Use Label Strings, 39
Use Label Strings command button, 39
Enable Zooming, 37
Right Y-axis, 38
F
Smooth Update file transfer protocol, 77
advantage, 37 FileToArray, 141, 153, 378
disadvantage, 37 fillmode, 257, 258
X-axis, 38 Grouped by Channel, 258
Y-axis, 38 Grouped by Channels, 258
Control Settings, 37 Grouped by Scan, 258
Cursors..., 35 FillTableCellRange, 141, 153
Edit Cursors FindResourcesCB, 200
Color, 35 firewall, 97
Cross Hair Style, 35 Format Choices
Cursor Number, 35 dialog box, 340, 342
Enabled, 35 Format String
Mode, 35 dialog box, 340, 342
Free Form, 35 indicator box, 340
Snap to Point, 35 framebuffer, 366
Number of Cursors, 35 frequency
Point Style, 35 counters used to measure, 273
Use Right Y Axis, 35 Frequency Measurement, 273–74
Edit Group ftp, 77
dialog window, 353, 354 function name
Edit Row prefix, 305
command button, 127 function panel, 332
Edit State, 123 change control
Edit Table Edit>>Change Control Type, 329
dialog window, 125 changing control type, 329
Index 407
N OGLATTR_BGCOLOR, 375
OGLATTR_COLOR_SCHEME, 380
NEGATIVE_POLARITY, 270 OGLATTR_ENABLE_PROPERTY_POPUP, 375
NewCtrl, 9, 10, 26 OGLATTR_FIRST_PLOTHANDLE, 378
controlLeft, 26 OGLATTR_LIGHT_DISTANCE, 375
controlTop, 26 OGLATTR_LIGHT_ENABLE, 375
NewCtrlMenuItem, 164 OGLATTR_LIGHT_SELECT, 375
NewPanel, 8, 15 OGLATTR_LIGHTING_ENABLE, 375
attributes OGLATTR_NUM_PLOTHANDLES, 378
panelHorizontalCoord, 27 OGLATTR_PLOTAREA_ZSIZE, 376
panelVerticalCoord, 27 OGLATTR_PLOTAREA_ZSTART, 376
NI-DAQ syntax, 253, 259 OGLATTR_PROJECTION_TYPE, 375
structure, 253 OGLATTR_SURFACE_SHININESS, 380
nidaqAICreateTask, 248, 249, 252, 254, 255, 288 OGLATTR_SURFACE_SPECULAR_FACTOR, 380
task types, 254 OGLATTR_SURFACE_STYLE, 380
nidaqAIDestroyTask, 255, 288 OGLATTR_VIEW_AUTO_DISTANCE, 376
nidaqAIRead, 248, 255, 290 OGLATTR_VIEW_DISTANCE, 375, 376
414 Index
P Prefix_GetErrorInfo, 346
Prefix_GetNextCoercionRecord, 346
pan Prefix_init, 345, 347
meaning, 34 Prefix_InitAttributes, 350
parallel, 221 Prefix_InitWithOptions, 346, 347
PCMCIA DAQ card, 220 options
PC-TIO-10 range checking, 347
counter numbers, 267 simulation, 347
pixel, 366 state-caching, 347
PlotArc, 57, 67 status checking, 347
PlotData, 41 Prefix_InvalidateAllAttributes, 346
PlotIntensity, 382, 393 Prefix_IviClose, 346
PlotLine, 56 Prefix_IviInit, 346
PlotOval, 58, 70 Prefix_LockSession, 334, 346
PlotRectangle, 58, 71 Prefix_ReadInstrData, 346
PlotStripChart, 255 Prefix_reset, 345
PlotText, 59, 72 Prefix_revision_query, 345
Plotting Geometric Patterns on Graph Control, Prefix_self_test, 345
50–59 Prefix_SetAttribute, 346, 349
PlotUniformCB, 15, 22 Prefix_SetAttribute<type>, 346
PlotY, 22, 41 Prefix_UnlockSession, 334, 346
Point Prefix_WriteInstrData, 346
structure, 141 PrintPanel, 385, 397
point by point, 254 Project window, 335
Polarity, 232 Project window list, 2
Polarity/Range, 232 project1-1
port main, 3
digital, 261 project1-1.c, 2
POSITIVE_POLARITY, 270 project5
power supply, 333, 335, 337, 339, 352 code for
Prefix, 346 Finding System Resources, 200
Prefix.doc, 361 header and the main function, 198
Prefix.hlp, 362 Configuring the function generator
Prefix_CheckAttribute, 349 code, 205
Prefix_ClearErrorInfo, 346 Setting up Communication code, 202
Prefix_close, 345
416 Index
S
Q sample and hold circuitry, 223
Quick Edit Window, 133 sampling rate, 225
scale types
linear, 241
R polynomial, 241
table scale, 241
range tables, 333 scaling factor, 241
dialog window, 354
Index 417
The accompanying CD-ROM includes a trial version of LabWindows/CVI 6.0 plus all the
project files discussed in this book. All the projects on the CD have been run and tested
thoroughly and neither the author nor Prentice Hall is liable for any errors or consequen-
tial damages occurring from the use of the software.
The “AdvProjects” folder must be copied to the hard disk and the Read-only and the
Archive attributes must be removed from all the files before running the projects. These
projects have been created and run using the full version of LabWindows/CVI 5.5 and
should have no problems running with the full version of LabWindows/CVI 6.0. How-
ever, due to the disabling of some of the menu commands in the evaluation version of Lab-
Windows/CVI 6.0 you may not be able to run some of the projects in their entirety.
HiQ is not functional on the CD. If you are interested in HiQ, please contact National
Instruments at www.ni.com.
License Agreement
Technical Support
Prentice Hall does not offer technical support for any of the programs on the CD-ROM.
However, if the CD-ROM is damaged, you may obtain a replacement copy by sending an
email that describes the problem to: [email protected].
LICENSE AGREEMENT AND LIMITED WARRANTY
1. GRANT OF LICENSE: In consideration of your payment of the license fee, which is part of the price
you paid for this product, and your agreement to abide by the terms and conditions of this Agreement, the Company
grants to you a nonexclusive right to use and display the copy of the enclosed software program (hereinafter the “soft-
ware”) on a single computer (i.e., with a single CPU) at a single location so long as you comply with the terms of this
Agreement. The Company reserves all rights not expressly granted to you under this Agreement.
2. OWNERSHIP OF SOFTWARE: You own only the magnetic or physical media (the enclosed software)
on which the software is recorded or fixed, but the Company retains all the rights, title, and ownership to the software
recorded on the original software copy(ies) and all subsequent copies of the software, regardless of the form or media on
which the original or other copies may exist. This license is not a sale of the original software or any copy to you.
3. COPY RESTRICTIONS: This software and the accompanying printed materials and user manual (the
“Documentation”) are the subject of copyright. You may not copy the Documentation or the software, except that you
may make a single copy of the software for backup or archival purposes only. You may be held legally responsible for any
copying or copyright infringement which is caused or encouraged by your failure to abide by the terms of this restric-
tion.
4. USE RESTRICTIONS: You may not network the software or otherwise use it on more than one com-
puter or computer terminal at the same time. You may physically transfer the software from one computer to another
provided that the software is used on only one computer at a time. You may not distribute copies of the software or
Documentation to others. You may not reverse engineer, disassemble, decompile, modify, adapt, translate, or create
derivative works based on the software or the Documentation without the prior written consent of the Company.
5. TRANSFER RESTRICTIONS: The enclosed software is licensed only to you and may not be trans-
ferred to any one else without the prior written consent of the Company. Any unauthorized transfer of the software
shall result in the immediate termination of this Agreement.
6. TERMINATION: This license is effective until terminated. This license will terminate automatically
without notice from the Company and become null and void if you fail to comply with any provisions or limitations of
this license. Upon termination, you shall destroy the Documentation and all copies of the software. All provisions of
this Agreement as to warranties, limitation of liability, remedies or damages, and our ownership rights shall survive ter-
mination.
7. MISCELLANEOUS: This Agreement shall be construed in accordance with the laws of the United
States of America and the State of New York and shall benefit the Company, its affiliates, and assignees.
8. LIMITED WARRANTY AND DISCLAIMER OF WARRANTY: The Company warrants that the
software, when properly used in accordance with the Documentation, will operate in substantial conformity with the
description of the software set forth in the Documentation. The Company does not warrant that the software will meet
your requirements or that the operation of the software will be uninterrupted or error-free. The Company warrants that
the media on which the software is delivered shall be free from defects in materials and workmanship under normal use
for a period of thirty (30) days from the date of your purchase. Your only remedy and the Company’s only obligation
under these limited warranties is, at the Company’s option, return of the warranted item for a refund of any amounts
paid by you or replacement of the item. Any replacement of software or media under the warranties shall not extend the
original warranty period. The limited warranty set forth above shall not apply to any software which the Company
determines in good faith has been subject to misuse, neglect, improper installation, repair, alteration, or damage by you.
EXCEPT FOR THE EXPRESSED WARRANTIES SET FORTH ABOVE, THE COMPANY DISCLAIMS ALL
WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, THE IMPLIED WARRAN-
TIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. EXCEPT FOR THE
EXPRESS WARRANTY SET FORTH ABOVE, THE COMPANY DOES NOT WARRANT, GUARANTEE, OR
MAKE ANY REPRESENTATION REGARDING THE USE OR THE RESULTS OF THE USE OF THE SOFT-
WARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY, CURRENTNESS, OR OTHERWISE.
ACKNOWLEDGMENT
YOU ACKNOWLEDGE THAT YOU HAVE READ THIS AGREEMENT, UNDERSTAND IT,
AND AGREE TO BE BOUND BY ITS TERMS AND CONDITIONS. YOU ALSO AGREE THAT THIS
AGREEMENT IS THE COMPLETE AND EXCLUSIVE STATEMENT OF THE AGREEMENT BETWEEN
YOU AND THE COMPANY AND SUPERSEDES ALL PROPOSALS OR PRIOR AGREEMENTS, ORAL, OR
WRITTEN, AND ANY OTHER COMMUNICATIONS BETWEEN YOU AND THE COMPANY OR ANY
REPRESENTATIVE OF THE COMPANY RELATING TO THE SUBJECT MATTER OF THIS AGREEMENT.
Should you have any questions concerning this Agreement or if you wish to contact the Company for
any reason, please contact in writing at the address below.
Robin Short
Prentice Hall PTR
One Lake Street
Upper Saddle River, New Jersey 07458
| VIRTUAL INSTRUMENTATION SERIES
Jeffrey Y. Beyon
■ Hands-On Exercise Manual for LabVIEW Programming, Data Acquisition, and Analysis
Jeffrey Y. Beyon
■ LabVIEW Programming, Data Acquisition, and Analysis
Mahesh L. Chugani, Abhay R. Samant, Michael Cerra
■ LabVIEW Signal Processing
Rahman Jamal • Herbert Pichlik
■ LabVIEW Applications and Solutions
Shahid F. Khalid
■ Advanced Topics in LabWindows/CVI
Shahid F. Khalid
■ LabWindows/CVI Programming for Beginners
Hall T. Martin • Meg L. Martin
■ LabVIEW for Automotive, Telecommunications, Semiconductor, Biomedical, and
Other Applications
Bruce Mihura
■ LabVIEW for Data Acquisition
Jon B. Olansen • Eric Rosow
■ Virtual Bio-Instrumentation:
Biomedical, Clinical, and Healthcare Applications in LabVIEW
Barry Paton
■ Sensors, Transducers, and LabVIEW
Jeffrey Travis
■ LabVIEW for Everyone, second edition
Jeffrey Travis
■ Internet Applications in LabVIEW
Solutions from experts you know and trust.
Articles Free Library eBooks Expert Q & A Training Career Center Downloads MyInformIT
Login Register About InformIT
Topics
Operating Systems
Web Development
Programming
www.informit.com
Networking
Certification Free, in-depth articles and
and more...
supplements
Visit today
Free and get great content
Content
from
PH PTR Online!
We strive to stay on the cutting edge of what’s happening in
professional computer science and engineering. Here’s a bit of what
you’ll find when you stop by www.phptr.com:
Special interest areas offering our latest books, book series, software,
features of the month, related links and other useful information to
help you get the job done.
Deals, deals, deals! Come to our promotions section for the latest
bargains offered to you exclusively from our retailers.
What’s new at PH PTR? We don’t just publish books for the professional
community, we’re a part of it. Check out our convention schedule, join
an author chat, get the latest reviews and press releases on topics of
interest to you.