Share this

Motion Control Card Application Development Tutorial in C#

2026-04-06 07:08:06 · · #1

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

We will start by explaining how to create a new project and add function libraries, then learn how to use PC functions, and finally use a project practice example—a continuous interpolation motion routine—to familiarize everyone with its 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 .NET Framework 4 as the Windows Forms application.

3. Locate the C# function library in the CD-ROM provided by the manufacturer. The path is as follows (for a 64-bit library):

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 shown in the following figure.

4. Copy the C# library files and related files provided by the vendor into the newly created project.

1) Copy the zmcaux.cs file into the newly created project.

2) Place the zaux.dll and zmotion.dll files into the bin\debug folder.

5. Open the newly created project file in Visual Studio. In the Solution Explorer on the right, click "Show All". Then, right-click the zmcaux.cs file and click "Include in Project".

6. Double-click Form1 in Form1.cs to open the code editing interface. At the beginning of the file, write using cszmcaux and declare the controller handle g_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 materials; the specific path is as follows.

2. PC programming generally begins by selecting the appropriate connection function based on the controller's connection method to connect to the controller and return a controller handle. Then, the returned controller handle is used to control the controller.

3. 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.

Project application screenshots

4. Using the obtained controller handle, perform single-axis motion control on the controller.

5. Perform multi-axis absolute interpolation motion using the obtained controller handle.

int [] axislist = { 0, 1, 2, 3 }; // Axis list

float [] destdis = { 100, 100, 200, 100 }; // List of movement distances

zmcaux.ZAux_Direct_MoveAbs(g_handle, 4 , axislist, destdis);

6. Obtain the remaining buffer quantity in the controller buffer using the obtained controller handle.


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 4 continuous trajectories.

2. Simplified flowchart of the routine.

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

//Connect controller

private void button_link_Click ( object sender, EventArgs e)

{

if (g_handle != (IntPtr) 0 )

{

zmcaux.ZAux_Close(g_handle); // Disconnect

g_handle = (IntPtr) 0 ;

}

zmcaux.ZAux_OpenEth(comboBox_IpList.Text, out g_handle); // Connect to the controller

if (g_handle != (IntPtr) 0 )

{

this.Text = " Connected ";

timer1.Enabled = true ;

// Initialize axis parameters

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

{

zmcaux.ZAux_Direct_SetAtype(g_handle, i, 1); // Axis type: Pulse axis

zmcaux.ZAux_Direct_SetUnits(g_handle, i, 1); // Pulse equivalent

}

}

else

{

MessageBox.Show(" Controller connection failed, please check your IP address!", "Warning" );

}

}

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

//Timer refresh

private void timer1_Tick ( object sender, EventArgs e)

{

int runstate = 0 ;

float [] curpos = new float [ 4 ];

float vspeed = 0 ;

int remin_buff = 0 ;

int curmark = 0 ;

//Get axis position

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

{

zmcaux.ZAux_Direct_GetDpos(g_handle, i, ref curpos[i]);

}

//Get axis motion status

zmcaux.ZAux_Direct_GetIfIdle(g_handle, 0 , ref runstate);

//Get the resultant velocity of the interpolated motion

zmcaux.ZAux_Direct_GetVpSpeed(g_handle, 0 , ref vspeed);

// Check the remaining buffer for storing lines

zmcaux.ZAux_Direct_GetRemain_LineBuffer(g_handle, 0 , ref remin_buff);

//Determine which movement the current movement has reached.

zmcaux.ZAux_Direct_GetMoveCurmark(g_handle, 0 , ref curmark);

label_pos.Text = " X: " + curpos[ 0 ] + " Y: " + curpos[ 1 ] + " Z: " + curpos[ 2 ] + " U: " + curpos[ 3 ];

label_state.Text = Convert.ToString(runstate == 0 ? " Running status: Running " : " Running status: Stopped ");

label_vspeed.Text = "Current speed: " + vspeed;

label_buff.Text = "Remaining Buffer: " + remin_buff;

label_mark.Text = "Current Mark: " + curmark;

}

5. Initiate the interpolation motion using the event handler function of the start button.

//Start button

private void button_start_Click ( object sender, EventArgs e)

{

int [] axislist = { 0, 1, 2, 3 }; // Axis list

float [] destdis = { 0, 0, 0, 0 }; // List of movement distances

int corner_mode = 0 ; // Corner mode

int merge_flag = 0 ; // Continuous interpolation

int iresult = 0 ; // Return value of PC function

int remin_buff = 0 ; // Remaining number of line buffers

if (checkBox1.Checked)

{

corner_mode = corner_mode + 2 ;

}

if (checkBox2.Checked)

{

corner_mode = corner_mode + 8 ;

}

if (checkBox3.Checked)

{

corner_mode = corner_mode + 32 ;

}

if (checkBox4.Checked)

{

merge_flag = 1 ;

}

//Set interpolation speed

zmcaux.ZAux_Direct_SetSpeed(g_handle, axislist[ 0 ], Convert.ToSingle(textBox_sp.Text));

//Set interpolation acceleration

zmcaux.ZAux_Direct_SetAccel(g_handle, axislist[ 0 ], Convert.ToSingle(textBox_acc.Text));

//Set interpolation deceleration

zmcaux.ZAux_Direct_SetDecel(g_handle, axislist[ 0 ], Convert.ToSingle(textBox_dec.Text));

//Set continuous interpolation

zmcaux.ZAux_Direct_SetMerge(g_handle, axislist[ 0 ], merge_flag);

//S-curve time

zmcaux.ZAux_Direct_SetSramp(g_handle, axislist[ 0 ], Convert.ToSingle(SRAMP.Text));

//Set SP speed

zmcaux.ZAux_Direct_SetForceSpeed(g_handle, axislist[ 0 ], Convert.ToSingle(textBox_for_sp.Text));

//Set corner mode

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

//Start deceleration angle, convert to radians

zmcaux.ZAux_Direct_SetDecelAngle(g_handle, axislist[ 0 ], (float)(Convert.ToSingle(textBox_ang1.Text) * 3.14 / 180));

//Stop deceleration angle, convert to radians

zmcaux.ZAux_Direct_SetStopAngle(g_handle, axislist[ 0 ], (float)(Convert.ToSingle(textBox_ang2.Text) * 3.14 / 180));

// Radius of the smaller circle

zmcaux.ZAux_Direct_SetFullSpRadius(g_handle, axislist[ 0 ], Convert.ToSingle(textBox_radio.Text));

// Chamfer

zmcaux.ZAux_Direct_SetZsmooth(g_handle, axislist[ 0 ], Convert.ToSingle(textBox_zsmooth.Text));

// Set MARK = 0 to determine the current execution level by reading CURMARK.

zmcaux.ZAux_Direct_SetMovemark(g_handle, axislist[ 0 ], 0 );

//Select base axis

zmcaux.ZAux_Direct_Base(g_handle, 4 , axislist);

zmcaux.ZAux_Trigger(g_handle);

//Calculate the remaining number of linear buffers

zmcaux.ZAux_Direct_GetRemain_LineBuffer(g_handle, 0, ref remin_buff);

while (remin_buff< 4 )

{

zmcaux.ZAux_Direct_GetRemain_LineBuffer(g_handle, 0, ref remin_buff);

System.Threading.Thread.Sleep(1); // 1 millisecond

}

//First segment of interpolation movement

destdis[ 0 ] = Convert.ToSingle(destdis1_X.Text);

destdis[ 1 ] = Convert.ToSingle(destdis1_Y.Text);

destdis[ 2 ] = Convert.ToSingle(destdis1_Z.Text);

destdis[ 3 ] = Convert.ToSingle(destdis1_U.Text);

iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4 , axislist, destdis); // 4-axis interpolation command

//If the function returns a non-zero value, it means the transmission failed, the buffer may be full, and you should resend.

while (iresult != 0 )

{

iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4 , axislist, destdis);

System.Threading.Thread.Sleep( 1 ); // 1 millisecond

}

//Second segment interpolation movement

destdis[ 0 ] = Convert.ToSingle(destdis2_X.Text);

destdis[ 1 ] = Convert.ToSingle(destdis2_Y.Text);

destdis[ 2 ] = Convert.ToSingle(destdis2_Z.Text);

destdis[ 3 ] = Convert.ToSingle(destdis2_U.Text);

iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4 , axislist, destdis); // 4-axis interpolation command

//If the function returns a non-zero value, it means the transmission failed, the buffer may be full, and you should resend.

while (iresult != 0 )

{

iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4, axislist, destdis);

System.Threading.Thread.Sleep(1); // 1 millisecond

}

//Third segment interpolation motion

destdis[ 0 ] = Convert.ToSingle(destdis3_X.Text);

destdis[ 1 ] = Convert.ToSingle(destdis3_Y.Text);

destdis[ 2 ] = Convert.ToSingle(destdis3_Z.Text);

destdis[ 3 ] = Convert.ToSingle(destdis3_U.Text);

iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4 , axislist, destdis); // 4-axis interpolation command

//If the function returns a non-zero value, it means the transmission failed, the buffer may be full, and you should resend.

while (iresult != 0 )

{

iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4 , axislist, destdis);

System.Threading.Thread.Sleep(1); // 1 millisecond

}

//Fourth segment interpolation movement

destdis[ 0 ] = Convert.ToSingle(destdis4_X.Text);

destdis[ 1 ] = Convert.ToSingle(destdis4_Y.Text);

destdis[ 2 ] = Convert.ToSingle(destdis4_Z.Text);

destdis[ 3 ] = Convert.ToSingle(destdis4_U.Text);

iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4 , axislist, destdis); // 4-axis interpolation command

//If the function returns a non-zero value, it means the transmission failed, the buffer may be full, and you should resend.

while (iresult != 0)

{

iresult = zmcaux.ZAux_Direct_MoveAbs(g_handle, 4 , axislist, destdis);

System.Threading.Thread.Sleep( 1 ); // 1 millisecond

}

}

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

//Stop moving

private void button_stop_Click ( object sender, EventArgs e)

{

//Cancel spindle motion

zmcaux.ZAux_Direct_Single_Cancel(g_handle, 0, 2);

}

7. Zero the axis coordinates.

//Reset coordinates

private void button_zero_Click ( object sender, EventArgs e)

{

if (g_handle == (IntPtr) 0 )

{

MessageBox.Show( "Not linked to controller!", "Prompt" );

}

else

{

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

{

zmcaux.ZAux_Direct_SetDpos(g_handle, i, 0 );

}

}

}

8. Compile and run the demonstration.

Compile and run the teaching examples, and simultaneously connect to the controller via ZDevelop software to monitor the axis parameters of motion control.

9. Position waveform with continuous interpolation and automatic chamfering.

10. Speed ​​waveform without continuous interpolation.

11. Speed ​​waveform with continuous interpolation and appropriate corner deceleration.

This concludes our tutorial on "Motion Control Card Application Development Tutorial in C#" for Zheng Motion Technology. For more learning videos and articles, please follow our WeChat Official Account "Zheng 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 132CM Luisa Silicone Doll

Height: 132 Silicone Weight: 28kg Shoulder Width: 36cm Bust/Waist/Hip: 60/58/76cm Oral Depth: N/A Vaginal Depth: 3-15cm...

Articles 2026-02-22