Compare commits

..

13 Commits

Author SHA1 Message Date
devdesk
4523cb6aff default offsets for the drawbot with limit switches 2025-12-04 14:41:38 +02:00
devdesk
e345067286 Add plotter_disable_command parameter with default value M5 2025-12-04 14:40:58 +02:00
devdesk
3b5a7e0e8c Update README with X/Y offset parameters documentation 2025-12-03 19:53:20 +02:00
devdesk
51a436ff5b Add configurable X/Y offset parameters for plotter positioning
- Added offset-x and offset-y parameters to plotter-lod.inx (default: X=180, Y=0)
- Updated plotter-lod.py to apply offsets to all G-code coordinates
- Modified footer to use dynamic offset values
- Allows users to adjust plotter start position through GUI without code changes
2025-12-03 19:43:40 +02:00
devdesk
925a23b0ef from the manufacture (to markdown) 2025-10-23 19:43:12 +03:00
devdesk
6adfb97eab fit for inkscape 1.3+ 2025-10-23 19:34:20 +03:00
Adrien Centonze
9fd2ec24e1 minor modification 2021-06-05 09:32:54 +02:00
Adrien Centonze
f16bd4398b renaming the project 2021-06-05 08:49:33 +02:00
adricen
d75c6782f6 minor modification of the README.md 2021-04-29 12:07:17 +02:00
adricen
2f11017bbf update of the documentation inside readme file 2021-04-29 11:40:18 +02:00
adricen
49f24f6d7f update Gcode render to display inside grblcontrol 2021-04-28 19:16:47 +02:00
adricen
3f0db2fe4d update inx direction for dependency 2021-04-02 12:22:26 +02:00
adricen
ef657bff91 update .py file 2021-04-02 12:18:15 +02:00
5 changed files with 156 additions and 29 deletions

View File

@@ -1,40 +1,57 @@
# XY Plotter Tool by Love Open Design
# LY Drawbot Tool
This is the ~~official~~ repository for the XY Plotter Tool Inkscape extension.
This is the official repository for the XY Plotter Tool Inkscape extension.
## Purpose
This extension work for the [DIY XY Plotter High Precision Drawbot](https://www.aliexpress.com/item/32917861259.html?spm=a2g0s.9042311.0.0.3d9f6c37xpT5iS) on Ali Express
This extension work for the [DIY XY Plotter High Precision Drawbot](https://www.aliexpress.com/item/32917861259.html?spm=a2g0s.9042311.0.0.3d9f6c37xpT5iS)
* This is made for Inkscape 1.0 and above.
* This machin is using GRBL Control with GRBL Arduino Shield
## Installation
Download the latest release [here](https://github.com/love-open-design/XY-Plotter-Tool-by-LOD/release). Make sure to select the release targeted towards the version of Inkscape you are using. You can find the version of Inkscape you're using under **Help** > **About**.
clone or downalod the zip of this git, Unzip the files directly into the Inkscape user extensions folder. Inkscape lists the location of your extensions folder under **Edit** > **Preferences** > **System**.
Unzip the files directly into the Inkscape user extensions folder. Inkscape lists the location of your extensions folder under **Edit** > **Preferences** > **System**.
Restart Inkscape and you're done. if you are just changing the `.py` you dont have to restart inkscape, but any changes to the `.idx` will need an inkscape resatrt.
Restart Inkscape and you're done.
## Gcode Panel
## Documentation
> Inside `Inkscape > Extension > drawbot`
## Basic command
![XY Plotter tool panel](img/GcodePanelByLOD.jpeg)
* Pen Up: `M5 S0`
* Pen Down: `M3 S1000`
* Pen Delay: `P4 P<your delay ms>`
* Pen Speed Movement: `G1 F<your speed>`
| Name | Definition | Default | Gcode Result |
|---|---| --- | --- |
| **Drawing On Command** | Gcode commande to lower down the Z-axis | `M3` | `M3 S1000` |
| **Drawing Off Command** | Gcode commande to upper the Z-axis | `M5` | `M5 S0` |
| **Pen Up Travel speed** | Travel speed with Pen Up | `3000` | `G1 F3000` |
| **Pen Down Travel speed** | Travel speed when drawing | `1500` | `G1 F1500` |
| **Pen Active Power** | command value to lower the pen | `1000` | `M3 S1000` |
| **Pen On Delay** | Delay after moving and before drawing | `0,1` | `G4 P0.1` |
| **Pen Off Delay** | Delay after drawing and before moving | `0,2` | `G4 P0.2` |
| **X Offset** | X-axis offset for plotter start position | `180` | All X coordinates shifted by offset value |
| **Y Offset** | Y-axis offset for plotter start position | `0` | All Y coordinates shifted by offset value |
| **Passes** | Number of Passes | | |
| **Pass Depth** | *relative to cnc milling* | `1,0` | |
| **Directory** | path directory to save your file in absolute | | |
| **Filename + numeric value** | the numeric value increment your file with the same name | `output.gcode` | |
| **All Units** | **Important** Be sure to setting everything up to the same unit inside Inkscape - Document Units, Inkscape Units and </br>this output units otherwise it mae some stranges things | `mm` | |
### Custom G-code Header and Footer
Add "header" and "footer" text files without extensions in your destination directory to add custom commands. Don't forget to add a new line at the end of these two files.
If no files are detected the default values are :
- Header : G90 ; Absolute positioning
- Header : G90 ; Absolute positioningon the
- Header : G0 Z0 ; Display path inside GRBL Control
- Footer : G1 X0 Y0 ; Move to X0 Y0
## For developers
Pull requests are welcome. Just make sure to test your code on both Python >=2.6 and >=3.5 for the main branch, and Python >= 3.6 for the development branch (In the next major release we'll drop support for older python versions in an effort to improve code readability).
## Credits
20251202 - thanks to [love-open-design.com](https://love-open-design.com/laboratoire/xy-plotter-tool-par-love-open-design/), which we forked and adapted. see [upstream](https://github.com/love-open-design/LY-Drawbot-Tool-by-LOD)
This inkscape extension is adapted from [J-Tech-Photonics-Laser-Tool](https://github.com/JTechPhotonics/J-Tech-Photonics-Laser-Tool) inkscape extension.
Thanks to [StuartB44](https://www.instructables.com/member/StuartB44/) for his work and infos on [Instructables](https://www.instructables.com/Fix-for-Image-Not-Showing-in-GRBLControl/) to display GCode inside GRBL Control

85
grbl_setup.md Normal file
View File

@@ -0,0 +1,85 @@
# GRBL Configuration and Setting Up Your Machine for the First Time
First, connect to Grbl using the serial terminal of your choice.
Set the baud rate to 115200 as 8-N-1 (8-bits, no parity, and 1-stop bit.)
Once connected you should get the Grbl-prompt, which looks like this:
```
Grbl 0.9i ['$' for help]
```
Type `$` and press enter to have Grbl print a help message.
You should not see any local echo of the $ and enter. Grbl should respond with:
```
[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H ~ ! ? ctrl-x]
```
The $-commands are Grbl system commands used to tweak the settings, view or change Grbl's states and running modes, and start a homing cycle. The last four non-'$' commands are realtime control commands that can be sent at anytime, no matter what Grbl is doing.
These either immediately change Grbl's running behavior or immediately print a report of the important realtime data like current position (aka DRO).
`$$` - View Grbl settingsTo view the settings, type `$$` and press enter after connecting to Grbl. Grbl should respond with a list of the current system settings, as shown in the example below. All of these settings are persistent and kept in EEPROM, so if you power down, these will be loaded back up the next time you power up your Arduino.
`$x=val` - Save Grbl settingThe $x=val command saves or alters a Grbl setting, which can be done manually by sending this command when connected to Grbl through a serial terminal program, but most Grbl GUIs will do this for you as a user-friendly feature.
To manually change e.g. the microseconds step pulse option to 10us you would type this, followed by an enter:
```
$0=10
```
If everything went well, Grbl will respond with an 'ok' and this setting is stored in EEPROM and will be retained forever or until you change them.
You can check if Grbl has received and stored your setting correctly by typing $$ to view the system settings again.
Grbl's default configuration is intentionally very generic to help ensure users can see successful motion without having to tweak settings. Generally, the first thing you'll want to do is get your stepper motors running, usually without it connected to the CNC.
Wire Grbl to your stepper drivers and stepper motors according to your manufacturer guidelines. Connect to Grbl through a serial terminal or one of many Grbl GUIs. Send some G1 or G0 commands to Grbl. You should see your stepper motor rotating. If you are having trouble with your stepper motors, try the following:
- Ensure everything is wired and powered correctly per your stepper driver manufacturer guidelines.
- If your steppers are mounted in your CNC already, ensure your axes move freely and don't obviously bind. If you can't easily tell, try removing your steppers and check if they run under no load.
- Ensure your stepper motors and axes linear mechanisms are all tight and secure. Small set screws on drivetrain components becoming loose is a very common problem. Re-tighten and try applying some non-permenant thread locker (Loctite blue) if it continually loosens.
- For more difficult issues, try the process of elimination to quickly isolate the problem. Start by disconnecting everything from the Arduino. Test if Grbl is operating ok by itself. Then, add one thing at a time and test.
- If your steppers are powered and making a grinding noise when trying to move, try lowering the '$' acceleration and max rate settings. This sound is a sign that your steppers is losing steps and not able to keep up due too much torque load or going too fast.
- Grbl's default step pulse settings cover the vast majority of stepper drivers on the market. While very uncommon, check these settings if you are still experiencing problems or have a unusual setup.
Next, you will need to make sure your machine is moving in the correct directions according to a Cartesian(XYZ) coordinate frame.
Mount your stepper motors into your CNC, if you haven't already done so. Send Grbl some motion commands, such as `G91 G0 X1` or `G91 G0 X-1`, which will move the x-axis +1mm and -1mm, respectively.
Check all axes. If an axis is not moving correctly, alter the $3 direction port mask setting to invert the direction.
If you are unfamiliar with how coordinate frames are setup on CNC machines, see this great diagram by LinuxCNC. Just keep in mind that motions are relative to the tool. So on a typical CNC gantry router, the tool will move rather than the fixed table. If the x-axis is aligned positive to the right, a positive motion command will move the tool to the right. Whereas, a moving table with a fixed tool will move the table to the left for the same command, because the tool is moving to the right relative to the table.
Finally, tune your settings to get close to your desired or max performance. Start by ensuring your `$100`,`$101`, and `$102` axes step/mm settings are correct for your setup. This is dependent on your stepper increments, micro steps on your driver, and mechanical parameters. There are multiple resources online to show you how to compute this for your particular machine, if your machine manufacturer has not supplied this for you. Tweak your `$11x` acceleration and `$12x` max rate settings to improve performance. Set to no greater than 80% of absolute max to account for inertia and cutting forces. Set your `$13x` max travel settings if you plan on using homing or soft limits. It's recommended to enter something approximately close to actual travel now to avoid problems in the future.
At this point, you're pretty much ready to get going! Grbl can now move your CNC machine and run g-code jobs. If you need to add more features, such as limit switches for homing or hard limits or spindle/laser control. There are other Wiki pages to help you that. Good luck and have fun!
Here is my Setting
```
$0 = 10 (step pulse, usec)
$1 = 25 (step idle delay, msec)
$2 = 0 (step port invert mask:00000000)
$3 = 0 (dir port invert mask:00000000)
$4 = 0 (step enable invert, bool)
$5 = 0 (limit pins invert, bool)
$6 = 0 (probe pin invert, bool)
$10 = 3 (status report mask:00000011)
$11 = 0.010 (junction deviation, mm)
$12 = 0.002 (arc tolerance, mm)
$13 = 0 (report inches, bool)
$20 = 0 (soft limits, bool)
$21 = 0 (hard limits, bool)
$22 = 0 (homing cycle, bool)
$23 = 0 (homing dir invert mask:00000000)
$24 = 25.000 (homing feed, mm/min)
$25 = 500.000 (homing seek, mm/min)
$26 = 250 (homing debounce, msec)
$27 = 1.000 (homing pull-off, mm)
$100 = 100.000 (x, step/mm)
$101 = 100.000 (y, step/mm)
$102 = 100.000 (z, step/mm)
$110 = 5000.000 (x max rate, mm/min)
$111 = 5000.000 (y max rate, mm/min)
$112 = 500.000 (z max rate, mm/min)
$120 = 5000.000 (x accel, mm/sec^2)
$121 = 5000.000 (y accel, mm/sec^2)
$122 = 10.000 (z accel, mm/sec^2)
$130 = 200.000 (x max travel, mm)
$131 = 200.000 (y max travel, mm)
$132 = 200.000 (z max travel, mm)
```

BIN
img/GcodePanelByLOD.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

View File

@@ -1,17 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<_name>XY Plotter tool by Love Open Design</_name>
<_name>LY Drawbot tool by Love Open Design</_name>
<id>love-open-design.com</id>
<dependency type="executable" location="inx">laser.py</dependency>
<dependency type="executable" location="extensions">inkex.py</dependency>
<dependency type="executable" location="inx">plotter-lod.py</dependency>
<dependency type="executable" location="extensions">inkex</dependency>
<param name="plotter-command" type="string" _gui-text="Drawing ON Command:">M03</param>
<param name="plotter-off-command" type="string" _gui-text="Drawing OFF Command:">M05</param>
<param name="plotter-off-command" type="string" _gui-text="Drawing OFF Command:">M03</param>
<param name="plotter-disable-command" type="string" _gui-text="Plotter Disable Command:">M05</param>
<param name="travel-speed" type="int" min="0" max="15000" _gui-text="Pen Up Travel Speed (mm/min or in/min):">3000</param>
<param name="plotter-speed" type="int" min="0" max="15000" _gui-text="Pen Down Travel Speed (mm/min or in/min):">750</param>
<param name="plotter-active" type="int" min="0" max="20000" _gui-text="Pen Active Power S# (0-255 or 0-12000):">1000</param>
<param name="plotter-on-delay" type="float" min="0" max="1000" _gui-text="Pen-On Delay (ms or s):">0,2</param>
<param name="plotter-off-delay" type="float" min="0" max="1000" _gui-text="Pen-Off Delay (ms or s):">0,2</param>
<param name="offset-x" type="float" min="-1000" max="1000" _gui-text="X Offset (mm or in):">-200</param>
<param name="offset-y" type="float" min="-1000" max="1000" _gui-text="Y Offset (mm or in):">-20</param>
<param name="passes" type="int" min="1" max="100" _gui-text="Passes:">1</param>
<param name="pass-depth" type="float" min="0" max="10" _gui-text="Pass Depth (mm or in):">1</param>
<param name="directory" type="string" _gui-text="Directory:"></param>
@@ -25,14 +28,13 @@
<effect>
<effects-menu>
<submenu _name="Generate Gcode for XY Plotter"/>
<submenu _name="Generate Gcode for LY Drawbot"/>
</effects-menu>
<object-type>path</object-type>
</effect>
<script>
<command reldir="inx" interpreter="python">laser.py</command>
<command reldir="inx" interpreter="python">plotter-lod.py</command>
</script>
</inkscape-extension>

View File

@@ -129,10 +129,12 @@ options = {}
defaults = {
'header': """
G90
G0 Z0
""",
'footer': """G1 X0 Y0
"""
# Note: footer will be dynamically updated with offset values in check_dir()
}
intersection_recursion_depth = 10
@@ -620,6 +622,9 @@ class LaserGcode(inkex.Effect):
{"name": "--plotter-off-command", "type": str, "dest": "plotter_off_command",
"default": "M05", "help": "Laser gcode end command"},
{"name": "--plotter-disable-command", "type": str, "dest": "plotter_disable_command",
"default": "M5", "help": "Plotter disable command"},
{"name": "--plotter-speed", "type": int, "dest": "plotter_speed", "default": 750,
"help": "Laser speed (mm/min},"},
@@ -641,6 +646,12 @@ class LaserGcode(inkex.Effect):
{"name": "--plotter-off-delay", "type": str, "dest": "plotter_off_delay",
"default": "0", "help": "Laser power-on delay (ms},"},
{"name": "--offset-x", "type": float, "dest": "offset_x",
"default": 180.0, "help": "X axis offset (mm or in)"},
{"name": "--offset-y", "type": float, "dest": "offset_y",
"default": 0.0, "help": "Y axis offset (mm or in)"},
{"name": "--suppress-all-messages", "type": inkex.Boolean,
"dest": "suppress_all_messages", "default": True,
"help": "Hide messages during g-code generation"},
@@ -803,6 +814,8 @@ class LaserGcode(inkex.Effect):
def check_dir(self):
if not self.options.directory:
self.options.directory = os.getcwd() + "/"
if self.options.directory[-1] not in ["/", "\\"]:
if "\\" in self.options.directory:
self.options.directory += "\\"
@@ -823,6 +836,9 @@ class LaserGcode(inkex.Effect):
else:
self.footer = defaults['footer']
# Always apply dynamic offset values to footer
self.footer = "G1 X%s Y%s\n\n" % (self.options.offset_x, self.options.offset_y)
if self.options.unit == "G21 (All units in mm)":
self.header += "G21\n"
elif self.options.unit == "G20 (All units in inches)":
@@ -875,6 +891,11 @@ class LaserGcode(inkex.Effect):
def c(c):
c = [c[i] if i < len(c) else None for i in range(6)]
if c[5] == 0: c[5] = None
# Apply plotter offset from options
if c[0] != None:
c[0] = c[0] + self.options.offset_x
if c[1] != None:
c[1] = c[1] + self.options.offset_y
s = [" X", " Y", " Z", " I", " J", " K"]
r = ''
for i in range(6):
@@ -937,7 +958,7 @@ class LaserGcode(inkex.Effect):
if 'transform' in list(g.keys()):
t = g.get('transform')
t = [list(row) for row in Transform(t).matrix]
trans = [list(row) for row in (Transform(t) * Transform(trans)).matrix] if trans != [] else t
trans = [list(row) for row in (Transform(t) @ Transform(trans)).matrix] if trans != [] else t
print_(trans)
g = g.getparent()
return trans
@@ -1071,15 +1092,15 @@ class LaserGcode(inkex.Effect):
active_layer_already_has_tool
active_layer_already_has_orientation_points
"""
if type_.lower() in re.split("[\s\n,\.]+", errors.lower()):
if type_.lower() in re.split(r"[\s\n,\.]+", errors.lower()):
print_(s)
inkex.errormsg(s + "\n")
sys.exit()
elif type_.lower() in re.split("[\s\n,\.]+", warnings.lower()):
elif type_.lower() in re.split(r"[\s\n,\.]+", warnings.lower()):
print_(s)
if not self.options.suppress_all_messages:
inkex.errormsg(s + "\n")
elif type_.lower() in re.split("[\s\n,\.]+", notes.lower()):
elif type_.lower() in re.split(r"[\s\n,\.]+", notes.lower()):
print_(s)
else:
print_(s)
@@ -1201,7 +1222,7 @@ class LaserGcode(inkex.Effect):
for path in self.selected_paths[layer]:
if self.options.dxfpoints_action == 'replace':
path.set("dxfpoint", "1")
r = re.match("^\s*.\s*(\S+)", path.get("d"))
r = re.match(r"^\s*.\s*(\S+)", path.get("d"))
if r != None:
print_(("got path=", r.group(1)))
path.set("d",
@@ -1428,6 +1449,8 @@ class LaserGcode(inkex.Effect):
options.doc_root = self.document.getroot()
# define print_ function
global print_
self.options.log_create_log = True # Force enable for verbose logging
self.options.log_filename = os.path.expanduser("~/log.log")
if self.options.log_create_log:
try:
if os.path.isfile(self.options.log_filename): os.remove(self.options.log_filename)