XPCIE1032H Functionality Overview
The XPCIE1032H is a PCI Express-based EtherCAT bus motion control card, offering optional 6-64 axis motion control and supporting multiple high-speed digital inputs and outputs. It easily achieves multi-axis synchronous control and high-speed data transmission. The XPCIE1032H integrates powerful motion control functions, combined with the MotionRT7 real-time motion control soft core, solving the pain point of non-real-time development in high-speed, high-precision applications using PC Windows. Its command interaction speed is 10 times faster than traditional PCI/PCIe.
The XPCIE1032H supports PWM and PSO functions, and features 16 inputs and 16 outputs of general-purpose I/O ports. All output ports are high-speed outputs, configurable as either 4 PWM outputs or 16 high-speed PSO hardware compare outputs. The input ports include 8 high-speed inputs, configurable as either 4 high-speed color mark latches or 2 encoder inputs.
The XPCIE1032H is equipped with the MotionRT7 real-time kernel and uses the local LOCAL interface for connection. Through high-speed intra-kernel interaction, it can achieve faster instruction interaction, with the interaction time for a single instruction or multiple instructions reaching about 3-5us.
The combination of XPCIE1032H and the MotionRT7 real-time kernel offers the following advantages:
1. Supports development using multiple host computer languages; all product series can call the same API function library.
2. Utilizing intra-core interaction, motion commands can be invoked rapidly, with response times down to the microsecond level, 10 times faster than traditional PCI/PCIe;
3. Solves the problem of non-real-time performance of traditional PCI/PCIe motion control cards in Windows environments;
4. Supports 1D/2D/3D PSO (high-speed hardware position comparison output), suitable for applications such as vision-based aerial photography, precision dispensing, and laser energy control;
5. Provides a high-speed input interface for easy position latching;
6. Supports hybrid linkage and hybrid interpolation of EtherCAT bus and pulse output.
➜ When developing projects using XPCIE1032H and MotionRT7, the following steps are typically required:
1. Install the driver to recognize the XPCIE1032H;
2. Open and execute the file "MotionRT710.exe" to configure parameters and run the real-time motion control kernel;
3. Connect to the controller using ZDevelop software for parameter monitoring. Please use the PCI/LOCAL connection method and ensure that the ZDevelop software version is 3.10 or higher.
4. Complete the development of the control program and connect it to the motion control card via a local link to achieve real-time motion control.
➜ Comparison of test data results with traditional PCI/PCIe cards and PLCs:
The test results show that the XPCIE1032H motion control card, paired with the MotionRT7 real-time motion control kernel, exhibits very stable command interaction efficiency in LOCAL linking (internal kernel interaction). Even when the number of tests increased from 10,000 to 100,000, the interaction time for single and multiple commands remained relatively stable, making it highly suitable for high-speed, high-precision applications. XPCIE1032H control card installation.
§ Turn off the computer power.
§ Open the computer case, select an unused XPC I/O slot, and use a screwdriver to remove the corresponding baffle strip.
Insert the motion control card into the slot and tighten the fixing screws on the baffle strip.
For XPCIE1032H driver installation and connection establishment, please refer to the previous article "EtherCAT Ultra-High-Speed Real-Time Motion Control Card XPCIE1032H Host Computer C# Development (Part 1): Driver Installation and Connection Establishment".
I. Creating a new C# project (VS2022)
Go to the download center on the official website of Zheng Sports Technology and select the required platform library file.
Download link: http://www.zmotion.com.cn/download_list_21.html
Extract the downloaded installation package and locate "Zmcaux.cs", "zauxdll.dll", and "zmotion.dll", then place them into your project file.
1. Place "Zmcaux.cs" in the project root directory, at the same level as the bin directory.
2. "zauxdll.dll" and "zmotion.dll" are placed in bin -> Debug.
Open the newly created project file in Visual Studio. In the Solution Explorer on the right, click "Show All", select the project, right-click and select "Add" -> "Existing Item", then select the zmcaux.cs file and add it to the project.
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.
II. Introduction to Relevant PC Functions For details on the relevant PC functions, please refer to "ZMotion PC Function Library Programming Manual V2.1.1".
Other basic axis parameter related PC functions:
In the form design interface, find the controls you need and drag them onto the form to design the UI. The design effect is shown below.
III. Related Procedures and Design Ideas This example uses an XPLCIE1032H CPU running on the MotionRT7 real-time kernel, connected to a Panasonic servo driver as node 0 via the EthereCAT bus port, as shown in the following figure:
The basic program (bus initialization script file) that accompanies the example is as follows. Users can configure the number of bus nodes, driver PDO and other parameters according to actual needs (the PDO list in the example is configured to 18, and the list also contains a digital dictionary of 607A-cycle position, 60FF-cycle speed and 6071-cycle torque, so it can support switching between the three bus modes).
To configure the PDO list, open the zbasic programming manual and search for the DRIVE_PROFILE instruction.
'ECAT bus initialization GLOBAL CONST BUS_TYPE = 0 'Bus type.' This can be used by the host computer to distinguish the current bus type. GLOBAL CONST Bus_Slot = 0 'Slot number 0 (default 0 for single bus controller) GLOBAL CONST Bus_AxisStart = 0 'Starting axis number of the bus axis GLOBAL CONST Bus_NodeNum = 1 'Number of bus configuration nodes, used to determine whether the actual number of detected slave stations is consistent GLOBAL MAX_AXISNUM 'Maximum number of axes MAX_AXISNUM = SYS_ZFEATURE(0) GLOBAL Bus_InitStatus 'Bus initialization completion status Bus_InitStatus = -1 GLOBAL Bus_TotalAxisnum 'Check the total number of axes scanned DELAY(3000) 'Delay 3S to wait for the driver to power on. The power-on time of different drivers is different. Adjust the delay according to the driver. "Bus communication cycle:", SERVO_PERIOD,"us" Ecat_Init() 'Initialize ECAT bus ENDGLOBAL SUB Ecat_Init() local Node_Num,Temp_Axis,Drive_Vender,Drive_Device,Drive_Alias RAPIDSTOP(2) for i=0 to SYS_ZFEATURE(0) - 1 'Initialize and restore axis type AXIS_ENABLE(i) = 0 ATYPE(i) = 0 DELAY(20) next Bus_InitStatus = -1 Bus_TotalAxisnum = 0 SLOT_STOP(Bus_Slot) DELAY(200) SLOT_SCAN(Bus_Slot) 'Scan the bus if return then 'Bus scan successful,'"Number of connected slave devices:" NODE_COUNT(Bus_Slot) 'Determine if the number of bus detected is the actual number of wires connected if NODE_COUNT(Bus_Slot) <> Bus_NodeNum then 'The number of scanned nodes is inconsistent with the number configured in the program!' "Configuration quantity:"Bus_NodeNum, "Detection quantity:"NODE_COUNT(Bus_Slot) Bus_InitStatus = 0 'Initialization failed. Alarm prompt endif 'Start mapping axis number for Node_Num = 0 to NODE_COUNT(Bus_Slot)-1 'Traverse all scanned slave nodes Drive_Vender = NODE_INFO(Bus_Slot,Node_Num,0) 'Read drive manufacturer Drive_Device = NODE_INFO(Bus_Slot,Node_Num,1) 'Read device number Drive_Alias = NODE_INFO(Bus_Slot,Node_Num,3) 'Read device DIP switch ID if NODE_AXIS_COUNT(Bus_Slot,Node_Num) <> 0 then 'Check if the current node has a motor for j = 0 to NODE_AXIS_COUNT(Bus_Slot,Node_Num) - 1 'Loop through and configure axis parameters according to the number of motors connected to the node (for a multi-drive system) Temp_Axis = Bus_AxisStart + Bus_TotalAxisnum 'Assign axis numbers in NODE order BASE(Temp_Axis) AXIS_ADDRESS = Bus_TotalAxisnum+1 'Map axis number ATYPE = 65 'Set control mode 65-position 66-speed 67-torque DRIVE_PROFILE = 18 'Driver PDO can be set to mode 18 DISABLE_GROUP(Temp_Axis) 'Group each axis separately Bus_TotalAxisnum = Bus_TotalAxisnum+1 'Total number of axes +1 next endif next 'Axis number mapping complete,'"Total number of axes connected:"Bus_TotalAxisnum WA 200 SLOT_START(Bus_Slot) 'Start bus if return then WDOG = 1 'Enable main switch?"Start clearing drive errors" for i = Bus_AxisStart to Bus_AxisStart + Bus_TotalAxisnum - 1 BASE(i) DRIVE_CLEAR(0) DELAY 50 "Driver error clearing complete" DATUM(0) 'Clear controller axis status error" WA 100 '"Axis enable" AXIS_ENABLE = 1 next Bus_InitStatus = 1 'Axis enable complete' 'Bus start successful' else 'Bus start failed' Bus_InitStatus = 0 endif else 'Bus scan failed' Bus_InitStatus = 0 endif ENDSUB
1. Connect to the motion control card via a local link.
private void Connect_Button_Click(object sender, EventArgs e){ if (g_handle == (IntPtr)0) { DisConnect_Button_Click(sender, e); } // MotionRT7 connects to the controller via local connection zmcaux.ZAux_FastOpen(5, "local", 1000, out g_handle); if (g_handle != (IntPtr)0) { this.Text = "Connected"; timer1.Enabled = true; // Start the timer after successful connection Connect_Button.BackColor = Color.Green; MessageBox.Show("Connection successful"); } else { MessageBox.Show("Connection failed, please select the correct LOCAL!"); }}
2. Select the edited BAS script file and download it to the controller RAM (this process will not be saved if power is lost). Note: After downloading, the BAS program will be executed automatically to initialize the bus.
private void BasDownLoad_Button_Click(object sender, EventArgs e){ if (g_handle == (IntPtr)0) { MessageBox.Show("Not linked to controller!", "Prompt"); } else { int tmpret = 0; string strFilePath; // Display a standard dialog box prompting the user to open the desired .bas file OpenFileDialog openFileDialog1 = new OpenFileDialog(); openFileDialog1.InitialDirectory = "\\"; openFileDialog1.Filter = "Configuration file (*.bas)|*.bas"; openFileDialog1.RestoreDirectory = true; openFileDialog1.FilterIndex = 1; // Open the configuration file if (openFileDialog1.ShowDialog() == DialogResult.OK) { strFilePath = openFileDialog1.FileName; // Download to RAM. After downloading, the .bas program will automatically run once to perform bus initialization tmpret = zmcaux.ZAux_BasDown(g_handle, strFilePath, 0);
if (tmpret != 0) { MessageBox.Show("File download failed!", "Prompt"); } else { DownLoadFlag = true; // Update the file download flag MessageBox.Show("File download successful!", "Prompt"); } } }
3. After the initialization program is executed, the ZAux_Direct_GetUserVar function interface can be used to read the variables defined by the basic program. In this case, the variables obtained are the number of axes mapped during bus initialization, the starting axis number of bus initialization, and the bus initialization completion status.
GLOBAL CONST Bus_AxisStart 'Starting axis number of the bus axis' GLOBAL Bus_InitStatus 'Bus initialization completion status' GLOBAL Bus_TotalAxisnum 'Check the total number of axes scanned'
Use a timer to update bus initialization information such as the number of bus axes, the starting axis number, and the initialization status.
private void Update_EcatInitMessage(){ // Read basic program-defined variables -- total number of axes during bus initialization zmcaux.ZAux_Direct_GetUserVar(g_handle, "Bus_TotalAxisnum", ref EcatAxisNum); // Read basic program-defined variables -- bus start axis number during bus initialization zmcaux.ZAux_Direct_GetUserVar(g_handle, "Bus_AxisStart", ref EcatStartAxisNum); // Read basic program-defined variables -- bus initialization status zmcaux.ZAux_Direct_GetUserVar(g_handle, "Bus_InitStatus", ref EcatInitStatus);
// Refresh the interface bus initialization information if (EcatInitStatus == 1 && DownLoadFlag == true) { BusAxisNum_Label.Text = "Number of bus axes: " + EcatAxisNum.ToString(); BusStartAxis_Label.Text = "Starting axis: " + EcatStartAxisNum.ToString(); InitState_Label.Text = "Initialization status: Success"; } else if(EcatInitStatus == 0 && DownLoadFlag == true) { BusAxisNum_Label.Text = "Number of bus axes: " + EcatAxisNum.ToString(); BusStartAxis_Label.Text = "Starting axis: " + EcatStartAxisNum.ToString(); InitState_Label.Text = "Initialization status: Failed"; } else { InitState_Label.Text = "Initialization status: Incomplete"; }}
4. Add functions such as ZAux_Direct_GetUnits to the timer to monitor and provide feedback on the axis's pulse equivalent, running speed, acceleration, deceleration, axis type, DPOS, MPOS, axis status, and axis motion status in real time.
private void Update_AxisPara(){ int CurAxisAtype = 0; // Current axis type int CurAxisIdle = 0; // Current axis motion completion flag int CurAxisStatus = 0; // Current axis status float CurAxisDpos = 0; // Current axis planned position (DPOS) float CurAxisMpos = 0; // Current axis feedback position (MPOS) float CurAxisUnits = 0; // Current axis pulse equivalent float CurAxisSpeed = 0; // Current axis running speed float CurAxisAccel = 0; // Current axis acceleration float CurAxisDecel = 0; // Current axis deceleration
if (DownLoadFlag == true) { // Update the current axis of motion MoveAxis = Convert.ToInt32(AxisNum_Value.Text); // Read the pulse equivalent of the current axis zmcaux.ZAux_Direct_GetUnits(g_handle, MoveAxis, ref CurAxisUnits); // Read the running speed of the current axis zmcaux.ZAux_Direct_GetSpeed(g_handle, MoveAxis, ref CurAxisSpeed); // Read the acceleration of the current axis zmcaux.ZAux_Direct_GetAccel(g_handle, MoveAxis, ref CurAxisAccel); // Read the deceleration of the current axis zmcaux.ZAux_Direct_GetDecel(g_handle, MoveAxis, ref CurAxisDecel); // Read the axis type of the current axis zmcaux.ZAux_Direct_GetAtype(g_handle, MoveAxis, ref `CurAxisAtype);` // Reads the planned position (DPOS) of the current axis. `zmcaux.ZAux_Direct_GetDpos(g_handle, MoveAxis, ref CurAxisDpos);` // Reads the feedback position (MPOS) of the current axis. `zmcaux.ZAux_Direct_GetMpos(g_handle, MoveAxis, ref CurAxisMpos);` // Reads whether the current axis has completed its motion. `zmcaux.ZAux_Direct_GetIfIdle(g_handle, MoveAxis, ref CurAxisIdle);` // Reads the axis status of the current axis. `zmcaux.ZAux_Direct_GetAxisStatus(g_handle, MoveAxis, ref CurAxisStatus);`
// Refresh axis parameter information on the interface DPOS_Label.Text = "DPOS position: " + CurAxisDpos; MPOS_Label.Text = "MPOS position: " + CurAxisMpos; AxisState_Label.Text = "Axis status: " + CurAxisStatus; // Refresh motion end information if (CurAxisIdle == 0) { Idle_Label.Text = "Motion status: In motion"; } else { Idle_Label.Text = "Motion status: Stopped"; } // Refresh axis type information if (CurAxisAtype == 65) { AxisAtype_Label.Text = "Axis type: 65(CSP)"; } else if (CurAxisAtype == 66) { AxisAtype_Label.Text = "Axis type: 66(CSV)"; } else if (CurAxisAtype == 67) { AxisAtype_Label.Text = "Axis type: 67(CST)"; } else { AxisAtype_Label.Text = "Axis type: " + CurAxisAtype; } } }
5. When PDO includes 607A, ATYPE can be set to 65, in periodic position mode, and motion commands are used to control the motor movement.
The pulse equivalent, running speed, acceleration, and deceleration parameters of the axis can be set through the TextChanged event (an event triggered by changing the text property) of the text control.
// Pulse equivalent change private void Units_Value_TextChanged(object sender, EventArgs e){ // Set the pulse equivalent of the axis zmcaux.ZAux_Direct_SetUnits(g_handle, MoveAxis, Convert.ToSingle(Units_Value.Text));}// Speed change private void Speed_Value_TextChanged(object sender, EventArgs e){ // Set the speed of the axis zmcaux.ZAux_Direct_SetSpeed(g_handle, MoveAxis, Convert.ToSingle(Speed_Value.Text));}// Acceleration change private void Accel_Value_TextChanged(object sender, EventArgs e){ // Set the acceleration of the axis zmcaux.ZAux_Direct_SetAccel(g_handle, MoveAxis, Convert.ToSingle(Accel_Value.Text));}// Deceleration change private void Decel_Value_TextChanged(object sender, EventArgs e){ // Set the axis deceleration zmcaux.ZAux_Direct_SetDecel(g_handle, MoveAxis, Convert.ToSingle(Decel_Value.Text));}
After setting the basic parameters of the axis, you can call the single-axis continuous motion function ZAux_Direct_Single_Vmove through the MouseDown event of the button control (which occurs when the mouse is over the component and pressed), and set the third parameter of the function to 1 (positive) to make the motor move continuously in the positive direction; you can call the single-axis stop motion function ZAux_Direct_Single_Cancel through the MouseUp event of the button control (which occurs when the mouse is over the component and released), and make the motor move to stop.
Similarly, for negative direction movement, simply set the third parameter of the ZAux_Direct_Single_Vmove function instruction to -1 (negative direction) to make the motor move continuously in the negative direction.
// Positive continuous motion private void PosiTive_Button_MouseDown(object sender, MouseEventArgs e){ // Single-axis continuous motion -- positive zmcaux.ZAux_Direct_Single_Vmove(g_handle, MoveAxis, 1);}// Positive stop private void PosiTive_Button_MouseUp(object sender, MouseEventArgs e){ // Single-axis stop motion zmcaux.ZAux_Direct_Single_Cancel(g_handle, MoveAxis, 2);}// Negative continuous motion private void NegaTive_Button_MouseDown(object sender, MouseEventArgs e){ // Single-axis continuous motion -- negative zmcaux.ZAux_Direct_Single_Vmove(g_handle, MoveAxis, -1);}// Negative stop private void NegaTive_Button_MouseUp(object sender, MouseEventArgs e){ // Single-axis continuous motion -- negative zmcaux.ZAux_Direct_Single_Vmove(g_handle, MoveAxis, -1);} e){ //Single-axis motion stop zmcaux.ZAux_Direct_Single_Cancel(g_handle, MoveAxis, 2);}
6. When PDO contains 60FF, ATYPE can be set to 66, in cycle speed mode, limiting the maximum torque. The DAC command controls the motor to run at the set speed. There are two speed units: pulses/s and R/MIN, determined by the driver. When using this method, start with a smaller value, observe the motor speed, and then increase it. Specifically, setting the DAC value to 0 stops the motor; a negative DAC value causes the motor to rotate in the opposite direction.
private void SpeedValue_Config_Button_Click(object sender, EventArgs e){ int ret1, ret2; // Set the DAC value for periodic speed mode ret1 = zmcaux.ZAux_Direct_SetDAC(g_handle, (uint)MoveAxis, Convert.ToSingle(CSV_Value.Text)); // Limit torque for periodic speed mode ret2 = zmcaux.ZAux_BusCmd_SetMaxDriveTorque(g_handle, (uint)MoveAxis, Convert.ToInt32(TorqueLimit_Value.Text)); if (ret1 == 0 && ret2 == 0) { MessageBox.Show("Setting successful!", "Prompt"); } else { MessageBox.Show("Setting failed!", "Prompt"); }}
7. When PDO includes 6071, ATYPE can be set to 67, activating the periodic torque mode and limiting the maximum speed. In this mode, DAC commands are used to control the motor to operate at the set torque value. The DAC value ranges from 0-1000, corresponding to 0-100% of the 6071 setting value. For example, DAC=10 means the motor torque is 1% of the 6071 value. Specifically, setting the DAC value to 0 stops the motor; a negative DAC value causes the motor to rotate in the opposite direction.
In CST cyclic torque mode, the torque setting should be gradually increased from small to large, and the speed limit should be properly implemented inside the drive to prevent the vehicle from overrunning and causing a safety accident.
private void CST_Set_Button_Click(object sender, EventArgs e){ if (g_handle == (IntPtr)0) { MessageBox.Show("Not linked to controller!", "Prompt"); return; } int ret1,ret2,ret3; // Set the maximum torque of the bus axis in periodic torque mode ret1 = zmcaux.ZAux_BusCmd_SetMaxDriveTorque(g_handle, (uint)MoveAxis, Convert.ToInt32(MaxTorque_Value.Text)); // Set the target torque of the bus axis in periodic torque mode ret2 = zmcaux.ZAux_Direct_SetDAC(g_handle, (uint)MoveAxis, Convert.ToSingle(TargetTorque_Value.Text)); // Speed limit in periodic torque mode -- the maximum speed limit of the Huichuan driver is 607Fh ret3 = `zmcaux.ZAux_BusCmd_SDOWriteAxis(g_handle, (uint)MoveAxis, 0x607F, 0, 7, Convert.ToInt32(SpeedLimit_Value.Text)); if (ret1 == 0 && ret2 == 0 && ret3 == 0) { MessageBox.Show("Setting successful!", "Prompt"); } else { MessageBox.Show("Setting failed!", "Prompt"); }}`
8. Use the CheckedChanged event (an event that occurs when the checked property changes) of the radio button control to set the axis type for the switching mode and set DAC to 0 to prevent accidents from occurring during actual processing.
In speed mode, the maximum torque is limited, and in torque mode, the maximum speed is typically limited by reading and writing driver parameters via SDO.
// Periodic position mode private void CSP_RadioButton_CheckedChanged(object sender, EventArgs e){ if (g_handle == (IntPtr)0) { MessageBox.Show("Not linked to controller!", "Prompt"); return; } // Set axis type to 65-periodic position mode zmcaux.ZAux_Direct_SetAtype(g_handle, MoveAxis, 65); // Set DAC to 0 to prevent accidents when switching to periodic speed mode or periodic torque mode zmcaux.ZAux_Direct_SetDAC(g_handle, (uint)MoveAxis, 0);}// Periodic speed mode private void CSV_RadioButton_CheckedChanged(object sender, EventArgs e){ if (g_handle == (IntPtr)0) { MessageBox.Show("Not linked to controller!", "Prompt"); return; } // Set the axis type to 66-cycle speed mode zmcaux.ZAux_Direct_SetAtype(g_handle, MoveAxis, 66); // Set DAC to 0 to prevent accidents when switching to cycle torque mode zmcaux.ZAux_Direct_SetDAC(g_handle, (uint)MoveAxis, 0);}// Cycle torque mode private void CST_RadioButton_CheckedChanged(object sender, EventArgs e){ if (g_handle == (IntPtr)0) { MessageBox.Show("Not linked to controller!", "Prompt"); return; } // Set the axis type to 67-cycle torque mode zmcaux.ZAux_Direct_SetAtype(g_handle, MoveAxis, 67); // Set DAC to 0 to prevent accidents when switching to cycle speed mode zmcaux.ZAux_Direct_SetDAC(g_handle, (uint)MoveAxis, 0);}
IV. Running Results 1. The running results are shown in the following figure.
(1) Results of running in periodic position mode.
(2) Results of operation in cycle speed mode.
(3) Results of operation in periodic torque mode.
Full code download address
▼
This concludes our presentation on the third part of developing the EtherCAT ultra-high-speed real-time motion control card XPCIE1032H in C#: switching between EtherCAT bus CSP, CSV, and CST modes.
For more exciting content, please follow the "Zheng Motion Assistant" WeChat official account. For related development environment and example code, please contact Zheng Motion's technical sales engineer: 400-089-8936.
This article is original content from Zheng Motion Technology. We welcome everyone to reprint it for mutual learning and to jointly improve China's intelligent manufacturing level. Copyright belongs to Zheng Motion Technology. Please indicate the source if you reprint this article.