meerk40t 0.9.3001__py2.py3-none-any.whl → 0.9.7020__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- meerk40t/__init__.py +1 -1
- meerk40t/balormk/balor_params.py +167 -167
- meerk40t/balormk/clone_loader.py +457 -457
- meerk40t/balormk/controller.py +1566 -1512
- meerk40t/balormk/cylindermod.py +64 -0
- meerk40t/balormk/device.py +966 -1959
- meerk40t/balormk/driver.py +778 -591
- meerk40t/balormk/galvo_commands.py +1194 -0
- meerk40t/balormk/gui/balorconfig.py +237 -111
- meerk40t/balormk/gui/balorcontroller.py +191 -184
- meerk40t/balormk/gui/baloroperationproperties.py +116 -115
- meerk40t/balormk/gui/corscene.py +845 -0
- meerk40t/balormk/gui/gui.py +179 -147
- meerk40t/balormk/livelightjob.py +466 -382
- meerk40t/balormk/mock_connection.py +131 -109
- meerk40t/balormk/plugin.py +133 -135
- meerk40t/balormk/usb_connection.py +306 -301
- meerk40t/camera/__init__.py +1 -1
- meerk40t/camera/camera.py +514 -397
- meerk40t/camera/gui/camerapanel.py +1241 -1095
- meerk40t/camera/gui/gui.py +58 -58
- meerk40t/camera/plugin.py +441 -399
- meerk40t/ch341/__init__.py +27 -27
- meerk40t/ch341/ch341device.py +628 -628
- meerk40t/ch341/libusb.py +595 -589
- meerk40t/ch341/mock.py +171 -171
- meerk40t/ch341/windriver.py +157 -157
- meerk40t/constants.py +13 -0
- meerk40t/core/__init__.py +1 -1
- meerk40t/core/bindalias.py +550 -539
- meerk40t/core/core.py +47 -47
- meerk40t/core/cutcode/cubiccut.py +73 -73
- meerk40t/core/cutcode/cutcode.py +315 -312
- meerk40t/core/cutcode/cutgroup.py +141 -137
- meerk40t/core/cutcode/cutobject.py +192 -185
- meerk40t/core/cutcode/dwellcut.py +37 -37
- meerk40t/core/cutcode/gotocut.py +29 -29
- meerk40t/core/cutcode/homecut.py +29 -29
- meerk40t/core/cutcode/inputcut.py +34 -34
- meerk40t/core/cutcode/linecut.py +33 -33
- meerk40t/core/cutcode/outputcut.py +34 -34
- meerk40t/core/cutcode/plotcut.py +335 -335
- meerk40t/core/cutcode/quadcut.py +61 -61
- meerk40t/core/cutcode/rastercut.py +168 -148
- meerk40t/core/cutcode/waitcut.py +34 -34
- meerk40t/core/cutplan.py +1843 -1316
- meerk40t/core/drivers.py +330 -329
- meerk40t/core/elements/align.py +801 -669
- meerk40t/core/elements/branches.py +1858 -1507
- meerk40t/core/elements/clipboard.py +229 -219
- meerk40t/core/elements/element_treeops.py +4595 -2837
- meerk40t/core/elements/element_types.py +125 -105
- meerk40t/core/elements/elements.py +4315 -3617
- meerk40t/core/elements/files.py +117 -64
- meerk40t/core/elements/geometry.py +473 -224
- meerk40t/core/elements/grid.py +467 -316
- meerk40t/core/elements/materials.py +158 -94
- meerk40t/core/elements/notes.py +50 -38
- meerk40t/core/elements/offset_clpr.py +934 -912
- meerk40t/core/elements/offset_mk.py +963 -955
- meerk40t/core/elements/penbox.py +339 -267
- meerk40t/core/elements/placements.py +300 -83
- meerk40t/core/elements/render.py +785 -687
- meerk40t/core/elements/shapes.py +2618 -2092
- meerk40t/core/elements/testcases.py +105 -0
- meerk40t/core/elements/trace.py +651 -563
- meerk40t/core/elements/tree_commands.py +415 -409
- meerk40t/core/elements/undo_redo.py +116 -58
- meerk40t/core/elements/wordlist.py +319 -200
- meerk40t/core/exceptions.py +9 -9
- meerk40t/core/laserjob.py +220 -220
- meerk40t/core/logging.py +63 -63
- meerk40t/core/node/blobnode.py +83 -86
- meerk40t/core/node/bootstrap.py +105 -103
- meerk40t/core/node/branch_elems.py +40 -31
- meerk40t/core/node/branch_ops.py +45 -38
- meerk40t/core/node/branch_regmark.py +48 -41
- meerk40t/core/node/cutnode.py +29 -32
- meerk40t/core/node/effect_hatch.py +375 -257
- meerk40t/core/node/effect_warp.py +398 -0
- meerk40t/core/node/effect_wobble.py +441 -309
- meerk40t/core/node/elem_ellipse.py +404 -309
- meerk40t/core/node/elem_image.py +1082 -801
- meerk40t/core/node/elem_line.py +358 -292
- meerk40t/core/node/elem_path.py +259 -201
- meerk40t/core/node/elem_point.py +129 -102
- meerk40t/core/node/elem_polyline.py +310 -246
- meerk40t/core/node/elem_rect.py +376 -286
- meerk40t/core/node/elem_text.py +445 -418
- meerk40t/core/node/filenode.py +59 -40
- meerk40t/core/node/groupnode.py +138 -74
- meerk40t/core/node/image_processed.py +777 -766
- meerk40t/core/node/image_raster.py +156 -113
- meerk40t/core/node/layernode.py +31 -31
- meerk40t/core/node/mixins.py +135 -107
- meerk40t/core/node/node.py +1427 -1304
- meerk40t/core/node/nutils.py +117 -114
- meerk40t/core/node/op_cut.py +463 -335
- meerk40t/core/node/op_dots.py +296 -251
- meerk40t/core/node/op_engrave.py +414 -311
- meerk40t/core/node/op_image.py +755 -369
- meerk40t/core/node/op_raster.py +787 -522
- meerk40t/core/node/place_current.py +37 -40
- meerk40t/core/node/place_point.py +329 -126
- meerk40t/core/node/refnode.py +58 -47
- meerk40t/core/node/rootnode.py +225 -219
- meerk40t/core/node/util_console.py +48 -48
- meerk40t/core/node/util_goto.py +84 -65
- meerk40t/core/node/util_home.py +61 -61
- meerk40t/core/node/util_input.py +102 -102
- meerk40t/core/node/util_output.py +102 -102
- meerk40t/core/node/util_wait.py +65 -65
- meerk40t/core/parameters.py +709 -707
- meerk40t/core/planner.py +875 -785
- meerk40t/core/plotplanner.py +656 -652
- meerk40t/core/space.py +120 -113
- meerk40t/core/spoolers.py +706 -705
- meerk40t/core/svg_io.py +1836 -1549
- meerk40t/core/treeop.py +534 -445
- meerk40t/core/undos.py +278 -124
- meerk40t/core/units.py +784 -680
- meerk40t/core/view.py +393 -322
- meerk40t/core/webhelp.py +62 -62
- meerk40t/core/wordlist.py +513 -504
- meerk40t/cylinder/cylinder.py +247 -0
- meerk40t/cylinder/gui/cylindersettings.py +41 -0
- meerk40t/cylinder/gui/gui.py +24 -0
- meerk40t/device/__init__.py +1 -1
- meerk40t/device/basedevice.py +322 -123
- meerk40t/device/devicechoices.py +50 -0
- meerk40t/device/dummydevice.py +163 -128
- meerk40t/device/gui/defaultactions.py +618 -602
- meerk40t/device/gui/effectspanel.py +114 -0
- meerk40t/device/gui/formatterpanel.py +253 -290
- meerk40t/device/gui/warningpanel.py +337 -260
- meerk40t/device/mixins.py +13 -13
- meerk40t/dxf/__init__.py +1 -1
- meerk40t/dxf/dxf_io.py +766 -554
- meerk40t/dxf/plugin.py +47 -35
- meerk40t/external_plugins.py +79 -79
- meerk40t/external_plugins_build.py +28 -28
- meerk40t/extra/cag.py +112 -116
- meerk40t/extra/coolant.py +403 -0
- meerk40t/extra/encode_detect.py +204 -0
- meerk40t/extra/ezd.py +1165 -1165
- meerk40t/extra/hershey.py +834 -340
- meerk40t/extra/imageactions.py +322 -316
- meerk40t/extra/inkscape.py +628 -622
- meerk40t/extra/lbrn.py +424 -424
- meerk40t/extra/outerworld.py +283 -0
- meerk40t/extra/param_functions.py +1542 -1556
- meerk40t/extra/potrace.py +257 -253
- meerk40t/extra/serial_exchange.py +118 -0
- meerk40t/extra/updater.py +602 -453
- meerk40t/extra/vectrace.py +147 -146
- meerk40t/extra/winsleep.py +83 -83
- meerk40t/extra/xcs_reader.py +597 -0
- meerk40t/fill/fills.py +781 -335
- meerk40t/fill/patternfill.py +1061 -1061
- meerk40t/fill/patterns.py +614 -567
- meerk40t/grbl/control.py +87 -87
- meerk40t/grbl/controller.py +990 -903
- meerk40t/grbl/device.py +1084 -768
- meerk40t/grbl/driver.py +989 -771
- meerk40t/grbl/emulator.py +532 -497
- meerk40t/grbl/gcodejob.py +783 -767
- meerk40t/grbl/gui/grblconfiguration.py +373 -298
- meerk40t/grbl/gui/grblcontroller.py +485 -271
- meerk40t/grbl/gui/grblhardwareconfig.py +269 -153
- meerk40t/grbl/gui/grbloperationconfig.py +105 -0
- meerk40t/grbl/gui/gui.py +147 -116
- meerk40t/grbl/interpreter.py +44 -44
- meerk40t/grbl/loader.py +22 -22
- meerk40t/grbl/mock_connection.py +56 -56
- meerk40t/grbl/plugin.py +294 -264
- meerk40t/grbl/serial_connection.py +93 -88
- meerk40t/grbl/tcp_connection.py +81 -79
- meerk40t/grbl/ws_connection.py +112 -0
- meerk40t/gui/__init__.py +1 -1
- meerk40t/gui/about.py +2042 -296
- meerk40t/gui/alignment.py +1644 -1608
- meerk40t/gui/autoexec.py +199 -0
- meerk40t/gui/basicops.py +791 -670
- meerk40t/gui/bufferview.py +77 -71
- meerk40t/gui/busy.py +232 -133
- meerk40t/gui/choicepropertypanel.py +1662 -1469
- meerk40t/gui/consolepanel.py +706 -542
- meerk40t/gui/devicepanel.py +687 -581
- meerk40t/gui/dialogoptions.py +110 -107
- meerk40t/gui/executejob.py +316 -306
- meerk40t/gui/fonts.py +90 -90
- meerk40t/gui/functionwrapper.py +252 -0
- meerk40t/gui/gui_mixins.py +729 -0
- meerk40t/gui/guicolors.py +205 -182
- meerk40t/gui/help_assets/help_assets.py +218 -201
- meerk40t/gui/helper.py +154 -0
- meerk40t/gui/hersheymanager.py +1440 -846
- meerk40t/gui/icons.py +3422 -2747
- meerk40t/gui/imagesplitter.py +555 -508
- meerk40t/gui/keymap.py +354 -344
- meerk40t/gui/laserpanel.py +897 -806
- meerk40t/gui/laserrender.py +1470 -1232
- meerk40t/gui/lasertoolpanel.py +805 -793
- meerk40t/gui/magnetoptions.py +436 -0
- meerk40t/gui/materialmanager.py +2944 -0
- meerk40t/gui/materialtest.py +1722 -1694
- meerk40t/gui/mkdebug.py +646 -359
- meerk40t/gui/mwindow.py +163 -140
- meerk40t/gui/navigationpanels.py +2605 -2467
- meerk40t/gui/notes.py +143 -142
- meerk40t/gui/opassignment.py +414 -410
- meerk40t/gui/operation_info.py +310 -299
- meerk40t/gui/plugin.py +500 -328
- meerk40t/gui/position.py +714 -669
- meerk40t/gui/preferences.py +901 -650
- meerk40t/gui/propertypanels/attributes.py +1461 -1131
- meerk40t/gui/propertypanels/blobproperty.py +117 -114
- meerk40t/gui/propertypanels/consoleproperty.py +83 -80
- meerk40t/gui/propertypanels/gotoproperty.py +77 -0
- meerk40t/gui/propertypanels/groupproperties.py +223 -217
- meerk40t/gui/propertypanels/hatchproperty.py +489 -469
- meerk40t/gui/propertypanels/imageproperty.py +2244 -1384
- meerk40t/gui/propertypanels/inputproperty.py +59 -58
- meerk40t/gui/propertypanels/opbranchproperties.py +82 -80
- meerk40t/gui/propertypanels/operationpropertymain.py +1890 -1638
- meerk40t/gui/propertypanels/outputproperty.py +59 -58
- meerk40t/gui/propertypanels/pathproperty.py +389 -380
- meerk40t/gui/propertypanels/placementproperty.py +1214 -383
- meerk40t/gui/propertypanels/pointproperty.py +140 -136
- meerk40t/gui/propertypanels/propertywindow.py +313 -181
- meerk40t/gui/propertypanels/rasterwizardpanels.py +996 -912
- meerk40t/gui/propertypanels/regbranchproperties.py +76 -0
- meerk40t/gui/propertypanels/textproperty.py +770 -755
- meerk40t/gui/propertypanels/waitproperty.py +56 -55
- meerk40t/gui/propertypanels/warpproperty.py +121 -0
- meerk40t/gui/propertypanels/wobbleproperty.py +255 -204
- meerk40t/gui/ribbon.py +2471 -2210
- meerk40t/gui/scene/scene.py +1100 -1051
- meerk40t/gui/scene/sceneconst.py +22 -22
- meerk40t/gui/scene/scenepanel.py +439 -349
- meerk40t/gui/scene/scenespacewidget.py +365 -365
- meerk40t/gui/scene/widget.py +518 -505
- meerk40t/gui/scenewidgets/affinemover.py +215 -215
- meerk40t/gui/scenewidgets/attractionwidget.py +315 -309
- meerk40t/gui/scenewidgets/bedwidget.py +120 -97
- meerk40t/gui/scenewidgets/elementswidget.py +137 -107
- meerk40t/gui/scenewidgets/gridwidget.py +785 -745
- meerk40t/gui/scenewidgets/guidewidget.py +765 -765
- meerk40t/gui/scenewidgets/laserpathwidget.py +66 -66
- meerk40t/gui/scenewidgets/machineoriginwidget.py +86 -86
- meerk40t/gui/scenewidgets/nodeselector.py +28 -28
- meerk40t/gui/scenewidgets/rectselectwidget.py +592 -346
- meerk40t/gui/scenewidgets/relocatewidget.py +33 -33
- meerk40t/gui/scenewidgets/reticlewidget.py +83 -83
- meerk40t/gui/scenewidgets/selectionwidget.py +2958 -2756
- meerk40t/gui/simpleui.py +362 -333
- meerk40t/gui/simulation.py +2451 -2094
- meerk40t/gui/snapoptions.py +208 -203
- meerk40t/gui/spoolerpanel.py +1227 -1180
- meerk40t/gui/statusbarwidgets/defaultoperations.py +480 -353
- meerk40t/gui/statusbarwidgets/infowidget.py +520 -483
- meerk40t/gui/statusbarwidgets/opassignwidget.py +356 -355
- meerk40t/gui/statusbarwidgets/selectionwidget.py +172 -171
- meerk40t/gui/statusbarwidgets/shapepropwidget.py +754 -236
- meerk40t/gui/statusbarwidgets/statusbar.py +272 -260
- meerk40t/gui/statusbarwidgets/statusbarwidget.py +268 -270
- meerk40t/gui/statusbarwidgets/strokewidget.py +267 -251
- meerk40t/gui/themes.py +200 -78
- meerk40t/gui/tips.py +590 -0
- meerk40t/gui/toolwidgets/circlebrush.py +35 -35
- meerk40t/gui/toolwidgets/toolcircle.py +248 -242
- meerk40t/gui/toolwidgets/toolcontainer.py +82 -77
- meerk40t/gui/toolwidgets/tooldraw.py +97 -90
- meerk40t/gui/toolwidgets/toolellipse.py +219 -212
- meerk40t/gui/toolwidgets/toolimagecut.py +25 -132
- meerk40t/gui/toolwidgets/toolline.py +39 -144
- meerk40t/gui/toolwidgets/toollinetext.py +79 -236
- meerk40t/gui/toolwidgets/toollinetext_inline.py +296 -0
- meerk40t/gui/toolwidgets/toolmeasure.py +163 -216
- meerk40t/gui/toolwidgets/toolnodeedit.py +2088 -2074
- meerk40t/gui/toolwidgets/toolnodemove.py +92 -94
- meerk40t/gui/toolwidgets/toolparameter.py +754 -668
- meerk40t/gui/toolwidgets/toolplacement.py +108 -108
- meerk40t/gui/toolwidgets/toolpoint.py +68 -59
- meerk40t/gui/toolwidgets/toolpointlistbuilder.py +294 -0
- meerk40t/gui/toolwidgets/toolpointmove.py +183 -0
- meerk40t/gui/toolwidgets/toolpolygon.py +288 -403
- meerk40t/gui/toolwidgets/toolpolyline.py +38 -196
- meerk40t/gui/toolwidgets/toolrect.py +211 -207
- meerk40t/gui/toolwidgets/toolrelocate.py +72 -72
- meerk40t/gui/toolwidgets/toolribbon.py +598 -113
- meerk40t/gui/toolwidgets/tooltabedit.py +546 -0
- meerk40t/gui/toolwidgets/tooltext.py +98 -89
- meerk40t/gui/toolwidgets/toolvector.py +213 -204
- meerk40t/gui/toolwidgets/toolwidget.py +39 -39
- meerk40t/gui/usbconnect.py +98 -91
- meerk40t/gui/utilitywidgets/buttonwidget.py +18 -18
- meerk40t/gui/utilitywidgets/checkboxwidget.py +90 -90
- meerk40t/gui/utilitywidgets/controlwidget.py +14 -14
- meerk40t/gui/utilitywidgets/cyclocycloidwidget.py +343 -340
- meerk40t/gui/utilitywidgets/debugwidgets.py +148 -0
- meerk40t/gui/utilitywidgets/handlewidget.py +27 -27
- meerk40t/gui/utilitywidgets/harmonograph.py +450 -447
- meerk40t/gui/utilitywidgets/openclosewidget.py +40 -40
- meerk40t/gui/utilitywidgets/rotationwidget.py +54 -54
- meerk40t/gui/utilitywidgets/scalewidget.py +75 -75
- meerk40t/gui/utilitywidgets/seekbarwidget.py +183 -183
- meerk40t/gui/utilitywidgets/togglewidget.py +142 -142
- meerk40t/gui/utilitywidgets/toolbarwidget.py +8 -8
- meerk40t/gui/wordlisteditor.py +985 -931
- meerk40t/gui/wxmeerk40t.py +1447 -1169
- meerk40t/gui/wxmmain.py +5644 -4112
- meerk40t/gui/wxmribbon.py +1591 -1076
- meerk40t/gui/wxmscene.py +1631 -1453
- meerk40t/gui/wxmtree.py +2416 -2089
- meerk40t/gui/wxutils.py +1769 -1099
- meerk40t/gui/zmatrix.py +102 -102
- meerk40t/image/__init__.py +1 -1
- meerk40t/image/dither.py +429 -0
- meerk40t/image/imagetools.py +2793 -2269
- meerk40t/internal_plugins.py +150 -130
- meerk40t/kernel/__init__.py +63 -12
- meerk40t/kernel/channel.py +259 -212
- meerk40t/kernel/context.py +538 -538
- meerk40t/kernel/exceptions.py +41 -41
- meerk40t/kernel/functions.py +463 -414
- meerk40t/kernel/jobs.py +100 -100
- meerk40t/kernel/kernel.py +3828 -3571
- meerk40t/kernel/lifecycles.py +71 -71
- meerk40t/kernel/module.py +49 -49
- meerk40t/kernel/service.py +147 -147
- meerk40t/kernel/settings.py +383 -343
- meerk40t/lihuiyu/controller.py +883 -876
- meerk40t/lihuiyu/device.py +1181 -1069
- meerk40t/lihuiyu/driver.py +1466 -1372
- meerk40t/lihuiyu/gui/gui.py +127 -106
- meerk40t/lihuiyu/gui/lhyaccelgui.py +377 -363
- meerk40t/lihuiyu/gui/lhycontrollergui.py +741 -651
- meerk40t/lihuiyu/gui/lhydrivergui.py +470 -446
- meerk40t/lihuiyu/gui/lhyoperationproperties.py +238 -237
- meerk40t/lihuiyu/gui/tcpcontroller.py +226 -190
- meerk40t/lihuiyu/interpreter.py +53 -53
- meerk40t/lihuiyu/laserspeed.py +450 -450
- meerk40t/lihuiyu/loader.py +90 -90
- meerk40t/lihuiyu/parser.py +404 -404
- meerk40t/lihuiyu/plugin.py +101 -102
- meerk40t/lihuiyu/tcp_connection.py +111 -109
- meerk40t/main.py +231 -165
- meerk40t/moshi/builder.py +788 -781
- meerk40t/moshi/controller.py +505 -499
- meerk40t/moshi/device.py +495 -442
- meerk40t/moshi/driver.py +862 -696
- meerk40t/moshi/gui/gui.py +78 -76
- meerk40t/moshi/gui/moshicontrollergui.py +538 -522
- meerk40t/moshi/gui/moshidrivergui.py +87 -75
- meerk40t/moshi/plugin.py +43 -43
- meerk40t/network/console_server.py +140 -57
- meerk40t/network/kernelserver.py +10 -9
- meerk40t/network/tcp_server.py +142 -140
- meerk40t/network/udp_server.py +103 -77
- meerk40t/network/web_server.py +404 -0
- meerk40t/newly/controller.py +1158 -1144
- meerk40t/newly/device.py +874 -732
- meerk40t/newly/driver.py +540 -412
- meerk40t/newly/gui/gui.py +219 -188
- meerk40t/newly/gui/newlyconfig.py +116 -101
- meerk40t/newly/gui/newlycontroller.py +193 -186
- meerk40t/newly/gui/operationproperties.py +51 -51
- meerk40t/newly/mock_connection.py +82 -82
- meerk40t/newly/newly_params.py +56 -56
- meerk40t/newly/plugin.py +1214 -1246
- meerk40t/newly/usb_connection.py +322 -322
- meerk40t/rotary/gui/gui.py +52 -46
- meerk40t/rotary/gui/rotarysettings.py +240 -232
- meerk40t/rotary/rotary.py +202 -98
- meerk40t/ruida/control.py +291 -91
- meerk40t/ruida/controller.py +138 -1088
- meerk40t/ruida/device.py +676 -231
- meerk40t/ruida/driver.py +534 -472
- meerk40t/ruida/emulator.py +1494 -1491
- meerk40t/ruida/exceptions.py +4 -4
- meerk40t/ruida/gui/gui.py +71 -76
- meerk40t/ruida/gui/ruidaconfig.py +239 -72
- meerk40t/ruida/gui/ruidacontroller.py +187 -184
- meerk40t/ruida/gui/ruidaoperationproperties.py +48 -47
- meerk40t/ruida/loader.py +54 -52
- meerk40t/ruida/mock_connection.py +57 -109
- meerk40t/ruida/plugin.py +124 -87
- meerk40t/ruida/rdjob.py +2084 -945
- meerk40t/ruida/serial_connection.py +116 -0
- meerk40t/ruida/tcp_connection.py +146 -0
- meerk40t/ruida/udp_connection.py +73 -0
- meerk40t/svgelements.py +9671 -9669
- meerk40t/tools/driver_to_path.py +584 -579
- meerk40t/tools/geomstr.py +5583 -4680
- meerk40t/tools/jhfparser.py +357 -292
- meerk40t/tools/kerftest.py +904 -890
- meerk40t/tools/livinghinges.py +1168 -1033
- meerk40t/tools/pathtools.py +987 -949
- meerk40t/tools/pmatrix.py +234 -0
- meerk40t/tools/pointfinder.py +942 -942
- meerk40t/tools/polybool.py +941 -940
- meerk40t/tools/rasterplotter.py +1660 -547
- meerk40t/tools/shxparser.py +1047 -901
- meerk40t/tools/ttfparser.py +726 -446
- meerk40t/tools/zinglplotter.py +595 -593
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/LICENSE +21 -21
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/METADATA +150 -139
- meerk40t-0.9.7020.dist-info/RECORD +446 -0
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/WHEEL +1 -1
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/top_level.txt +0 -1
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/zip-safe +1 -1
- meerk40t/balormk/elementlightjob.py +0 -159
- meerk40t-0.9.3001.dist-info/RECORD +0 -437
- test/bootstrap.py +0 -63
- test/test_cli.py +0 -12
- test/test_core_cutcode.py +0 -418
- test/test_core_elements.py +0 -144
- test/test_core_plotplanner.py +0 -397
- test/test_core_viewports.py +0 -312
- test/test_drivers_grbl.py +0 -108
- test/test_drivers_lihuiyu.py +0 -443
- test/test_drivers_newly.py +0 -113
- test/test_element_degenerate_points.py +0 -43
- test/test_elements_classify.py +0 -97
- test/test_elements_penbox.py +0 -22
- test/test_file_svg.py +0 -176
- test/test_fill.py +0 -155
- test/test_geomstr.py +0 -1523
- test/test_geomstr_nodes.py +0 -18
- test/test_imagetools_actualize.py +0 -306
- test/test_imagetools_wizard.py +0 -258
- test/test_kernel.py +0 -200
- test/test_laser_speeds.py +0 -3303
- test/test_length.py +0 -57
- test/test_lifecycle.py +0 -66
- test/test_operations.py +0 -251
- test/test_operations_hatch.py +0 -57
- test/test_ruida.py +0 -19
- test/test_spooler.py +0 -22
- test/test_tools_rasterplotter.py +0 -29
- test/test_wobble.py +0 -133
- test/test_zingl.py +0 -124
- {test → meerk40t/cylinder}/__init__.py +0 -0
- /meerk40t/{core/element_commands.py → cylinder/gui/__init__.py} +0 -0
- {meerk40t-0.9.3001.dist-info → meerk40t-0.9.7020.dist-info}/entry_points.txt +0 -0
meerk40t/lihuiyu/laserspeed.py
CHANGED
@@ -1,450 +1,450 @@
|
|
1
|
-
#!/usr/bin/env python
|
2
|
-
|
3
|
-
"""
|
4
|
-
LaserSpeed
|
5
|
-
|
6
|
-
This is the standard library for converting to and from speed code information for LHYMICRO-GL.
|
7
|
-
"""
|
8
|
-
|
9
|
-
|
10
|
-
from math import floor
|
11
|
-
|
12
|
-
|
13
|
-
class LaserSpeed:
|
14
|
-
"""
|
15
|
-
MIT License.
|
16
|
-
|
17
|
-
This is the standard library for converting to and from speed code information for LHYMICRO-GL.
|
18
|
-
|
19
|
-
The units in the speed code have acceleration/deceleration factors which slightly modifies the equations used
|
20
|
-
to convert between values and speeds. The fundamental units within the speed code values are period-ticks.
|
21
|
-
All values relate to a value in the counter to count off the number of oscillations within the
|
22
|
-
(typically 22.1184) Mhz crystal. The max value here is 65535, with the addition of a diagonal delay.
|
23
|
-
|
24
|
-
For the M2 board, the original Chinese Software gave a slope of 12120. However, experiments with the actual
|
25
|
-
physical speed put this value at 11142, which properly reflects that all speeds tend to be at 91.98% of the
|
26
|
-
requested speed.
|
27
|
-
|
28
|
-
The board is ultimately controlling a stepper motor and the speed a stepper motor travels is the result of
|
29
|
-
the time between the ticks. Since the crystal oscillator is the same, the delay is controlled by the counted
|
30
|
-
oscillations subticks, which gives us the time between stepper motor pulses. Most of the devices we are
|
31
|
-
dealing with are 1000 dpi stepper motors, so, for example, to travel at 1 inch a second requires that the
|
32
|
-
device tick at 1 kHz. To do this it must delay 1 ms between ticks. This corresponds to a value of 48296 in
|
33
|
-
the M2 board. Which has an equation of 65536 - (5120 + 12120T) where T is the period requested in ms. This is
|
34
|
-
equal to 25.4 mm/s. If we want a 2 ms delay, which is half the speed (0.5kHz, 0.5 inches/second, 12.7 mm/s)
|
35
|
-
we do 65536 - (5120 + 24240) which gives us a value of 36176. This would be encoded as a 16-bit number
|
36
|
-
broken up into 2 ascii 3 digit strings between 0-255. 141 for the high bits and 80 for the low bits.
|
37
|
-
So CV01410801 where the final character "1" is the acceleration factor since it's within that range.
|
38
|
-
|
39
|
-
The speed in mm/s is also used for determining which acceleration to use and as a factor for some boards
|
40
|
-
(B2, M2) the horizontal encoded value. Slowing down the device down while traveling diagonally makes the
|
41
|
-
diagonal and orthogonal take the same amount of time (thereby cutting to the same depth). These are the same
|
42
|
-
period-ticks units and is simply summed with the 65536 - (b + mT) value in cases that both stepper motors
|
43
|
-
are used.
|
44
|
-
"""
|
45
|
-
|
46
|
-
def __init__(
|
47
|
-
self,
|
48
|
-
board="M2",
|
49
|
-
speed=None,
|
50
|
-
raster_step=None,
|
51
|
-
d_ratio=None,
|
52
|
-
suffix_c=None,
|
53
|
-
acceleration=None,
|
54
|
-
raster_horizontal=True,
|
55
|
-
fix_speeds=False,
|
56
|
-
fix_lows=False,
|
57
|
-
fix_limit=False,
|
58
|
-
):
|
59
|
-
self.speed = speed
|
60
|
-
self.board = board
|
61
|
-
self.d_ratio = d_ratio
|
62
|
-
self.raster_step = raster_step
|
63
|
-
|
64
|
-
self.acceleration = acceleration
|
65
|
-
self.suffix_c = suffix_c
|
66
|
-
self.raster_horizontal = raster_horizontal
|
67
|
-
self.fix_speeds = fix_speeds
|
68
|
-
self.fix_lows = fix_lows
|
69
|
-
self.fix_limit = fix_limit
|
70
|
-
|
71
|
-
if isinstance(speed, str):
|
72
|
-
# this is a speedcode value.
|
73
|
-
(
|
74
|
-
code_value,
|
75
|
-
accel,
|
76
|
-
step_value,
|
77
|
-
diagonal,
|
78
|
-
raster_step,
|
79
|
-
suffix_c,
|
80
|
-
) = parse_speed_code(self.speed)
|
81
|
-
b, m = get_equation(
|
82
|
-
self.board,
|
83
|
-
accel=accel,
|
84
|
-
suffix_c=suffix_c,
|
85
|
-
fix_speeds=self.fix_speeds,
|
86
|
-
)
|
87
|
-
self.speed = get_speed_from_value(code_value, b, m)
|
88
|
-
self.acceleration = accel
|
89
|
-
self.raster_step = raster_step
|
90
|
-
self.suffix_c = suffix_c
|
91
|
-
|
92
|
-
def __str__(self):
|
93
|
-
return self.speedcode
|
94
|
-
|
95
|
-
def __repr__(self):
|
96
|
-
parts = list()
|
97
|
-
if self.board != "M2":
|
98
|
-
parts.append(f'board="{self.board}"')
|
99
|
-
if self.speed is not None:
|
100
|
-
parts.append(f"speed={self.speed}")
|
101
|
-
if self.d_ratio is not None:
|
102
|
-
parts.append(f"d_ratio={self.d_ratio}")
|
103
|
-
if self.raster_step != 0:
|
104
|
-
parts.append(f"raster_step={self.raster_step}")
|
105
|
-
if self.suffix_c is not None:
|
106
|
-
parts.append(f"suffix_c={str(self.suffix_c)}")
|
107
|
-
if self.acceleration is not None:
|
108
|
-
parts.append(f"acceleration={self.acceleration}")
|
109
|
-
if self.fix_speeds:
|
110
|
-
parts.append(f"fix_speeds={str(self.fix_speeds)}")
|
111
|
-
if self.fix_lows:
|
112
|
-
parts.append(f"fix_lows={str(self.fix_lows)}")
|
113
|
-
if self.fix_limit:
|
114
|
-
parts.append(f"fix_limit={str(self.fix_limit)}")
|
115
|
-
if not self.raster_horizontal:
|
116
|
-
parts.append(f"raster_horizontal={str(self.raster_horizontal)}")
|
117
|
-
return f"LaserSpeed({', '.join(parts)})"
|
118
|
-
|
119
|
-
@property
|
120
|
-
def speedcode(self):
|
121
|
-
return get_code_from_speed(
|
122
|
-
self.speed,
|
123
|
-
self.raster_step,
|
124
|
-
self.board,
|
125
|
-
self.d_ratio,
|
126
|
-
self.acceleration,
|
127
|
-
self.suffix_c,
|
128
|
-
fix_limit=self.fix_limit,
|
129
|
-
fix_speeds=self.fix_speeds,
|
130
|
-
fix_lows=self.fix_lows,
|
131
|
-
raster_horizontal=self.raster_horizontal,
|
132
|
-
)
|
133
|
-
|
134
|
-
|
135
|
-
def get_speed_from_code(speed_code, board="M2", fix_speeds=False):
|
136
|
-
"""
|
137
|
-
Gets the speed expected from a speedcode. Should calculate the expected speed from the data code given.
|
138
|
-
@param speed_code: The speedcode to check.
|
139
|
-
@param board: The board this speedcode was made for.
|
140
|
-
@param fix_speeds: Is this speedcode in a fixed_speed code?
|
141
|
-
@return:
|
142
|
-
"""
|
143
|
-
(
|
144
|
-
code_value,
|
145
|
-
accel,
|
146
|
-
step_value,
|
147
|
-
diagonal,
|
148
|
-
raster_step,
|
149
|
-
suffix_c,
|
150
|
-
) = parse_speed_code(speed_code)
|
151
|
-
b, m = get_equation(board, accel=accel, suffix_c=suffix_c, fix_speeds=fix_speeds)
|
152
|
-
return get_speed_from_value(code_value, b, m)
|
153
|
-
|
154
|
-
|
155
|
-
def get_code_from_speed(
|
156
|
-
mm_per_second,
|
157
|
-
raster_step=0,
|
158
|
-
board="M2",
|
159
|
-
d_ratio=None,
|
160
|
-
acceleration=None,
|
161
|
-
suffix_c=None,
|
162
|
-
fix_limit=False,
|
163
|
-
fix_speeds=False,
|
164
|
-
fix_lows=False,
|
165
|
-
raster_horizontal=True,
|
166
|
-
):
|
167
|
-
"""
|
168
|
-
Get a speedcode from a given speed. The raster step appends the 'G' value and uses speed ranges.
|
169
|
-
The d_ratio uses the default/auto ratio. The accel is optional and forces the speedcode to work
|
170
|
-
for that particular acceleration.
|
171
|
-
|
172
|
-
@param mm_per_second: speed to convert to code.
|
173
|
-
@param raster_step: raster step mode to use. Use (g0,g1) tuple for unidirectional valuations.
|
174
|
-
@param board: Nano Board Model
|
175
|
-
@param d_ratio: M1, M2, B1, B2 have ratio of optional speed
|
176
|
-
@param acceleration: Optional force acceleration code rather than default for that speed.
|
177
|
-
@param suffix_c: Optional force suffix_c mode for the board. (True forces suffix_c on, False forces it off)
|
178
|
-
@param fix_limit: Removes max speed limit.
|
179
|
-
@param fix_speeds: Give corrected speed (faster by 8.9%)
|
180
|
-
@param fix_lows: Force low speeds into correct bounds.
|
181
|
-
@param raster_horizontal: is it rastering with the laser head, or the much heavier bar?
|
182
|
-
@return: speed code produced.
|
183
|
-
"""
|
184
|
-
if d_ratio is None:
|
185
|
-
d_ratio = 0.261199033289
|
186
|
-
if not fix_limit and mm_per_second > 240 and raster_step == 0:
|
187
|
-
mm_per_second = 19.05 # Arbitrary default speed for out range value.
|
188
|
-
if acceleration is None:
|
189
|
-
acceleration = get_acceleration_for_speed(
|
190
|
-
mm_per_second,
|
191
|
-
raster_step != 0,
|
192
|
-
raster_horizontal=raster_horizontal,
|
193
|
-
fix_speeds=fix_speeds,
|
194
|
-
)
|
195
|
-
if suffix_c is None:
|
196
|
-
suffix_c = get_suffix_c(board, mm_per_second)
|
197
|
-
|
198
|
-
b, m = get_equation(
|
199
|
-
board, accel=acceleration, suffix_c=suffix_c, fix_speeds=fix_speeds
|
200
|
-
)
|
201
|
-
speed_value = get_value_from_speed(mm_per_second, b, m)
|
202
|
-
|
203
|
-
if fix_lows and speed_value < 0:
|
204
|
-
# produced a negative speed value, go ahead and set that to 0
|
205
|
-
speed_value = 0
|
206
|
-
encoded_speed = encode_16bit(speed_value)
|
207
|
-
|
208
|
-
if raster_step != 0:
|
209
|
-
# There is no C suffix notation for raster step.
|
210
|
-
if isinstance(raster_step, tuple):
|
211
|
-
return f"V{encoded_speed}{acceleration:1d}G{abs(raster_step[0]):03d}G{abs(raster_step[1]):03d}"
|
212
|
-
else:
|
213
|
-
return f"V{encoded_speed}{acceleration:1d}G{abs(raster_step):03d}"
|
214
|
-
|
215
|
-
if d_ratio == 0 or board in ("A", "B", "M"):
|
216
|
-
# We do not need the diagonal code.
|
217
|
-
if raster_step == 0:
|
218
|
-
if suffix_c:
|
219
|
-
return f"CV{encoded_speed}1C"
|
220
|
-
else:
|
221
|
-
return f"CV{encoded_speed}{acceleration:1d}"
|
222
|
-
else:
|
223
|
-
step_value = min(int(floor(mm_per_second) + 1), 128)
|
224
|
-
frequency_kHz = float(mm_per_second) / 25.4
|
225
|
-
try:
|
226
|
-
period_in_ms = 1 / frequency_kHz
|
227
|
-
except ZeroDivisionError:
|
228
|
-
period_in_ms = 0
|
229
|
-
d_value = d_ratio * m * period_in_ms / float(step_value)
|
230
|
-
|
231
|
-
if fix_lows:
|
232
|
-
if d_value > 0xFFFF:
|
233
|
-
d_value = 0xFFFF
|
234
|
-
if d_value < 0:
|
235
|
-
d_value = 0
|
236
|
-
encoded_diagonal = encode_16bit(d_value)
|
237
|
-
if suffix_c:
|
238
|
-
return f"CV{encoded_speed}1{step_value:03d}{encoded_diagonal}C"
|
239
|
-
else:
|
240
|
-
return (
|
241
|
-
f"CV{encoded_speed}{acceleration:1d}{step_value:03d}{encoded_diagonal}"
|
242
|
-
)
|
243
|
-
|
244
|
-
|
245
|
-
def parse_speed_code(speed_code):
|
246
|
-
"""
|
247
|
-
Parses a speedcode into the relevant parts these are:
|
248
|
-
Prefixed codes CV or V, the code value which is a string of numbers that is either
|
249
|
-
7 or 16 characters long. With bugged versions being permitted to be 5 characters longer
|
250
|
-
being either 12 or 21 characters long. Since the initial 3 character string becomes an
|
251
|
-
8 character string falling out of the 000-255 range and becoming (16777216-v).
|
252
|
-
|
253
|
-
Codes with a suffix-c value are equal to 1/12th with different timings.
|
254
|
-
|
255
|
-
Codes with G-values are raster stepped. Two of these codes implies unidirectional rasters
|
256
|
-
but the those are a specific (x,0) step sequence.
|
257
|
-
|
258
|
-
@param speed_code: Speedcode to parse
|
259
|
-
@return: code_value, accel, step_value, diagonal, raster_step, suffix_c
|
260
|
-
"""
|
261
|
-
|
262
|
-
suffix_c = False
|
263
|
-
prefix_c = False
|
264
|
-
start = 0
|
265
|
-
end = len(speed_code)
|
266
|
-
if speed_code[start] == "C":
|
267
|
-
start += 1
|
268
|
-
prefix_c = True
|
269
|
-
if speed_code[end - 1] == "C":
|
270
|
-
end -= 1
|
271
|
-
suffix_c = True
|
272
|
-
if speed_code[start : start + 4] == "V167" and speed_code[start + 4] not in (
|
273
|
-
"0",
|
274
|
-
"1",
|
275
|
-
"2",
|
276
|
-
):
|
277
|
-
# The 4th character can only be 0,1,2 except for error speeds.
|
278
|
-
code_value = decode_16bit(speed_code[start + 1 : start + 12])
|
279
|
-
start += 12
|
280
|
-
# The value for this speed is so low, it's negative
|
281
|
-
# and bit-shifted in 24 bits of a negative number.
|
282
|
-
# These are produced by chinese software but are not valid.
|
283
|
-
else:
|
284
|
-
code_value = decode_16bit(speed_code[start + 1 : start + 7])
|
285
|
-
start += 7
|
286
|
-
code_value = 65536 - code_value
|
287
|
-
accel = int(speed_code[start])
|
288
|
-
start += 1
|
289
|
-
|
290
|
-
raster_step = 0
|
291
|
-
if speed_code[end - 4] == "G":
|
292
|
-
raster_step = int(speed_code[end - 3 : end])
|
293
|
-
end -= 4
|
294
|
-
# Removes Gxxx
|
295
|
-
if speed_code[end - 4] == "G":
|
296
|
-
raster_step = (int(speed_code[end - 3 : end]), raster_step)
|
297
|
-
end -= 4
|
298
|
-
# Removes `Gxxx`, means this it was `GxxxGxxx`.
|
299
|
-
step_value = 0
|
300
|
-
diagonal = 0
|
301
|
-
if (end + 1) - start >= 9:
|
302
|
-
step_value = int(speed_code[start : start + 3])
|
303
|
-
diagonal = decode_16bit(speed_code[start + 3 : end])
|
304
|
-
return code_value, accel, step_value, diagonal, raster_step, suffix_c
|
305
|
-
|
306
|
-
|
307
|
-
def get_value_from_speed(mm_per_second, b, m):
|
308
|
-
"""
|
309
|
-
Calculates speed value from a given speed.
|
310
|
-
"""
|
311
|
-
try:
|
312
|
-
frequency_kHz = float(mm_per_second) / 25.4
|
313
|
-
period_in_ms = 1.0 / frequency_kHz
|
314
|
-
return 65536 - get_value_from_period(period_in_ms, b, m)
|
315
|
-
except ZeroDivisionError:
|
316
|
-
return 65536 - b
|
317
|
-
|
318
|
-
|
319
|
-
def get_value_from_period(x, b, m):
|
320
|
-
"""
|
321
|
-
Takes in period in ms and converts it to value.
|
322
|
-
This is a simple linear relationship.
|
323
|
-
"""
|
324
|
-
return m * x + b
|
325
|
-
|
326
|
-
|
327
|
-
def get_speed_from_value(value, b, m):
|
328
|
-
try:
|
329
|
-
period_in_ms = get_period_from_value(value, b, m)
|
330
|
-
frequency_kHz = 1 / period_in_ms
|
331
|
-
return 25.4 * frequency_kHz
|
332
|
-
except ZeroDivisionError:
|
333
|
-
return 0
|
334
|
-
|
335
|
-
|
336
|
-
def get_period_from_value(y, b, m):
|
337
|
-
try:
|
338
|
-
return (y - b) / m
|
339
|
-
except ZeroDivisionError:
|
340
|
-
return float("inf")
|
341
|
-
|
342
|
-
|
343
|
-
def decode_16bit(code):
|
344
|
-
b1 = int(code[0:-3])
|
345
|
-
if b1 > 16000000:
|
346
|
-
b1 -= 16777216 # decode error negative numbers
|
347
|
-
if b1 > 0x7FFF:
|
348
|
-
b1 = b1 - 0xFFFF
|
349
|
-
b2 = int(code[-3:])
|
350
|
-
return (b1 << 8) + b2
|
351
|
-
|
352
|
-
|
353
|
-
def encode_16bit(value):
|
354
|
-
value = int(value)
|
355
|
-
b0 = value & 255
|
356
|
-
b1 = (value >> 8) & 0xFFFFFF # unsigned shift, to emulate bugged form.
|
357
|
-
return f"{b1:03d}{b0:03d}"
|
358
|
-
|
359
|
-
|
360
|
-
def get_acceleration_for_speed(
|
361
|
-
mm_per_second, raster=False, raster_horizontal=True, fix_speeds=False
|
362
|
-
):
|
363
|
-
"""
|
364
|
-
Gets the acceleration factor for a particular speed.
|
365
|
-
|
366
|
-
It is known that vertical rastering has different acceleration factors.
|
367
|
-
|
368
|
-
This is not fully mapped out but appeared more in line with non-rastering values.
|
369
|
-
|
370
|
-
@param mm_per_second: Speed to find acceleration value for.
|
371
|
-
@param raster: Whether this speed is for a rastering.
|
372
|
-
@param raster_horizontal: Whether this speed is for horizontal rastering (top-to-bottom, y-axis speed)
|
373
|
-
@param fix_speeds: is fixed speed mode on?
|
374
|
-
@return: 1-4: Value for the accel factor.
|
375
|
-
"""
|
376
|
-
if fix_speeds:
|
377
|
-
# when speeds are fixed the values from the software were determined based on the flawed codes empirically
|
378
|
-
mm_per_second /= 0.919493599053179
|
379
|
-
if mm_per_second <= 25.4:
|
380
|
-
return 1
|
381
|
-
if 25.4 < mm_per_second <= 60:
|
382
|
-
return 2
|
383
|
-
if raster and raster_horizontal:
|
384
|
-
if 60 < mm_per_second < 127:
|
385
|
-
return 2
|
386
|
-
if 127 <= mm_per_second <= 320:
|
387
|
-
return 3
|
388
|
-
if 320 <= mm_per_second:
|
389
|
-
return 4
|
390
|
-
else:
|
391
|
-
if 60 < mm_per_second < 127:
|
392
|
-
return 3
|
393
|
-
if 127 <= mm_per_second:
|
394
|
-
return 4
|
395
|
-
|
396
|
-
|
397
|
-
def get_suffix_c(board, mm_per_second=None):
|
398
|
-
"""
|
399
|
-
Due to a bug in the Chinese software the cutoff for the B2 machine is the same as the M2
|
400
|
-
at 7, but because if the half-stepping the invalid range the minimum speed is 9.509.
|
401
|
-
And this is below the threshold. Speeds between 7-9.509 will be invalid.
|
402
|
-
|
403
|
-
Since the B2 board is intended to duplicate this it will error as well.
|
404
|
-
"""
|
405
|
-
|
406
|
-
if board == "B2":
|
407
|
-
if mm_per_second < 7:
|
408
|
-
return True
|
409
|
-
if board in ("M2", "M3") and mm_per_second < 7:
|
410
|
-
return True
|
411
|
-
return False
|
412
|
-
|
413
|
-
|
414
|
-
def get_equation(board, accel=1, suffix_c=False, fix_speeds=False):
|
415
|
-
"""
|
416
|
-
The speed for the M2 was physically checked and found to be inaccurate.
|
417
|
-
If strict is used it will seek to strictly emulate the Chinese software.
|
418
|
-
|
419
|
-
The physical device scaled properly with a different slope.
|
420
|
-
|
421
|
-
The correct value has been established for the M2 board. It's guessed at for
|
422
|
-
the B2 board being twice the M2 board. It is not known for A or B, B1 or B2
|
423
|
-
"""
|
424
|
-
b = 784.0
|
425
|
-
if accel == 3:
|
426
|
-
b = 896.0
|
427
|
-
if accel == 4:
|
428
|
-
b = 1024.0
|
429
|
-
if board in ("A", "B", "B1"):
|
430
|
-
# A, B, B1 have no known suffix-C equations.
|
431
|
-
return b, 2000.0
|
432
|
-
|
433
|
-
m = 12120.0
|
434
|
-
if fix_speeds:
|
435
|
-
m = 11148.0
|
436
|
-
if board == "B2":
|
437
|
-
m *= 2
|
438
|
-
if suffix_c:
|
439
|
-
return b, m / 12.0
|
440
|
-
else:
|
441
|
-
# Non-B2 b-values
|
442
|
-
if accel == 3:
|
443
|
-
b = 5632.0
|
444
|
-
elif accel == 4:
|
445
|
-
b = 6144.0
|
446
|
-
else:
|
447
|
-
b = 5120.0
|
448
|
-
if suffix_c:
|
449
|
-
return 8.0, m / 12.0
|
450
|
-
return b, m
|
1
|
+
#!/usr/bin/env python
|
2
|
+
|
3
|
+
"""
|
4
|
+
LaserSpeed
|
5
|
+
|
6
|
+
This is the standard library for converting to and from speed code information for LHYMICRO-GL.
|
7
|
+
"""
|
8
|
+
|
9
|
+
|
10
|
+
from math import floor
|
11
|
+
|
12
|
+
|
13
|
+
class LaserSpeed:
|
14
|
+
"""
|
15
|
+
MIT License.
|
16
|
+
|
17
|
+
This is the standard library for converting to and from speed code information for LHYMICRO-GL.
|
18
|
+
|
19
|
+
The units in the speed code have acceleration/deceleration factors which slightly modifies the equations used
|
20
|
+
to convert between values and speeds. The fundamental units within the speed code values are period-ticks.
|
21
|
+
All values relate to a value in the counter to count off the number of oscillations within the
|
22
|
+
(typically 22.1184) Mhz crystal. The max value here is 65535, with the addition of a diagonal delay.
|
23
|
+
|
24
|
+
For the M2 board, the original Chinese Software gave a slope of 12120. However, experiments with the actual
|
25
|
+
physical speed put this value at 11142, which properly reflects that all speeds tend to be at 91.98% of the
|
26
|
+
requested speed.
|
27
|
+
|
28
|
+
The board is ultimately controlling a stepper motor and the speed a stepper motor travels is the result of
|
29
|
+
the time between the ticks. Since the crystal oscillator is the same, the delay is controlled by the counted
|
30
|
+
oscillations subticks, which gives us the time between stepper motor pulses. Most of the devices we are
|
31
|
+
dealing with are 1000 dpi stepper motors, so, for example, to travel at 1 inch a second requires that the
|
32
|
+
device tick at 1 kHz. To do this it must delay 1 ms between ticks. This corresponds to a value of 48296 in
|
33
|
+
the M2 board. Which has an equation of 65536 - (5120 + 12120T) where T is the period requested in ms. This is
|
34
|
+
equal to 25.4 mm/s. If we want a 2 ms delay, which is half the speed (0.5kHz, 0.5 inches/second, 12.7 mm/s)
|
35
|
+
we do 65536 - (5120 + 24240) which gives us a value of 36176. This would be encoded as a 16-bit number
|
36
|
+
broken up into 2 ascii 3 digit strings between 0-255. 141 for the high bits and 80 for the low bits.
|
37
|
+
So CV01410801 where the final character "1" is the acceleration factor since it's within that range.
|
38
|
+
|
39
|
+
The speed in mm/s is also used for determining which acceleration to use and as a factor for some boards
|
40
|
+
(B2, M2) the horizontal encoded value. Slowing down the device down while traveling diagonally makes the
|
41
|
+
diagonal and orthogonal take the same amount of time (thereby cutting to the same depth). These are the same
|
42
|
+
period-ticks units and is simply summed with the 65536 - (b + mT) value in cases that both stepper motors
|
43
|
+
are used.
|
44
|
+
"""
|
45
|
+
|
46
|
+
def __init__(
|
47
|
+
self,
|
48
|
+
board="M2",
|
49
|
+
speed=None,
|
50
|
+
raster_step=None,
|
51
|
+
d_ratio=None,
|
52
|
+
suffix_c=None,
|
53
|
+
acceleration=None,
|
54
|
+
raster_horizontal=True,
|
55
|
+
fix_speeds=False,
|
56
|
+
fix_lows=False,
|
57
|
+
fix_limit=False,
|
58
|
+
):
|
59
|
+
self.speed = speed
|
60
|
+
self.board = board
|
61
|
+
self.d_ratio = d_ratio
|
62
|
+
self.raster_step = raster_step
|
63
|
+
|
64
|
+
self.acceleration = acceleration
|
65
|
+
self.suffix_c = suffix_c
|
66
|
+
self.raster_horizontal = raster_horizontal
|
67
|
+
self.fix_speeds = fix_speeds
|
68
|
+
self.fix_lows = fix_lows
|
69
|
+
self.fix_limit = fix_limit
|
70
|
+
|
71
|
+
if isinstance(speed, str):
|
72
|
+
# this is a speedcode value.
|
73
|
+
(
|
74
|
+
code_value,
|
75
|
+
accel,
|
76
|
+
step_value,
|
77
|
+
diagonal,
|
78
|
+
raster_step,
|
79
|
+
suffix_c,
|
80
|
+
) = parse_speed_code(self.speed)
|
81
|
+
b, m = get_equation(
|
82
|
+
self.board,
|
83
|
+
accel=accel,
|
84
|
+
suffix_c=suffix_c,
|
85
|
+
fix_speeds=self.fix_speeds,
|
86
|
+
)
|
87
|
+
self.speed = get_speed_from_value(code_value, b, m)
|
88
|
+
self.acceleration = accel
|
89
|
+
self.raster_step = raster_step
|
90
|
+
self.suffix_c = suffix_c
|
91
|
+
|
92
|
+
def __str__(self):
|
93
|
+
return self.speedcode
|
94
|
+
|
95
|
+
def __repr__(self):
|
96
|
+
parts = list()
|
97
|
+
if self.board != "M2":
|
98
|
+
parts.append(f'board="{self.board}"')
|
99
|
+
if self.speed is not None:
|
100
|
+
parts.append(f"speed={self.speed}")
|
101
|
+
if self.d_ratio is not None:
|
102
|
+
parts.append(f"d_ratio={self.d_ratio}")
|
103
|
+
if self.raster_step != 0:
|
104
|
+
parts.append(f"raster_step={self.raster_step}")
|
105
|
+
if self.suffix_c is not None:
|
106
|
+
parts.append(f"suffix_c={str(self.suffix_c)}")
|
107
|
+
if self.acceleration is not None:
|
108
|
+
parts.append(f"acceleration={self.acceleration}")
|
109
|
+
if self.fix_speeds:
|
110
|
+
parts.append(f"fix_speeds={str(self.fix_speeds)}")
|
111
|
+
if self.fix_lows:
|
112
|
+
parts.append(f"fix_lows={str(self.fix_lows)}")
|
113
|
+
if self.fix_limit:
|
114
|
+
parts.append(f"fix_limit={str(self.fix_limit)}")
|
115
|
+
if not self.raster_horizontal:
|
116
|
+
parts.append(f"raster_horizontal={str(self.raster_horizontal)}")
|
117
|
+
return f"LaserSpeed({', '.join(parts)})"
|
118
|
+
|
119
|
+
@property
|
120
|
+
def speedcode(self):
|
121
|
+
return get_code_from_speed(
|
122
|
+
self.speed,
|
123
|
+
self.raster_step,
|
124
|
+
self.board,
|
125
|
+
self.d_ratio,
|
126
|
+
self.acceleration,
|
127
|
+
self.suffix_c,
|
128
|
+
fix_limit=self.fix_limit,
|
129
|
+
fix_speeds=self.fix_speeds,
|
130
|
+
fix_lows=self.fix_lows,
|
131
|
+
raster_horizontal=self.raster_horizontal,
|
132
|
+
)
|
133
|
+
|
134
|
+
|
135
|
+
def get_speed_from_code(speed_code, board="M2", fix_speeds=False):
|
136
|
+
"""
|
137
|
+
Gets the speed expected from a speedcode. Should calculate the expected speed from the data code given.
|
138
|
+
@param speed_code: The speedcode to check.
|
139
|
+
@param board: The board this speedcode was made for.
|
140
|
+
@param fix_speeds: Is this speedcode in a fixed_speed code?
|
141
|
+
@return:
|
142
|
+
"""
|
143
|
+
(
|
144
|
+
code_value,
|
145
|
+
accel,
|
146
|
+
step_value,
|
147
|
+
diagonal,
|
148
|
+
raster_step,
|
149
|
+
suffix_c,
|
150
|
+
) = parse_speed_code(speed_code)
|
151
|
+
b, m = get_equation(board, accel=accel, suffix_c=suffix_c, fix_speeds=fix_speeds)
|
152
|
+
return get_speed_from_value(code_value, b, m)
|
153
|
+
|
154
|
+
|
155
|
+
def get_code_from_speed(
|
156
|
+
mm_per_second,
|
157
|
+
raster_step=0,
|
158
|
+
board="M2",
|
159
|
+
d_ratio=None,
|
160
|
+
acceleration=None,
|
161
|
+
suffix_c=None,
|
162
|
+
fix_limit=False,
|
163
|
+
fix_speeds=False,
|
164
|
+
fix_lows=False,
|
165
|
+
raster_horizontal=True,
|
166
|
+
):
|
167
|
+
"""
|
168
|
+
Get a speedcode from a given speed. The raster step appends the 'G' value and uses speed ranges.
|
169
|
+
The d_ratio uses the default/auto ratio. The accel is optional and forces the speedcode to work
|
170
|
+
for that particular acceleration.
|
171
|
+
|
172
|
+
@param mm_per_second: speed to convert to code.
|
173
|
+
@param raster_step: raster step mode to use. Use (g0,g1) tuple for unidirectional valuations.
|
174
|
+
@param board: Nano Board Model
|
175
|
+
@param d_ratio: M1, M2, B1, B2 have ratio of optional speed
|
176
|
+
@param acceleration: Optional force acceleration code rather than default for that speed.
|
177
|
+
@param suffix_c: Optional force suffix_c mode for the board. (True forces suffix_c on, False forces it off)
|
178
|
+
@param fix_limit: Removes max speed limit.
|
179
|
+
@param fix_speeds: Give corrected speed (faster by 8.9%)
|
180
|
+
@param fix_lows: Force low speeds into correct bounds.
|
181
|
+
@param raster_horizontal: is it rastering with the laser head, or the much heavier bar?
|
182
|
+
@return: speed code produced.
|
183
|
+
"""
|
184
|
+
if d_ratio is None:
|
185
|
+
d_ratio = 0.261199033289
|
186
|
+
if not fix_limit and mm_per_second > 240 and raster_step == 0:
|
187
|
+
mm_per_second = 19.05 # Arbitrary default speed for out range value.
|
188
|
+
if acceleration is None:
|
189
|
+
acceleration = get_acceleration_for_speed(
|
190
|
+
mm_per_second,
|
191
|
+
raster_step != 0,
|
192
|
+
raster_horizontal=raster_horizontal,
|
193
|
+
fix_speeds=fix_speeds,
|
194
|
+
)
|
195
|
+
if suffix_c is None:
|
196
|
+
suffix_c = get_suffix_c(board, mm_per_second)
|
197
|
+
|
198
|
+
b, m = get_equation(
|
199
|
+
board, accel=acceleration, suffix_c=suffix_c, fix_speeds=fix_speeds
|
200
|
+
)
|
201
|
+
speed_value = get_value_from_speed(mm_per_second, b, m)
|
202
|
+
|
203
|
+
if fix_lows and speed_value < 0:
|
204
|
+
# produced a negative speed value, go ahead and set that to 0
|
205
|
+
speed_value = 0
|
206
|
+
encoded_speed = encode_16bit(speed_value)
|
207
|
+
|
208
|
+
if raster_step != 0:
|
209
|
+
# There is no C suffix notation for raster step.
|
210
|
+
if isinstance(raster_step, tuple):
|
211
|
+
return f"V{encoded_speed}{acceleration:1d}G{abs(raster_step[0]):03d}G{abs(raster_step[1]):03d}"
|
212
|
+
else:
|
213
|
+
return f"V{encoded_speed}{acceleration:1d}G{abs(raster_step):03d}"
|
214
|
+
|
215
|
+
if d_ratio == 0 or board in ("A", "B", "M"):
|
216
|
+
# We do not need the diagonal code.
|
217
|
+
if raster_step == 0:
|
218
|
+
if suffix_c:
|
219
|
+
return f"CV{encoded_speed}1C"
|
220
|
+
else:
|
221
|
+
return f"CV{encoded_speed}{acceleration:1d}"
|
222
|
+
else:
|
223
|
+
step_value = min(int(floor(mm_per_second) + 1), 128)
|
224
|
+
frequency_kHz = float(mm_per_second) / 25.4
|
225
|
+
try:
|
226
|
+
period_in_ms = 1 / frequency_kHz
|
227
|
+
except ZeroDivisionError:
|
228
|
+
period_in_ms = 0
|
229
|
+
d_value = d_ratio * m * period_in_ms / float(step_value)
|
230
|
+
|
231
|
+
if fix_lows:
|
232
|
+
if d_value > 0xFFFF:
|
233
|
+
d_value = 0xFFFF
|
234
|
+
if d_value < 0:
|
235
|
+
d_value = 0
|
236
|
+
encoded_diagonal = encode_16bit(d_value)
|
237
|
+
if suffix_c:
|
238
|
+
return f"CV{encoded_speed}1{step_value:03d}{encoded_diagonal}C"
|
239
|
+
else:
|
240
|
+
return (
|
241
|
+
f"CV{encoded_speed}{acceleration:1d}{step_value:03d}{encoded_diagonal}"
|
242
|
+
)
|
243
|
+
|
244
|
+
|
245
|
+
def parse_speed_code(speed_code):
|
246
|
+
"""
|
247
|
+
Parses a speedcode into the relevant parts these are:
|
248
|
+
Prefixed codes CV or V, the code value which is a string of numbers that is either
|
249
|
+
7 or 16 characters long. With bugged versions being permitted to be 5 characters longer
|
250
|
+
being either 12 or 21 characters long. Since the initial 3 character string becomes an
|
251
|
+
8 character string falling out of the 000-255 range and becoming (16777216-v).
|
252
|
+
|
253
|
+
Codes with a suffix-c value are equal to 1/12th with different timings.
|
254
|
+
|
255
|
+
Codes with G-values are raster stepped. Two of these codes implies unidirectional rasters
|
256
|
+
but the those are a specific (x,0) step sequence.
|
257
|
+
|
258
|
+
@param speed_code: Speedcode to parse
|
259
|
+
@return: code_value, accel, step_value, diagonal, raster_step, suffix_c
|
260
|
+
"""
|
261
|
+
|
262
|
+
suffix_c = False
|
263
|
+
prefix_c = False
|
264
|
+
start = 0
|
265
|
+
end = len(speed_code)
|
266
|
+
if speed_code[start] == "C":
|
267
|
+
start += 1
|
268
|
+
prefix_c = True
|
269
|
+
if speed_code[end - 1] == "C":
|
270
|
+
end -= 1
|
271
|
+
suffix_c = True
|
272
|
+
if speed_code[start : start + 4] == "V167" and speed_code[start + 4] not in (
|
273
|
+
"0",
|
274
|
+
"1",
|
275
|
+
"2",
|
276
|
+
):
|
277
|
+
# The 4th character can only be 0,1,2 except for error speeds.
|
278
|
+
code_value = decode_16bit(speed_code[start + 1 : start + 12])
|
279
|
+
start += 12
|
280
|
+
# The value for this speed is so low, it's negative
|
281
|
+
# and bit-shifted in 24 bits of a negative number.
|
282
|
+
# These are produced by chinese software but are not valid.
|
283
|
+
else:
|
284
|
+
code_value = decode_16bit(speed_code[start + 1 : start + 7])
|
285
|
+
start += 7
|
286
|
+
code_value = 65536 - code_value
|
287
|
+
accel = int(speed_code[start])
|
288
|
+
start += 1
|
289
|
+
|
290
|
+
raster_step = 0
|
291
|
+
if speed_code[end - 4] == "G":
|
292
|
+
raster_step = int(speed_code[end - 3 : end])
|
293
|
+
end -= 4
|
294
|
+
# Removes Gxxx
|
295
|
+
if speed_code[end - 4] == "G":
|
296
|
+
raster_step = (int(speed_code[end - 3 : end]), raster_step)
|
297
|
+
end -= 4
|
298
|
+
# Removes `Gxxx`, means this it was `GxxxGxxx`.
|
299
|
+
step_value = 0
|
300
|
+
diagonal = 0
|
301
|
+
if (end + 1) - start >= 9:
|
302
|
+
step_value = int(speed_code[start : start + 3])
|
303
|
+
diagonal = decode_16bit(speed_code[start + 3 : end])
|
304
|
+
return code_value, accel, step_value, diagonal, raster_step, suffix_c
|
305
|
+
|
306
|
+
|
307
|
+
def get_value_from_speed(mm_per_second, b, m):
|
308
|
+
"""
|
309
|
+
Calculates speed value from a given speed.
|
310
|
+
"""
|
311
|
+
try:
|
312
|
+
frequency_kHz = float(mm_per_second) / 25.4
|
313
|
+
period_in_ms = 1.0 / frequency_kHz
|
314
|
+
return 65536 - get_value_from_period(period_in_ms, b, m)
|
315
|
+
except ZeroDivisionError:
|
316
|
+
return 65536 - b
|
317
|
+
|
318
|
+
|
319
|
+
def get_value_from_period(x, b, m):
|
320
|
+
"""
|
321
|
+
Takes in period in ms and converts it to value.
|
322
|
+
This is a simple linear relationship.
|
323
|
+
"""
|
324
|
+
return m * x + b
|
325
|
+
|
326
|
+
|
327
|
+
def get_speed_from_value(value, b, m):
|
328
|
+
try:
|
329
|
+
period_in_ms = get_period_from_value(value, b, m)
|
330
|
+
frequency_kHz = 1 / period_in_ms
|
331
|
+
return 25.4 * frequency_kHz
|
332
|
+
except ZeroDivisionError:
|
333
|
+
return 0
|
334
|
+
|
335
|
+
|
336
|
+
def get_period_from_value(y, b, m):
|
337
|
+
try:
|
338
|
+
return (y - b) / m
|
339
|
+
except ZeroDivisionError:
|
340
|
+
return float("inf")
|
341
|
+
|
342
|
+
|
343
|
+
def decode_16bit(code):
|
344
|
+
b1 = int(code[0:-3])
|
345
|
+
if b1 > 16000000:
|
346
|
+
b1 -= 16777216 # decode error negative numbers
|
347
|
+
if b1 > 0x7FFF:
|
348
|
+
b1 = b1 - 0xFFFF
|
349
|
+
b2 = int(code[-3:])
|
350
|
+
return (b1 << 8) + b2
|
351
|
+
|
352
|
+
|
353
|
+
def encode_16bit(value):
|
354
|
+
value = int(value)
|
355
|
+
b0 = value & 255
|
356
|
+
b1 = (value >> 8) & 0xFFFFFF # unsigned shift, to emulate bugged form.
|
357
|
+
return f"{b1:03d}{b0:03d}"
|
358
|
+
|
359
|
+
|
360
|
+
def get_acceleration_for_speed(
|
361
|
+
mm_per_second, raster=False, raster_horizontal=True, fix_speeds=False
|
362
|
+
):
|
363
|
+
"""
|
364
|
+
Gets the acceleration factor for a particular speed.
|
365
|
+
|
366
|
+
It is known that vertical rastering has different acceleration factors.
|
367
|
+
|
368
|
+
This is not fully mapped out but appeared more in line with non-rastering values.
|
369
|
+
|
370
|
+
@param mm_per_second: Speed to find acceleration value for.
|
371
|
+
@param raster: Whether this speed is for a rastering.
|
372
|
+
@param raster_horizontal: Whether this speed is for horizontal rastering (top-to-bottom, y-axis speed)
|
373
|
+
@param fix_speeds: is fixed speed mode on?
|
374
|
+
@return: 1-4: Value for the accel factor.
|
375
|
+
"""
|
376
|
+
if fix_speeds:
|
377
|
+
# when speeds are fixed the values from the software were determined based on the flawed codes empirically
|
378
|
+
mm_per_second /= 0.919493599053179
|
379
|
+
if mm_per_second <= 25.4:
|
380
|
+
return 1
|
381
|
+
if 25.4 < mm_per_second <= 60:
|
382
|
+
return 2
|
383
|
+
if raster and raster_horizontal:
|
384
|
+
if 60 < mm_per_second < 127:
|
385
|
+
return 2
|
386
|
+
if 127 <= mm_per_second <= 320:
|
387
|
+
return 3
|
388
|
+
if 320 <= mm_per_second:
|
389
|
+
return 4
|
390
|
+
else:
|
391
|
+
if 60 < mm_per_second < 127:
|
392
|
+
return 3
|
393
|
+
if 127 <= mm_per_second:
|
394
|
+
return 4
|
395
|
+
|
396
|
+
|
397
|
+
def get_suffix_c(board, mm_per_second=None):
|
398
|
+
"""
|
399
|
+
Due to a bug in the Chinese software the cutoff for the B2 machine is the same as the M2
|
400
|
+
at 7, but because if the half-stepping the invalid range the minimum speed is 9.509.
|
401
|
+
And this is below the threshold. Speeds between 7-9.509 will be invalid.
|
402
|
+
|
403
|
+
Since the B2 board is intended to duplicate this it will error as well.
|
404
|
+
"""
|
405
|
+
|
406
|
+
if board == "B2":
|
407
|
+
if mm_per_second < 7:
|
408
|
+
return True
|
409
|
+
if board in ("M2", "M3") and mm_per_second < 7:
|
410
|
+
return True
|
411
|
+
return False
|
412
|
+
|
413
|
+
|
414
|
+
def get_equation(board, accel=1, suffix_c=False, fix_speeds=False):
|
415
|
+
"""
|
416
|
+
The speed for the M2 was physically checked and found to be inaccurate.
|
417
|
+
If strict is used it will seek to strictly emulate the Chinese software.
|
418
|
+
|
419
|
+
The physical device scaled properly with a different slope.
|
420
|
+
|
421
|
+
The correct value has been established for the M2 board. It's guessed at for
|
422
|
+
the B2 board being twice the M2 board. It is not known for A or B, B1 or B2
|
423
|
+
"""
|
424
|
+
b = 784.0
|
425
|
+
if accel == 3:
|
426
|
+
b = 896.0
|
427
|
+
if accel == 4:
|
428
|
+
b = 1024.0
|
429
|
+
if board in ("A", "B", "B1"):
|
430
|
+
# A, B, B1 have no known suffix-C equations.
|
431
|
+
return b, 2000.0
|
432
|
+
|
433
|
+
m = 12120.0
|
434
|
+
if fix_speeds:
|
435
|
+
m = 11148.0
|
436
|
+
if board == "B2":
|
437
|
+
m *= 2
|
438
|
+
if suffix_c:
|
439
|
+
return b, m / 12.0
|
440
|
+
else:
|
441
|
+
# Non-B2 b-values
|
442
|
+
if accel == 3:
|
443
|
+
b = 5632.0
|
444
|
+
elif accel == 4:
|
445
|
+
b = 6144.0
|
446
|
+
else:
|
447
|
+
b = 5120.0
|
448
|
+
if suffix_c:
|
449
|
+
return 8.0, m / 12.0
|
450
|
+
return b, m
|