1 lnLroducLlon ln Lhls 1uLorlal we wlll learn how Lo creaLe uAC (uaLa AcqulslLlon) appllcaLlons ln vlsual SLudlo and C#. We wlll use a uS8-6008 uAC devlce from naLlonal lnsLrumenLs as an example. ln order Lo use uAC devlces from naLlonal lnsLrumenLs ln C# and vlsual SLudlo we need Lo nl-uACmx drlver provldes by naLlonal lnsLrumenLs. As parL of Lhls lnsLallaLlon you can lnsLall a .nL1 Al. We wlll use Lhls Al Lo creaLe a slmple uAC appllcaLlon. ln addlLlon we wlll use MeasuremenL SLudlo whlch ls an add-on Lo vlsual SLudlo whlch makes lL easler Lo creaLe more advanced uAC appllcaLlons. ln Lhls 1uLorlal we end up wlLh a conLrol appllcaLlon. We wlll send and read daLa Lo a uAC devlce, and we wlll creaLe our own dlscreLe lu conLroller, low-pass fllLer and a dlscreLe model of our sysLem. We wlll also read and wrlLe daLa Lo an CC server. ?ou wlll flnd Lhls documenL and loLs of oLher lnformaLlon ln Lhe followlng web slLe: http:]]home.h|t.no]~hansha]?tutor|a|=csharp_daq 1.1 vlsual SLudlo MlcrosofL vlsual SLudlo ls an lnLegraLed developmenL envlronmenL (luL) from MlcrosofL. lL can be used Lo develop console and graphlcal user lnLerface appllcaLlons along wlLh Wlndows lorms appllcaLlons, web slLes, web appllcaLlons, and web servlces ln boLh naLlve code LogeLher wlLh managed code for all plaLforms supporLed by MlcrosofL Wlndows, Wlndows hone, Wlndows CL, .nL1 lramework, .nL1 CompacL lramework and MlcrosofL SllverllghL. lor more lnformaLlon abouL vlsual SLudlo and C#, vlslL Lhe followlng web page: http:]]home.h|t.no]~hansha]?tutor|a|=csharp 8elow we see Lhe lnLegraLed developmenL envlronmenL (luL) ln vlsual SLudlo: 6 lnLroducLlon 1uLorlal: uaLa AcqulslLlon ln C#
new pro[ecLs are creaLed from Lhe new ro[ecL" wlndow:
1.2 uAC Pardware ln Lhls 1uLorlal we wlll use dlfferenL hardware avalllble from naLlonal lnsLrumenLs as examples: 7 lnLroducLlon 1uLorlal: uaLa AcqulslLlon ln C# 1C-01 1hermocouple devlce uS8-6008 uAC uevlce MyuAC 1.2.1 nl uS8 1C-01 1hermocouple uevlce 8elow we see Lhe nl uS8-1C01 1hermocouple MeasuremenL devlce.
We wlll glve code examples of how Lo use Lhls devlce ln C#. Slnce Lhls ls a uACmx supporLed devlce from naLlonal lnsLrumenLs, Lhe programlng sLrucLure wlll be Lhe same as for nl uS8-6008. We wlll use Lhe nl uS8-1C01 devlce ln ChapLer 10 - uslng nl 1C-01 ln vlsual SLudlo and C#. 1.2.2 nl uS8-6008 uAC uevlce nl uS8-6008 ls a slmple and low-cosL mulLlfuncLlon l/C devlce from naLlonal lnsLrumenLs.
1he devlce has Lhe followlng speclflcaLlons: 8 analog lnpuLs (12-blL, 10 kS/s) 8 lnLroducLlon 1uLorlal: uaLa AcqulslLlon ln C# 2 analog ouLpuLs (12-blL, 130 S/s) 12 dlglLal l/C uS8 connecLlon, no exLra power-supply neeeded CompaLlble wlLh LabvlLW, LabWlndows/Cvl, and MeasuremenL SLudlo for vlsual SLudlo .nL1 nl-uACmx drlver sofLware 1he nl uS8-6008 ls well sulLed for educaLlon purposes due Lo lLs small slze and easy uS8 connecLlon. 1.2.3 myuAC nl myuAC ls a slmple and lnLulLlve uAC devlce from naLlonal lnsLrumenLs. nl myuAC have Analog lnpuLs (Al), Analog CuLpuLs (AC), ulglLal lnpuLs (ul) and ulglLal CuLpuLs (uC).
SpeclflcaLlons: 1wo ulfferenLlal Analog lnpuL and Analog CuLpuL Channels (200 ks/s, 16 blL, +/- 10 volLs) LlghL ulglLal lnpuL and ulglLal CuLpuL Llnes (3.3 volL 11L-CompaLlble) +3 , +13, and -13 volL ower Supply CuLpuLs (up Lo 300m WaLLs of ower) 60 volL ulglLal MulLlmeLer (uMM) for Measurlng volLage, CurrenL, and 8eslsLance ln addlLlon Lo LradlLlonal l/C, Lhe myuAC have a bullL-ln D|g|ta| Mu|t|meter. 1he myuAC can also be used as a ower Supp|y. uslng Lhe bullL-ln sofLware Lhe myuAC can also be used as an Csc|||oscope and Iunct|on Generator. When you plug ln Lhe devlce ln Lhe uS8 connecLlon on your C, Lhe followlng wlll pop-up auLomaLlcally (nl LLvlSmx lnsLrumenL Launcher): 9 lnLroducLlon 1uLorlal: uaLa AcqulslLlon ln C#
noLe! ?ou need Lo lnsLall Lhe nl LLvlSmx drlver sofLware flrsL lf you cllck on Lhe uMM buLLon, Lhe bullL-ln ulglLal MulLlmeLer wlll appear:
1.3 nl uACmx drlver naLlonal lnsLrumenLs provldes a naLlve .nL1 Al for nl-uACmx. 1hls ls avallable as a parL of Lhe nl-uACmx drlver and does noL requlre MeasuremenL SLudlo. Note! ln order Lo lnsLall Lhe uACmx Al for C#, make sure Lo selecL .nL1 SupporL" when lnsLalllng Lhe uACmx drlver. 1hls appllcaLlon uses Lhe C# Al lncluded ln Lhe nl uACmx drlver, so make sure LhaL you have lnsLalled Lhe nl uACmx drlver ln advance. uurlng Lhe lnsLallaLlon makesure Lo selecL CusLom": 10 lnLroducLlon 1uLorlal: uaLa AcqulslLlon ln C#
nexL, make sure LhaL you selecL .nL1 lramework x.x SupporL for Lhe verslon of .nL1 LhaL yourverslon of vlsual SLudlo ld uslng:
1.4 MeasuremenL SLudlo 11 lnLroducLlon 1uLorlal: uaLa AcqulslLlon ln C# C# ls a powerful programmlng language, buL has few bullL-ln feaLures for measuremenL and conLrol appllcaLlons. MeasuremenL SLudlo ls an add-on Lo vlsual SLudlo whlch makes lL easler Lo creaLe such appllcaLlons. WlLh MeasuremenL SLudlo we can lmplemenL uaLa AcqulslLlon and a graphlcal PMl.
12
2 uaLa AcqulslLlon 2.1 lnLroducLlon 1he purpose of daLa acqulslLlon ls Lo measure an elecLrlcal or physlcal phenomenon such as volLage, currenL, LemperaLure, pressure, or sound. C-based daLa acqulslLlon uses a comblnaLlon of modular hardware, appllcaLlon sofLware, and a compuLer Lo Lake measuremenLs. Whlle each daLa acqulslLlon sysLem ls deflned by lLs appllcaLlon requlremenLs, every sysLem shares a common goal of acqulrlng, analyzlng, and presenLlng lnformaLlon. uaLa acqulslLlon sysLems lncorporaLe slgnals, sensors, acLuaLors, slgnal condlLlonlng, daLa acqulslLlon devlces, and appllcaLlon sofLware. So summlng up, uaLa AcqulslLlon ls Lhe process of: Acqulrlng slgnals from real-world phenomena ulglLlzlng Lhe slgnals Analyzlng, presenLlng and savlng Lhe daLa 1he uAC sysLem has Lhe followlng parLs lnvolved, see llgure:
1he parLs are: hyslcal lnpuL/ouLpuL slgnals uAC devlce/hardware urlver sofLware ?our sofLware appllcaLlon (AppllcaLlon sofLware) 13 uaLa AcqulslLlon 1uLorlal: uaLa AcqulslLlon ln C# lor an lnLroducLlon Lo uaLa AcqulslLlon, see Lhls webcasL: http:]]zone.n|.com]wv]app]doc]p]|d]wv-169 2.1.1 hyslcal lnpuL/ouLpuL slgnals A physlcal lnpuL/ouLpuL slgnal ls Lyplcally a volLage or currenL slgnal. 2.1.2 uAC devlce/hardware uAC hardware acLs as Lhe lnLerface beLween Lhe compuLer and Lhe ouLslde world. lL prlmarlly funcLlons as a devlce LhaL dlglLlzes lncomlng analog slgnals so LhaL Lhe compuLer can lnLerpreL Lhem A uAC devlce (uaLa AcqulslLlon Pardware) usually has Lhese funcLlons: Analog lnpuL Analog ouLpuL ulglLal l/C CounLer/Llmers We have dlfferenL uAC devlces, such as: Desktop uAC devlces" where you need Lo plug a Cl uAC board lnLo your compuLer. 1he sofLware ls runnlng on a compuLer. ortab|e uAC devlces" for connecLlon Lo Lhe uS8 porL, Wl-ll connecLlons, eLc. 1he sofLware ls runnlng on a compuLer D|str|buted uAC devlces" where Lhe sofLware ls developed on your compuLer and Lhen laLer downloaded Lo Lhe dlsLrlbuLed uAC devlce.
2.1.3 urlver sofLware urlver sofLware ls Lhe layer of sofLware for easlly communlcaLlng wlLh Lhe hardware. lL forms Lhe mlddle layer beLween Lhe appllcaLlon sofLware and Lhe hardware. urlver sofLware also prevenLs a programmer from havlng Lo do reglsLer-level programmlng or compllcaLed commands ln order Lo access Lhe hardware funcLlons. urlver sofLware from naLlonal lnsLrumenLs: nl-uACmx 2.1.4 ?our sofLware appllcaLlon 13 uaLa AcqulslLlon 1uLorlal: uaLa AcqulslLlon ln C# AppllcaLlon sofLware adds analysls and presenLaLlon capablllLles Lo Lhe drlver sofLware. ?our sofLware appllcaLlon normally does such Lasks as: 8eal-Llme monlLorlng uaLa analysls uaLa logglng ConLrol algorlLhms Puman machlne lnLerface (PMl) ln order Lo creaLe your uAC appllcaLlon you need a programmlng developmenL Lool, such as vlsual SLudlo/C#, LabvlLW, eLc.. 2.2 MAx - MeasuremenL and AuLomaLlon Lxplorer MeasuremenL & AuLomaLlon Lxplorer (MAx) provldes access Lo your naLlonal lnsLrumenLs devlces and sysLems. WlLh MAx, you can: Conflgure your naLlonal lnsLrumenLs hardware and sofLware CreaLe and edlL channels, Lasks, lnLerfaces, scales, and vlrLual lnsLrumenLs LxecuLe sysLem dlagnosLlcs vlew devlces and lnsLrumenLs connecLed Lo your sysLem updaLe your naLlonal lnsLrumenLs sofLware ln addlLlon Lo Lhe sLandard Lools, MAx can expose lLem-speclflc Lools you can use Lo conflgure, dlagnose, or LesL your sysLem, dependlng on whlch nl producLs you lnsLall. As you navlgaLe Lhrough MAx, Lhe conLenLs of Lhe appllcaLlon menu and Loolbar change Lo reflecL Lhese new Lools. 16 uaLa AcqulslLlon 1uLorlal: uaLa AcqulslLlon ln C#
2.3 uAC ln vlsual SLudlo We can creaLe uAC appllcaLlons wlLh or wlLhouL MeasuremenL SLudlo. ln boLh slLuaLlons you need Lhe nl-uACmx drlver llbrary. 2.3.1 nl-uACmx naLlonal lnsLrumenLs provldes a naLlve .nL1 Al for nl-uACmx. 1hls ls avallable as a parL of Lhe nl-uACmx drlver and does noL requlre MeasuremenL SLudlo. ln general, daLa acqulslLlon programmlng wlLh uACmx lnvolves Lhe followlng sLeps: 17 uaLa AcqulslLlon 1uLorlal: uaLa AcqulslLlon ln C# CreaLe a 1ask and vlrLual Channels SLarL Lhe 1ask erform a 8ead operaLlon from Lhe uAC erform a WrlLe operaLlon Lo Lhe uAC SLop and Clear Lhe 1ask. uaLa acqulslLlon ln LexL based-programmlng envlronmenL ls very slmllar Lo Lhe LabvlLW nl-uACmx programmlng as Lhe funcLlons calls ls Lhe same as Lhe nl-uACmx vl's. uslng nl-uACmx ln 1exL 8ased rogrammlng LnvlronmenLs: http:]]zone.n|.com]devzone]cda]tut]p]|d]S409#toc4 2.3.2 Lxamples Lxamples lnsLalled as parL of nl-uACmx: 1he locaLlon of examples wlll depend on Lhe verslon of vlsual SLudlo and ls llsLed ln Lhe followlng ueveloper Zone ArLlcle: uslng nl-uACmx ln 1exL 8ased rogrammlng LnvlronmenLs. 1he mosL common locaLlon ls: C:\uocumenLs and SeLLlngs\All users\uocumenLs\naLlonal lnsLrumenLs\nl-uAC\Lxamples\uoLnL1<.nL1 lramework verslon>\ newesL examples for .nL1 x.x and vlsual SLudlo 20xx: C:\uocumenLs and SeLLlngs\All users\uocumenLs\naLlonal lnsLrumenLs\nl-uAC\Lxamples\uoLnL1x.x\ Sub-folders named CS conLaln C# examples. 1hese examples lnsLall wlLh nl-uACmx. MeasuremenL SLudlo ls noL requlred Lo lnsLall Lhe class llbrarles or Lhe examples. Note! lf Lhe paLhs above do noL exlsL, be sure you have .nL1 supporL lnsLalled for nl-uACmx.
18
3 My llrsL uAC App We wlll creaLe a slmple appllcaLlon ln vlsual SLudlo LhaL uses a nl uS8-6008 uAC devlce.
3.1 lnLroducLlon 1hls appllcaLlon uses Lhe C# Al lncluded ln Lhe nl uACmx drlver, so make sure LhaL you have lnsLalled Lhe nl uACmx drlver ln advance. ?ou don'L need MeasuremenL SLudlo Lo creaLe Lhls appllcaLlon. SLarL vlsual SLudlo and creaLe a new Wlndows lorms appllcaLlon. We wlll creaLe Lhe followlng appllcaLlon ln vlsual SLudlo 2010 and C#:
19 My llrsL uAC App 1uLorlal: uaLa AcqulslLlon ln C# 1he user lnLerface looks llke Lhls:
We sLarL by connecLlng Lhe Analog ln and Analog CuL wlres LogeLher (a so called Loopback LesL). When we cllck Lhe WrlLe uaLa" buLLon, Lhe value enLered ln Lhe LexL box Analog CuL" wlll be wrlLLen Lo Lhe uAC devlce. lf we have connecLed Lhe Analog ln and Analog CuL wlres LogeLher we wlll read Lhe same value ln Lhe Analog ln" LexLbox when we push Lhe CeL uaLa" buLLon. 3.2 Source Code We wlll go Lhrough Lhe dlfferenL parLs of Lhe code ln deLall. keferences: 1hls appllcaLlon uses Lhe C# Al lncluded ln Lhe nl uACmx drlver, so make sure LhaL you have lnsLalled Lhe nl uACmx drlver ln advance. We need Lo add Lhe followlng Assembly references: naLlonallnsLrumenLs.Common naLlonallnsLrumenLs.uACmx
We add 8eferences by rlghL-cllcklng Lhe 8eferences node ln Lhe SoluLlon Lxplorer: 20 My llrsL uAC App 1uLorlal: uaLa AcqulslLlon ln C#
When we have added Lhe necessary 8eferences, Lhe SoluLlon Lxplorer wlll look llke Lhls:
In|t|a||zat|on: We need Lo add Lhe followlng namespaces: using NationalInstruments; using NationalInstruments.DAQmx;
Ana|og Cut: We lmplemenL Lhe code for wrlLlng Lo Lhe Analog CuL channel ln Lhe LvenL Pandler for Lhe WrlLe uaLa" buLLon: private void btnWriteAnalogOut_Click(object sender, EventArgs e) {
Ana|og In: We lmplemenL Lhe code for readlng daLa from Lhe Analog ln channel ln Lhe LvenL Pandler for Lhe CeL uaLa" buLLon: private void btnGetAnalogIn_Click(object sender, EventArgs e) {
AnalogSingleChannelReader reader = new AnalogSingleChannelReader(analogInTask.Stream);
double analogDataIn = reader.ReadSingleSample();
txtAnalogIn.Text = analogDataIn.ToString();
}
22
4 1emperaLure Logglng Lxample ln Lhls example we wlll use a nl 1C-01 uS8 1hermocouple devlce.
We vlll creaLe Lhe followlng slmple appllcaLlon:
Add keference: We need Lo add Lhe followlng Assembly references: naLlonallnsLrumenLs.Common naLlonallnsLrumenLs.uACmx We add 8eferences by rlghL-cllcklng Lhe 8eferences node ln Lhe SoluLlon Lxplorer: 23 1emperaLure Logglng Lxample 1uLorlal: uaLa AcqulslLlon ln C#
When we have added Lhe necessary 8eferences, Lhe SoluLlon Lxplorer wlll look llke Lhls:
1he dlls are normally Lo flnd here:
In|t|a||zat|on: We need Lo add Lhe followlng namespaces: 24 1emperaLure Logglng Lxample 1uLorlal: uaLa AcqulslLlon ln C# using NationalInstruments; using NationalInstruments.DAQmx; Add Code: LnLer Lhe followlng code llnes: 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; using NationalInstruments; using NationalInstruments.DAQmx;
namespace TC01_DAQ_Example { public partial class Form1 : Form { public Form1() { InitializeComponent(); }
AnalogSingleChannelReader reader = new AnalogSingleChannelReader(temperatureTask.Stream);
double analogDataIn = reader.ReadSingleSample();
txtTempData.Text = analogDataIn.ToString();
} } } 1est your app||cat|on: 8un your appllcaLlon. When cllcklng Lhe buLLon, you should now reLrleve daLa from Lhe LemoeraLure devlce. Lrror? lf your appllcaLlon runs wlLhouL error LhaL's flne, buL perhaps you geL Lhe followlng error: 23 1emperaLure Logglng Lxample 1uLorlal: uaLa AcqulslLlon ln C#
ln order Lo flx Lhe problem, open Lhe roperLles for your pro[ecL:
Make sure Lo selecL .nL1 lramework x" ln Lhe 1argeL framework" drop-down menu.
26
3 MeasuremenL SLudlo 3.1 lnLroducLlon
C# ls a powerful programmlng language, buL has few bullL-ln feaLures for measuremenL and conLrol appllcaLlons. MeasuremenL SLudlo ls an add-on Lo vlsual SLudlo whlch makes lL easler Lo creaLe such appllcaLlons. WlLh MeasuremenL SLudlo we can lmplemenL uaLa AcqulslLlon and a graphlcal PMl.
MeasuremenL SLudlo for vlsual C# .nL1 provldes: Managed .nL1 conLrols for creaLlng rlch Web and Wlndows Culs MulLlLhreaded Al for daLa acqulslLlon lnsLrumenL conLrol Als Analysls llbrarles deslgned for englneers and sclenLlsLs 27 MeasuremenL SLudlo 1uLorlal: uaLa AcqulslLlon ln C#
3.2 1emplaLes MeasuremenL SLudlo has several 1emplaLes LhaL make lL easler Lo bulld uAC appllcaLlons.
3.3 1oolbox 8elow we see Lhe 1oolbox ln vlsual SLudlo LhaL ls lnsLalled wlLh MeasuremenL SLudlo: 28 MeasuremenL SLudlo 1uLorlal: uaLa AcqulslLlon ln C#
ln addlLlon Lo Lhe 1oolbox, MeasuremenL SLudlo also lnsLalls Lhe followlng menu lLem:
3.4 Lxample ln Lhls example, we wlll selecL Lhe nl wlndows AppllcaLlon" 1emplaLe ln Lhe new ro[ecL" wlndow . 29 MeasuremenL SLudlo 1uLorlal: uaLa AcqulslLlon ln C#
nexL we selecL Lhe Class Llbrarles we wanL Lo lnclude. ln our case we need aL leasL Lo selecL Lhe uACmx Llbrary".
When we cllck llnlsh" an empLy pro[ecL wlll be creaLed for us. We are now ready Lo creaLe our own appllcaLlon. We sLarL by creaLlng a slmple user lnLerface: 30 MeasuremenL SLudlo 1uLorlal: uaLa AcqulslLlon ln C#
When we cllck Lhe 8ead 1emp" buLLon, Lhe 1emperaLure daLa shall be shown ln Lhe 1emp uaLa" 1exL8ox. ln Lhe evenL Pandler for Lhe 8ead 1emp" buLLon, we creaLe Lhe followlng code: private void btnReadTempData_Click(object sender, EventArgs e) {
AnalogSingleChannelReader reader = new AnalogSingleChannelReader(analogInTask.Stream);
double analogDataIn = reader.ReadSingleSample();
txtTempData.Text = analogDataIn.ToString();
} 1hen we can LesL our appllcaLlon:
31 MeasuremenL SLudlo 1uLorlal: uaLa AcqulslLlon ln C# Improvements: We should use a "1|mer" ln order Lo read 1emperaLure daLa aL speclflc lnLervals lnsLead of pushlng a buLLon each Llme we need daLa.
We drag ln a 1lmer componenL from Lhe 1oolbox. llrsL, we need Lo sLarL Lhe 1lmer: public Form1() { InitializeComponent();
timer1.Start(); } nexL, we need Lo speclfy Lhe lnLerval. We can do LhaL ln Lhe ropert|es wlndow:
ln Lhe 1lmer LvenL we wrlLe Lhe code for readlng Lhe 1emperaLure: private void timer1_Tick(object sender, EventArgs e) {
AnalogSingleChannelReader reader = new AnalogSingleChannelReader(analogInTask.Stream);
double analogDataIn = reader.ReadSingleSample();
txtTempData.Text = analogDataIn.ToString("0.0");
} llnally, we LesL Lhe appllcaLlon: 32 MeasuremenL SLudlo 1uLorlal: uaLa AcqulslLlon ln C#
33
6 ConLrol AppllcaLlon 6.1 lnLroducLlon ln Lhls example we wlll use MeasuremenL SLudlo Lo creaLe a slmple conLrol appllcaLlon. We wlll conLrol Lhe level ln a waLer Lank uslng manual conLrol. 1he process ls as follows:
We wanL Lo conLrol Lhe level ln Lhe waLer Lank uslng a pump on Lhe lnflow. We wlll read Lhe level uslng our uS8-6008 uAC devlce (Analog ln) and wrlLe Lhe conLrol slgnal (Analog CuL) Lo Lhe uAC devlce. 1he Analog CuL (conLrol slgnal) wlll be a slgnal beLween ! !!! and Lhe Analog ln (Level) wlll be a ! !!! slgnal LhaL we need Lo scale Lo ! !!"!". We wlll creaLe Lhe followlng appllcaLlon: 34 ConLrol AppllcaLlon 1uLorlal: uaLa AcqulslLlon ln C#
We wlll use a Sllder" Lo manually ad[usL Lhe conLrol slgnal and a 1ank Lo lndlcaLe Lhe level ln Lhe real process. ln Lhls example we wlll use Lhe Sllde" conLrol and 1ank" conLrol LhaL comes wlLh MeasuremenL SLudlo.
6.2 Source Code SLarL a new ro[ecL ln vlsual SLudlo: 33 ConLrol AppllcaLlon 1uLorlal: uaLa AcqulslLlon ln C#
SelecL Lhe nl Wlndows AppllcaLlon" 1emplaLe ln Lhe MeasuremenL SLudlo" node. ln Lhe wlndow LhaL appears nexL, selecL Lhe Llbrarles you wanL Lo lnclude:
We creaLe Lhe user lnLerface above ln vlsual SLudlo, and lL looks llke Lhls: 36 ConLrol AppllcaLlon 1uLorlal: uaLa AcqulslLlon ln C#
lor Lhe read and wrlLe operaLlons we have creaLed a slmple Class wlLh Lwo meLhods: public class DaqData {
public double ReadDaqData() { ... }
public void WriteDaqData(double analogDataOut) { ... } }
More abouL Lhe keadDaqData() and Wr|teDaqData() meLhods below. kead Leve|: 1he 8eaduaquaLa() meLhod handles Lhe loglc for readlng from Lhe uAC devlce: public double ReadDaqData() {
AnalogSingleChannelWriter writer = new AnalogSingleChannelWriter(analogOutTask.Stream);
writer.WriteSingleSample(true, analogDataOut);
}
1|mer: ln Lhe prevlous example (My llrsL uAC App") we was readlng and wrlLlng Lo Lhe uAC devlce when cllcklng a buLLon, buL ln an ordlnary appllcaLlon Lhls ls noL a good soluLlon. ln order Lo read and wrlLe daLa on regular lnLervals we wlll use a 1lmer". ln Lhe ComponenLs" Loolbox we flnd Lhe 1lmer" ConLrol: 38 ConLrol AppllcaLlon 1uLorlal: uaLa AcqulslLlon ln C#
ln Lhe roperLles wlndow we can speclfy Lhe lnLerval (Sampllng 1lme") ln mllllseconds.
We can sLarL Lhe Llmer wlLh Lhe followlng code: public Form1() { InitializeComponent();
timer1.Start(); }
ln Lhe 1lmer LvenL we creaLe Lhe maln loglc ln our appllcaLlon. We call Lhe 8eaduaquaLa() and WrlLeuaquaLa() meLhods, updaLes Lhe Cul, eLc. private void timer1_Tick(object sender, EventArgs e) {
7 1rendlng uaLa now we wanL Lo exLend our appllcaLlon wlLh funcLlonallLy for vlewlng hlsLorlcal daLa uslng a Lrend ploL. 8elow we see Lhe new user lnLerface:
ln Lhls example we wlll use Lhe WaveformCraph" conLrol ln MeasuremenL SLudlo. 1he source code ls Lhe same as ln Lhe prevlous example, excepL for one new llne of code ln Lhe 1lmer LvenL: waveformGraph.PlotYAppend(analogDataIn);
1he WaveformCraph" conLrol has loLs of funcLlonallLy you can seL ln Lhe roperLles wlndow or cllcklng Lhe SmarL 1ag Anchor (llLLle arrow ln Lhe upper rlghL corner of Lhe conLrol).
8elow we see Lhe roperLles wlndow (lefL slde) and Lhe SmarL 1ag anel (rlghL slde) for Lhe WaveformCraph conLrol: 41 1rendlng uaLa 1uLorlal: uaLa AcqulslLlon ln C#
42
8 ulscreLlzaLlon 1he nexL lmprovemenLs Lo our appllcaLlon would be Lo lmplemenL a Low-pass lllLer ln order Lo remove Lhe nolse from Lhe slgnal when readlng Lhe level. AnoLher lmprovemenL would be Lo replace Lhe manual conLrol wlLh a l conLroller LhaL do Lhe [ob for us. llnally lL would be nlce Lo have a maLhemaLlcal model of our waLer Lank so we can slmulaLe and LesL Lhe behavlor of Lhe real sysLem wlLhouL connecL Lo lL. So we need Lo creaLe dlscreLe verslons of Lhe low-pass fllLer, Lhe l conLroller and Lhe process model. We can, e.g., use Lhe Luler lorward dlscreLlzaLlon meLhod: ! ! ! !!! !! ! ! !
or Lhe Luler 8ackward dlscreLlzaLlon meLhod: ! ! ! ! !! !!! ! !
! ! ls Lhe Sampllng 1lme. 8.1 Low-pass lllLer 1he Lransfer funcLlon for a flrsL-order low-pass fllLer may be wrlLLen: ! ! ! !!!! !!!! ! ! ! ! ! !!
Where ! ! ls Lhe Llme-consLanL of Lhe fllLer, !!!! ls Lhe fllLer lnpuL and ! ! ls Lhe fllLer ouLpuL. D|screte vers|on: lL can be shown LhaL a dlscreLe verslon can be sLaLed as: ! ! ! ! !! ! !!! !!! !
Where ! ! ! ! ! ! !! !
43 ulscreLlzaLlon 1uLorlal: uaLa AcqulslLlon ln C# Where ! ! ls Lhe Sampllng 1lme. lL ls a golden rule LhaL ! ! ! ! ! and ln pracLlce we should use Lhe followlng rule: ! ! ! ! ! !
1hls algorlLhm can easlly be lmplemenLed ln C#. 8.3 rocess Model A very slmple (llnear) model of Lhe waLer Lank ls as follows: ! ! ! ! ! ! !!! !"#
or ! ! ! ! ! ! ! !!! !"#
Where: ! [cm] ls Lhe level ln Lhe waLer Lank ! [v] ls Lhe pump conLrol slgnal Lo Lhe pump ! ! [cm2] ls Lhe cross-secLlonal area ln Lhe Lank ! ! [(cm3/s)/v] ls Lhe pump galn ! !"# [cm3/s] ls Lhe ouLflow Lhrough Lhe valve (Lhls ouLflow can be modeled more accuraLely Laklng lnLo accounL Lhe valve characLerlsLlc expresslng Lhe relaLlon beLween pressure drop across Lhe valve and Lhe flow Lhrough Lhe valve).
We can use Lhe Luler lorward dlscreLlzaLlon meLhod ln order Lo creaLe a dlscreLe model: ! ! ! !!! !! ! ! !
8.4 llnal AppllcaLlon We exLend our ConLrol AppllcaLlon wlLh a dlscreLe l conLroller, a dlscreLe Low-pass fllLer and a dlscreLe process model, so we can swlLch beLween Lhe real process and a slmulaLor. Cur user lnLerface ls as follows:
8elow we see Lhe ro[ecL and SoluLlon ln vlsual SLudlo: 48 ulscreLlzaLlon 1uLorlal: uaLa AcqulslLlon ln C#
8elow we wlll show and descrlbe Lhe lmporLanL parLs of Lhe code. I Contro||er: We creaLe a new Class for our lu algorlLhm, by rlghL-cllck ln Lhe SoluLlon Lxplorer (Add-new lLem.)
SelecL Lhe Class lLem and a proper name, e.g. ldConLroller". 1he |dContro||er Class ls as follows: class PidController {
public double r; //Reference Value public double Kp; //Proportional Gain for PID Controler public double Ti; //Integral Time for PID Controler public double Ts; //Sampling Time
private double z; //Internal variable
public double PiController(double y) { double e; // Error between Reference and Measurement double u; // Controller Output
//PID Algoritm e = r - y; u = Kp * e + (Kp / Ti) * z; z = z + Ts * e;
return u; }
} We Lhen lnlLlallze Lhe ldConLroller Class: PidController pidControl = new PidController { Ts=0.1, r=5, Kp=0.8, Ti=15 }; llnally we use Lhe conLroller: private void ControlSystem() 30 ulscreLlzaLlon 1uLorlal: uaLa AcqulslLlon ln C# {
//Write Control Value
if (switchController.Value == true) //Use Manual Control {
//Set boundaries if (controllerOutput < 0) controllerOutput = 0; if (controllerOutput > 5) controllerOutput = 5; }
myDaqData.WriteDaqData(controllerOutput); //Write to DAQ
}
Low-pass I||ter: We creaLe Lhe Low-pass lllLer as a separaLe Class Lo: class Filter {
public double yk; public double Ts; public double Tf;
public double LowPassFilter(double yFromDaq) {
double a; double yFiltered;
a = Ts / (Ts + Tf);
yFiltered = (1 - a) * yk + a * yFromDaq; yk = yFiltered;
return yFiltered;
} } We Lhen lnlLlallze Lhe fllLer: Filter filter = new Filter { Ts = 0.1, Tf = 2 }; llnally we use Lhe fllLer: 31 ulscreLlzaLlon 1uLorlal: uaLa AcqulslLlon ln C# // Lowpass filtering the Measure Value due to noise levelMeasurement = filter.LowPassFilter(levelMeasurement);
D|screte Mode|: We do Lhe same for Lhe dlscreLe model. We have creaLed a Class and a Level1ankModel MeLhod LhaL we use ln our slmulaLlon: levelMeasurement = model.LevelTankModel(controllerOutput);
32
9 CC ln order Lo communlcaLe wlLh an CC Server we can use Lhe uaLaSockeL Al LhaL ls parL of Lhe MeasuremenL SLudlo. We use Lhe MaLrlkon CC SlmulaLlon Server. 9.1 8ead CC uaLa 8elow we wlll go Lhrough a very slmple example. We wlll read one value from Lhe CC Server each Llme we cllck a buLLon. V|sua| Stud|o ro[ect:
Code: We deflne a uaLaSockeL ob[ecL: DataSocket dataSocket = new DataSocket(); nexL, We ConnecL Lo Lhe CC Server: string opcUrl; opcUrl = "opc://localhost/MATRIKON.OPC.Simulation/Bucket Brigade.Real4"; 33 CC 1uLorlal: uaLa AcqulslLlon ln C#
if (dataSocket.IsConnected) dataSocket.Disconnect();
dataSocket.Connect(opcUrl, AccessMode.Read); llnally, we 8ead CC uaLa: private void btnReadOpc_Click(object sender, EventArgs e) { dataSocket.Update();
We LesL Lhe AppllcaLlon uslng Lhe MaLrlkon CC Lxplorer:
Se|ectUr|: We can use Lhe Se|ectUr| meLhod lf we wanL Lo plck Lhe CC lLem from a llsL of avallable servers (boLh local servers and neLwork servers) and lLems. dataSocket.SelectUrl(); 1he Se|ctUr| meLhod wlll pop up Lhe followlng wlndow: 34 CC 1uLorlal: uaLa AcqulslLlon ln C#
9.2 WrlLe CC uaLa We use Lhe same uaLaSockeL Al here. V|sua| Stud|o ro[ect: 8elow we wlll go Lhrough a very slmple example. We wlll wrlLe one value Lo Lhe CC Server each Llme we cllck a buLLon.
33 CC 1uLorlal: uaLa AcqulslLlon ln C# Code: We deflne a uaLaSockeL ob[ecL: DataSocket dataSocket = new DataSocket(); nexL, We ConnecL Lo Lhe CC Server: string opcUrl; opcUrl = "opc://localhost/MATRIKON.OPC.Simulation/Bucket Brigade.Real4";
if (dataSocket.IsConnected) dataSocket.Disconnect();
dataSocket.Connect(opcUrl, AccessMode.Write); llnally, we WrlLe CC uaLa: private void btnWriteOpc_Click(object sender, EventArgs e) {
We LesL Lhe AppllcaLlon uslng Lhe MaLrlkon CC Lxplorer:
36 CC 1uLorlal: uaLa AcqulslLlon ln C# 9.3 uslng a 1lmer We can use a Llmer ln order Lo read values conLlnuously", l.e. aL speclflc lnLervals. ln Lhe ComponenLs" Loolbox we flnd Lhe 1lmer" ConLrol:
ln Lhe roperLles wlndow we can speclfy Lhe lnLerval (Sampllng 1lme") ln mllllseconds.
We can sLarL Lhe Llmer wlLh Lhe followlng code: public Form1() { InitializeComponent();
timer1.Start(); }
ln Lhe 1lmer LvenL we creaLe Lhe code ln order Lo read daLa aL Lhls speclflc lnLerval. 37 CC 1uLorlal: uaLa AcqulslLlon ln C# private void timer1_Tick(object sender, EventArgs e) {
}
38
10 uslng nl 1C-01 ln vlsual SLudlo and C# ln order Lo use Lhe nl uS8-1C01 1hermocouple MeasuremenL devlce wlLh C# we need Lo have Lhe DAmx dr|ver and Lhe uACmx Al for C# lnsLalled. ln order Lo lnsLall Lhe uACmx Al for C#, make sure Lo selecL .nL1 SupporL" when lnsLalllng Lhe uACmx drlver. C# ls a powerful programmlng language, buL has few bullL-ln feaLures for measuremenL and conLrol appllcaLlons. Measurement Stud|o ls an add-on Lo vlsual SLudlo whlch makes lL easler Lo creaLe such appllcaLlons. WlLh MeasuremenL SLudlo we can lmplemenL uaLa AcqulslLlon and a graphlcal PMl. ?ou don'L need Lo use Lhe MeasuremenL SLudlo Lo creaLe an appllcaLlon where you use Lhe nl uS8-1C01 1hermocouple MeasuremenL devlce, buL lL ls easler. Pere we wlll use vlsual SLudlo and Lhe MeasuremenL SLudlo Add-ln Lo creaLe some uAC examples where we geL LemperaLure daLa from Lhe nl uS8-1C01 1hermocouple MeasuremenL devlce. 10.1 CreaLe a nl Wlndows AppllcaLlon ln Lhls example, we wlll selecL Lhe nl wlndows AppllcaLlon" 1emplaLe ln Lhe new ro[ecL" wlndow. 39 uslng nl 1C-01 ln vlsual SLudlo and C# 1uLorlal: uaLa AcqulslLlon ln C#
Note! 1he new ro[ecL" wlndow may look dlfferenL on your compuLer, lL depends on whaL feaLures you have lnsLalled and whlch verslon or edlLlon of MeasuremenL SLudlo you are uslng. nexL we selecL Lhe Class Llbrarles we wanL Lo lnclude. ln our case we need aL leasL Lo selecL Lhe uACmx Llbrary".
When we cllck llnlsh" an empLy pro[ecL wlll be creaLed for us. We are now ready Lo creaLe our own appllcaLlon. 60 uslng nl 1C-01 ln vlsual SLudlo and C# 1uLorlal: uaLa AcqulslLlon ln C# We sLarL by creaLlng a slmple user lnLerface:
When we cllck Lhe 8ead 1emp" buLLon, Lhe 1emperaLure daLa shall be shown ln Lhe 1emp uaLa" 1exL8ox. ln Lhe evenL Pandler for Lhe 8ead 1emp" buLLon, we creaLe Lhe followlng code: private void btnReadTempData_Click(object sender, EventArgs e) {
AnalogSingleChannelReader reader = new AnalogSingleChannelReader(analogInTask.Stream);
double analogDataIn = reader.ReadSingleSample();
txtTempData.Text = analogDataIn.ToString();
} 1hen we can LesL our appllcaLlon:
61 uslng nl 1C-01 ln vlsual SLudlo and C# 1uLorlal: uaLa AcqulslLlon ln C# Improvements: We should use a "1|mer" ln order Lo read 1emperaLure daLa aL speclflc lnLervals lnsLead of pushlng a buLLon each Llme we need daLa.
We drag ln a 1lmer componenL from Lhe 1oolbox. llrsL, we need Lo sLarL Lhe 1lmer: public Form1() { InitializeComponent();
timer1.Start(); } nexL, we need Lo speclfy Lhe lnLerval. We can do LhaL ln Lhe ropert|es wlndow:
ln Lhe 1lmer LvenL we wrlLe Lhe code for readlng Lhe 1emperaLure: private void timer1_Tick(object sender, EventArgs e) {
AnalogSingleChannelReader reader = new AnalogSingleChannelReader(analogInTask.Stream);
double analogDataIn = reader.ReadSingleSample();
txtTempData.Text = analogDataIn.ToString("0.0");
} llnally, we LesL Lhe appllcaLlon: 62 uslng nl 1C-01 ln vlsual SLudlo and C# 1uLorlal: uaLa AcqulslLlon ln C#
10.2 CreaLe a nl uAC Wlndows AppllcaLlon Note! 1hls opLlon ls only avalllble lf you Lo have elLher Lhe rofesslonal or LnLerprlse verslon of Lhe MeasuremenL SLudlo sofLware. We sLarL by creaLlng a new ro[ecL" from vlsual SLudlo. ln Lhe new ro[ecL" wlndow we selecL vlsual C#" MeasuremenL SLudlo", and Lhen selecL Lhe nl uAC Wlndows AppllcaLlon" 1emplaLe LhaL ls parL of Lhe MeasuremenL SLudlo.
Note! 1he new ro[ecL" wlndow may look dlfferenL on your compuLer, lL depends on whaL feaLures you have lnsLalled and whlch verslon or edlLlon of MeasuremenL SLudlo you are uslng.
nexL, we need Lo go Lhrough dlfferenL sLeps ln a wlzard. ln Lhe flrsL sLep we selecL CreaLe a new pro[ecL Lask": 63 uslng nl 1C-01 ln vlsual SLudlo and C# 1uLorlal: uaLa AcqulslLlon ln C#
ln Lhe nexL sLep we selecL Lhe measuremenL Lype, and slnce Lhe nl uS8-1C01 1hermocouple MeasuremenL devlce ls for readlng 1emperaLure values, we need Lo selecL Acqulre Slgnals".
ln Lhe Acqulre Slgnals" node we flrsL selecL 1emperaLure" and Lhen selecL 1hermocouple". 64 uslng nl 1C-01 ln vlsual SLudlo and C# 1uLorlal: uaLa AcqulslLlon ln C#
nexL we need Lo selecL Lhe physlcal channel(s). Slnce Lhe nl uS8-1C01 1hermocouple MeasuremenL devlce has only one channel avallable, we need Lo selecL al0" (Analog ln, Channel 0).
nexL we can seL dlfferenL roperLles, such as lnpuL 8ange", AcqulslLlon Mode", 1hermocouple 1ype", eLc. 63 uslng nl 1C-01 ln vlsual SLudlo and C# 1uLorlal: uaLa AcqulslLlon ln C#
llnally we see a revlew of Lhe user lnLerface before lL ls auLomaLlcally generaLed by Lhe MeasuremenL SLudlo: 66 uslng nl 1C-01 ln vlsual SLudlo and C# 1uLorlal: uaLa AcqulslLlon ln C#
When we cllck llnlsh", Lhe SoluLlon, Lhe ro[ecL and user lnLerface wlll be auLomaLlcally creaLed.
I|gure 1: V|sua| Stud|o Generated So|ut|on llnally we can LesL Lhe AppllcaLlon: 67 uslng nl 1C-01 ln vlsual SLudlo and C# 1uLorlal: uaLa AcqulslLlon ln C#
WlLh Lhls approach we geL a flylng sLarL" and we can change Lhe code as we please. 1he drawback wlLh Lhls approach ls LhaL Lhe code LhaL ls auLomaLlcally generaLed ls a llLLle blL messy". So acLually, Lhls ls noL a meLhod l wlll recommend Lo use.
68
Appendlx A: Source Code ln Lhls Appendlx Lhe compleLe source code for all Lhe examples wlll be llsLed. My llrsL uAC App 1he code for Lhls appllcaLlon ls 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(); }
ConLrol AppllcaLlon 1he code for Lhls appllcaLlon ls 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();
AnalogSingleChannelWriter writer = new AnalogSingleChannelWriter(analogOutTask.Stream);
writer.WriteSingleSample(true, analogDataOut);
} }
}
10.3 CC 8ead using NationalInstruments; using NationalInstruments.Net; 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 OPC_Read { public partial class Form1 : Form { DataSocket dataSocket = new DataSocket();
txtReadOpcValue.Text = dataSocket.Data.Value.ToString(); } } } 10.4 CC WrlLe using NationalInstruments; using NationalInstruments.Net; using System; using System.Collections.Generic; 72 Appendlx A: Source Code 1uLorlal: uaLa AcqulslLlon ln C# 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 {
nans-etter na|vorsen, M.Sc. 1e|emark Un|vers|ty Co||ege Iacu|ty of 1echno|ogy Department of L|ectr|ca| Lng|neer|ng, Informat|on 1echno|ogy and Cybernet|cs