Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Positive space capability #2654

Merged
merged 3 commits into from
Dec 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 13 additions & 17 deletions ugs-core/src/com/willwinder/universalgcodesender/Capabilities.java
Original file line number Diff line number Diff line change
Expand Up @@ -181,30 +181,21 @@ public boolean hasReturnToZero() {
return hasCapability(CapabilitiesConstants.RETURN_TO_ZERO);
}


/**
* Returns if the controller has support for the given axis
*
* @param axis - the axis to check support for
* @return true if the axis is supported
*/
public boolean hasAxis(Axis axis) {
switch (axis) {
case X:
return hasCapability(CapabilitiesConstants.X_AXIS);
case Y:
return hasCapability(CapabilitiesConstants.Y_AXIS);
case Z:
return hasCapability(CapabilitiesConstants.Z_AXIS);
case A:
return hasCapability(CapabilitiesConstants.A_AXIS);
case B:
return hasCapability(CapabilitiesConstants.B_AXIS);
case C:
return hasCapability(CapabilitiesConstants.C_AXIS);
default:
return false;
}
return switch (axis) {
case X -> hasCapability(CapabilitiesConstants.X_AXIS);
case Y -> hasCapability(CapabilitiesConstants.Y_AXIS);
case Z -> hasCapability(CapabilitiesConstants.Z_AXIS);
case A -> hasCapability(CapabilitiesConstants.A_AXIS);
case B -> hasCapability(CapabilitiesConstants.B_AXIS);
case C -> hasCapability(CapabilitiesConstants.C_AXIS);
};
}

/**
Expand All @@ -215,4 +206,9 @@ public boolean hasAxis(Axis axis) {
public boolean hasOpenDoor() {
return hasCapability(CapabilitiesConstants.OPEN_DOOR);
}

@Override
public String toString() {
return String.join(", ", capabilities);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ public class CapabilitiesConstants {
public static final String RETURN_TO_ZERO = "RETURN_TO_ZERO";

/**
* A key for identifying if the firmware supports opening the door
* A key for identifying if the firmware supports triggering the DOOR state
* from the sender.
*/
public static final String OPEN_DOOR = "DOOR_DOOR";
public static final String OPEN_DOOR = "OPEN_DOOR";

public static final String X_AXIS = "X_AXIS";
public static final String Y_AXIS = "Y_AXIS";
Expand All @@ -91,4 +92,21 @@ public class CapabilitiesConstants {
* A key for identifying if the firmware supports handling the device file system
*/
public static final String FILE_SYSTEM = "FILE_SYSTEM";

/**
* Traditionally CNC:s works in a negative machine space. When the machine is homed it is usually done
* in the right, far, upper corner which is then set to 0, therefore all coordinates in the machine space is
* defined with negative values.
* <p>
* Some controllers have the option to inverse this, making the machine zero at the left, lower, close corner of
* the machine.
* <p>
* By defining this capability we can account for this in the visualizer.
*/
public static final String MACHINE_POSITION_IN_POSITIVE_SPACE = "MACHINE_POSITION_IN_POSITIVE_SPACE";

/**
* Does the controller support variable spindles (typically PWM or through RS484 interfaces)
*/
public static final String VARIABLE_SPINDLE = "VARIABLE_SPINDLE";
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.universalgcodesender.communicator.ICommunicator;
import com.willwinder.universalgcodesender.connection.ConnectionDriver;
import com.willwinder.universalgcodesender.firmware.IFirmwareSettings;
import com.willwinder.universalgcodesender.firmware.grbl.GrblCapabilitiesConstants;
import com.willwinder.universalgcodesender.firmware.grbl.GrblCommandCreator;
import com.willwinder.universalgcodesender.firmware.grbl.GrblFirmwareSettings;
import com.willwinder.universalgcodesender.firmware.grbl.GrblFirmwareSettingsInterceptor;
Expand Down Expand Up @@ -192,7 +193,8 @@ private void initialize() {
return;
}

capabilities = GrblUtils.getGrblStatusCapabilities(initializer.getVersion().getVersionNumber(), initializer.getVersion().getVersionLetter());
capabilities = GrblUtils.getGrblStatusCapabilities(initializer.getVersion().getVersionNumber(), initializer.getVersion().getVersionLetter(), initializer.getOptions());
logger.info("Identified controller capabilities: " + capabilities);

// Toggle the state to force UI update
setControllerState(ControllerState.CONNECTING);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.willwinder.universalgcodesender;

import com.willwinder.universalgcodesender.firmware.grbl.GrblBuildOptions;
import com.willwinder.universalgcodesender.firmware.grbl.GrblVersion;
import com.willwinder.universalgcodesender.firmware.grbl.commands.GetBuildInfoCommand;
import com.willwinder.universalgcodesender.firmware.grbl.commands.GetParserStateCommand;
Expand Down Expand Up @@ -32,13 +33,14 @@ public class GrblControllerInitializer implements IControllerInitializer {
private final AtomicBoolean isInitialized = new AtomicBoolean(false);
private final GrblController controller;
private GrblVersion version = GrblVersion.NO_VERSION;
private GrblBuildOptions options = new GrblBuildOptions();

public GrblControllerInitializer(GrblController controller) {
this.controller = controller;
}

@Override
public boolean initialize() throws ControllerException{
public boolean initialize() throws ControllerException {
// Only allow one initialization at a time
if (isInitializing.get() || isInitialized.get()) {
return false;
Expand Down Expand Up @@ -100,6 +102,7 @@ private void fetchControllerVersion() throws InterruptedException {
}

version = optionalVersion.get();
options = getBuildInfoCommand.getBuildOptions();
}

@Override
Expand All @@ -121,4 +124,8 @@ public boolean isInitializing() {
public GrblVersion getVersion() {
return version;
}

public GrblBuildOptions getOptions() {
return options;
}
}
13 changes: 12 additions & 1 deletion ugs-core/src/com/willwinder/universalgcodesender/GrblUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ This file is part of Universal Gcode Sender (UGS).

package com.willwinder.universalgcodesender;

import com.willwinder.universalgcodesender.firmware.grbl.GrblCapabilitiesConstants;
import com.willwinder.universalgcodesender.firmware.grbl.GrblBuildOption;
import com.willwinder.universalgcodesender.firmware.grbl.GrblBuildOptions;
import com.willwinder.universalgcodesender.firmware.grbl.commands.GetStatusCommand;
import com.willwinder.universalgcodesender.firmware.grbl.commands.GrblSystemCommand;
import com.willwinder.universalgcodesender.listeners.AccessoryStates;
Expand Down Expand Up @@ -232,7 +235,7 @@ protected static String getViewParserStateCommand(final double version, final Ch
/**
* Determines version of GRBL position capability.
*/
protected static Capabilities getGrblStatusCapabilities(final double version, final Character letter) {
protected static Capabilities getGrblStatusCapabilities(final double version, final Character letter, GrblBuildOptions options) {
Capabilities ret = new Capabilities();
ret.addCapability(CapabilitiesConstants.JOGGING);
ret.addCapability(CapabilitiesConstants.CHECK_MODE);
Expand Down Expand Up @@ -266,6 +269,14 @@ protected static Capabilities getGrblStatusCapabilities(final double version, fi
ret.addCapability(CapabilitiesConstants.OPEN_DOOR);
}

if (options.isEnabled(GrblBuildOption.HOMING_FORCE_ORIGIN_ENABLED)) {
ret.addCapability(CapabilitiesConstants.MACHINE_POSITION_IN_POSITIVE_SPACE);
}

if (options.isEnabled(GrblBuildOption.VARIABLE_SPINDLE_ENABLED)) {
ret.addCapability(CapabilitiesConstants.VARIABLE_SPINDLE);
}

return ret;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.universalgcodesender.Capabilities;
import com.willwinder.universalgcodesender.ConnectionWatchTimer;
import com.willwinder.universalgcodesender.ControllerException;
import com.willwinder.universalgcodesender.GrblCapabilitiesConstants;
import com.willwinder.universalgcodesender.GrblUtils;
import com.willwinder.universalgcodesender.IController;
import com.willwinder.universalgcodesender.IFileService;
Expand All @@ -41,12 +40,13 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.universalgcodesender.firmware.fluidnc.commands.DetectEchoCommand;
import com.willwinder.universalgcodesender.firmware.fluidnc.commands.FluidNCCommand;
import com.willwinder.universalgcodesender.firmware.fluidnc.commands.GetAlarmCodesCommand;
import com.willwinder.universalgcodesender.firmware.fluidnc.commands.GetBuildInfoCommand;
import com.willwinder.universalgcodesender.firmware.fluidnc.commands.GetErrorCodesCommand;
import com.willwinder.universalgcodesender.firmware.fluidnc.commands.GetFirmwareVersionCommand;
import com.willwinder.universalgcodesender.firmware.fluidnc.commands.GetParserStateCommand;
import com.willwinder.universalgcodesender.firmware.fluidnc.commands.GetStartupMessagesCommand;
import com.willwinder.universalgcodesender.firmware.fluidnc.commands.GetStatusCommand;
import com.willwinder.universalgcodesender.firmware.fluidnc.commands.SystemCommand;
import com.willwinder.universalgcodesender.firmware.grbl.GrblCapabilitiesConstants;
import com.willwinder.universalgcodesender.firmware.grbl.GrblOverrideManager;
import com.willwinder.universalgcodesender.gcode.GcodeParser;
import com.willwinder.universalgcodesender.gcode.GcodeState;
Expand Down Expand Up @@ -582,9 +582,9 @@ private void disableEcho() throws Exception {
private void queryFirmwareVersion() throws Exception {
// A sleep is required to make the next query reliable
Thread.sleep(200);
GetFirmwareVersionCommand getFirmwareVersionCommand = FluidNCUtils.queryFirmwareVersion(this, messageService);
semanticVersion = getFirmwareVersionCommand.getVersion();
firmwareVariant = getFirmwareVersionCommand.getFirmware();
GetBuildInfoCommand getBuildInfoCommand = FluidNCUtils.queryBuildInformation(this, messageService);
semanticVersion = getBuildInfoCommand.getVersion();
firmwareVariant = getBuildInfoCommand.getFirmware();
capabilities.addCapability(GrblCapabilitiesConstants.V1_FORMAT);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import com.willwinder.universalgcodesender.firmware.FirmwareSetting;
import com.willwinder.universalgcodesender.firmware.FirmwareSettingsException;
import com.willwinder.universalgcodesender.firmware.IFirmwareSettings;
import com.willwinder.universalgcodesender.firmware.fluidnc.commands.GetFirmwareVersionCommand;
import com.willwinder.universalgcodesender.firmware.fluidnc.commands.GetBuildInfoCommand;
import com.willwinder.universalgcodesender.firmware.fluidnc.commands.GetStatusCommand;
import com.willwinder.universalgcodesender.firmware.fluidnc.commands.SystemCommand;
import com.willwinder.universalgcodesender.listeners.ControllerState;
Expand All @@ -16,6 +16,8 @@
import com.willwinder.universalgcodesender.model.Position;
import com.willwinder.universalgcodesender.model.UnitUtils;
import com.willwinder.universalgcodesender.services.MessageService;
import static com.willwinder.universalgcodesender.utils.ControllerUtils.sendAndWaitForCompletion;
import static com.willwinder.universalgcodesender.utils.ControllerUtils.sendAndWaitForCompletionWithRetry;
import com.willwinder.universalgcodesender.utils.SemanticVersion;
import org.apache.commons.lang3.StringUtils;

Expand All @@ -24,9 +26,6 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.willwinder.universalgcodesender.utils.ControllerUtils.sendAndWaitForCompletion;
import static com.willwinder.universalgcodesender.utils.ControllerUtils.sendAndWaitForCompletionWithRetry;

public class FluidNCUtils {
public static final double GRBL_COMPABILITY_VERSION = 1.1d;
public static final SemanticVersion MINIMUM_VERSION = new SemanticVersion(3, 3, 0);
Expand Down Expand Up @@ -150,18 +149,18 @@ private static void addCapabilityIfSettingStartsWith(Capabilities capabilities,
* @throws Exception if the command couldn't be sent
* @throws IllegalStateException if the parsed version is not for a FluidNC controller or the version is too old
*/
public static GetFirmwareVersionCommand queryFirmwareVersion(IController controller, MessageService messageService) throws Exception {
public static GetBuildInfoCommand queryBuildInformation(IController controller, MessageService messageService) throws Exception {
messageService.dispatchMessage(MessageType.INFO, "*** Fetching device firmware version\n");
GetFirmwareVersionCommand getFirmwareVersionCommand = sendAndWaitForCompletion(controller, new GetFirmwareVersionCommand());
String firmwareVariant = getFirmwareVersionCommand.getFirmware();
SemanticVersion semanticVersion = getFirmwareVersionCommand.getVersion();
GetBuildInfoCommand getBuildInfoCommand = sendAndWaitForCompletion(controller, new GetBuildInfoCommand());
String firmwareVariant = getBuildInfoCommand.getFirmware();
SemanticVersion semanticVersion = getBuildInfoCommand.getVersion();

if (!firmwareVariant.equalsIgnoreCase("FluidNC") || semanticVersion.compareTo(MINIMUM_VERSION) < 0) {
messageService.dispatchMessage(MessageType.INFO, String.format("*** Expected a 'FluidNC %s' or later but got '%s %s'\n", MINIMUM_VERSION, firmwareVariant, semanticVersion));
throw new IllegalStateException("Unknown controller version: " + semanticVersion.toString());
}

return getFirmwareVersionCommand;
return getBuildInfoCommand;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ This file is part of Universal Gcode Sender (UGS).
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class GetFirmwareVersionCommand extends SystemCommand {
public class GetBuildInfoCommand extends SystemCommand {
private static final Pattern VERSION_FLUIDNC_PATTERN = Pattern.compile("\\[VER:[0-9.]+ (?<variant>[a-zA-Z0-9]+) v?(?<version>(?<major>[0-9]*)(.(?<minor>[0-9]+)(.(?<patch>[0-9]+))?)?([a-zA-Z]+)?)(.*:.*)*]", Pattern.CASE_INSENSITIVE);
private static final Pattern VERSION_GRBL_PATTERN = Pattern.compile("\\[VER:(?<version>(?<major>[0-9]*)(.(?<minor>[0-9]+)(.(?<patch>[0-9]+))?)).*]", Pattern.CASE_INSENSITIVE);

public GetFirmwareVersionCommand() {
public GetBuildInfoCommand() {
super("$I");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
Copyright 2024 Will Winder

This file is part of Universal Gcode Sender (UGS).

UGS is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

UGS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with UGS. If not, see <http://www.gnu.org/licenses/>.
*/
package com.willwinder.universalgcodesender.firmware.grbl;

/**
* GRBL options are reported by the build info command ($I). This enum contains the known options.
*/
public enum GrblBuildOption {
VARIABLE_SPINDLE_ENABLED("V"),
LINE_NUMBERS_ENABLED("N"),
MIST_COOLANT_ENABLED("M"),
CORE_XY_ENABLED("C"),
PARKING_MOTION_ENABLED("P"),
HOMING_FORCE_ORIGIN_ENABLED("Z"),
HOMING_SINGLE_AXIS_COMMAND_ENABLED("H"),
TWO_LIMIT_SWITCHES_ON_AXIS_ENABLED("T"),
TWO_ALLOW_OVERRIDE_ON_PROBING_ENABLED("A"),
USE_SPINDLE_DIRECTION_AS_ENABLE_PIN_ENABLED("D"),
SPINDLE_OFF_ON_ZERO_SPEED_ENABLED("0"),
SOFTWARE_LIMIT_PIN_DEBOUNCING_ENABLED("S"),
PARKING_OVERRIDE_CONTROL_ENABLED("R"),
SAFETY_DOOR_INPUT_ENABLED("+"),
RESTORE_ALL_EEPROM_DISABLED("*"),
RESTORE_EEPROM_SETTINGS_DISABLED("$"),
RESTORE_EEPROM_PARAMETER_DATA_DISABLED("#"),
BUILD_INFO_USER_STRING_DISABLED("I"),
FORCE_SYNC_ON_EEPROM_WRITE_DISABLED("E"),
FORCE_SYNC_ON_WORK_COORDINATE_CHANGE_DISABLED("W"),
HOMING_INITIALIZATION_LOCK_DISABLED("L"),
DUAL_AXIS_MOTORS_ENABLED("2");

private final String code;

GrblBuildOption(String code) {
this.code = code;
}

public String getCode() {
return code;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
Copyright 2024 Will Winder

This file is part of Universal Gcode Sender (UGS).

UGS is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

UGS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with UGS. If not, see <http://www.gnu.org/licenses/>.
*/
package com.willwinder.universalgcodesender.firmware.grbl;

import org.apache.commons.lang3.StringUtils;

/**
* Parses options from the build info command ($I)
* <a href="https://github.com/gnea/grbl/wiki/Grbl-v1.1-Interface#feedback-messages">Documentation</a>
*
* @author Joacim Breiler
*/
public class GrblBuildOptions {
private final String options;

public GrblBuildOptions() {
this("[OPT:]");
}

public GrblBuildOptions(String options) {
this.options = options;
}

public boolean isEnabled(GrblBuildOption grblBuildOption) {
String buildOptions = StringUtils.substringBefore(StringUtils.substringBetween(options, "[OPT:", "]"), ",");
return buildOptions.contains(grblBuildOption.getCode());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ This file is part of Universal Gcode Sender (UGS).
You should have received a copy of the GNU General Public License
along with UGS. If not, see <http://www.gnu.org/licenses/>.
*/
package com.willwinder.universalgcodesender;
package com.willwinder.universalgcodesender.firmware.grbl;

/**
* Constants for defining additional capabilities from {@link CapabilitiesConstants} that a
* GRBL controller may support. The constants may be added to a {@link Capabilities} object.
* Constants for defining additional capabilities from {@link com.willwinder.universalgcodesender.CapabilitiesConstants} that a
* GRBL controller may support. The constants may be added to a {@link com.willwinder.universalgcodesender.Capabilities} object.
*
* @author Joacim Breiler
*/
Expand Down
Loading