Skip to content

Universal G-Code — Chat Transcript

Word for word transcript of my conversation with Claude while setting up Universal G-Code Sender (UGS) and generating G-code for our cookie decorator pen plotter.


Dorian: i just downloaded UGS version: MacOSX x64 MacOSX (Intel) MacOSX version with bundled Java, and I need to run a code XY machine, can you help walk me through the process

Claude: Sure! UGS (Universal G-code Sender) is a great tool for this. To get started:

1. Launch UGS - Open the downloaded file — it should be a .dmg or a folder with a launch script

2. Connect to your machine - Plug your machine into your Mac via USB - In UGS, set the Baud rate (usually 115200) - Select the correct Port (will look like /dev/tty.usbmodem...) - Click Connect

3. Before running anything: - What kind of machine is it? (brand/model) - Do you already have a G-code file ready to run, or are you starting from a design? - Is this the Cubiko, or a different machine?

This will help me give you the right settings.


Dorian: we built the machine for fab academy that is basically a pen plotter. i downloaded the .dmg, how do i open it?

Claude: Double-click the .dmg file — it will mount and open a window. Then drag the UGS app icon into your Applications folder, or just double-click it directly to launch.

If Mac blocks it with "cannot be opened because it is from an unidentified developer": - Go to System Settings → Privacy & Security - Scroll down and click Open Anyway


Claude: It's already mounted — "Universal Gcode Sender" is showing in your Volumes. Open Finder, look in the left sidebar under Locations, and you should see it there. Double-click to open it and drag the app to your Applications folder.


Dorian: i see it

Claude: Open it and you should see the UGS app inside. Drag it to your Applications folder, then double-click to launch it.


Dorian: [screenshot of UGS DMG contents showing Applications alias and Universal Gcode Sender app]

Claude: Drag Universal Gcode Sender onto the Applications alias (the blue folder) — that will install it. Then open it from your Applications folder.


Dorian: [screenshot of Mac security warning: "Universal Gcode Sender can't be opened because Apple cannot check it for malicious software"]

Claude: Click OK, then: 1. Go to System Settings → Privacy & Security 2. Scroll down — you'll see a message about UGS being blocked 3. Click Open Anyway


Dorian: [screenshot showing Open/Show in Finder/Cancel dialog with Privacy & Security in background]

Claude: Click Open — that will launch UGS despite the warning.


Dorian: [screenshot of UGS open with Java accessibility prompt]

Claude: UGS is open (you can see it in the background)! Click Deny on this accessibility prompt — you don't need that for running G-code.


Dorian: do i need to load a core xy program

Claude: Yes — your pen plotter needs firmware to interpret G-code. The most common choice for a CoreXY machine is GRBL (or Marlin if it's already installed).

Do you know what controller board your machine uses? For example: - Arduino Uno/Nano → GRBL - Arduino Mega → Marlin - Custom board → depends

If you're not sure, what microcontroller did your group use to control the motors?


Dorian: I have this xycore_grbl that my team members used on a pc computer. do i use this on my mac? It opened in arduino ide.

Claude: Yes, this is exactly what you need — it's the firmware that makes your machine understand G-code from UGS. It runs on the Arduino controlling your stepper motors.

What you need to do: 1. Check what board your machine uses — the pin definitions at the top use a CNC Shield layout (pins 2, 3, 5, 6, 8). Does your machine use an Arduino Uno with a CNC shield? 2. Upload this to the controller board — connect the machine's Arduino to your Mac, select the correct board in Arduino IDE, and upload 3. Then connect UGS to that same board

Before uploading, confirm: - What Arduino board is the machine built on? - Do the pin numbers (X_STEP=2, X_DIR=5, Y_STEP=3, Y_DIR=6) match your machine's wiring?


Dorian: arduino uno with cnc shield [photo of CNC Shield v3 with A4988 drivers]

Claude: That's exactly the standard CNC Shield v3 layout — the pin definitions in the code match perfectly. You're good to upload as-is.

Upload the firmware: 1. In Arduino IDE, select Arduino Uno as the board 2. Select the correct port 3. Upload the code

Once it says "Done uploading", open UGS, set baud to 115200, select the port, and click Connect. You should see:

Grbl 1.1h ['$' for help]
in the UGS console, which means it's ready.


Dorian: I have an svg file that I need to convert to a g-code. I want to make the code in 3 parts as there are 3 colors that will need pen changes. We also had used a servo to lift our pen up in between lines to prevent extra lines being traced. This worked when manually entering the code, using "servo 90" or "servo 0", and moving the x or y as "x #to move", but it does not work when sending a g-code as the z axis is disabled since we are using a servo not another stepper. what do you suggest to fix this?

Claude: Good news — this is fixable by modifying the firmware to intercept Z moves and translate them to servo commands. Most SVG-to-G-code tools use G0 Z1 (pen up) and G0 Z0 (pen down), so if the firmware converts those Z moves to servo angles automatically, any standard G-code file will work.

Here's the plan:

1. Modify xycore_grbl — add a servo and map Z moves: - G0 Z1 (or any Z > 0) → servo.write(90) — pen up - G0 Z0 (or any Z ≤ 0) → servo.write(0) — pen down

Add this to the top of the firmware:

#include <Servo.h>
#define SERVO_PIN 11
Servo penServo;

Add to setup():

penServo.attach(SERVO_PIN);
penServo.write(90);  // start with pen up

Add Z handling in handleLine(), before the G0/G1 blocks:

float zVal = extractWord(line, 'Z', 999);  // 999 = not present
if (zVal != 999) {
  penServo.write(zVal > 0 ? 90 : 0);
  delayMicroseconds(300000);  // give servo time to move
}

2. For SVG → G-code, use Inkscape with the "Gcodetools" extension — it generates Z moves for pen up/down automatically, and you can export each color layer separately as its own file.

3. Three files for three colors — export one G-code file per color layer, run each one, swap the pen, run the next.


Dorian: no, but can you check that I did it correctly? I commented before and after each addition I made.

Claude: Almost — there's one problem. You declared float zVal twice in the same function, which will cause a compile error. C++ doesn't allow redeclaring the same variable in the same scope.

The fix: remove the second block (the one before G1) and move the first block up to where xVal, yVal, and fVal are extracted. That way it runs once and covers both G0 and G1:

  // Extract word values
  float xVal = extractWord(line, 'X', posX);
  float yVal = extractWord(line, 'Y', posY);
  float fVal = extractWord(line, 'F', -1);
  if (fVal > 0) feedRate = fVal;
  // start Dorian addition
  float zVal = extractWord(line, 'Z', 999);
  if (zVal != 999) {
    penServo.write(zVal > 0 ? 90 : 0);
    delayMicroseconds(300000);
  }
  // end Dorian addition

Then delete both of the blocks you added before G0 and G1. The servo will now respond to any Z move regardless of whether it's in a G0 or G1 command.


Dorian: great! thanks


Dorian: is there a way to do a practice run of the code without it attached to the machine?

Claude: Yes — two options:

1. UGS with no machine connected - In UGS, go to Machine → Setup Wizard or just connect to a fake port - Better: use UGS in demo mode — some versions let you simulate without a port

2. Better option: use an online G-code simulator - ncviewer.com — paste or upload your G-code and it shows a visual preview of the toolpath - camotics.org — more advanced simulator, shows the full motion path

I'd recommend ncviewer.com as the quickest option — just upload your .gcode file and you can see exactly what the machine will draw before running it on the real machine. No installation needed.

Do you have a G-code file ready to test?


Dorian: i do not. I do have the svg files. can I use mod's to create the gcode?

Claude: Yes! Mods can convert SVG to G-code. Here's how:

  1. Go to mods.cba.mit.edu in your browser
  2. Right-click on the page → programsopen server programG-codeSVG
  3. Load your SVG file
  4. Set your cut depth/pen settings
  5. Calculate and download the G-code file

However, mods is designed more for milling than pen plotting, so the output may need tweaking.

An easier option for a pen plotter SVG is Inkscape with the Gcodetools extension: 1. Open your SVG in Inkscape 2. Extensions → Gcodetools → Path to Gcode 3. Set Z safe height (pen up) and Z cutting depth (pen down) 4. Export

Do you have Inkscape installed, or would you prefer to try mods first?


Dorian: is inkscape similar to corelDraw? I own CorelDraw

Claude: Yes, very similar — both are vector graphics editors. If you have CorelDraw you can use it directly.

CorelDraw can export G-code through its GCode output feature, or you can: 1. Export the SVG from CorelDraw and run it through an online converter like jscut.org or ncviewer 2. Use the CorelDraw G-code plugin if you have one installed

The simplest path for your pen plotter: 1. Open your SVG in CorelDraw 2. Export as DXF or keep as SVG 3. Upload to jscut.org — set pen up/down Z values and download the G-code

Do you want to try that route?


Dorian: how do i know if i have the G-code plugin?

Claude: In CorelDraw, check: Tools → Macros or Extensions → Plugins

Look for anything mentioning "G-code", "CNC", or "CAM".

If you don't see anything, the quickest free option is just to use your SVG directly at jscut.org — no plugin needed. What version of CorelDraw do you have?


Dorian: [screenshot of CorelDraw 2026 showing Fab Academy logo with 3 colors]

Claude: I can see the menu bar — CorelDraw 2026 on Mac doesn't have a Tools menu. No G-code plugin is visible.

The easiest path: export your SVG from CorelDraw and use an online converter. 1. In CorelDraw: File → Export → choose SVG format → save 2. Go to jscut.org in your browser 3. Upload the SVG 4. Set your parameters and download the G-code

Is the Fab Academy logo the design you want to plot, or is that just open for reference?


Dorian: yes i am plotting the fab academy logo.

Claude: That's a great choice — it has 3 colors (red, green, blue) which matches your 3-pen plan perfectly.

Here's the workflow:

In CorelDraw: 1. Select only the red elements 2. File → Export → SVG → name it logo-red.svg 3. Repeat for greenlogo-green.svg 4. Repeat for bluelogo-blue.svg

This gives you 3 separate SVGs, one per pen color, which you'll convert to 3 separate G-code files and run one at a time.

Have you already separated the colors into layers, or are they all on one layer?


Dorian: yes, they are all separated by color in separate svg files

Claude: Perfect — you're ready to convert. Let's do one at a time.

Go to jscut.org and click Open SVG and load logo-red.svg. Take a screenshot of what you see and share it — the interface can be a bit confusing the first time and I'll walk you through the settings from there.


Dorian: [screenshot of jscut.org with red element of Fab Academy logo loaded]

Claude: The SVG loaded — you can see the red element. Now follow these steps:

1. Click the red shape in the preview to select it (it will highlight)

2. Click "Create Operation" on the left

3. Set the operation type to "Engrave" — this traces the outline of the shape, which is what a pen plotter needs

4. For the Material settings on the right, set: - Units: mm - Clearance: 5 (pen up height — triggers servo up) - Z Origin: Top

5. For the Tool settings on the left, change: - Units to mm - Diameter: 1 (pen tip approximation) - Rapid: 1000 mm/min - Cut: 500 mm/min - Pass Depth: 1

Then click Simulate GCODE to preview before saving.


Dorian: I want to color in the image. my pen makes a line that is 1mm thick

Claude: For a fill, use a Pocket operation — it creates parallel lines spaced at your pen width to completely fill the shape.

Settings for a 1mm pen:

Tool (left panel), change to mm: - Diameter: 1 - Step Over: 0.9 (90% of 1mm = slight overlap for full coverage, no gaps) - Rapid: 1000 mm/min - Cut: 500 mm/min - Pass Depth: 1

Material (right panel): - Units: mm - Clearance: 5

Steps: 1. Click the red shape to select it 2. Click Create Operation 3. Change operation type to Pocket 4. Apply the settings above 5. Click Simulate GCODE to preview the fill pattern

The pocket operation will trace back-and-forth lines 0.9mm apart across the entire shape, which with a 1mm pen will give you solid coverage.


Dorian: what is plunge?

Claude: Plunge is the speed at which the tool moves downward (Z axis) — in your case, it's how fast the servo drops the pen onto the surface.

For a pen plotter you don't need to worry about it much since your servo moves the pen, not a motor. You can leave it at the default or set it to the same as your Cut speed (500 mm/min).


Dorian: i clicked on my gcode file, and it opened in bambu studio. Are g-codes the same as 3d printer files? I can open stl or obj or 3mf in bambu, are any of those considered g-code?

Claude: G-code is actually the same underlying language that 3D printers use — Bambu Studio opened it because it recognized the .gcode extension. However the commands are different:

  • 3D printer G-code — includes temperature, extrusion, layer changes
  • CNC/pen plotter G-code — only has XY moves, Z up/down, feed rates

So same file format, different commands. Bambu Studio can't run your pen plotter file correctly, and UGS can't run a 3D printer file.

STL, OBJ, 3MF are 3D geometry files, not G-code — Bambu converts those into G-code internally when you slice them.

To open your G-code file in UGS instead: - Open UGS - Click the folder icon to load a file - Navigate to your .gcode file and open it

You can also preview it first at ncviewer.com — just drag and drop the file there to see the toolpath before sending it to the machine.


Dorian: do i need to run each color's gcode separately?

Claude: Yes — run them one at a time: 1. Load and run logo-red.gcode → machine draws all red 2. Swap pen to green → load and run logo-green.gcode 3. Swap pen to blue → load and run logo-blue.gcode

Between each run the machine will return to home (0,0), so the colors will line up correctly as long as you don't move the cookie/paper between runs.


Dorian: with my arduino uno with cnc shield, do I plug the wires for my servo into the z motor driver area? or the spn En pin?

Claude: For a servo, use the Spindle Enable (SpnEn) pin — it's pin 12 on the CNC shield and outputs a PWM signal, which is what a servo needs.

Do not use the Z motor driver area — that's designed for a stepper motor, not a servo.

In the firmware the servo is defined as:

#define SERVO_PIN 11

But the CNC shield's SpnEn is actually pin 12. Change that line to:

#define SERVO_PIN 12

Then connect your servo signal wire to the SpnEn pin on the shield, and power the servo separately (5V and GND from the shield's power pins, not from the SpnEn pin).


Dorian: is spinDir pin 11?

Claude: Yes! On the CNC shield: - SpnDir = pin 11 - SpnEn = pin 12

Either will work for a servo since both can output PWM. If your servo is already wired to pin 11, keep #define SERVO_PIN 11 in the firmware — no need to change it.


Dorian: [screenshot showing firmware uploaded successfully to Arduino UNO 3]

Claude: Firmware is uploaded. Now open UGS: 1. Select the port (should appear as something like /dev/cu.usbserial-XXXX) 2. Set baud to 115200 3. Click Connect

You should see Grbl 1.1h ['$' for help] in the console.


Dorian: [screenshot showing UGS disconnected]

Claude: The port isn't connecting yet. Try: 1. Unplug and replug the USB cable 2. In UGS, click the refresh button next to the port dropdown 3. Select the port again and click Connect

If Arduino IDE is still open, close it first — it may be holding the port.


Dorian: [screenshot showing UGS still disconnected]

Claude: Close Arduino IDE completely if it's open — Arduino IDE and UGS cannot share the port at the same time. Then unplug the USB, wait 5 seconds, replug, and try connecting again in UGS.


Dorian: [screenshot showing UGS connected — status shows IDLE]

Claude: You're connected! The status shows Idle which means GRBL is ready to receive commands. You can now load a G-code file or use the jog controls to test movement.


Dorian: how do i jog?

Claude: In UGS, go to the Machine Controls tab (or click the jog panel icon). You'll see arrow buttons for X and Y movement, and a step size field.

  1. Set the step size (e.g. 10mm to start)
  2. Click the X+, X-, Y+, Y- arrows to move the machine
  3. Make sure the motors are enabled — if they're not responding, type M17 in the console and press Enter

Dorian: [screenshot showing jog controller panel]


Dorian: not responding

Claude: A few things to check: 1. Type M17 in the console and press Enter — that enables the motors 2. Try jogging again after that 3. If still nothing, type ? and share what it shows — that gives the machine status


Dorian: it still won't jog, but it does have power. it worked on another computer with a different arduino file

Claude: That's an important clue — if it worked with a different Arduino file, the xycore_grbl firmware may have a bug in the motor movement code. The version on the other computer was likely real GRBL (the standard open-source firmware), not the custom xycore_grbl.

Real GRBL is well-tested and will definitely respond to UGS jog commands. I'd recommend uploading the real GRBL: 1. In Arduino IDE, go to File → Examples → grbl → grblUpload 2. Upload that to the Arduino Uno 3. Reconnect in UGS and try jogging again


Dorian: the custom code may not have been working, the other person had been running the real grbl file

Claude: That confirms it — upload the real GRBL (grblUpload example) and you'll have the same setup that was working on the other computer.


Dorian: it moves!

Claude: Great — real GRBL is running and the motors are responding to jog commands. You're now in the same state as the working setup.


Dorian: will that run the servo? do i need to change a config.h file?

Claude: Real GRBL controls the servo through the spindle PWM output. The config.h in your GRBL library has #define SPINDLE_RPM_CONTROLLED_BY_Z_POS — when enabled, Z moves automatically drive the spindle PWM, which can drive a servo.

Check your config.h at: Documents/Arduino/libraries/grbl/config.h

Look for:

#define SPINDLE_RPM_CONTROLLED_BY_Z_POS

If it's already uncommented (no // before it), it's already active.


Dorian: if it was already in the file, do i need to resend it?

Claude: Yes — you need to re-upload the GRBL firmware after changing config.h for the changes to take effect. Even if the line was already there, the compiled firmware on the Arduino was built before you confirmed it. Re-upload grblUpload to be sure.


Dorian: do i have to soft reset?

Claude: After uploading new firmware, the Arduino resets automatically — you don't need a separate soft reset. Just reconnect in UGS after the upload finishes.


Dorian: nothing happens when i press soft reset

Claude: Soft reset in UGS sends Ctrl+X to GRBL. If nothing happens, try: 1. Disconnect in UGS 2. Unplug and replug the USB 3. Reconnect — the board resets on power cycle


Dorian: no [servo not moving]

Claude: The spindle PWM output on real GRBL is at 244Hz by default, which is not the standard 50Hz that most servos expect. The servo may not respond at that frequency.

Try connecting the servo signal wire to the Z-axis direction pin on the CNC shield instead of the SpnDir/SpnEn pins — some setups use a direct Z output pin. Alternatively, send M3 S500 in the UGS console to activate the spindle and see if the servo twitches at all.


Dorian: [screenshot showing M3 and M5 commands acknowledged in UGS console]

Claude: GRBL is accepting the M3/M5 commands. The servo may still not be moving because the PWM frequency is mismatched. Try plugging the servo signal wire into the -Z pin (the Z-axis step or enable pin area on the CNC shield) and send a G0 Z1 command to see if it responds.


Dorian: i plugged it into the white -z pin and the servo moves about 1/8 turn!

Claude: Progress! The servo is responding to Z moves but only moving 1/8 of a turn because the PWM parameters in GRBL's config.h are set for a spindle motor, not a servo's 0–180° range.

In config.h, find:

#define Z_MM_FOR_MAX_SPINDLE_RPM
#define Z_MM_FOR_MIN_SPINDLE_RPM

These values control the PWM duty cycle range. Adjusting them changes how much the servo moves. Try setting a wider range — for example:

#define Z_MM_FOR_MAX_SPINDLE_RPM 15.0
#define Z_MM_FOR_MIN_SPINDLE_RPM 19.0

Then re-upload the firmware and test again.


Dorian: it didn't change the amount of spin

Claude: The issue is likely the PWM frequency itself — at 244Hz the servo can't complete a full rotation because standard servos are designed for 50Hz. The cpu_map.h file controls the timer prescaler. Changing that to get closer to 50Hz would give the servo a proper signal.

For now, the servo is partially working. You can continue testing the XY movement and G-code workflow while the servo issue is a separate tuning task.


Dorian: my g-code file is very large, but the object being drawn is small. when i look at the preview in UGS the object is in the bottom right corner far from zero

Claude: The G-code coordinates are offset from the origin — jscut exported the file using the SVG's absolute coordinates instead of starting at 0,0. The drawing starts at X130 or similar, far from where the machine homes to.

To fix this in jscut: 1. In the Gcode Conversion panel (bottom left), look for X Offset and Y Offset fields 2. Set the offsets to shift the drawing back to the origin

What coordinates does the G-code start at? I can calculate the exact offset values you need.


Dorian: since it starts at x130 the drawing goes past the limits of the machine

Claude: Set X Offset to -130 in the jscut Gcode Conversion panel — that shifts the entire drawing 130mm to the left, putting it near the origin.

If there's also a Y offset (the drawing shows Y as negative or far from 0), set Y Offset to 104 (or whatever value brings it to 0). Regenerate the G-code after changing the offsets and re-upload to UGS.


Dorian: can I add a line of code that defines x as x/2, y as y/2?

Claude: You could, but scaling the G-code coordinates would also shrink the drawing itself — your Fab Academy logo would come out half the size.

The offset approach is better: X Offset -130, Y Offset 104 just moves the drawing without changing its size. Re-export from jscut with those values set in the Gcode Conversion panel and try the preview again.


Dorian: it worked!

Claude: The drawing is now positioned correctly near the origin. You're ready to run the full file on the machine.

Remember for each color: 1. Home the machine to 0,0 before each run 2. Load the G-code file in UGS 3. Run it, then swap the pen before loading the next color's file 4. Don't move the cookie between runs or the colors won't line up