Share this

Motion Control Card Application Development Tutorial in C++

2026-04-06 05:43:21 · · #1

Today, Zheng Motion Technology will share with you how to develop a motion control application using C++ for multi-segment continuous interpolation.

We will start by creating a new MFC project and adding function libraries, then learn about the usage of PC functions, and finally use a project practice—a continuous interpolation motion routine—to familiarize everyone with C++ project development.

Before we begin our formal learning, let's first understand the motion control cards ECI2418 and ECI2618 from Zheng Motion Technology. These two products are 4-axis and 6-axis motion control cards, respectively.

The ECI2418 supports 4-axis pulse input and encoder feedback, with 24 onboard inputs, 16 onboard outputs, 2 AD, 2 DA, and a handwheel interface. Some output ports support high-speed PWM control.

The ECI2618 supports 6-axis pulse input and encoder feedback, with 24 onboard inputs, 16 onboard outputs, 2 AD converters, 2 DA converters, and a handwheel interface. Some output ports support high-speed PWM control.

Both ECI2418 and ECI2618 use the same set of API functions and support development languages ​​such as C, C++, C#, LabVIEW, Python, and Delphi. They also support platforms such as VC6.0, VB6.0, Qt, and .Net, and operating systems such as Windows, Linux, WinCE, and iMac.

The following is C++

Development process

01 Create a new MFC project and add function libraries.

1. In VS2015, go to "File" → "New" → "Project" to start the Project Creation Wizard.

2. Select "Visual C++" as the development language and "MFC Application" as the program type.

3. Proceed to the next step.

4. Select "Dialog-based" as the type, then click Next or Finish.

The next step is to continue configuring, and once completed, you can simply click "Finish". No further configuration is needed here; it's not crucial. Just ensure the correct type is selected; the rest can be edited within the project.

5. Locate the CD-ROM data provided by the manufacturer. The path is as follows (64-bit library as an example).

1) Go to the CD-ROM data and find the PC function folder.

2) Select function library 2.1.

3) Windows platform.

4) Select the corresponding function library as needed. Here, we choose the 64-bit library.

5) Unzip the C++ compressed file, which contains the corresponding C++ function library.

6) The specific path to the function library is as follows.

6. Copy the C++ library files and related header files provided by the vendor into the newly created project.

7. Add static libraries and related header files to the project.

Static libraries: zauxdll.lib, zmotion.lib

Relevant header files: zauxdll2.h, zmotion.h

1) First, right-click the header file, then select: "Add" → "Existing Item".

2) In the pop-up window, add the static library and related header files in sequence.

3) Declare the header files used and define the controller connection handle.

The project is now complete.

02. Consult the PC function manual to learn how to use it.

1. The PC function manual is also included in the CD-ROM.

The specific path is as follows:

2. PC Programming

First, select the corresponding connection function based on the controller connection method to connect to the controller and return the controller handle. Then, use the returned controller handle to control the controller.

For example, to connect to the controller via the network port, first use ZAux_OpenEth() to connect to the controller and obtain the controller handle.

By obtaining the controller handle, single-axis motion control is performed on the controller.

By obtaining the controller handle, multi-axis motion control is performed on the controller.

//Multi-axis motion

int axislist[ 4 ] = { 0 , 1 , 2 , 3 }; // List of motion base axes

float dislist[ 4 ] = { 100,100,100,100 }; // List of movement distances

ZAux_Direct_Move(g_handle, 4 , axislist, dislist); // Multi-axis motion

03 Project Practice: Explanation of Continuous Interpolation Motion Routine

1. The routine aims to establish the connection of the board and perform the processing of 3 consecutive trajectories.

2. Simplified flowchart of the routine.

// Related functions

ZAux_OpenEth(IP_buffer, &g_handle); // Connect to the controller

ZAux_Direct_GetAllAxisPara(g_handle, " DPOS ", 4, showpos); // Get the current axis position

ZAux_Direct_GetAllAxisPara(g_handle, " MSPEED ", 4, mspeed); // Update axis speed

ZAux_Direct_Single_Cancel(g_handle, 0, 2); // Stop the spindle motion

ZAux_Direct_Move(g_handle, 4, axislist, dislist1); // First multi-axis interpolation command

ZAux_Direct_Move(g_handle, 4, axislist, dislist2); // Second multi-axis interpolation command

ZAux_Direct_Move(g_handle, 4, axislist, dislist3); // The third multi-axis interpolation command

ZAux_Close(g_handle); // Disconnect

3. Connect to the controller via the network port and obtain the controller connection handle.

//Link button event handler function

void CMergeDlg::OnBnClickedButtonLink()

{

char buffer[256];

int32 iresult;

//If there was a controller connection previously, disconnect it first.

if (NULL != g_handle)

{

ZAux_Close(g_handle);

g_handle = NULL;

}

//Get IP from IP dropdown list

GetDlgItemText(IDC_COMBOX_IP, buffer, 255);

buffer[255] = '\0';

// Connect to the controller via the API function interface provided by the PC function library.

iresult = ZAux_OpenEth(buffer, &g_handle);

if (ERR_SUCCESS != iresult)

{

g_handle = NULL;

MessageBox(_T(" Connection failed "));

SetWindowText(" Unlinked ");

return ;

}

SetWindowText(" Linked ");

//Start the timer

SetTimer(1, 100, NULL);

SetTimer(2, 100, NULL);

// Initialize axis parameters

for ( int i = 0; i<4; i++)

{

ZAux_Direct_SetAtype(g_handle, i, 1); // Axis type

ZAux_Direct_SetUnits(g_handle, i, 1000); // Pulse equivalent

ZAux_Direct_SetSpeed(g_handle, i, 100); //Speed

ZAux_Direct_SetAccel(g_handle, i, 1000); //Acceleration

ZAux_Direct_SetDecel(g_handle, i, 1000); // Deceleration

ZAux_Direct_SetSramp(g_handle, i, 100); // S-curve time

}

}

4. Update the position and speed information of controller axes 0-3 using timer 1.

//Timer

void CMergeDlg::OnTimer(UINT_PTR nIDEvent)

{

if (NULL == g_handle)

{

MessageBox(_T(" Connection lost "));

return;

}

switch (nIDEvent)

{

Case 1: // Update the position and velocity information of controller axes 0-3

CString Xpos, Xmspeed;

CString Ypos, Ymspeed;

CString Zpos, Zmspeed;

CString Upos, Umspeed;

float showpos[4] = { 0 };

float mspeed[4] = { 0 };

int status = 0;

//Get current axis position

ZAux_Direct_GetAllAxisPara(g_handle, " DPOS ", 4, showpos);

Xpos.Format(" X: %.2f ", showpos[0]);

Ypos.Format(" Y: %.2f ", showpos[1]);

Zpos.Format(" Z: %.2f ", showpos[2]);

Upos.Format(" U: %.2f ", showpos[3]);

GetDlgItem(IDC_XPOS)->SetWindowText(Xpos);

GetDlgItem(IDC_YPOS)->SetWindowText(Ypos);

GetDlgItem(IDC_ZPOS)->SetWindowText(Zpos);

GetDlgItem(IDC_UPOS)->SetWindowText(Upos);

// Determine the state of the primary axis (i.e., the first axis of the base).

ZAux_Direct_GetIfIdle(g_handle, 0, &status);

if (status == -1)

{

GetDlgItem(IDC_RUNSTATUS)->SetWindowText(" Motion Status: Stopped ");

}

else

{

GetDlgItem(IDC_RUNSTATUS)->SetWindowText(" Motion Status: In Motion ");

}

//Update axis speed

ZAux_Direct_GetAllAxisPara(g_handle, " MSPEED ", 4, mspeed);

Xmspeed.Format(" X-axis speed: %.2f ", mspeed[0]);

Ymspeed.Format(" Y-axis speed: %.2f ", mspeed[1]);

Zmspeed.Format(" Z-axis speed: %.2f ", mspeed[2]);

Umspeed.Format(" U-axis speed: %.2f ", mspeed[3]);

GetDlgItem(IDC_SPEED_X)->SetWindowText(Xmspeed);

GetDlgItem(IDC_SPEED_Y)->SetWindowText(Ymspeed);

GetDlgItem(IDC_SPEED_Z)->SetWindowText(Zmspeed);

GetDlgItem(IDC_SPEED_U)->SetWindowText(Umspeed);

break

}

CDialogEx::OnTimer(nIDEvent);

}

5. Start the continuous interpolation motion by using the event handler function of the start button.

//Start button

void CMergeDlg::OnBnClickedButtonRun()

{

if (NULL == g_handle)

{

MessageBox(_T( "Connection lost" ));

return;

}

UpdateData(true); // Refresh parameters

int corner_mode = 0;

int axislist[4] = { 0,1,2,3 }; // List of motion base axes

float dislist1[4] = { 0 }; // List of movement distances

float dislist2[4] = { 0 };

float dislist3[4] = { 0 };

//Select the axes involved in the motion; the first axis is the master axis, and all interpolation parameters use the master axis parameters.

ZAux_Direct_SetSpeed(g_handle, axislist[0], M_Speed); //Speed

ZAux_Direct_SetAccel(g_handle, axislist[0], M_Accel); //Acceleration

ZAux_Direct_SetDecel(g_handle, axislist[0], M_Decel); // Deceleration

ZAux_Direct_SetSramp(g_handle, axislist[0], M_SRAMP); // S-curve time

//Set corner mode

if (m_mode1 == 1)

{

corner_mode = corner_mode + 2;

}

if (m_mode2 == 1)

{

corner_mode = corner_mode + 8;

}

if (m_mode3 == 1)

{

corner_mode = corner_mode + 32;

}

ZAux_Direct_SetCornerMode(g_handle, axislist[0], corner_mode);

//Set continuous interpolation

ZAux_Direct_SetMerge(g_handle, axislist[0], m_mode);

//Set SP speed

ZAux_Direct_SetForceSpeed(g_handle, axislist[0], SP_Speed);

//Set the start and end deceleration angles, converted to radians

ZAux_Direct_SetDecelAngle(g_handle, axislist[0], StartAngle * 3.14 / 180);

ZAux_Direct_SetStopAngle(g_handle, axislist[0], StopAngle * 3.14 / 180);

//Set the speed limit radius of the small circle

ZAux_Direct_SetFullSpRadius(g_handle, axislist[0], SP_Radius);

//Set corner radius

ZAux_Direct_SetZsmooth(g_handle, axislist[0], CornerRadius);

//In the SP command, set a large startmovespeed and endmovespeed in the automatic cornering mode.

ZAux_Direct_SetStartMoveSpeed(g_handle, axislist[0], 10000);

ZAux_Direct_SetEndMoveSpeed(g_handle, axislist[0], 10000);

//Update exercise data

dislist1[0] = DPOS_X_1; dislist1[1] = DPOS_Y_1;

dislist1[2] = DPOS_Z_1; dislist1[3] = DPOS_U_1;

dislist2[0] = DPOS_X_2; dislist2[1] = DPOS_Y_2;

dislist2[2] = DPOS_Z_2; dislist2[3] = DPOS_U_2;

dislist3[0] = DPOS_X_3; dislist3[1] = DPOS_Y_3;

dislist3[2] = DPOS_Z_3; dislist3[3] = DPOS_U_3;

//Start exercising

ZAux_Direct_Move(g_handle, 4, axislist, dislist1);

ZAux_Direct_Move(g_handle, 4, axislist, dislist2);

ZAux_Direct_Move(g_handle, 4, axislist, dislist3);

}

6. Stop the interpolation motion by using the event handler function of the stop button.

//Stop button

void CMergeDlg::OnBnClickedButtonStop()

{

if (NULL == g_handle)

{

MessageBox(_T("Connection lost"));

return;

}

ZAux_Direct_Single_Cancel(g_handle, 0, 2); // Stop one axis of the main spindle base.

}

7. Zero the axis coordinates.

//Reset coordinates

void CMergeDlg::OnBnClickedButtonClear()

{

if (NULL == g_handle)

{

MessageBox(_T("Connection lost"));

return;

}

for (int i = 0; i<4; i++)

{

ZAux_Direct_SetDpos(g_handle, i, 0); // Set DPOS to zero

}

}

8. Compile and run the demonstration.

1) Compile and run the teaching example.

2) Simultaneously, the same controller is connected via ZDevelop software to monitor the axis parameters of motion control.

A. Position waveform of continuous interpolation with automatic chamfering.

B. Speed ​​waveform without continuous interpolation.

C. Speed ​​waveform of continuous interpolation plus appropriate corner deceleration.


That concludes our discussion of C++ development for positive motion technology. For more learning videos and articles, please follow our WeChat official account, "Positive Motion Assistant".

This article was originally created by Zheng Motion Assistant. We welcome everyone to reprint it for mutual learning and to improve China's intelligent manufacturing capabilities. Copyright belongs to Zheng Motion Technology. Please indicate the source if you reprint this article.


Read next

CATDOLL 133CM Ingrid Shota Doll

Height: 133cm Male Weight: 28kg Shoulder Width: 31cm Bust/Waist/Hip: 64/59/73cm Oral Depth: 3-5cm Vaginal Depth: N/A An...

Articles 2026-02-22
CATDOLL Laura Soft Silicone Head

CATDOLL Laura Soft Silicone Head

Articles
2026-02-22
CATDOLL Airi TPE Head

CATDOLL Airi TPE Head

Articles
2026-02-22