Data Acquisition in CSharp
Data Acquisition in CSharp
Faculty of Technology, Postboks 203, Kjølnes ring 56, N-3901 Porsgrunn, Norway. Tel: +47 35 57 50 00 Fax: +47 35 57 54 01
3 My First DAQ App with USB-‐6008 using DAQmx Driver ................................................... 18
2
3
Table
of
Contents
5.4 Logging Temperature Data with TC-‐01 Thermocouple Example ............................... 29
1 Introduction
In
this
Tutorial
we
will
learn
how
to
create
DAQ
(Data
Acquisition)
applications
in
Visual
Studio
and
C#.
We
will
use
a
USB-‐6008
DAQ
device
from
National
Instruments
as
an
example.
In
order
to
use
DAQ
devices
from
National
Instruments
in
C#
and
Visual
Studio
we
need
to
NI-‐DAQmx
driver
provides
by
National
Instruments.
As
part
of
this
installation
you
can
install
a
.NET
API.
We
will
use
this
API
to
create
a
simple
DAQ
application.
In
addition
we
will
use
Measurement
Studio
which
is
an
add-‐on
to
Visual
Studio
which
makes
it
easier
to
create
more
advanced
DAQ
applications.
In
this
Tutorial
we
end
up
with
a
control
application.
We
will
send
and
read
data
to
a
DAQ
device,
and
we
will
create
our
own
discrete
PID
controller,
low-‐pass
filter
and
a
discrete
model
of
our
system.
We
will
also
read
and
write
data
to
an
OPC
server.
You will find this document and lots of other information in the following web site:
http://home.hit.no/~hansha/?tutorial=csharp_daq
For more information about Visual Studio and C#, visit the following web page:
http://home.hit.no/~hansha/?tutorial=csharp
Below we see the integrated development environment (IDE) in Visual Studio:
5
6
Introduction
We
will
give
code
examples
of
how
to
use
this
device
in
C#.
Since
this
is
a
DAQmx
supported
device
from
National
Instruments,
the
programing
structure
will
be
the
same
as
for
NI
USB-‐6008.
The
NI
USB-‐6008
is
well
suited
for
education
purposes
due
to
its
small
size
and
easy
USB
connection.
1.2.3 myDAQ
NI
myDAQ
is
a
simple
and
intuitive
DAQ
device
from
National
Instruments.
NI
myDAQ
have
Analog
Inputs
(AI),
Analog
Outputs
(AO),
Digital
Inputs
(DI)
and
Digital
Outputs
(DO).
Specifications:
• Two
Differential
Analog
Input
and
Analog
Output
Channels
(200
ks/s,
16
bit,
+/-‐
10
Volts)
• Eight
Digital
Input
and
Digital
Output
Lines
(3.3
Volt
TTL-‐Compatible)
• +5
,
+15,
and
-‐15
Volt
Power
Supply
Outputs
(up
to
500m
Watts
of
Power)
• 60
Volt
Digital
Multimeter
(DMM)
for
Measuring
Voltage,
Current,
and
Resistance
In
addition
to
traditional
I/O,
the
myDAQ
have
a
built-‐in
Digital
Multimeter.
The
myDAQ
can
also
be
used
as
a
Power
Supply.
Using
the
built-‐in
software
the
myDAQ
can
also
be
used
as
an
Oscilloscope
and
Function
Generator.
When
you
plug
in
the
device
in
the
USB
connection
on
your
PC,
the
following
will
pop-‐up
automatically
(NI
ELVISmx
Instrument
Launcher):
Note!
You
need
to
install
the
NI
ELVISmx
driver
software
first
If you click on the DMM button, the built-‐in Digital Multimeter will appear:
Note!
In
order
to
install
the
DAQmx
API
for
C#,
make
sure
to
select
“.NET
Support”
when
installing
the
DAQmx
driver.
This
application
uses
the
C#
API
included
in
the
NI
DAQmx
driver,
so
make
sure
that
you
have
installed
the
NI
DAQmx
driver
in
advance.
Next,
make
sure
that
you
select
.NET
Framework
X.x
Support
for
the
version
of
.NET
that
yourversion
of
Visual
Studio
id
using:
2 Data
Acquisition
2.1 Introduction
The
purpose
of
data
acquisition
is
to
measure
an
electrical
or
physical
phenomenon
such
as
voltage,
current,
temperature,
pressure,
or
sound.
PC-‐based
data
acquisition
uses
a
combination
of
modular
hardware,
application
software,
and
a
computer
to
take
measurements.
While
each
data
acquisition
system
is
defined
by
its
application
requirements,
every
system
shares
a
common
goal
of
acquiring,
analyzing,
and
presenting
information.
Data
acquisition
systems
incorporate
signals,
sensors,
actuators,
signal
conditioning,
data
acquisition
devices,
and
application
software.
The DAQ system has the following parts involved, see Figure:
The
parts
are:
12
13
Data
Acquisition
• Analog
input
• Analog
output
• Digital
I/O
• Counter/timers
• “Desktop
DAQ
devices”
where
you
need
to
plug
a
PCI
DAQ
board
into
your
computer.
The
software
is
running
on
a
computer.
• “Portable
DAQ
devices”
for
connection
to
the
USB
port,
Wi-‐Fi
connections,
etc.
The
software
is
running
on
a
computer
• “Distributed
DAQ
devices”
where
the
software
is
developed
on
your
computer
and
then
later
downloaded
to
the
distributed
DAQ
device.
Application
software
adds
analysis
and
presentation
capabilities
to
the
driver
software.
Your
software
application
normally
does
such
tasks
as:
• Real-‐time
monitoring
• Data
analysis
• Data
logging
• Control
algorithms
• Human
machine
interface
(HMI)
In
order
to
create
your
DAQ
application
you
need
a
programming
development
tool,
such
as
Visual
Studio/C#,
LabVIEW,
etc..
In
addition
to
the
standard
tools,
MAX
can
expose
item-‐specific
tools
you
can
use
to
configure,
diagnose,
or
test
your
system,
depending
on
which
NI
products
you
install.
As
you
navigate
through
MAX,
the
contents
of
the
application
menu
and
toolbar
change
to
reflect
these
new
tools.
2.3.1 NI-‐DAQmx
National
Instruments
provides
a
native
.NET
API
for
NI-‐DAQmx.
This
is
available
as
a
part
of
the
NI-‐DAQmx
driver
and
does
not
require
Measurement
Studio.
In general, data acquisition programming with DAQmx involves the following steps:
Data
acquisition
in
text
based-‐programming
environment
is
very
similar
to
the
LabVIEW
NI-‐DAQmx
programming
as
the
functions
calls
is
the
same
as
the
NI-‐DAQmx
VI’s.
http://zone.ni.com/devzone/cda/tut/p/id/5409#toc4
2.3.2 Examples
Examples
installed
as
part
of
NI-‐DAQmx:
The
location
of
examples
will
depend
on
the
version
of
Visual
Studio
and
is
listed
in
the
following
Developer
Zone
Article:
Using
NI-‐DAQmx
in
Text
Based
Programming
Environments.
The
most
common
location
is:
C:\Documents
and
Settings\All
Users\Documents\National
Instruments\NI-‐DAQ\Examples\DotNET<.NET
Framework
Version>\
Sub-‐folders
named
CS
contain
C#
examples.
These
examples
install
with
NI-‐DAQmx.
Measurement
Studio
is
not
required
to
install
the
class
libraries
or
the
examples.
Note! If the paths above do not exist, be sure you have .NET support installed for NI-‐DAQmx.
3.1 Introduction
This
application
uses
the
C#
API
included
in
the
NI
DAQmx
driver,
so
make
sure
that
you
have
installed
the
NI
DAQmx
driver
in
advance.
You
don’t
need
Measurement
Studio
to
create
this
application.
We will create the following application in Visual Studio 2010 and C#:
18
19
My
First
DAQ
App
The
User
Interface
looks
like
this:
We
start
by
connecting
the
Analog
In
and
Analog
Out
wires
together
(a
so
called
Loopback
test).
When
we
click
the
“Write
Data”
button,
the
value
entered
in
the
text
box
“Analog
Out”
will
be
written
to
the
DAQ
device.
If
we
have
connected
the
Analog
In
and
Analog
Out
wires
together
we
will
read
the
same
value
in
the
“Analog
In”
textbox
when
we
push
the
“Get
Data”
button.
3.2 Example
We
will
go
through
the
different
parts
of
the
code
in
detail.
• NationalInstruments.Common
• NationalInstruments.DAQmx
We add References by right-‐clicking the References node in the Solution Explorer:
When
we
have
added
the
necessary
References,
the
Solution
Explorer
will
look
like
this:
3.2.2 Initialization
We
need
to
add
the
following
Namespaces:
using NationalInstruments;
using NationalInstruments.DAQmx;
3.2.3 Analog
O ut
We
implement
the
code
for
writing
to
the
Analog
Out
channel
in
the
Event
Handler
for
the
“Write
Data”
button:
AOChannel myAOChannel;
myAOChannel = analogOutTask.AOChannels.CreateVoltageChannel(
"dev1/ao0",
"myAOChannel",
0,
5,
AOVoltageUnits.Volts
);
double analogDataOut;
analogDataOut = Convert.ToDouble(txtAnalogOut.Text);
writer.WriteSingleSample(true, analogDataOut);
3.2.4 Analog
I n
We
implement
the
code
for
reading
data
from
the
Analog
In
channel
in
the
Event
Handler
for
the
“Get
Data”
button:
AIChannel myAIChannel;
myAIChannel = analogInTask.AIChannels.CreateVoltageChannel(
"dev1/ai0",
"myAIChannel",
AITerminalConfiguration.Differential,
0,
5,
AIVoltageUnits.Volts
);
txtAnalogIn.Text = analogDataIn.ToString();
3.2.5 Error?
If
your
application
runs
without
error
that’s
fine,
but
perhaps
you
get
the
following
error:
In
order
to
fix
the
problem,
open
the
Properties
for
your
project:
Make
sure
to
select
“.NET
Framework
X”
in
the
“Target
framework”
drop-‐down
menu.
4.1 Example
We
vill
create
the
following
simple
application:
23
24
Temperature
Logging
• NationalInstruments.Common
• NationalInstruments.DAQmx
We add References by right-‐clicking the References node in the Solution Explorer:
When
we
have
added
the
necessary
References,
the
Solution
Explorer
will
look
like
this:
The
dlls
are
normally
to
find
here:
4.1.2 Initialization
We
need
to
add
the
following
Namespaces:
using NationalInstruments;
using NationalInstruments.DAQmx;
namespace TC01_DAQ_Example
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
AIChannel myAIChannel;
myAIChannel = temperatureTask.AIChannels.CreateThermocoupleChannel(
"Dev1/ai0",
"Temperature",
0,
100,
AIThermocoupleType.J,
AITemperatureUnits.DegreesC,
25
);
txtTempData.Text = analogDataIn.ToString();
}
}
}
4.1.5 Error?
If
your
application
runs
without
error
that’s
fine,
but
perhaps
you
get
the
following
error:
In
order
to
fix
the
problem,
open
the
Properties
for
your
project:
Make
sure
to
select
“.NET
Framework
X”
in
the
“Target
framework”
drop-‐down
menu.
5 Measurement
Studio
5.1 Introduction
C#
is
a
powerful
programming
language,
but
has
few
built-‐in
features
for
measurement
and
control
applications.
Measurement
Studio
is
an
add-‐on
to
Visual
Studio
which
makes
it
easier
to
create
such
applications.
With
Measurement
Studio
we
can
implement
Data
Acquisition
and
a
graphical
HMI.
Measurement
Studio
for
Visual
C#
.NET
provides:
• Managed
.NET
controls
for
creating
rich
Web
and
Windows
GUIs
• Multithreaded
API
for
data
acquisition
• Instrument
control
APIs
• Analysis
libraries
designed
for
engineers
and
scientists
27
28
Measurement
Studio
5.2 Templates
Measurement
Studio
has
several
Templates
that
make
it
easier
to
build
DAQ
applications.
5.3 Toolbox
Below
we
see
the
Toolbox
in
Visual
Studio
that
is
installed
with
Measurement
Studio:
In addition to the Toolbox, Measurement Studio also installs the following menu item:
When
we
click
“Finish”
an
empty
project
will
be
created
for
us.
We
are
now
ready
to
create
our
own
application.
When
we
click
the
“Read
Temp”
button,
the
Temperature
data
shall
be
shown
in
the
“Temp
Data”
TextBox.
In
the
event
Handler
for
the
“Read
Temp”
button,
we
create
the
following
code:
private void btnReadTempData_Click(object sender, EventArgs e)
{
AIChannel myAIChannel;
myAIChannel = analogInTask.AIChannels.CreateThermocoupleChannel(
"Dev1/ai0",
"Temperature",
0,
100,
AIThermocoupleType.J,
AITemperatureUnits.DegreesC,
25
);
txtTempData.Text = analogDataIn.ToString();
We
drag
in
a
Timer
component
from
the
Toolbox.
First,
we
need
to
start
the
Timer:
public Form1()
{
InitializeComponent();
timer1.Start();
}
Next, we need to specify the interval. We can do that in the Properties window:
In
the
Timer
Event
we
write
the
code
for
reading
the
Temperature:
private void timer1_Tick(object sender, EventArgs e)
{
AIChannel myAIChannel;
myAIChannel = analogInTask.AIChannels.CreateThermocoupleChannel(
"Dev1/ai0",
"Temperature",
0,
100,
AIThermocoupleType.J,
AITemperatureUnits.DegreesC,
25
);
txtTempData.Text = analogDataIn.ToString("0.0");
In
addition
we
will
use
a
Pt-‐100
sensor
that
we
connect
to
one
of
the
Analog
Input
channels
on
the
USB-‐6008
device:
The
Output
from
this
device
is
between
1-‐5V
that
illustrates
a
temperature
between
0
and
100
degrees
Celsius.
The
procedure
and
code
is
identical
as
the
previous
example,
except
a
small
part
as
shown
below:
private void timer1_Tick(object sender, EventArgs e)
{
AIChannel myAIChannel;
myAIChannel = analogInTask.AIChannels.CreateVoltageChannel(
"dev1/ai0",
"myAIChannel",
AITerminalConfiguration.Differential,
1,
5,
AIVoltageUnits.Volts
);
txtTempData.Text = analogDataIn.ToString("0.0");
6 Control
Application
6.1 Introduction
t o
t he
E xample
In
this
example
we
will
use
Measurement
Studio
to
create
a
simple
control
application.
We
will
control
the
level
in
a
water
tank
using
manual
control.
The
process
is
as
follows:
In
this
example
we
will
use
a
small-‐scale
laboratory
process
called
LM-‐900
Level
System:
36
37
Control
Application
We
want
to
control
the
level
in
the
water
tank
using
a
pump
on
the
inflow.
We
will
read
the
level
using
our
USB-‐6008
DAQ
device
(Analog
In)
and
write
the
control
signal
(Analog
Out)
to
the
DAQ
device.
The
Analog
Out
(control
signal)
will
be
a
signal
between
0 − 5𝑉
and
the
Analog
In
(Level)
will
be
a
0 − 5𝑉
signal
that
we
need
to
scale
to
0 − 20𝑐𝑚.
We
will
use
a
“Slider”
to
manually
adjust
the
control
signal
and
a
Tank
to
indicate
the
level
in
the
real
process.
In
this
example
we
will
use
the
“Slide”
control
and
“Tank”
control
that
comes
with
Measurement
Studio.
6.2 Coding
Start
a
New
Project
in
Visual
Studio:
Select
the
“NI
Windows
Application”
Template
in
the
“Measurement
Studio”
node.
In the window that appears next, select the Libraries you want to include:
We
create
the
User
Interface
above
in
Visual
Studio,
and
it
looks
like
this:
For
the
read
and
write
operations
we
have
created
a
simple
Class
with
two
methods:
public class DaqData
{
{
...
}
}
AIChannel myAIChannel;
myAIChannel = analogInTask.AIChannels.CreateVoltageChannel(
"dev1/ai0",
"myAIChannel",
AITerminalConfiguration.Differential,
0,
5,
AIVoltageUnits.Volts
);
return analogDataIn;
}
AOChannel myAOChannel;
myAOChannel = analogOutTask.AOChannels.CreateVoltageChannel(
"dev1/ao0",
"myAOChannel",
0,
5,
AOVoltageUnits.Volts
);
writer.WriteSingleSample(true, analogDataOut);
In
the
Properties
window
we
can
specify
the
Interval
(“Sampling
Time”)
in
milliseconds.
We
can
start
the
timer
with
the
following
code:
public Form1()
{
InitializeComponent();
timer1.Start();
}
In
the
Timer
Event
we
create
the
main
logic
in
our
application.
We
call
the
ReadDaqData()
and
WriteDaqData()
methods,
updates
the
GUI,
etc.
private void timer1_Tick(object sender, EventArgs e)
{
//Read Data
double analogDataIn;
analogDataIn = myDaqData.ReadDaqData();
if (analogDataIn < 0)
analogDataIn = 0;
if (analogDataIn > 5)
analogDataIn = 5;
//Scaling:
analogDataIn = analogDataIn * 4; //0-5V -> 0-20cm
tank.Value = analogDataIn;
txtLevelValue.Text = analogDataIn.ToString("0.00");
//Write Data
double analogDataOut;
analogDataOut = sliderControl.Value;
myDaqData.WriteDaqData(analogDataOut);
7 Trending
Data
Now
we
want
to
extend
our
application
with
functionality
for
viewing
historical
data
using
a
trend
plot.
In
this
example
we
will
use
the
“WaveformGraph”
control
in
Measurement
Studio.
The
source
code
is
the
same
as
in
the
previous
example,
except
for
one
new
line
of
code
in
the
Timer
Event:
waveformGraph.PlotYAppend(analogDataIn);
The
“WaveformGraph”
control
has
lots
of
functionality
you
can
set
in
the
Properties
window
or
clicking
the
Smart
Tag
Anchor
(little
arrow
in
the
upper
right
corner
of
the
control).
Below
we
see
the
Properties
window
(left
side)
and
the
Smart
Tag
Panel
(right
side)
for
the
WaveformGraph
control:
43
44
Trending
Data
8 Discretization
The
next
improvements
to
our
application
would
be
to
implement
a
Low-‐pass
Filter
in
order
to
remove
the
noise
from
the
signal
when
reading
the
level.
Another
improvement
would
be
to
replace
the
manual
control
with
a
PI
controller
that
do
the
job
for
us.
Finally
it
would
be
nice
to
have
a
mathematical
model
of
our
water
tank
so
we
can
simulate
and
test
the
behavior
of
the
real
system
without
connect
to
it.
So
we
need
to
create
discrete
versions
of
the
low-‐pass
filter,
the
PI
controller
and
the
process
model.
We
can,
e.g.,
use
the
Euler
Forward
discretization
method:
𝑥!!! − 𝑥!
𝑥≈
𝑇!
𝑦(𝑠) 1
𝐻 𝑠 = =
𝑢(𝑠) 𝑇! 𝑠 + 1
Where
𝑇!
is
the
time-‐constant
of
the
filter,
𝑢(𝑠)
is
the
filter
input
and
𝑦 𝑠
is
the
filter
output.
Discrete version:
It can be shown that a discrete version can be stated as:
𝒚𝒌 = 𝟏 − 𝒂 𝒚𝒌!𝟏 + 𝒂𝒖𝒌
Where
𝑻𝒔
𝒂=
𝑻𝒇 + 𝑻𝒔
45
46
Discretization
It is a golden rule that 𝑇! ≪ 𝑇! and in practice we should use the following rule:
𝑇!
𝑇! ≤
5
Proof:
Given:
𝑦 1
=
𝑢 𝑇! 𝑠 + 1
This gives:
𝑇! 𝑠 + 1 𝑦 = 𝑢
𝑇! 𝑠𝑦 + 𝑦 = 𝑢
𝑇! 𝑦 + 𝑦 = 𝑢
!! !!!!!
We
use
the
Euler
Backward
discretization
method,
𝑥 ≈ !!
,
which
gives:
𝑦! − 𝑦!!!
𝑇! + 𝑦! = 𝑢!
𝑇!
𝑇! 𝑦! − 𝑦!!! + 𝑦! 𝑇! = 𝑢! 𝑇!
𝑇! 𝑦! − 𝑇! 𝑦!!! + 𝑦! 𝑇! = 𝑢! 𝑇!
𝑦! (𝑇! + 𝑇! ) = 𝑇! 𝑦!!! + 𝑢! 𝑇!
This gives:
𝑇! 𝑇!
𝑦! = 𝑦!!! + 𝑢
𝑇! + 𝑇! 𝑇! + 𝑇! !
𝑇!
≡ 𝑎
𝑇! + 𝑇!
This gives:
𝑦! = (1 − 𝑎)𝑦!!! + 𝑎𝑢!
𝑇!
𝑎=
𝑇! + 𝑇!
8.2 PI
C ontroller
A
PI
controller
may
be
written:
!
𝐾!
𝑢 𝑡 = 𝑢! + 𝐾! 𝑒 𝑡 + 𝑒𝑑𝜏
𝑇! !
𝑒 𝑡 = 𝑟 𝑡 − 𝑦(𝑡)
Laplace:
𝐾!
𝑢 𝑠 = 𝐾! 𝑒 𝑠 + 𝑒 𝑠
𝑇! 𝑠
Discrete version:
We
start
with:
!
𝐾!
𝑢 𝑡 = 𝑢! + 𝐾! 𝑒 𝑡 + 𝑒𝑑𝜏
𝑇! !
In
order
to
make
a
discrete
version
using,
e.g.,
Euler,
we
can
derive
both
sides
of
the
equation:
𝐾!
𝑢 = 𝑢! + 𝐾! 𝑒 + 𝑒
𝑇!
𝑲𝒑
𝒖𝒌 = 𝒖𝒌!𝟏 + 𝒖𝟎,𝒌 − 𝒖𝟎,𝒌!𝟏 + 𝑲𝒑 𝒆𝒌 − 𝒆𝒌!𝟏 + 𝑻 𝒆
𝑻𝒊 𝒔 𝒌
Where
𝑒! = 𝑟! − 𝑦!
We can also split the equation above in 2 different pars by setting:
∆𝑢! = 𝑢! − 𝑢!!!
𝒆𝒌 = 𝒓𝒌 − 𝒚𝒌
𝑲𝒑
∆𝒖𝒌 = 𝒖𝟎,𝒌 − 𝒖𝟎,𝒌!𝟏 + 𝑲𝒑 𝒆𝒌 − 𝒆𝒌!𝟏 + 𝑻 𝒆
𝑻𝒊 𝒔 𝒌
𝒖𝒌 = 𝒖𝒌!𝟏 + ∆𝒖𝒌
𝐾!
𝑢 𝑠 = 𝐾! 𝑒 𝑠 + 𝑒 𝑠
𝑇! 𝑠
!
We
set
𝑧 = ! 𝑒 ⇒ 𝑠𝑧 = 𝑒 ⇒ 𝑧 = 𝑒
This gives:
𝑧 = 𝑒
𝐾!
𝑢 = 𝐾! 𝑒 + 𝑧
𝑇!
Where
𝑒 = 𝑟 − 𝑦
Discrete version:
Using
Euler:
𝑧!!! − 𝑧!
𝑧≈
𝑇!
This
gives:
𝑧!!! − 𝑧!
= 𝑒!
𝑇!
𝐾!
𝑢! = 𝐾! 𝑒! + 𝑧
𝑇! !
Finally:
𝒆𝒌 = 𝒓𝒌 − 𝒚𝒌
𝑲𝒑
𝒖𝒌 = 𝑲𝒑 𝒆𝒌 + 𝒛
𝑻𝒊 𝒌
𝒛𝒌!𝟏 = 𝒛𝒌 + 𝑻𝒔 𝒆𝒌
A
very
simple
(linear)
model
of
the
water
tank
is
as
follows:
𝐴! ℎ = 𝐾! 𝑢−𝐹!"#
or
1
ℎ= 𝐾 𝑢−𝐹!"#
𝐴! !
Where:
We
can
use
the
Euler
Forward
discretization
method
in
order
to
create
a
discrete
model:
𝑥!!! − 𝑥!
𝑥≈
𝑇!
ℎ!!! − ℎ! 1
= 𝐾 𝑢 −𝐹
𝑇! 𝐴! ! ! !"#
Finally:
𝑻𝒔
𝒉𝒌!𝟏 = 𝒉𝒌 + 𝑲 𝒖 −𝑭
𝑨𝒕 𝒑 𝒌 𝒐𝒖𝒕
Below
we
see
the
Project
and
Solution
in
Visual
Studio:
Below
we
will
show
and
describe
the
important
parts
of
the
code.
PI Controller:
We
create
a
new
Class
for
our
PID
algorithm,
by
right-‐click
in
the
Solution
Explorer
(Add→New
Item…)
The
Add
New
Item
window
appears:
Select
the
Class
Item
and
a
proper
Name,
e.g.
“PidController”.
//PID Algoritm
e = r - y;
u = Kp * e + (Kp / Ti) * z;
z = z + Ts * e;
return u;
}
controllerOutput = sliderControl.Value;
}
else // Use PID Control
{
controllerOutput = pidControl.PiController(levelMeasurement);
//Scaling
controllerOutput = controllerOutput / 4; //0-20cm -> 0-5V
//Set boundaries
if (controllerOutput < 0)
controllerOutput = 0;
if (controllerOutput > 5)
controllerOutput = 5;
}
Low-‐pass Filter:
double a;
double yFiltered;
a = Ts / (Ts + Tf);
yFiltered = (1 - a) * yk + a * yFromDaq;
yk = yFiltered;
return yFiltered;
}
}
Discrete Model:
We
have
created
a
Class
and
a
LevelTankModel
Method
that
we
use
in
our
simulation:
levelMeasurement = model.LevelTankModel(controllerOutput);
9 OPC
In
order
to
communicate
with
an
OPC
Server
we
can
use
the
DataSocket
API
that
is
part
of
the
Measurement
Studio.
We
use
the
Matrikon
OPC
Simulation
Server.
Code:
55
56
OPC
if (dataSocket.IsConnected)
dataSocket.Disconnect();
dataSocket.Connect(opcUrl, AccessMode.Read);
txtReadOpcValue.Text = dataSocket.Data.Value.ToString();
}
SelectUrl:
We
can
use
the
SelectUrl
method
if
we
want
to
pick
the
OPC
item
from
a
list
of
available
servers
(both
local
servers
and
network
servers)
and
items.
dataSocket.SelectUrl();
Below
we
will
go
through
a
very
simple
example.
We
will
write
one
value
to
the
OPC
Server
each
time
we
click
a
button.
Code:
if (dataSocket.IsConnected)
dataSocket.Disconnect();
dataSocket.Connect(opcUrl, AccessMode.Write);
double opcValue = 0;
opcValue = Convert.ToDouble(txtWriteOpcValue.Text);
dataSocket.Data.Value = opcValue;
dataSocket.Update();
}
In
the
Properties
window
we
can
specify
the
Interval
(“Sampling
Time”)
in
milliseconds.
timer1.Start();
}
In the Timer Event we create the code in order to read data at this specific interval.
…
…
10
Using
Measurement
Studio
Templates
In
order
to
use
the
NI
USB-‐TC01
Thermocouple
Measurement
device
with
C#
we
need
to
have
the
DAQmx
driver
and
the
DAQmx
API
for
C#
installed.
In
order
to
install
the
DAQmx
API
for
C#,
make
sure
to
select
“.NET
Support”
when
installing
the
DAQmx
driver.
C#
is
a
powerful
programming
language,
but
has
few
built-‐in
features
for
measurement
and
control
applications.
Measurement
Studio
is
an
add-‐on
to
Visual
Studio
which
makes
it
easier
to
create
such
applications.
With
Measurement
Studio
we
can
implement
Data
Acquisition
and
a
graphical
HMI.
You
don’t
need
to
use
the
Measurement
Studio
to
create
an
application
where
you
use
the
NI
USB-‐TC01
Thermocouple
Measurement
device,
but
it
is
easier.
Here
we
will
use
Visual
Studio
and
the
Measurement
Studio
Add-‐in
to
create
some
DAQ
examples
where
we
get
temperature
data
from
the
NI
USB-‐TC01
Thermocouple
Measurement
device.
61
62
Using
Measurement
Studio
Templates
Note!
The
“New
Project”
window
may
look
different
on
your
computer,
it
depends
on
what
features
you
have
installed
and
which
version
or
edition
of
Measurement
Studio
you
are
using.
Next
we
select
the
Class
Libraries
we
want
to
include.
In
our
case
we
need
at
least
to
select
the
“DAQmx
Library”.
When
we
click
“Finish”
an
empty
project
will
be
created
for
us.
We
are
now
ready
to
create
our
own
application.
When
we
click
the
“Read
Temp”
button,
the
Temperature
data
shall
be
shown
in
the
“Temp
Data”
TextBox.
In
the
event
Handler
for
the
“Read
Temp”
button,
we
create
the
following
code:
private void btnReadTempData_Click(object sender, EventArgs e)
{
AIChannel myAIChannel;
myAIChannel = analogInTask.AIChannels.CreateThermocoupleChannel(
"Dev1/ai0",
"Temperature",
0,
100,
AIThermocoupleType.J,
AITemperatureUnits.DegreesC,
25
);
txtTempData.Text = analogDataIn.ToString();
Improvements:
We
should
use
a
“Timer”
in
order
to
read
Temperature
data
at
specific
intervals
instead
of
pushing
a
button
each
time
we
need
data.
We
drag
in
a
Timer
component
from
the
Toolbox.
First,
we
need
to
start
the
Timer:
public Form1()
{
InitializeComponent();
timer1.Start();
}
Next, we need to specify the interval. We can do that in the Properties window:
In
the
Timer
Event
we
write
the
code
for
reading
the
Temperature:
private void timer1_Tick(object sender, EventArgs e)
{
AIChannel myAIChannel;
myAIChannel = analogInTask.AIChannels.CreateThermocoupleChannel(
"Dev1/ai0",
"Temperature",
0,
100,
AIThermocoupleType.J,
AITemperatureUnits.DegreesC,
25
);
txtTempData.Text = analogDataIn.ToString("0.0");
We
start
by
creating
a
“New
Project”
from
Visual
Studio.
In
the
“New
Project”
window
we
select
“Visual
C#”
»
“Measurement
Studio”,
and
then
select
the
“NI
DAQ
Windows
Application”
Template
that
is
part
of
the
Measurement
Studio.
Note!
The
“New
Project”
window
may
look
different
on
your
computer,
it
depends
on
what
features
you
have
installed
and
which
version
or
edition
of
Measurement
Studio
you
are
using.
Next, we need to go through different steps in a wizard.
In
the
next
step
we
select
the
measurement
type,
and
since
the
NI
USB-‐TC01
Thermocouple
Measurement
device
is
for
reading
Temperature
values,
we
need
to
select
“Acquire
Signals”.
In
the
“Acquire
Signals”
node
we
first
select
“Temperature”
and
then
select
“Thermocouple”.
Next
we
need
to
select
the
physical
channel(s).
Since
the
NI
USB-‐TC01
Thermocouple
Measurement
device
has
only
one
channel
available,
we
need
to
select
“ai0”
(Analog
In,
Channel
0).
Next
we
can
set
different
Properties,
such
as
“Input
Range”,
“Acquisition
Mode”,
“Thermocouple
Type”,
etc.
Finally
we
see
a
Preview
of
the
User
Interface
before
it
is
automatically
generated
by
the
Measurement
Studio:
When
we
click
“Finish”,
the
Solution,
the
Project
and
User
Interface
will
be
automatically
created.
Figure
1:
Visual
Studio
Generated
Solution
With
this
approach
we
get
a
“flying
start”
and
we
can
change
the
code
as
we
please.
The
drawback
with
this
approach
is
that
the
code
that
is
automatically
generated
is
a
little
bit
“messy”.
My
F irst
D AQ
A pp
The
code
for
this
application
is
as
follows:
using NationalInstruments;
using NationalInstruments.DAQmx;
using NationalInstruments.UI;
using NationalInstruments.UI.WindowsForms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MyFirstDAQApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
AIChannel myAIChannel;
myAIChannel = analogInTask.AIChannels.CreateVoltageChannel(
"dev1/ai0",
"myAIChannel",
AITerminalConfiguration.Differential,
0,
5,
AIVoltageUnits.Volts
);
txtAnalogIn.Text = analogDataIn.ToString();
71
72
Appendix
A:
Source
Code
AOChannel myAOChannel;
myAOChannel = analogOutTask.AOChannels.CreateVoltageChannel(
"dev1/ao0",
"myAOChannel",
0,
5,
AOVoltageUnits.Volts
);
double analogDataOut;
analogDataOut = Convert.ToDouble(txtAnalogOut.Text);
writer.WriteSingleSample(true, analogDataOut);
}
}
Control
A pplication
The
code
for
this
application
is
as
follows:
using NationalInstruments;
using NationalInstruments.DAQmx;
using NationalInstruments.UI;
using NationalInstruments.UI.WindowsForms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Control_Application
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
timer1.Start();
}
//Read Data
double analogDataIn;
analogDataIn = myDaqData.ReadDaqData();
if (analogDataIn < 0)
analogDataIn = 0;
if (analogDataIn > 5)
analogDataIn = 5;
//Scaling:
analogDataIn = analogDataIn * 4; //0-5V -> 0-20cm
tank.Value = analogDataIn;
txtLevelValue.Text = analogDataIn.ToString("0.00");
//Write Data
double analogDataOut;
analogDataOut = sliderControl.Value;
myDaqData.WriteDaqData(analogDataOut);
/// <summary>
/// Reading and Writing Data from DAQ Device
/// </summary>
public class DaqData
{
AIChannel myAIChannel;
myAIChannel = analogInTask.AIChannels.CreateVoltageChannel(
"dev1/ai0",
"myAIChannel",
AITerminalConfiguration.Differential,
0,
5,
AIVoltageUnits.Volts
);
return analogDataIn;
}
AOChannel myAOChannel;
myAOChannel = analogOutTask.AOChannels.CreateVoltageChannel(
"dev1/ao0",
"myAOChannel",
0,
5,
AOVoltageUnits.Volts
);
writer.WriteSingleSample(true, analogDataOut);
}
}
}
namespace OPC_Read
{
public partial class Form1 : Form
{
DataSocket dataSocket = new DataSocket();
public Form1()
{
InitializeComponent();
string opcUrl;
opcUrl = "opc://localhost/MATRIKON.OPC.Simulation/Bucket Brigade.Real4";
if (dataSocket.IsConnected)
dataSocket.Disconnect();
dataSocket.Connect(opcUrl, AccessMode.Read);
}
dataSocket.Update();
txtReadOpcValue.Text = dataSocket.Data.Value.ToString();
}
}
}
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace OPC_Write
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
string opcUrl;
opcUrl = "opc://localhost/MATRIKON.OPC.Simulation/Bucket Brigade.Real4";
if (dataSocket.IsConnected)
dataSocket.Disconnect();
dataSocket.Connect(opcUrl, AccessMode.Write);
}
double opcValue = 0;
opcValue = Convert.ToDouble(txtWriteOpcValue.Text);
dataSocket.Data.Value = opcValue;
dataSocket.Update();
}
}
}
www.hit.no
E-‐mail: hans.p.halvorsen@hit.no
Blog: http://home.hit.no/~hansha/