학습목표    1

학습주제    1

예습내용    1

실습방법    1

        1

중요함수    1

탱크2 수위 측정

학습목표

1대의 탱크는 저조로 사용하고 1대는 물이 흘러나가는 상태에서 수위조절을 한다.

학습주제

1.      물탱크를 2 만들고 1대는 저조로 사용하고 1대는 수위조절용으로 사용한다.

2.      화면에서 조절할 물의 높이와 제어 범위를 선택하면 펌프가 On/Off 되면서 수위를 조절한다.

3.      기본 프로그램은 시간의 탱크 수위 조절 프로그램을 이어서 작성한다.

 

다음과 회로를 연결한다.

이 때 “USB-6008”에는 DC24V AC220V 단자가 연결되면 PC가 회손 됨으로 각별히 조심해야 한다.

예습내용

 

실습방법

   

 

다이어로그 박스에 그림과 같이 탱크를 모두 복사 하여 똑같이 2개를 만들고 펌프 Led 추가한다. 그리고 그래프를 추가한다.

아래는 마우스로 선택하고 마우스 오른쪽 버튼을 눌러서 변수 추가를 하여 멤버 베리어블을 정의 한다.

헤더 파일에 아래를 추가한다.

 

// LevelDlg.h : 헤더파일

//

 

#pragma once

#include "nislide.h"

#include "nibutton.h"

#include "ninumedit.h"

#include "nigraph.h"

 

 

// CLevelDlg 대화상자

class CLevelDlg : public CDialog

{

// 생성입니다.

public:

        CNiDAQmxTask TaskIn01;  // 입력을위한Task

        CNiDAQmxTask TaskIn02;  // 입력을위한Task

        CNiDAQmxTask TaskOut01; // 출력을위한Task

        CNiDAQmxTask TaskOut02;

        CLevelDlg(CWnd* pParent = NULL); // 표준생성자입니다.

 

        // 다이어로그박스에글씨를쓰기위한정의

        BOOL m_bTransparent;

       COLORREF m_colorText;

       COLORREF m_colorBk;

       LOGFONT m_logFont;

 

// 대화상자데이터입니다.

        enum { IDD = IDD_LEVEL_DIALOG };

 

        protected:

        virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원입니다.

 

 

// 구현입니다.

protected:

        HICON m_hIcon;

 

        // 생성된메시지맵함수

        virtual BOOL OnInitDialog();

        afx_msg void OnSysCommand(UINT nID, LPARAM lParam);

        afx_msg void OnPaint();

        afx_msg HCURSOR OnQueryDragIcon();

        DECLARE_MESSAGE_MAP()

public:

        NI::CNiSlide m_Tank1;

        afx_msg void OnTimer(UINT_PTR nIDEvent);

        NI::CNiSlide m_Alarm1;

        NI::CNiButton m_bLed1_1;

        NI::CNiButton m_bLed1_2;

        NI::CNiButton m_bLed2_1;

        NI::CNiButton m_bLed2_2;

        NI::CNiSlide m_Alarm2;

        NI::CNiSlide m_Tank2;

public:

        NI::CNiNumEdit m_dK;

public:

        NI::CNiButton m_nPump;

        NI::CNiGraph m_Graph;

};

 

 

 

LevelDlg.cpp 파일에서 다음 빨간 글씨 부분을 수정한다.

 

// LevelDlg.cpp : 구현파일

//

 

#include "stdafx.h"

#include "Level.h"

#include "LevelDlg.h"

#include <stdlib.h>

 

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

 

CNiBoolVector vector(8);

 

 

// 응용프로그램정보에사용되는CAboutDlg 대화상자입니다.

 

class CAboutDlg : public CDialog

{

public:

        CAboutDlg();

 

// 대화상자데이터입니다.

        enum { IDD = IDD_ABOUTBOX };

 

        protected:

        virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 지원입니다.

 

// 구현입니다.

protected:

        DECLARE_MESSAGE_MAP()

};

 

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

}

 

void CAboutDlg::DoDataExchange(CDataExchange* pDX)

{

        CDialog::DoDataExchange(pDX);

}

 

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

END_MESSAGE_MAP()

 

 

// CLevelDlg 대화상자

CLevelDlg::CLevelDlg(CWnd* pParent /*=NULL*/)

        : CDialog(CLevelDlg::IDD, pParent)

{

        m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}

 

void CLevelDlg::DoDataExchange(CDataExchange* pDX)

{

        CDialog::DoDataExchange(pDX);

        DDX_Control(pDX, IDC_CWSLIDE1, m_Tank1);

        DDX_Control(pDX, IDC_CWSLIDE2, m_Alarm1);

        DDX_Control(pDX, IDC_CWBOOLEAN1, m_bLed1_1);

        DDX_Control(pDX, IDC_CWBOOLEAN2, m_bLed1_2);

        DDX_Control(pDX, IDC_CWBOOLEAN3, m_bLed2_1);

        DDX_Control(pDX, IDC_CWBOOLEAN4, m_bLed2_2);

        DDX_Control(pDX, IDC_CWSLIDE4, m_Alarm2);

        DDX_Control(pDX, IDC_CWSLIDE3, m_Tank2);

        DDX_Control(pDX, IDC_CWNUMEDIT1, m_dK);

        DDX_Control(pDX, IDC_CWBOOLEAN5, m_nPump);

        DDX_Control(pDX, IDC_CWGRAPH1, m_Graph);

}

 

BEGIN_MESSAGE_MAP(CLevelDlg, CDialog)

        ON_WM_SYSCOMMAND()

        ON_WM_PAINT()

        ON_WM_QUERYDRAGICON()

        //}}AFX_MSG_MAP

        ON_WM_TIMER()

END_MESSAGE_MAP()

 

 

// CLevelDlg 메시지처리기

 

BOOL CLevelDlg::OnInitDialog()

{

        CDialog::OnInitDialog();

 

        // 시스템메뉴에"정보..." 메뉴항목을추가합니다.

 

        // IDM_ABOUTBOX는시스템명령범위에있어야합니다.

        ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

        ASSERT(IDM_ABOUTBOX < 0xF000);

 

        CMenu* pSysMenu = GetSystemMenu(FALSE);

        if (pSysMenu != NULL)

        {

                CString strAboutMenu;

                strAboutMenu.LoadString(IDS_ABOUTBOX);

                if (!strAboutMenu.IsEmpty())

                {

                        pSysMenu->AppendMenu(MF_SEPARATOR);

                        pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

                }

        }

 

        // 이대화상자의아이콘을설정합니다. 응용프로그램의주창이대화상자가아닐경우에는

        //  프레임워크가이작업을자동으로수행합니다.

        SetIcon(m_hIcon, TRUE);                  // 큰아이콘을설정합니다.

        SetIcon(m_hIcon, FALSE);         // 작은아이콘을설정합니다.

 

        // TODO: 여기에추가초기화작업을추가합니다.

        // 디지탈출력을위한초기화

        //========== 폰트설정===========================

        m_bTransparent = FALSE;

       m_colorText = RGB(0, 0, 0);                // 폰트색상

       m_colorBk = RGB(230,230,230);              // 폰트배겅색상

 

       m_logFont.lfHeight                  = -40; //폰트크기

       m_logFont.lfWidth                   = 0;

       m_logFont.lfEscapement              = 0;

       m_logFont.lfOrientation             = 0;

       //m_logFont.lfWeight                = FW_NORMAL;

       m_logFont.lfWeight                  = 900; // 굵은글씨

       m_logFont.lfItalic                  = FALSE;

       m_logFont.lfUnderline        = FALSE;

       m_logFont.lfStrikeOut        = FALSE;

       m_logFont.lfCharSet                 = DEFAULT_CHARSET;

       m_logFont.lfOutPrecision     = OUT_CHARACTER_PRECIS;

       m_logFont.lfClipPrecision    = CLIP_CHARACTER_PRECIS;

       m_logFont.lfQuality                 = DEFAULT_QUALITY;

       m_logFont.lfPitchAndFamily   = DEFAULT_PITCH|FF_DONTCARE;

       strcpy(m_logFont.lfFaceName, "Arial");

        //========== 폰트설정===========================

        vector[0]=1;vector[1]=1;vector[2]=1;vector[3]=1;

       vector[4]=1;vector[5]=1;vector[6]=1;vector[7]=1;

      

       double minimum=-10;

        double maximum=10;

      

        TaskIn01.AIChannels.CreateVoltageChannel("Dev1/ai0",_T(""),

            static_cast<DAQmxAITerminalConfiguration>(-1),

            minimum, maximum, DAQmxAIVoltageUnitsVolts);

       TaskIn02.AIChannels.CreateVoltageChannel("Dev1/ai1",_T(""),

            static_cast<DAQmxAITerminalConfiguration>(-1),

            minimum, maximum, DAQmxAIVoltageUnitsVolts);

       TaskOut01.DOChannels.CreateChannel("Dev1/port0/line0:7", "",

                     DAQmxOneChannelForAllLines);

       TaskOut02.DOChannels.CreateChannel("Dev1/port0/line0:7", "",

                     DAQmxOneChannelForAllLines);

                    

 

       SetTimer(1,200,NULL);

 

        return TRUE;  // 포커스를컨트롤에설정하지않으면TRUE를반환합니다.

}

 

void CLevelDlg::OnSysCommand(UINT nID, LPARAM lParam)

{

        if ((nID & 0xFFF0) == IDM_ABOUTBOX)

        {

                CAboutDlg dlgAbout;

                dlgAbout.DoModal();

        }

        else

        {

                CDialog::OnSysCommand(nID, lParam);

        }

}

 

// 대화상자에최소화단추를추가할경우아이콘을그리려면

//  아래코드가필요합니다. 문서/뷰모델을사용하는MFC 응용프로그램의경우에는

//  프레임워크에서이작업을자동으로수행합니다.

void CLevelDlg::OnPaint()

{

        /*

        // 폰트를쓰기위해원래의함수를지우고아래프로그램을추가한다.

        if (IsIconic())

        {

                CPaintDC dc(this); // 그리기를위한디바이스컨텍스트

 

                SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

 

                // 클라이언트사각형에서아이콘을가운데에맞춥니다.

                int cxIcon = GetSystemMetrics(SM_CXICON);

                int cyIcon = GetSystemMetrics(SM_CYICON);

                CRect rect;

                GetClientRect(&rect);

                int x = (rect.Width() - cxIcon + 1) / 2;

                int y = (rect.Height() - cyIcon + 1) / 2;

 

                // 아이콘을그립니다.

                dc.DrawIcon(x, y, m_hIcon);

        }

        else

        {

                CDialog::OnPaint();

        }

        */

 

        CPaintDC dc(this); // device context for painting

      

       // TODO: Add your message handler code here

       CRect rect;

       CString s;

       int x,y;

       GetClientRect(&rect);

 

       // LOGFONT로부터폰트를생성

       CFont newFont, *pOldFont;

       newFont.CreateFontIndirect(&m_logFont);

 

       // 생성된폰트를DC에선택

       pOldFont = (CFont *)dc.SelectObject(&newFont);

 

       // 텍스트의전경색과배경색설정

       dc.SetTextColor(m_colorText);

       dc.SetBkColor(m_colorBk);

      

       // 배경모드를설정

       if(m_bTransparent) dc.SetBkMode(TRANSPARENT);

       else dc.SetBkMode(OPAQUE);

 

       // 텍스트를그림

       x=70; y=0;    // 글씨의위치

       rect=CRect(x,y,x+900,y+50);  // 글씨를쓰는박스의크기

       dc.DrawText("2008년메카트로닉스과수위조절졸업작품", &rect, DT_SINGLELINE|DT_CENTER|DT_VCENTER);

        // Do not call CDialog::OnPaint() for painting messages

}

 

// 사용자가최소화된창을끄는동안에커서가표시되도록시스템에서

//  이함수를호출합니다.

HCURSOR CLevelDlg::OnQueryDragIcon()

{

        return static_cast<HCURSOR>(m_hIcon);

}

 

 

void CLevelDlg::OnTimer(UINT_PTR nIDEvent)

{

        // TODO: 여기에메시지처리기코드를추가및/또는기본값을호출합니다.

        CNiString data;

       double meanValue,meanValue2;

 

       //데이터를측정한다.

       CNiDAQmxAnalogSingleChannelReader reader(TaskIn01.Stream);

       CNiDAQmxAnalogSingleChannelReader reader2(TaskIn02.Stream);

 

       //측정값을탱크레벨로출력한다.

       data<<reader.ReadSingleSample();

       data >> meanValue;

       m_Tank1.Value = meanValue;

       m_Alarm1.GetPointers().Item(1).Value = meanValue;

 

       data<<reader2.ReadSingleSample();

       data >> meanValue2;

       m_Tank2.Value = meanValue2;

       m_Alarm2.GetPointers().Item(1).Value = meanValue2;

       

        // 탱크수위최대, 최소설정에따른출력을내보낸다.

        // 탱크의상위레벨Led 램프표시

        //(상위레벨보다높으면출력을멈춘다.)

        if(meanValue >= m_Alarm1.GetPointers().Item(3).Value) {

              m_bLed1_1.Value = 1;

              //vector[0]=1;

       }

       else

              m_bLed1_1.Value = 0;

        //펌프출력제어

        double k=m_dK.Value;

       if(meanValue >= m_Alarm1.GetPointers().Item(3).Value+m_dK.Value) {

              vector[0]=1;

              m_nPump.Value = 0;

       }

       else if(meanValue <= m_Alarm1.GetPointers().Item(3).Value-m_dK.Value) {

              vector[0]=0;

              m_nPump.Value = 1;

       }

 

 

        // 탱크의하위레벨Led 램프표시

        //(하위레벨보다낯으면출력을내보낸다.)

        if(meanValue<=m_Alarm1.GetPointers().Item(2).Value) {

              m_bLed1_2.Value = 0;

              //vector[0]=0;

       }

       else

              m_bLed1_2.Value = 0;

 

        // 탱크의상위레벨Led 램프표시

        if(meanValue2 >= m_Alarm2.GetPointers().Item(3).Value)

              m_bLed2_1.Value = 1;

       else

              m_bLed2_1.Value = 0;

 

        // 탱크의하위레벨Led 램프표시

        if(meanValue2<=m_Alarm2.GetPointers().Item(2).Value)

              m_bLed2_2.Value = 1;

       else

              m_bLed2_2.Value = 0;

 

       CNiDAQmxDigitalSingleChannelWriter writer(TaskOut01.Stream);

       writer.WriteSingleSampleMultiLine(true, vector);

 

       // 그래프를그린다.

       m_Graph.GetPlots().Item("Plot-1").ChartY(meanValue);

       m_Graph.GetPlots().Item("Plot-2").ChartY(m_Alarm1.GetPointers().Item(3).Value);

 

       

        CDialog::OnTimer(nIDEvent);

}

 

 

 

 

처음

   

 

중요함수