ActiveDAQ控件的VC编程 数据采集 VARIANT数据类型的使用

2 篇文章 0 订阅

// 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;
   }
  };
 }
}

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();
}

 

 

 

 

 

https://p-blog.csdn.net/images/p_blog_csdn_net/tobyforever/EntryImages/20090403/研华采集卡编程.PNG

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值