Share this

Open-source laser galvanometer motion controller: Rapid development in C++

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

Today, Zheng Motion Technology will share with you the C++ development of the ZMC408SCAN open laser galvanometer motion controller to realize laser galvanometer marking. You can scan the QR code at the end of the article to get the example source code.

In addition to C++, it also supports the use of other host computer software for development. The host computer program requires the dynamic library "zmotion.dll" to run. When developing and debugging the host computer, the ZDevelop software can be connected to the controller at the same time to assist in debugging.

01. Introduction to ZMC408SCAN Controller

The ZMC408SCAN is a newly launched open-source laser galvanometer motion controller from Zheng Motion Technology, supporting the EtherCAT bus and designed specifically for industrial laser + galvanometer + motion control applications. It enables multi-axis联动 motion control via the EtherCAT bus and pulse axis interface.

The ZMC408SCAN supports communication interfaces such as ETHERNET, EtherCAT, USB, CAN, RS485, and RS232. Various expansion modules can be connected via CAN and EtherCAT buses to expand digital, analog, or motion axes.

0) { // Delay to turn off the light sprintf(tempbuff, "MOVEOP_DELAY = 0\nMOVE_DELAY(%f)\n",m_nLastDelay/1000); strcat(cmdbuff, tempbuff); } else { sprintf(tempbuff, "MOVEOP_DELAY = %f\n",m_nLastDelay/1000); strcat(cmdbuff, tempbuff); } // Turn off the light sprintf(tempbuff, "MOVE_OP(%d,OFF)\n",m_nLaserIO); strcat(cmdbuff, tempbuff); // Check the command length to send strcat(g_MoveStr,cmdbuff); Zscan_Z3pFile_Down();} IV. Final Effect First, click the drop-down box to select the controller IP, click Connect, set the laser parameters and motion parameters in sequence, enter the parameters for the trajectory, click Start Motion to draw a circular trajectory, and click Stop to end. The motion results were sampled using an oscilloscope in ZDevelop software: The laser first moves from another position to the starting position, then the laser is turned on 1ms in advance, completes a circular trajectory, and then the laser is turned off (with a delay before turning off). It then moves to the starting point of the next circular trajectory, turns on the laser (1ms in advance), completes another trajectory, and then turns off the laser (with a 5ms delay before turning off). This cycle repeats until the set number of rows and columns is reached (the stop button can also be clicked during the trajectory marking process). The trajectory in XY mode includes both circular marking trajectories and idle trajectories. This concludes our sharing of the Zheng Motion Technology Open Laser Galvanometer Motion Controller: Rapid C++ Development. For more exciting content, please follow the "Zheng Motion Assistant" WeChat official account. For related development environments and example code, please contact Zheng Motion Technology sales engineers: 400-089-8936. This article is original from Zheng Motion Technology. We welcome everyone to reprint it for mutual learning and to improve the level of intelligent manufacturing in China. Copyright belongs to Zheng Motion Technology. Please indicate the source if you reprint this article. Today, Zheng Motion Technology will share with you the C++ development of the ZMC408SCAN open laser galvanometer motion controller to achieve laser galvanometer marking. You can scan the QR code at the end of the article to obtain the example source code. Besides C++, it also supports development using other host computer software. The host computer program requires the dynamic library "zmotion.dll" to run. During host computer development and debugging, ZDevelop software can be connected to the controller simultaneously for auxiliary debugging. 01 Introduction to the ZMC408SCAN Controller The ZMC408SCAN is a newly launched open laser galvanometer motion controller from Zheng Motion Technology that supports the EtherCAT bus. It is designed specifically for industrial laser + galvanometer + motion control applications. Multi-axis linkage motion control can be achieved through the EtherCAT bus and pulse axis interface. The ZMC408SCAN supports communication interfaces such as ETHERNET, EtherCAT, USB, CAN, RS485, and RS232. Various expansion modules can be connected through the CAN and EtherCAT buses to expand digital, analog, or motion axes. (1) The ZMC408SCAN has a built-in high-precision PSO position synchronization output function. Even when deceleration is adjusted during the processing of rounded corners and curves, the laser output spacing can be kept constant in high-speed processing situations. (2) It supports laser galvanometer control and galvanometer feedback. It includes two galvanometer interfaces, supports 2D galvanometers and 3D galvanometers. With the MOVESCAN motion command without acceleration or deceleration, the galvanometer processing at corners is automatically delayed, achieving precise and efficient laser control and improving the productivity of laser processing equipment. (3) The laser on/off delay can be flexibly adjusted during movement through commands. It has a fast response, accurate control down to the microsecond level, and a simple setup process, which greatly shortens the parameter adjustment time for engineers. (4) It comes with a LASER laser control interface, supports IPG, YLR, YLS and other types of laser power supplies, and also has an EXIO expansion IO interface. Through a customized adapter board, it can flexibly control various mainstream lasers on the market. (5) It supports PC to control 16 ZMC408SCAN controllers to work simultaneously, forming a galvanometer array laser processing. (6) Onboard 4-channel high-speed differential pulse output, with 4-channel high-speed differential encoder feedback, supports EtherCAT bus driver control, supports 5-axis XYZAC interpolation, and supports mixed interpolation of galvanometer axis and motion axis. (7) Supports linear interpolation, arbitrary circular interpolation, spatial circular arc, helical interpolation, electronic cam, electronic gear, synchronous following, virtual axis setting and other motion control functions. 02 System Architecture The following figure is the reference architecture of ZMC408SCAN open laser controller, which supports control of various types of lasers. 03 Communication between host computer and controller The host computer and controller call the function library encapsulated by positive motion, providing many function library interfaces such as motion control and laser control. See the following figure for the system architecture of laser galvanometer. In this example, the controller is connected via EtherNET network port. The communication connection is established through the function ZAux_OpenEth(). The user can select the controller IP under the current network segment in the set interface to complete the connection. The controller's factory IP address is 192.168.0.11, see the following figure. 04 Laser Control I. Command Introduction Below are the interface functions used in our program, mainly including laser control and laser galvanometer control. The program can directly use the encapsulated interface functions to send commands to the controller. This example uses a FIBER laser and a 2D laser galvanometer, and uses the following function interfaces: § ZAux_Direct_MoveScanAbs: Multi-axis absolute linear interpolation SCAN motion of the galvanometer axis, without acceleration or deceleration. We use it here to control the movement of the galvanometer axis, fitting a circular trajectory in the form of small line segments; § ZAux_Direct_MoveOpDelay: Buffered output delay, setting the delay time to a negative number when turning on the light early; § ZAux_Direct_MoveDelay: Buffered output delay, used here to delay turning off the light. Laser Power Settings: Provides analog input ZAux_Direct_SetDA, PWM duty cycle ZAux_Direct_SetPwmDuty, and frequency ZAux_Direct_SetPwmFreq to control automatic delay at galvanometer axis corners: ZAux_Direct_SetCornerMode 1. Galvanometer axis linear interpolation ZAux_Direct_MoveScanAbs for absolute motion, ZAux_Direct_MoveScan for relative motion. 2. Sets the switch beam output state to 0 (off) and 1 (on). 3. Switch beam delay. 4. Positive delay time for advance/delay of the switch beam, negative delay time for advance switching beam. 5. Sets laser energy (power) by changing the analog output voltage value. 6. PWM duty cycle adjusts the laser frequency by setting the PWM duty cycle; this must be set before starting trajectory marking. 7. PWM frequency 8. Galvanometer axis corner delay 9. Corner delay start angle 10. Corner delay end angle II. Program Flow First, establish controller communication, obtain the connection handle, select the laser and set parameters. Then, edit the red light and laser port control switch, set motion parameters, process the trajectory parameters into small line segments, start the motion, and stop the motion. III. Main Program Display Initialize and define relevant variables, initialize axis parameters, configure the FIBER adapter board direction as output, and subsequent laser trajectory processing control is triggered by a button. Before motion, we need to set parameters such as idle speed, marking speed, switch light delay, trajectory circle radius, number of marking rows and columns, and circle center distance. At the start of motion, directly call these relevant parameters to execute. After obtaining the trajectory, call the file execution 3 times. 1. Initialize the 408 FIBER converter board pin definition. Different laser types define a different set of output ports. The output ports can be modified on the interface after selecting the laser type. 408 FIBER converter board parameter initialization program: · void CZmc_fontToMoveDlg::OnCbnSelchangeComboLaser(){ // TODO: Add control notification handler code here UpdateData(TRUE); if(m_nLaserType == FIBER_408) //408 FIBER converter board parameter settings{ char cmdbuffAck[2048] = ""; int iresult = ZAux_Execute(m_Handle,"EXIO_DIR(0, $8FFFF)",cmdbuffAck,2048); m_nEnableIO = 47; //Enable io m_nLaserIO = 8; //Out-of-field io m_nRedIO = 48; //Red light io m_nAout = 3; //Power io m_nPwmIo = 9; //Frequency io } else if(m_nLaserType == YLR_408) { m_nEnableIO = 31; // Enable io m_nLaserIO = 8; // Off io m_nRedIO = 32; // Red light io m_nAout = 2; // Power io m_nPwmIo = 9; // Frequency io } else if(m_nLaserType == YAG_408) // 408 YAG converter board parameter settings { char cmdbuffAck[2048] = ""; int iresult = ZAux_Execute(m_Handle,"EXIO_DIR(0, $AFBBF)",cmdbuffAck,2048); m_nEnableIO = 47; // Enable io m_nLaserIO = 8; // Off io m_nRedIO = 48; // Red light io m_nAout = 3; // Power io m_nPwmIo = 9; // Frequency io } else if(m_nLaserType == FIBER_504) //504 { m_nEnableIO = 5; //Enable IO m_nLaserIO = 6; //Output IO m_nRedIO = 28; //Red light IO m_nAout = 2; //Power IO m_nPwmIo = 7; //Frequency IO } UpdateData(FALSE);} 2. Set the corner delay and laser power, then call the motion execution, as shown in the following program. void CZmc_fontToMoveDlg::OnBnClickedBtnMove(){ // TODO: Add control notification handler code here UpdateData(TRUE); // Set corner deceleration This ZSMOOTH is the corner delay int iresult = ZAux_Direct_SetCornerMode(m_Handle,SCAN_AxisX,2); // Set precise output iresult = ZAux_Direct_SetParam(m_Handle,"AXIS_ZSET",SCAN_AxisX,3); // Set corner delay iresult = ZAux_Direct_SetZsmooth(m_Handle,SCAN_AxisX,m_nCorDelay); // Set the corner start angle, the deceleration time changes linearly between DecelAngle and StopAngle iresult = ZAux_Direct_SetDecelAngle(m_Handle,SCAN_AxisX,0); // Set the corner end angle iresult = ZAux_Direct_SetStopAngle(m_Handle,SCAN_AxisX,90/180*3.1415926); // Set laser power iresult = ZAux_Direct_SetDA(m_Handle,m_nAout,m_nAoutVal); // Set laser frequency iresult = ZAux_Direct_SetPwmDuty(m_Handle,m_nPwmIo,0.5); iresult = ZAux_Direct_SetPwmFreq(m_Handle,m_nPwmIo,m_nPwmFreq); // Get trajectory data, (0,0) is the circumscribed starting point of the circle, draw small circles with a radius of 5 with a spacing of 5*5 Cal_WorkData(m_fStartX, m_fStartY, m_nStepDis, m_nColNum, m_nRowNum, m_fRadius); Run_3FileMode();} 3. Converting arcs to small line segments involves converting our set arc trajectory into small line segments, storing them, and then loading and executing them in the form of three files. The program for converting an arc to a smaller line segment is as follows: · void CZmc_fontToMoveDlg::Cal_WorkData(float fStartX, float fStartY, float iStepDis, int iColNum, int iRowNum, float fRadius){ // Convert arc to smaller line segment int ilen = -1; double ArcX; double ArcY; // Get the conversion length of a single full circle int iret = ZMotionOptimize_TransArcSeges(m_Handle,fStartX - fRadius, fStartY, fStartX + fRadius, fStartY + 2 * fRadius, 0, -2 * PI, m_refDistance, &ArcX, &ArcY, &ilen); if (iret != 0 || ilen < 0) { CString StrErr; StrErr.Format("Failed to convert arc to smaller line segment error code: %d",iret); MessageBox(StrErr); return; } double *ArcToLineX; double *ArcToLineY; ArcToLineX = (double*)malloc(sizeof(double)*ilen); ArcToLineY = (double*)malloc(sizeof(double)*ilen); // Get data iret = ZMotionOptimize_TransArcSeges(m_Handle, fStartX - fRadius, fStartY, fStartX + fRadius, fStartY + 2 * fRadius, 0, -2 * PI, m_refDistance, ArcToLineX, ArcToLineY, &ilen); // Total length of the trajectory m_GraphTotalLen = ilen * iColNum * iRowNum; m_GraphData = (struct_GraphPos*)malloc(sizeof(struct_GraphPos)*m_GraphTotalLen); // Allocate memory // Fill in data int iAcr = 0; for (int icol = 0; icol < iColNum ; icol++) { for(int irow = 0 ;irow 4. Here the program completes the empty movement, and before the movement is completed, if the next motion instruction is to execute the trajectory movement, then turn on the laser in advance. · // Empty movement to the starting point of the marking point void CZmc_fontToMoveDlg::Zscan_Z3pFile_StartString(struct_GraphPos *iGraphData){ char cmdbuff[2048] = ""; char tempbuff[2048] = ""; // Generate command sprintf(tempbuff, "BASE(%d,%d)\n",SCAN_AxisX,SCAN_AxisY); // Set the marking axis strcat(cmdbuff, tempbuff); // Empty movement to the starting point sprintf(tempbuff, "FORCE_SPEED = %f\n",m_dEmpSpeed); // Set the empty movement speed strcat(cmdbuff, tempbuff); sprintf(tempbuff, "MOVESCANABS(%f,%f)\n",(*iGraphData).fposx,(*iGraphData).fposy); // Move strcat(cmdbuff, tempbuff); // Set early activation if (m_nStartDelay < 0) // Early activation { sprintf(tempbuff, "MOVEOP_DELAY = %f\n",m_nStartDelay/1000); strcat(cmdbuff, tempbuff); } else { sprintf(tempbuff, "MOVE_DELAY(%f)\n",m_nStartDelay/1000); strcat(cmdbuff, tempbuff); } // Activate activation sprintf(tempbuff, "MOVE_OP(%d,1)\nMOVE_DELAY(10)\nMOVE_OP(%d,1)\n",m_nEnableIO,m_nLaserIO); strcat(cmdbuff, tempbuff); // Check if the command length is sent strcat(g_MoveStr,cmdbuff); Zscan_Z3pFile_Down();} // Generate the marked line segment string void CZmc_fontToMoveDlg::Zscan_Z3pFile_LineString(struct_GraphPos *iGraphData){ char cmdbuff[2048] = ""; char tempbuff[2048] = ""; // Generate command // Move to the starting point sprintf(tempbuff, "FORCE_SPEED = %f\n",m_dSpeed); // Set the marking speed strcat(cmdbuff, tempbuff); sprintf(tempbuff, "MOVESCANABS(%f,%f)\n",(*iGraphData).fposx,(*iGraphData).fposy); // Move strcat(cmdbuff, tempbuff); // Check if the command length is sent strcat(g_MoveStr,cmdbuff); Zscan_Z3pFile_Down();} 5. Delayed laser shutdown is performed after the marking trajectory is completed, and the laser is turned off after a delay. The delayed laser shutdown program is as follows: · void CZmc_fontToMoveDlg::Zscan_Z3pFile_EndString(struct_GraphPos *iGraphData){ char cmdbuff[2048] = ""; char tempbuff[2048] = ""; // Generate command sprintf(tempbuff, "FORCE_SPEED = %f\n",m_dEmpSpeed); // Set empty movement speed strcat(cmdbuff, tempbuff); sprintf(tempbuff, "MOVESCANABS(%f,%f)\n",(*iGraphData).fposx,(*iGraphData).fposy); // Move strcat(cmdbuff, tempbuff); // Delayed laser shutdown if(m_nLastDelay >0) { // Delay to turn off the light sprintf(tempbuff, "MOVEOP_DELAY = 0\nMOVE_DELAY(%f)\n",m_nLastDelay/1000); strcat(cmdbuff, tempbuff); } else { sprintf(tempbuff, "MOVEOP_DELAY = %f\n",m_nLastDelay/1000); strcat(cmdbuff, tempbuff); } // Turn off the light sprintf(tempbuff, "MOVE_OP(%d,OFF)\n",m_nLaserIO); strcat(cmdbuff, tempbuff); // Check the command length to send strcat(g_MoveStr,cmdbuff); Zscan_Z3pFile_Down();} IV. Final Effect First, click the drop-down box to select the controller IP, click Connect, set the laser parameters and motion parameters in sequence, enter the parameters for the trajectory, click Start Motion to draw a circular trajectory, and click Stop to end. The motion results were sampled using an oscilloscope in ZDevelop software: The laser first moves from another position to the starting position, then the laser is turned on 1ms in advance, completes a circular trajectory, and then the laser is turned off (with a delay before turning off). It then moves to the starting point of the next circular trajectory, turns on the laser (1ms in advance), completes another trajectory, and then turns off the laser (with a 5ms delay before turning off). This cycle repeats until the set number of rows and columns is reached (the stop button can also be clicked during the trajectory marking process). The trajectory in XY mode includes both circular marking trajectories and idle trajectories. This concludes our sharing of the Zheng Motion Technology Open Laser Galvanometer Motion Controller: Rapid C++ Development. For more exciting content, please follow the "Zheng Motion Assistant" WeChat official account. For related development environments and example code, please contact Zheng Motion Technology sales engineers: 400-089-8936. This article is original from Zheng Motion Technology. We welcome everyone to reprint it for mutual learning and to improve China's intelligent manufacturing level. Copyright belongs to Zheng Motion Technology. Please indicate the source if you reprint it.

(1) The ZMC408SCAN has a built-in high-precision PSO position synchronization output function, which can keep the laser output spacing constant even when deceleration adjustment is made when machining fillets and curves, in high-speed machining situations;

(2) Supports laser galvanometer control and galvanometer feedback, including 2 galvanometer interfaces, supporting 2D galvanometers and 3D galvanometers. With the MOVESCAN motion command without acceleration or deceleration, the galvanometer processing at corners is automatically delayed, achieving precise and efficient laser control and improving the productivity of laser processing equipment;

(3) The laser on/off delay can be flexibly adjusted during movement via commands, with fast response, precise control down to the microsecond level, and simple setup process, greatly reducing the engineer's parameter adjustment time;

(4) It comes with a built-in LASER laser control interface, supporting laser power supplies of IPG, YLR, YLS and other types. It also has an EXIO expansion IO interface, which can flexibly control various mainstream lasers on the market through a customized adapter board;

(5) Supports simultaneous control of 16 ZMC408SCAN controllers by PC to form a laser processing system with a galvanometer array;

(6) It has 4 high-speed differential pulse outputs on board and 4 high-speed differential encoder feedbacks. It supports EtherCAT bus driver control, 5-axis XYZAC interpolation, and mixed interpolation of galvanometer axis and motion axis.

(7) Supports a variety of motion control functions such as linear interpolation, arbitrary circular interpolation, spatial circular arc, helical interpolation, electronic cam, electronic gear, synchronous following, and virtual axis setting.

02. System Architecture

The following diagram shows the reference architecture of the ZMC408SCAN open laser controller, which supports control of various types of lasers.

03. Communication between the host computer and the controller

The host computer and controller communicate by calling the pre-packaged function library of Zhengdong, which provides numerous function library interfaces such as motion control and laser control. The system architecture of the laser galvanometer is shown in the figure below.

This example uses the Ethernet port to connect to the controller. The communication connection is established through the function ZAux_OpenEth(). Users can select the controller IP under the current network segment in the configured interface to complete the connection. The controller's factory IP address is 192.168.0.11, as shown in the figure below.

04. Laser Control

I. Introduction to the Instructions

Below are the interface functions used in our program, which mainly include two parts: laser control and laser galvanometer control. The program can directly use the encapsulated interface functions to send commands to the controller.

This example uses a FIBER laser and a 2D laser galvanometer, and utilizes the following function interface:

§ ZAux_Direct_MoveScanAbs: Multi-axis absolute linear interpolation SCAN motion of the galvanometer axis, without acceleration or deceleration. We use it here to control the motion of the galvanometer axis, fitting a circular trajectory through small line segments;

§ ZAux_Direct_MoveOpDelay: Buffered output delay; sets the delay time to a negative number when turning on the light ahead of schedule.

§ ZAux_Direct_MoveDelay: Buffered output delay, which we use here to delay turning off the light.

Laser power settings: Automatic delay at the galvanometer axis corners can be controlled via analog quantities ZAux_Direct_SetDA, PWM duty cycle ZAux_Direct_SetPwmDuty, and frequency ZAux_Direct_SetPwmFreq.

ZAux_Direct_SetCornerMode

1. Linear interpolation of galvanometer axis

ZAux_Direct_MoveScanAbs represents absolute motion, while ZAux_Direct_MoveScan represents relative motion.

2. Set the switch light

Output status 0 is off, output status 1 is on.

3. Switching optical delay

4. Advance/delay switching of light

Positive time delays the switch, while negative time advances the switch.

5. Set the laser energy (power)

The laser energy is controlled by changing the voltage value of the analog output.

6. PWM duty cycle

The laser frequency is adjusted by setting the duty cycle of the PWM. This setting must be done before starting to draw the trajectory.

7. PWM frequency

8. Mirror axis corner delay

9. Corner delay start angle

10. Corner delay end angle

II. Procedure Flow

First, establish controller communication, obtain the connection handle, select the laser and set the parameters. Then, edit the red light and laser port control switch, set the motion parameters, process the trajectory parameters into small line segments, start the motion, and stop the motion.

III. Main Program Demonstration

Initialize the relevant variables, initialize the axis parameters, configure the direction of the FIBER adapter plate as the output, and then control the subsequent laser trajectory processing by the button.

Before starting the motion, we need to set parameters such as the idle speed, marking speed, on/off optical delay, trajectory circle radius, number of marking rows and columns, and circle center distance. Once the motion begins, these parameters are called directly for execution. After acquiring the trajectory, the file is executed three times.

1. Initialize the pin definitions of the 408FIBER converter board. Different laser types define a different set of output ports, which can be modified on the interface after selecting the laser type.

408 FIBER converter board parameter initialization procedure:

·

void CZmc_fontToMoveDlg::OnCbnSelchangeComboLaser(){ // TODO: Add control notification handler code here UpdateData(TRUE); if(m_nLaserType == FIBER_408) //408 FIBER converter board parameter settings { char cmdbuffAck[2048] = ""; int iresult = ZAux_Execute(m_Handle,"EXIO_DIR(0, $8FFFF)",cmdbuffAck,2048); m_nEnableIO = 47; //Enable io m_nLaserIO = 8; //Out-of-gate io m_nRedIO = 48; //Red light io m_nAout = 3; //Power io m_nPwmIo = 9; //Frequency io } else if(m_nLaserType == YLR_408) { m_nEnableIO = 31; //Enable io m_nLaserIO = 8; //Exit io m_nRedIO = 32; //Red light io m_nAout = 2; //Power io m_nPwmIo = 9; //Frequency io } else if(m_nLaserType == YAG_408) //408 YAG converter board parameter settings { char cmdbuffAck[2048] = ""; int iresult = ZAux_Execute(m_Handle,"EXIO_DIR(0, $AFBBF)",cmdbuffAck,2048); m_nEnableIO = 47; //Enable io m_nLaserIO = 8; //Exit io m_nRedIO = 48; //Red light io m_nAout = 3; //Power io m_nPwmIo = 9; //Frequency io } else if(m_nLaserType == FIBER_504) //504 { m_nEnableIO = 5; // Enable I/O m_nLaserIO = 6; // Exit I/O m_nRedIO = 28; // Red light I/O m_nAout = 2; // Power I/O m_nPwmIo = 7; // Frequency I/O } UpdateData(FALSE);}

2. Set the corner delay and laser power, then call the motion execution, as shown in the following program.

·

void CZmc_fontToMoveDlg::OnBnClickedBtnMove(){ // TODO: Add control notification handler code here UpdateData(TRUE); // Set corner deceleration This ZSMOOTH is the corner delay int iresult = ZAux_Direct_SetCornerMode(m_Handle,SCAN_AxisX,2); // Set precise output iresult = ZAux_Direct_SetParam(m_Handle,"AXIS_ZSET",SCAN_AxisX,3); // Set corner delay iresult = ZAux_Direct_SetZsmooth(m_Handle,SCAN_AxisX,m_nCorDelay); // Set the corner start angle, the deceleration time changes linearly between DecelAngle and StopAngle iresult = ZAux_Direct_SetDecelAngle(m_Handle,SCAN_AxisX,0); // Set the corner end angle iresult = ZAux_Direct_SetStopAngle(m_Handle,SCAN_AxisX,90/180*3.1415926); // Set laser power iresult = ZAux_Direct_SetDA(m_Handle,m_nAout,m_nAoutVal); // Set laser frequency iresult = ZAux_Direct_SetPwmDuty(m_Handle,m_nPwmIo,0.5); iresult = ZAux_Direct_SetPwmFreq(m_Handle,m_nPwmIo,m_nPwmFreq); // Get trajectory data, (0,0) is the circumscribed starting point of the circle, draw small circles with a radius of 5 with a spacing of 5*5 Cal_WorkData(m_fStartX, m_fStartY, m_nStepDis, m_nColNum, m_nRowNum, m_fRadius); Run_3FileMode();}

3. Converting arcs to small line segments involves converting our set arc trajectory into small line segments, storing them, and then loading and executing them in the form of three files.

The program for converting an arc into a smaller line segment is as follows:

·

void CZmc_fontToMoveDlg::Cal_WorkData(float fStartX, float fStartY, float iStepDis, int iColNum, int iRowNum, float fRadius){ // Convert arc to line segment int ilen = -1; double ArcX; double ArcY; // Get the conversion length of a single full circle int iret = ZMotionOptimize_TransArcSeges(m_Handle,fStartX - fRadius, fStartY, fStartX + fRadius, fStartY + 2 * fRadius, 0, -2 * PI, m_refDistance, &ArcX, &ArcY, &ilen); if (iret != 0 || ilen < 0) { CString StrErr; StrErr.Format("Failed to convert arc to line segment error code: %d",iret); MessageBox(StrErr); return; } double *ArcToLineX; double *ArcToLineY; ArcToLineX = (double*)malloc(sizeof(double)*ilen); ArcToLineY = (double*)malloc(sizeof(double)*ilen); // Get data iret = ZMotionOptimize_TransArcSeges(m_Handle, fStartX - fRadius, fStartY, fStartX + fRadius, fStartY + 2 * fRadius, 0, -2 * PI, m_refDistance, ArcToLineX, ArcToLineY, &ilen); // Total length of the trajectory m_GraphTotalLen = ilen * iColNum * iRowNum; m_GraphData = (struct_GraphPos*)malloc(sizeof(struct_GraphPos)*m_GraphTotalLen); // Allocate memory // Fill in data int iAcr = 0; for (int icol = 0; icol < iColNum ; icol++) { for(int irow = 0 irow

4. Here, the program completes the empty movement. Before the movement is completed, if the next motion command is a trajectory movement, then the laser will be turned on in advance.

·

// Move to the starting point of the marker void CZmc_fontToMoveDlg::Zscan_Z3pFile_StartString(struct_GraphPos *iGraphData){ char cmdbuff[2048] = ""; char tempbuff[2048] = ""; // Generate command sprintf(tempbuff, "BASE(%d,%d)\n",SCAN_AxisX,SCAN_AxisY); // Set the marker axis strcat(cmdbuff, tempbuff); // Move to the starting point sprintf(tempbuff, "FORCE_SPEED = %f\n",m_dEmpSpeed); // Set the speed of the move strcat(cmdbuff, tempbuff); sprintf(tempbuff, "MOVESCANABS(%f,%f)\n",(*iGraphData).fposx,(*iGraphData).fposy); // Move strcat(cmdbuff, tempbuff); // Set early activation if (m_nStartDelay < 0) // Early activation { sprintf(tempbuff, "MOVEOP_DELAY = %f\n",m_nStartDelay/1000); strcat(cmdbuff, tempbuff); } else { sprintf(tempbuff, "MOVE_DELAY(%f)\n",m_nStartDelay/1000); strcat(cmdbuff, tempbuff); } // Activate activation sprintf(tempbuff, "MOVE_OP(%d,1)\nMOVE_DELAY(10)\nMOVE_OP(%d,1)\n",m_nEnableIO,m_nLaserIO); strcat(cmdbuff, tempbuff); // Check command length to send strcat(g_MoveStr,cmdbuff); Zscan_Z3pFile_Down();}

// Generate the marked line segment string void CZmc_fontToMoveDlg::Zscan_Z3pFile_LineString(struct_GraphPos *iGraphData){ char cmdbuff[2048] = ""; char tempbuff[2048] = ""; // Generate command // Move to the starting point sprintf(tempbuff, "FORCE_SPEED = %f\n",m_dSpeed); // Set the marking speed strcat(cmdbuff, tempbuff); sprintf(tempbuff, "MOVESCANABS(%f,%f)\n",(*iGraphData).fposx,(*iGraphData).fposy); // Move strcat(cmdbuff, tempbuff); // Check the command length to send strcat(g_MoveStr,cmdbuff); Zscan_Z3pFile_Down();}

5. Delayed laser shut-off means turning off the laser after a delay once the marking trajectory is completed.

The delay-off procedure is as follows:

·

void CZmc_fontToMoveDlg::Zscan_Z3pFile_EndString(struct_GraphPos *iGraphData){ char cmdbuff[2048] = ""; char tempbuff[2048] = ""; // Generate command sprintf(tempbuff, "FORCE_SPEED = %f\n",m_dEmpSpeed); // Set empty movement speed strcat(cmdbuff, tempbuff); sprintf(tempbuff, "MOVESCANABS(%f,%f)\n",(*iGraphData).fposx,(*iGraphData).fposy); // Move strcat(cmdbuff, tempbuff); // Delay to turn off light if(m_nLastDelay >0) { // Delay to turn off light sprintf(tempbuff, "MOVEOP_DELAY = 0\nMOVE_DELAY(%f)\n",m_nLastDelay/1000); strcat(cmdbuff, tempbuff); } else { sprintf(tempbuff, "MOVEOP_DELAY = %f\n",m_nLastDelay/1000); strcat(cmdbuff, tempbuff); } // Turn off sprintf(tempbuff, "MOVE_OP(%d,OFF)\n",m_nLaserIO); strcat(cmdbuff, tempbuff); // Check command length to send strcat(g_MoveStr,cmdbuff); Zscan_Z3pFile_Down();}

IV. Final Result

First, click the drop-down menu to select the controller IP, then click Connect. Set the laser parameters and motion parameters in sequence. After setting them, enter the parameters for the trajectory, click Start Motion to draw a circular trajectory, and click Stop to end.

The motion results are sampled using the oscilloscope in Zdevelop software: First, the laser moves from other positions to the starting position, then the laser is turned on 1ms in advance, completes one circular trajectory, and then the laser is turned off (with a delay before turning off). Then, the laser moves to the starting point of the next circular trajectory, and the laser is turned on (1ms in advance). After completing another trajectory, the laser is turned off (with a 5ms delay before turning off). This process is repeated until the set number of rows and columns is completed (the stop button can also be clicked during the trajectory process).

The trajectory in XY mode includes a circular marking trajectory and an idle trajectory:

That concludes our presentation on the open-source laser galvanometer motion controller for positive motion technology: rapid development in C++.

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.

Read next

CATDOLL 136CM Sasha

Height: 136cm Weight: 23.3kg Shoulder Width: 31cm Bust/Waist/Hip: 60/54/68cm Oral Depth: 3-5cm Vaginal Depth: 3-15cm An...

Articles 2026-02-22