// activetestDlg.cpp : implementation file
//
#include "math.h"
#include "stdafx.h"
#include "activetest.h"
#include "activetestDlg.h"
#include "stdafx.h"
#include "windows.h"
#include "mmsystem.h"
#include "DlgPIDSetup.h"
#pragma comment (lib,"winmm.lib")
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////GLOBALs
bool bPosFollow=false;
FLOAT fSinA=0;
FLOAT fSinF=0;
FLOAT fSinY0=0;
HANDLE hSemaphoreTimerPWM;
USHORT usMotionMode=0; //运动模式标志,手动0;定点1;正弦2;
volatile USHORT usDurationH[4]={0,0,0,0};
volatile USHORT usDurationL[4]={0,0,0,0};
volatile BOOL bDir[4]={TRUE,TRUE,TRUE,TRUE};
volatile FLOAT Kp=0.05;
volatile FLOAT Ki=0.01;
volatile FLOAT Kd=0.01;
volatile FLOAT K0[4]={1,1,1,1};
volatile FLOAT K1[4]={0,0,0,0};
volatile FLOAT K2[4]={0.01,0.01,0.01,0.01};
volatile FLOAT fError[4][3]={{0,0,0},{0,0,0},{0,0,0},{0,0,0}};
volatile FLOAT fPosition[4]={0,0,0,0};
volatile FLOAT fPositionSet[4]={200,200,200,200};
volatile FLOAT fU_PID[4]={0,0,0,0}; //PID 输出结果
//void CALLBACK TimerCallback(UINT wTimerID,UINT msg,DWORD dwUser,DWORD dw1,DWORD dw2);
void ThreadProc1();
void ThreadProc2();
void ThreadProc3();
void ThreadProc4();
void Control_Logic(volatile FLOAT* fPosition,volatile FLOAT* fPositionSet,volatile FLOAT* K0,volatile FLOAT* K1,volatile FLOAT* K2,volatile FLOAT fError[4][3],volatile BOOL* bDir,volatile USHORT* usDurationH,volatile FLOAT* fU_PID);
void UpdatePositionSet(DOUBLE* dTimeSec);
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CActivetestDlg dialog
CActivetestDlg::CActivetestDlg(CWnd* pParent /*=NULL*/)
: CDialog(CActivetestDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CActivetestDlg)
m_F1 = 0.0f;
m_F2 = 0.0f;
m_F3 = 0.0f;
m_F4 = 0.0f;
m_L1 = 0.0f;
m_L2 = 0.0f;
m_L3 = 0.0f;
m_L4 = 0.0f;
m_P1 = 0.0f;
m_P2 = 0.0f;
m_P3 = 0.0f;
m_P4 = 0.0f;
m_Duration1 = 0;
m_bDIR1 = FALSE;
m_error1 = 0.0f;
m_fPos1 = 0.0f;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CActivetestDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CActivetestDlg)
DDX_Control(pDX, IDC_STOPDAQ, m_BtnStopDAQ);
DDX_Control(pDX, IDC_STARTDAQ, m_BtnStartDAQ);
DDX_Control(pDX, IDC_POS_FOLLOW_STOP, m_BtnPosFollowStop);
DDX_Control(pDX, IDC_POS_FOLLOW, m_BtnPosFollow);
DDX_Control(pDX, IDC_SetupPID, m_BtnSetupPID);
DDX_Control(pDX, IDC_ADVAI1, m_AdvAI);
DDX_Control(pDX, IDC_ADVGRAPH1, m_graph1);
DDX_Control(pDX, IDC_ADVGRAPH2, m_graph2);
DDX_Control(pDX, IDC_ADVGRAPH3, m_graph3);
DDX_Control(pDX, IDC_ADVGRAPH4, m_graph4);
DDX_Control(pDX, IDC_ADVDIOCTRL1, m_AdvDIO);
DDX_Text(pDX, IDC_EDIT_F1, m_F1);
DDX_Text(pDX, IDC_EDIT_F2, m_F2);
DDX_Text(pDX, IDC_EDIT_F3, m_F3);
DDX_Text(pDX, IDC_EDIT_F4, m_F4);
DDX_Text(pDX, IDC_EDIT_L1, m_L1);
DDX_Text(pDX, IDC_EDIT_L2, m_L2);
DDX_Text(pDX, IDC_EDIT_L3, m_L3);
DDX_Text(pDX, IDC_EDIT_L4, m_L4);
DDX_Text(pDX, IDC_EDIT_P1, m_P1);
DDX_Text(pDX, IDC_EDIT_P2, m_P2);
DDX_Text(pDX, IDC_EDIT_P3, m_P3);
DDX_Text(pDX, IDC_EDIT_P4, m_P4);
DDX_Text(pDX, IDC_EDIT_Duration1, m_Duration1);
DDX_Text(pDX, IDC_EDIT_bDIR1, m_bDIR1);
DDX_Text(pDX, IDC_EDIT_ERROR1, m_error1);
DDX_Text(pDX, IDC_EDIT_fPos1, m_fPos1);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CActivetestDlg, CDialog)
//{{AFX_MSG_MAP(CActivetestDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_STARTDAQ, OnStartdaq)
ON_BN_CLICKED(IDC_STOPDAQ, OnStopdaq)
ON_BN_CLICKED(IDC_displaytest, Ondisplaytest)
ON_BN_CLICKED(IDC_POS_FOLLOW, OnPosFollow)
ON_BN_CLICKED(IDC_BtnUP, OnBtnUP)
ON_BN_CLICKED(IDC_BtnDown, OnBtnDown)
ON_BN_CLICKED(IDC_HALT, OnHalt)
ON_BN_CLICKED(IDC_SetupPID, OnSetupPID)
ON_BN_CLICKED(IDC_POS_FOLLOW_STOP, OnPosFollowStop)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CActivetestDlg message handlers
BOOL CActivetestDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
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);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
usDurationH[0]=0;
usDurationL[0]=20-usDurationH[0];
hSemaphoreTimerPWM=::CreateSemaphore(NULL,4,4,NULL);
//利用函数timeGetDeVCaps取出系统分辨率的取值范围,如果无错则继续;
if(timeGetDevCaps(&tc,sizeof(TIMECAPS))==TIMERR_NOERROR)
{
UINT wAccuracy=min(max(tc.wPeriodMin,1),tc.wPeriodMax);
//调用timeBeginPeriod函数设置定时器的分辨率
::timeBeginPeriod(wAccuracy);
}
dSecCountStart=(DOUBLE)(::GetTickCount()/((DOUBLE)1000));
dSecCount=(DOUBLE)(::GetTickCount()/((DOUBLE)1000))-dSecCountStart;
::VariantInit( &m_index );
V_VT( &m_index ) = VT_I4;
V_I4( &m_index ) = 0;
//init m_xFirst
::VariantInit( &m_xFirst );
V_VT( &m_xFirst ) = VT_I4; //integer
V_I4( &m_xFirst ) = 0;
//init m_bChartPerRow
::VariantInit( &m_bChartPerRow);
V_VT( &m_bChartPerRow) = VT_BOOL; //BOOL
V_BOOL( &m_bChartPerRow) = true; //每行一通道显示
//init m_xInc
::VariantInit( &m_xInc );
V_VT( &m_xInc ) = VT_I4; //integer
V_I4( &m_xInc ) = 1;
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_graph1.SetChartLength(2000);
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_graph2.SetChartLength(2000);
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_graph3.SetChartLength(2000);
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_graph4.SetChartLength(2000);
CActivetestDlg::DeviceName="";
CActivetestDlg::DeviceNumber=((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvAI.GetDeviceListFirst((BSTR*)&DeviceName);//optional
if(!((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvAI.SelectDevice())
{
AfxMessageBox("select Device failed!");
}
CActivetestDlg::DeviceNumber=((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvAI.GetDeviceNumber();
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.SetDeviceNumber(DeviceNumber); //指定DIO控件设备
CActivetestDlg::DeviceName=((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvAI.GetDeviceName();
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvAI.SetChannelScanStart(0);
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvAI.SetChannelScanCount(16);
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvAI.SetDataSampleRate(160); //SampleRate 160
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvAI.SetDataReturnType(2); //return float
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvAI.SetTraceTriggerMode(0); //no trigger
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvAI.SetDataPacerSource(0); //internal pacer
///////////////设置按钮状态
m_BtnPosFollow.EnableWindow();
m_BtnSetupPID.EnableWindow();
m_BtnPosFollowStop.EnableWindow(FALSE);
m_BtnStartDAQ.EnableWindow();
m_BtnStopDAQ.EnableWindow(FALSE);
//////////////////
return TRUE; // return TRUE unless you set the focus to a control
}
void CActivetestDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CActivetestDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
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;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CActivetestDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
BEGIN_EVENTSINK_MAP(CActivetestDlg, CDialog)
//{{AFX_EVENTSINK_MAP(CActivetestDlg)
ON_EVENT(CActivetestDlg, IDC_ADVAI1, 3 /* OnFirstHalfBulkDataReady */, OnOnFirstHalfBulkDataReadyAdvai1, VTS_PVARIANT VTS_PVARIANT VTS_I4)
ON_EVENT(CActivetestDlg, IDC_ADVAI1, 2 /* OnSecondHalfBulkDataReady */, OnOnSecondHalfBulkDataReadyAdvai1, VTS_PVARIANT VTS_PVARIANT VTS_I4)
//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()
void CActivetestDlg::OnOnFirstHalfBulkDataReadyAdvai1(VARIANT FAR* digitalArray, VARIANT FAR* analogArray, long dataCount)
{
// TODO: Add your control notification handler code here
// ::AfxMessageBox("first half data ready!");
dSecCount=(DOUBLE)(::GetTickCount()/((DOUBLE)1000))-dSecCountStart; //记下当时的时间dSecCount(s)
CActivetestDlg::ConvertData(analogArray,&varDATA1,&varDATA2,&varDATA3,&varDATA4,&varDATA5,&varDATA6,&varDATA7,&varDATA8,&varDATA9,&varDATA10,&varDATA11,&varDATA12,&varTime,&dSecCount);
/////////////////////////
UpdatePositionSet(&dSecCount); //在位置波形伺服模式下需要更新目的定点的值
for(long j=12,k=0;j<16,k<4;j++,k++) //储存当前位移值
{
FLOAT temp;
::SafeArrayGetElement(analogArray->parray,&j,&temp);
fPosition[k]=temp*800/8.16-200;
}
m_fPos1=fPosition[0]; //调试用 位置缓存
Control_Logic(fPosition,fPositionSet,K0,K1,K2,fError,bDir,usDurationH,fU_PID);
m_Duration1=usDurationH[0]; //调试用 显示占空比幅值
m_error1=fError[0][2];
m_bDIR1=bDir[0];
/////
V_I4( &m_index ) = 0;
m_graph1.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA1);
m_graph2.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA2);
m_graph3.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA3);
m_graph4.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA4);
V_I4( &m_index ) = 1;
m_graph1.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA5);
m_graph2.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA6);
m_graph3.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA7);
m_graph4.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA8);
V_I4( &m_index ) = 2;
m_graph1.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA9);
m_graph2.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA10);
m_graph3.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA11);
m_graph4.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA12);
}
void CActivetestDlg::OnOnSecondHalfBulkDataReadyAdvai1(VARIANT FAR* digitalArray, VARIANT FAR* analogArray, long dataCount)
{
// TODO: Add your control notification handler code here
dSecCount=(DOUBLE)(::GetTickCount()/((DOUBLE)1000))-dSecCountStart; //记下当时的时间dSecCount(s)
CActivetestDlg::ConvertData(analogArray,&varDATA1,&varDATA2,&varDATA3,&varDATA4,&varDATA5,&varDATA6,&varDATA7,&varDATA8,&varDATA9,&varDATA10,&varDATA11,&varDATA12,&varTime,&dSecCount);
/////////////////////////
for(long j=12,k=0;j<16,k<4;j++,k++) //储存当前位移值
{
FLOAT temp;
::SafeArrayGetElement(analogArray->parray,&j,&temp);
fPosition[k]=temp*800/8.16-200;
}
Control_Logic(fPosition,fPositionSet,K0,K1,K2,fError,bDir,usDurationH,fU_PID);
///////////
V_I4( &m_index ) = 0;
m_graph1.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA1);
m_graph2.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA2);
m_graph3.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA3);
m_graph4.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA4);
V_I4( &m_index ) = 1;
m_graph1.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA5);
m_graph2.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA6);
m_graph3.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA7);
m_graph4.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA8);
V_I4( &m_index ) = 2;
m_graph1.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA9);
m_graph2.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA10);
m_graph3.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA11);
m_graph4.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA12);
}
void CActivetestDlg::OnStartdaq()
{
// TODO: Add your control notification handler code here
//清除屏幕
m_graph1.ClearData();
m_graph2.ClearData();
m_graph3.ClearData();
m_graph4.ClearData();
/////设置按钮状态
m_BtnStartDAQ.EnableWindow(FALSE);
m_BtnStopDAQ.EnableWindow();
////
dSecCountStart=(DOUBLE)(::GetTickCount()/((DOUBLE)1000)); //设置计时起点
dSecCount=(DOUBLE)(::GetTickCount()/((DOUBLE)1000))-dSecCountStart;
if(((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvAI.AcquireBulkDataToMemory(32,NULL,-1,true,false)==0) //循环模式,异步采集.超时请设为-1,缓存数32
{
AfxMessageBox("AcquireBulkDataToMemory failed!");
}
}
void CActivetestDlg::OnStopdaq()
{
// TODO: Add your control notification handler code here
/////设置按钮状态
m_BtnStopDAQ.EnableWindow(FALSE);
m_BtnStartDAQ.EnableWindow();
////
m_AdvAI.StopAcquireBulkData(0);
}
void CActivetestDlg::ConvertData(VARIANT* analogArray,VARIANT* pvarDATA1,VARIANT* pvarDATA2,VARIANT* pvarDATA3,VARIANT* pvarDATA4,VARIANT* pvarDATA5,VARIANT* pvarDATA6,VARIANT* pvarDATA7,VARIANT* pvarDATA8,VARIANT* pvarDATA9,VARIANT* pvarDATA10,VARIANT* pvarDATA11,VARIANT* pvarDATA12,VARIANT* pvarDATAtime,DOUBLE* pTime)
{
//暂存analogArray中的数据至普通数组
FLOAT fReadingBuf[16];
for(long index=0;index<16;index++)
{
::SafeArrayGetElement(analogArray->parray,&index,&fReadingBuf[index]);
}
/////////////////////// 转换被测量单位
for(int i=0;i<8;i++)
{
fReadingBuf[i]=fReadingBuf[i]*1000;
}
for(i=12;i<16;i++)
{
fReadingBuf[i]=fReadingBuf[i]*800/8.16-200;
}
/////显示采样数值
DisplayNumeric(fReadingBuf);
/////////////////////构造graph1的输入变量DATA1
SAFEARRAY* psaDATA1;
SAFEARRAYBOUND sabd[1];
sabd[0].cElements=1; //1*1的数组。PLOTY的参数必须是数组型
sabd[0].lLbound=0;
psaDATA1=::SafeArrayCreate(VT_R4,1,sabd); //创造了safearray
LPVOID pData= NULL;
::SafeArrayAccessData(psaDATA1,(void HUGEP**)&pData);
((FLOAT*)pData)[0]=fReadingBuf[0]; //赋值
::SafeArrayUnaccessData(psaDATA1);
::VariantInit(pvarDATA1);
V_VT(pvarDATA1)=(VT_ARRAY|VT_R4);
V_ARRAY(pvarDATA1)=psaDATA1;
////////////////////////////////////构造GRAPH1输入变量DATA2
SAFEARRAY* psaDATA2;
psaDATA2=::SafeArrayCreate(VT_R4,1,sabd); //创造了safearray
pData= NULL;
::SafeArrayAccessData(psaDATA2,(void HUGEP**)&pData);
((FLOAT*)pData)[0]=fReadingBuf[1]; //赋值
::SafeArrayUnaccessData(psaDATA2);
::VariantInit(pvarDATA2);
V_VT(pvarDATA2)=(VT_ARRAY|VT_R4);
V_ARRAY(pvarDATA2)=psaDATA2;
////////////////////////////////////
SAFEARRAY* psaDATA3;
psaDATA3=::SafeArrayCreate(VT_R4,1,sabd); //创造了safearray
pData= NULL;
::SafeArrayAccessData(psaDATA3,(void HUGEP**)&pData);
((FLOAT*)pData)[0]=fReadingBuf[2]; //赋值
::SafeArrayUnaccessData(psaDATA3);
::VariantInit(pvarDATA3);
V_VT(pvarDATA3)=(VT_ARRAY|VT_R4);
V_ARRAY(pvarDATA3)=psaDATA3;
////////////////////////////////////
SAFEARRAY* psaDATA4;
psaDATA4=::SafeArrayCreate(VT_R4,1,sabd); //创造了safearray
pData= NULL;
::SafeArrayAccessData(psaDATA4,(void HUGEP**)&pData);
((FLOAT*)pData)[0]=fReadingBuf[3]; //赋值
::SafeArrayUnaccessData(psaDATA4);
::VariantInit(pvarDATA4);
V_VT(pvarDATA4)=(VT_ARRAY|VT_R4);
V_ARRAY(pvarDATA4)=psaDATA4;
/////////////////////////////////////
SAFEARRAY* psaDATA5;
psaDATA5=::SafeArrayCreate(VT_R4,1,sabd); //创造了safearray
pData= NULL;
::SafeArrayAccessData(psaDATA5,(void HUGEP**)&pData);
((FLOAT*)pData)[0]=fReadingBuf[4]; //赋值
::SafeArrayUnaccessData(psaDATA5);
::VariantInit(pvarDATA5);
V_VT(pvarDATA5)=(VT_ARRAY|VT_R4);
V_ARRAY(pvarDATA5)=psaDATA5;
///////////////////////////////////
SAFEARRAY* psaDATA6;
psaDATA6=::SafeArrayCreate(VT_R4,1,sabd); //创造了safearray
pData= NULL;
::SafeArrayAccessData(psaDATA6,(void HUGEP**)&pData);
((FLOAT*)pData)[0]=fReadingBuf[5]; //赋值
::SafeArrayUnaccessData(psaDATA6);
::VariantInit(pvarDATA6);
V_VT(pvarDATA6)=(VT_ARRAY|VT_R4);
V_ARRAY(pvarDATA6)=psaDATA6;
//////////////////////////////////
SAFEARRAY* psaDATA7;
psaDATA7=::SafeArrayCreate(VT_R4,1,sabd); //创造了safearray
pData= NULL;
::SafeArrayAccessData(psaDATA7,(void HUGEP**)&pData);
((FLOAT*)pData)[0]=fReadingBuf[6]; //赋值
::SafeArrayUnaccessData(psaDATA7);
::VariantInit(pvarDATA7);
V_VT(pvarDATA7)=(VT_ARRAY|VT_R4);
V_ARRAY(pvarDATA7)=psaDATA7;
//////////////////////////////////
SAFEARRAY* psaDATA8;
psaDATA8=::SafeArrayCreate(VT_R4,1,sabd); //创造了safearray
pData= NULL;
::SafeArrayAccessData(psaDATA8,(void HUGEP**)&pData);
((FLOAT*)pData)[0]=fReadingBuf[7]; //赋值
::SafeArrayUnaccessData(psaDATA8);
::VariantInit(pvarDATA8);
V_VT(pvarDATA8)=(VT_ARRAY|VT_R4);
V_ARRAY(pvarDATA8)=psaDATA8;
///////////////////////////////////
SAFEARRAY* psaDATA9;
psaDATA9=::SafeArrayCreate(VT_R4,1,sabd); //创造了safearray
pData= NULL;
::SafeArrayAccessData(psaDATA9,(void HUGEP**)&pData);
((FLOAT*)pData)[0]=fReadingBuf[12]; //赋值
::SafeArrayUnaccessData(psaDATA9);
::VariantInit(pvarDATA9);
V_VT(pvarDATA9)=(VT_ARRAY|VT_R4);
V_ARRAY(pvarDATA9)=psaDATA9;
///////////////////////////////////
SAFEARRAY* psaDATA10;
psaDATA10=::SafeArrayCreate(VT_R4,1,sabd); //创造了safearray
pData= NULL;
::SafeArrayAccessData(psaDATA10,(void HUGEP**)&pData);
((FLOAT*)pData)[0]=fReadingBuf[13]; //赋值
::SafeArrayUnaccessData(psaDATA10);
::VariantInit(pvarDATA10);
V_VT(pvarDATA10)=(VT_ARRAY|VT_R4);
V_ARRAY(pvarDATA10)=psaDATA10;
///////////////////////////////////
SAFEARRAY* psaDATA11;
psaDATA11=::SafeArrayCreate(VT_R4,1,sabd); //创造了safearray
pData= NULL;
::SafeArrayAccessData(psaDATA11,(void HUGEP**)&pData);
((FLOAT*)pData)[0]=fReadingBuf[14]; //赋值
::SafeArrayUnaccessData(psaDATA11);
::VariantInit(pvarDATA11);
V_VT(pvarDATA11)=(VT_ARRAY|VT_R4);
V_ARRAY(pvarDATA11)=psaDATA11;
///////////////////////////////////
SAFEARRAY* psaDATA12;
psaDATA12=::SafeArrayCreate(VT_R4,1,sabd); //创造了safearray
pData= NULL;
::SafeArrayAccessData(psaDATA12,(void HUGEP**)&pData);
((FLOAT*)pData)[0]=fReadingBuf[15]; //赋值
::SafeArrayUnaccessData(psaDATA12);
::VariantInit(pvarDATA12);
V_VT(pvarDATA12)=(VT_ARRAY|VT_R4);
V_ARRAY(pvarDATA12)=psaDATA12;
////////////////////////////////////
/////////////////////构造时间变量varDATAtime
SAFEARRAY* psaDATAtime;
psaDATAtime=::SafeArrayCreate(VT_R8,1,sabd); //创造了safearray DOUBLE型vt_r8
pData= NULL;
::SafeArrayAccessData(psaDATAtime,(void HUGEP**)&pData);
((DOUBLE*)pData)[0]=*pTime; //赋值
::SafeArrayUnaccessData(psaDATAtime);
::VariantInit(pvarDATAtime);
V_VT(pvarDATAtime)=(VT_ARRAY|VT_R8);
V_ARRAY(pvarDATAtime)=psaDATAtime;
////////////////////////////////////
}
void CActivetestDlg::Ondisplaytest()
{
// TODO: Add your control notification handler code here
SAFEARRAY* psaDATAtest;
SAFEARRAYBOUND sabd[1];
sabd[0].cElements=16;
sabd[0].lLbound=0;
psaDATAtest=::SafeArrayCreate(VT_R4,1,sabd); //创造了safearray
LPVOID pData= NULL;
::SafeArrayAccessData(psaDATAtest,(void HUGEP**)&pData);
for(long index=0;index<16;index++)
{
((FLOAT*)pData)[index]=(FLOAT)(index+0.763485); //赋值
};
::SafeArrayUnaccessData(psaDATAtest);
VARIANT varDATAtest;
::VariantInit(&varDATAtest);
V_VT(&varDATAtest)=(VT_ARRAY|VT_R4);
V_ARRAY(&varDATAtest)=psaDATAtest;
//////////////
//数据处理显示
/////////////
dSecCount=(DOUBLE)(::GetTickCount()/((DOUBLE)1000))-dSecCountStart; //记下当时的时间dSecCount(s)
CActivetestDlg::ConvertData(&varDATAtest,&varDATA1,&varDATA2,&varDATA3,&varDATA4,&varDATA5,&varDATA6,&varDATA7,&varDATA8,&varDATA9,&varDATA10,&varDATA11,&varDATA12,&varTime,&dSecCount);
//dSecCount被转换成varTime以供显示
V_I4( &m_index ) = 0;
m_graph1.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA1);
m_graph2.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA2);
m_graph3.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA3);
m_graph4.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA4);
V_I4( &m_index ) = 1;
m_graph1.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA5);
m_graph2.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA6);
m_graph3.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA7);
m_graph4.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA8);
V_I4( &m_index ) = 2;
m_graph1.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA9);
m_graph2.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA10);
m_graph3.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA11);
m_graph4.GetPlots().Item(m_index).ChartXvsY(&varTime,&varDATA12);
}
void CALLBACK ImplementControl(UINT wTimerID,UINT msg,DWORD dwUser,DWORD dw1,DWORD dw2)
{
::ReleaseSemaphore(hSemaphoreTimerPWM,4,NULL);
//printf("timer callback! at tick: %d\n",::GetTickCount());
}
void CActivetestDlg::OnPosFollow()
{
// TODO: Add your control notification handler code here
//////
m_BtnPosFollow.EnableWindow(FALSE);
// m_BtnSetupPID.EnableWindow(FALSE);
m_BtnPosFollowStop.EnableWindow();
////////set flag to run controlling threads
bPosFollow=true;
/////
if ((TimerID_1ms=timeSetEvent(5,1,(LPTIMECALLBACK)ImplementControl,0,TIME_PERIODIC))==0)
{
AfxMessageBox("cannot set PWM timer!");
};
AfxBeginThread((AFX_THREADPROC)ThreadProc1,(LPVOID)AfxGetApp()->m_pMainWnd->GetSafeHwnd(),THREAD_PRIORITY_NORMAL);
AfxBeginThread((AFX_THREADPROC)ThreadProc2,(LPVOID)AfxGetApp()->m_pMainWnd->GetSafeHwnd(),THREAD_PRIORITY_NORMAL);
AfxBeginThread((AFX_THREADPROC)ThreadProc3,(LPVOID)AfxGetApp()->m_pMainWnd->GetSafeHwnd(),THREAD_PRIORITY_NORMAL);
AfxBeginThread((AFX_THREADPROC)ThreadProc4,(LPVOID)AfxGetApp()->m_pMainWnd->GetSafeHwnd(),THREAD_PRIORITY_NORMAL);
}
void UpdatePositionSet(DOUBLE* dTimeSec)
{
switch(usMotionMode)
{
case 2:
{
for(int i=0;i<4;i++)
{
fPositionSet[i]=fSinA*sin(6.2831852*fSinF*(*dTimeSec))+fSinY0;
}
break;
};
}
}
void Control_Logic(volatile FLOAT* fPosition,volatile FLOAT* fPositionSet,volatile FLOAT* K0,volatile FLOAT* K1,volatile FLOAT* K2,volatile FLOAT fError[4][3],volatile BOOL* bDir,volatile USHORT* usDurationH,volatile FLOAT* fU_PID)
{
for(int i=0;i<4;i++)
{
fError[i][0]=fError[i][1];
fError[i][1]=fError[i][2];
fError[i][2]=fPositionSet[i]-fPosition[i];
if(fPosition[i]>600) //超出位移安全范围自动急停
{
bPosFollow=false;
AfxMessageBox("位移超出安全范围,位置伺服强制结束");
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,0);
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,1);
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,2);
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,3);
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,4);
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,5);
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,6);
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,7);
}
};
for(i=0;i<4;i++)
{
fU_PID[i]=(fU_PID[i]+K0[i]*(fError[i][2])+K1[i]*(fError[i][1])+K2[i]*(fError[i][0]));
// fU_PID[i]=fError[i][2]/2;
// if(abs(fError[i][2])<=1) fU_PID[i]=0; //设置死区
if(fError[i][2]>=0) bDir[i]=true;
else bDir[i]=false;
usDurationH[i]=(volatile USHORT)abs(fU_PID[i]);
if(usDurationH[i]>20)usDurationH[i]=20; // 输出限幅!
};
}
void ThreadProc1() //肌肉1控制线程
{
int PeriodCount=0;
USHORT usHiDelay=0;
while(bPosFollow)
{
::WaitForSingleObject(hSemaphoreTimerPWM,INFINITE); //PWM BASE period is 5ms*20=100ms
if(PeriodCount==0)
{
usHiDelay=usDurationH[0];
PeriodCount=20;
}
if(bDir[0]) // fU_PID>=0 向上运动
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,1); //关闭电磁阀1 //注意!类成员m_AdvDIO必须使用(CActivetestDlg*)AfxGetApp()->m_pMainWnd)->指针来指向,而不能用CActivetestDlg::m_AdvDIO来直接引用,否则会出现不认数据类型的编译错误
if(usHiDelay!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,0); //电磁阀0输出高
usHiDelay--;
PeriodCount--;
}
else
{
if(PeriodCount!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,0); //电磁阀0输出低
PeriodCount--;
}
}
}
else
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,0); //关闭电磁阀0
if(usHiDelay!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,1); //电磁阀1输出高
usHiDelay--;
PeriodCount--;
}
else
{
if(PeriodCount!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,1); //电磁阀1输出低
PeriodCount--;
}
}
}
}
}
void ThreadProc2() //肌肉2控制线程
{
int PeriodCount=0;
USHORT usHiDelay=0;
while(bPosFollow)
{
::WaitForSingleObject(hSemaphoreTimerPWM,INFINITE); //PWM BASE period is 1ms*20=20ms
if(PeriodCount==0)
{
usHiDelay=usDurationH[1];
PeriodCount=20;
}
if(bDir[1]) // fU_PID>=0 向上运动
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,3); //关闭电磁阀3 //注意!类成员m_AdvDIO必须使用(CActivetestDlg*)AfxGetApp()->m_pMainWnd)->指针来指向,而不能用CActivetestDlg::m_AdvDIO来直接引用,否则会出现不认数据类型的编译错误
if(usHiDelay!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,2); //电磁阀2输出高
usHiDelay--;
PeriodCount--;
}
else
{
if(PeriodCount!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,2); //电磁阀2输出低
PeriodCount--;;
}
}
}
else
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,2); //关闭电磁阀2
if(usHiDelay!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,3); //电磁阀3输出高
usHiDelay--;
PeriodCount--;
}
else
{
if(PeriodCount!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,3); //电磁阀3输出低
PeriodCount--;
}
}
}
}
}
void ThreadProc3() //肌肉3控制线程
{
int PeriodCount=0;
USHORT usHiDelay=0;
while(bPosFollow)
{
::WaitForSingleObject(hSemaphoreTimerPWM,INFINITE); //PWM BASE period is 1ms*20=20ms
if(PeriodCount==0)
{
usHiDelay=usDurationH[2];
PeriodCount=20;
}
if(bDir[2]) // fU_PID>=0 向上运动
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,5); //关闭电磁阀5 //注意!类成员m_AdvDIO必须使用(CActivetestDlg*)AfxGetApp()->m_pMainWnd)->指针来指向,而不能用CActivetestDlg::m_AdvDIO来直接引用,否则会出现不认数据类型的编译错误
if(usHiDelay!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,4); //电磁阀4输出高
usHiDelay--;
PeriodCount--;
}
else
{
if(PeriodCount!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,4); //电磁阀4输出低
PeriodCount--;
}
}
}
else
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,4); //关闭电磁阀4
if(usHiDelay!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,5); //电磁阀5输出高
usHiDelay--;
PeriodCount--;
}
else
{
if(PeriodCount!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,5); //电磁阀5输出低
PeriodCount--;
}
}
}
}
}
void ThreadProc4() //肌肉4控制线程
{
int PeriodCount=0;
USHORT usHiDelay=0;
while(bPosFollow)
{
::WaitForSingleObject(hSemaphoreTimerPWM,INFINITE); //PWM BASE period is 1ms*20=20ms
if(PeriodCount==0)
{
usHiDelay=usDurationH[3];
PeriodCount=20;
}
if(bDir[3]) // fU_PID>=0 向上运动
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,7); //关闭电磁阀7 //注意!类成员m_AdvDIO必须使用(CActivetestDlg*)AfxGetApp()->m_pMainWnd)->指针来指向,而不能用CActivetestDlg::m_AdvDIO来直接引用,否则会出现不认数据类型的编译错误
if(usHiDelay!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,6); //电磁阀6输出高
usHiDelay--;
PeriodCount--;
}
else
{
if(PeriodCount!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,6); //电磁阀6输出低
PeriodCount--;
}
}
}
else
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,6); //关闭电磁阀6
if(usHiDelay!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,7); //电磁阀7输出高
usHiDelay--;
PeriodCount--;
}
else
{
if(PeriodCount!=0)
{
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,7); //电磁阀7输出低
PeriodCount--;
}
}
}
}
}
void CActivetestDlg::OnBtnUP()
{
// TODO: Add your control notification handler code here
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,0);//0进气阀 肌肉1
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,1);//1排气阀 肌肉1
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,2);//2进气阀 肌肉2
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,3);//3排气阀 肌肉2
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,4);//4进气阀 肌肉3
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,5);//5排气阀 肌肉3
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,6);//6进气阀 肌肉4
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,7);//7排气阀 肌肉4
}
void CActivetestDlg::OnBtnDown()
{
// TODO: Add your control notification handler code here
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,0);//0进气阀 肌肉1
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,1);//1排气阀 肌肉1
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,2);//2进气阀 肌肉2
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,3);//3排气阀 肌肉2
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,4);//4进气阀 肌肉3
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,5);//5排气阀 肌肉3
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,6);//6进气阀 肌肉4
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,7);//7排气阀 肌肉4
}
void CActivetestDlg::OnHalt()
{
// TODO: Add your control notification handler code here
bPosFollow=false;
m_AdvDIO.WriteDoChannel(0,0);
m_AdvDIO.WriteDoChannel(0,1);
m_AdvDIO.WriteDoChannel(0,2);
m_AdvDIO.WriteDoChannel(0,3);
m_AdvDIO.WriteDoChannel(0,4);
m_AdvDIO.WriteDoChannel(0,5);
m_AdvDIO.WriteDoChannel(0,6);
m_AdvDIO.WriteDoChannel(0,7);
}
void CActivetestDlg::OnSetupPID()
{
// TODO: Add your control notification handler code here
CDlgPIDSetup DlgPIDSetup;
DlgPIDSetup.m_Kp=Kp;
DlgPIDSetup.m_Ki=Ki;
DlgPIDSetup.m_Kd=Kd;
DlgPIDSetup.m_PosSet=fPositionSet[0];
DlgPIDSetup.m_SinA=fSinA;
DlgPIDSetup.m_SinF=fSinF;
DlgPIDSetup.m_SinY0=fSinY0;
if(DlgPIDSetup.DoModal()==IDOK)
{
Kp=DlgPIDSetup.m_Kp;
Ki=DlgPIDSetup.m_Ki;
Kd=DlgPIDSetup.m_Kd;
for(int i=0;i<4;i++)
{
K0[i]=Kp+Ki+Kd;
K1[i]=-1*(Kp+2*Kd);
K2[i]=Kd;
fPositionSet[i]=DlgPIDSetup.m_PosSet;
};
fSinA=DlgPIDSetup.m_SinA;
fSinF=DlgPIDSetup.m_SinF;
fSinY0=DlgPIDSetup.m_SinY0;
}
}
void CActivetestDlg::OnPosFollowStop()
{
// TODO: Add your control notification handler code here
m_BtnPosFollowStop.EnableWindow(FALSE);
m_BtnSetupPID.EnableWindow();
m_BtnPosFollow.EnableWindow();
//CALL ALL STOP AND SET FLAG TO KILL ALL THREAD
bPosFollow=false; //control threads will return and end naturally
}
void CActivetestDlg::DisplayNumeric(float* DataArray)
{
m_P1=DataArray[0];
m_P2=DataArray[1];
m_P3=DataArray[2];
m_P4=DataArray[3];
m_F1=DataArray[4];
m_F2=DataArray[5];
m_F3=DataArray[6];
m_F4=DataArray[7];
m_L1=DataArray[12];
m_L2=DataArray[13];
m_L3=DataArray[14];
m_L4=DataArray[15];
UpdateData(false);
}
void CActivetestDlg::OnCancel()
{
// TODO: Add extra cleanup here
//每次退出均将肌肉排气
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,0);//0进气阀 肌肉1
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,1);//1排气阀 肌肉1
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,2);//2进气阀 肌肉2
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,3);//3排气阀 肌肉2
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,4);//4进气阀 肌肉3
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,5);//5排气阀 肌肉3
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(0,6);//6进气阀 肌肉4
((CActivetestDlg*)AfxGetApp()->m_pMainWnd)->m_AdvDIO.WriteDoChannel(1,7);//7排气阀 肌肉4
CDialog::OnCancel();
}