The smaller and more rigid CNC 3018-Pro should be able to engrave text faster than the larger and rather springy MPCNC, which could engrave text at about 50 mm/min. This test pattern pushes both cutting depth and engraving speed to absurd values:

Compile the GCMC source to generate G-Code, lash a CD / DVD to the platform (masking tape works fine), touch off the XY coordinates in the center, touch off Z=0 on the surface, then see what happens:

The “engraving depth” translates directly into the force applied to the diamond point, because the spring converts displacement into force. Knowing the Z depth, you can calculate or guesstimate the force.
Early results from the 3018 suggest it can engrave good-looking text about 20 times faster than the MPCNC:

You must trade off speed with accuracy on your very own machine, as your mileage will certainly differ!
The GCMC source code as a GitHub Gist:
| // Engraving test piece | |
| // Ed Nisley KE4ZNU – 2019-09 | |
| //—– | |
| // Command line parameters | |
| // -D OuterDia=number | |
| if (!isdefined("OuterDia")) { | |
| OuterDia = 120mm – 2mm; // CD = 120, 3.5 inch drive = 95 | |
| } | |
| OuterRad = OuterDia / 2.0; | |
| comment("Outer Diameter: ",OuterDia); | |
| comment(" Radius: ",OuterRad); | |
| //—– | |
| // Library routines | |
| include("tracepath.inc.gcmc"); | |
| include("engrave.inc.gcmc"); | |
| //—– | |
| // Bend text around an arc | |
| function ArcText(TextPath,Center,Radius,BaseAngle,Align) { | |
| PathLength = TextPath[-1].x; | |
| Circumf = 2*pi()*Radius; | |
| TextAngle = to_deg(360 * PathLength / Circumf); | |
| AlignAngle = BaseAngle + (Align == "Left" ? 0 : | |
| Align == "Center" ? -TextAngle / 2 : | |
| Align == "Right" ? -TextAngle : | |
| 0); | |
| ArcPath = {}; | |
| foreach(TextPath; pt) { | |
| if (!isundef(pt.x) && !isundef(pt.y) && isundef(pt.z)) { // XY motion, no Z | |
| r = Radius – pt.y; | |
| a = 360deg * (pt.x / Circumf) + AlignAngle; | |
| ArcPath += {[r*cos(a) + Center.x, r*sin(a) + Center.y,-]}; | |
| } | |
| elif (isundef(pt.x) && isundef(pt.y) && !isundef(pt.z)) { // no XY, Z up/down | |
| ArcPath += {pt}; | |
| } | |
| else { | |
| error("Point is not pure XY or pure Z: " + to_string(pt)); | |
| } | |
| } | |
| return ArcPath; | |
| } | |
| //—– | |
| // Set up for drawing | |
| SafeZ = 10.0mm; // above clamps and screws | |
| TravelZ = 1.0mm; // above workpiece | |
| PlotZ = -0.5mm; // tune for best results | |
| TextSpeed = 1000mm; // intricate detail | |
| DrawSpeed = 2000mm; // smooth curves | |
| TextFont = FONT_HSANS_1_RS; | |
| TextSize = [2.0mm,2.0mm]; | |
| TextLeading = 2*TextSize.y; // line spacing | |
| DiskCenter = [0mm,0mm]; // middle of the platter | |
| InnerDia = 40mm; | |
| InnerRad = InnerDia / 2.0; | |
| comment("Inner Diameter: ",InnerDia); | |
| comment(" Radius: ",InnerRad); | |
| NumRings = ceil((OuterRad – (InnerRad + TextLeading))/TextLeading); // number of rings to draw | |
| comment("Numer of rings: ",NumRings); | |
| if (1) { | |
| comment("Text Size begins"); | |
| feedrate(TextSpeed); | |
| ts = "Text size: " + to_string(TextSize); | |
| tp = scale(typeset(ts,TextFont),TextSize); | |
| tpa = ArcText(tp,DiskCenter,OuterRad,90deg,"Left"); | |
| engrave(tpa,TravelZ,PlotZ); | |
| } | |
| if (1) { | |
| comment("Depth variations begin"); | |
| TextRadius = OuterRad; | |
| pz = 0.0mm; | |
| repeat(NumRings ; i) { | |
| comment(" depth: " + to_string(pz)); | |
| feedrate(TextSpeed); | |
| ts = "Depth: " + to_string(pz) + " at " + to_string(TextSpeed) + "/min"; | |
| tp = scale(typeset(ts,TextFont),TextSize); | |
| tpa = ArcText(tp,DiskCenter,TextRadius,-5deg,"Right"); | |
| engrave(tpa,TravelZ,pz); | |
| feedrate(DrawSpeed); | |
| goto([0,-TextRadius,-]); | |
| move([-,-,pz]); | |
| arc_ccw([-TextRadius,0,-],-TextRadius); | |
| goto([-,-,TravelZ]); | |
| feedrate(TextSpeed); | |
| tp = scale(typeset("Rad: " + to_string(TextRadius),TextFont),TextSize); | |
| tpa = ArcText(tp,DiskCenter,TextRadius,180deg,"Right"); | |
| engrave(tpa,TravelZ,PlotZ); | |
| TextRadius -= TextLeading; | |
| pz -= 0.10mm; | |
| } | |
| } | |
| if (1) { | |
| comment("Feedrate variations begin"); | |
| TextRadius = OuterRad; | |
| ps = 250mm; | |
| repeat(NumRings ; i) { | |
| comment(" speed: " + to_string(ps) + "/min"); | |
| feedrate(ps); | |
| ts = "Speed: " + to_string(ps) + "/min at " + to_string(PlotZ); | |
| tp = scale(typeset(ts,TextFont),TextSize); | |
| tpa = ArcText(tp,DiskCenter,TextRadius,5deg,"Left"); | |
| engrave(tpa,TravelZ,PlotZ); | |
| TextRadius -= TextLeading; | |
| ps += 250mm; | |
| } | |
| } | |
| if (1) { | |
| comment("Off-center text arcs begin"); | |
| feedrate(TextSpeed); | |
| tc = [-40mm/sqrt(2),-40mm/sqrt(2)]; // center point | |
| r = 3mm; | |
| s = [0.5mm,0.5mm]; | |
| ts = "Radius: " + to_string(r) + " Size: " + to_string(s); | |
| tp = scale(typeset(ts,TextFont),s); | |
| tpa = ArcText(tp,tc,r,0deg,"Center"); | |
| engrave(tpa,TravelZ,PlotZ); | |
| r = 5mm; | |
| s = [1.0mm,1.0mm]; | |
| ts = "Radius: " + to_string(r) + " Size: " + to_string(s); | |
| tp = scale(typeset(ts,TextFont),s); | |
| tpa = ArcText(tp,tc,r,0deg,"Center"); | |
| engrave(tpa,TravelZ,PlotZ); | |
| r = 8mm; | |
| s = [1.5mm,1.5mm]; | |
| ts = "Radius: " + to_string(r) + " Size: " + to_string(s); | |
| tp = scale(typeset(ts,TextFont),s); | |
| tpa = ArcText(tp,tc,r,0deg,"Center"); | |
| engrave(tpa,TravelZ,PlotZ); | |
| r = 15mm; | |
| s = [3.0mm,3.0mm]; | |
| ts = "Radius: " + to_string(r) + " Size: " + to_string(s); | |
| tp = scale(typeset(ts,FONT_HSCRIPT_2),s); | |
| tpa = ArcText(tp,tc,r,0deg,"Center"); | |
| engrave(tpa,TravelZ,PlotZ); | |
| } | |
| if (1) { | |
| comment("Attribution begins"); | |
| feedrate(TextSpeed); | |
| tp = scale(typeset("Ed Nisley – KE4ZNU – softsolder.com",TextFont),TextSize); | |
| tpa = ArcText(tp,DiskCenter,15mm,0deg,"Center"); | |
| engrave(tpa,TravelZ,PlotZ); | |
| tp = scale(typeset("Engraving Test Disc",TextFont),TextSize); | |
| tpa = ArcText(tp,DiskCenter,15mm,180deg,"Center"); | |
| engrave(tpa,TravelZ,PlotZ); | |
| } | |
| goto([-,-,SafeZ]); | |
| goto([0mm,0mm,-]); | |
| comment("Done!"); |
| #!/bin/bash | |
| # Engraving test pattern generator | |
| # Ed Nisley KE4ZNU – 2019-08 | |
| Diameter='OuterDia=116mm' | |
| Flags='-P 3 –pedantic' | |
| # Set these to match your file layout | |
| LibPath='/opt/gcmc/library' | |
| Prolog='/mnt/bulkdata/Project Files/CNC 3018-Pro Router/Patterns/gcmc/prolog.gcmc' | |
| Epilog='/mnt/bulkdata/Project Files/CNC 3018-Pro Router/Patterns/gcmc/epilog.gcmc' | |
| Script='/mnt/bulkdata/Project Files/CNC 3018-Pro Router/Patterns/Engraving Test.gcmc' | |
| ts=$(date +%Y%m%d-%H%M%S) | |
| fn='TestPattern_'${ts}'.ngc' | |
| echo Output: $fn | |
| rm -f $fn | |
| echo "(File: "$fn")" > $fn | |
| /opt/gcmc/src/gcmc -D $Diameter $Flags \ | |
| –include "$LibPath" –prologue "$Prolog" –epilogue "$Epilog" \ | |
| "$Script" >> $fn | |




















