Skip to content

Commit

Permalink
Reads the max spindle speed from the controller and automatically upd…
Browse files Browse the repository at this point in the history
…ates the designer job (#2543)
  • Loading branch information
breiler authored Jun 9, 2024
1 parent bf72cd1 commit d00d1b5
Show file tree
Hide file tree
Showing 24 changed files with 464 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ public double getMaximumRate(Axis axis) {
return 0;
}

@Override
public int getMaxSpindleSpeed() throws FirmwareSettingsException {
return 0;
}

@Override
public UnitUtils.Units getReportingUnits() {
return UnitUtils.Units.UNKNOWN;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public interface IFirmwareSettings {
/**
* Sets the number of steps needed to move the machine one millimeter.
*
* @param axis the axis to retrieve the setting for
* @param axis the axis to retrieve the setting for
* @param stepsPerMillimeter the number of steps to move one millimeter
* @throws FirmwareSettingsException if the settings couldn't be saved
*/
Expand Down Expand Up @@ -185,7 +185,7 @@ public interface IFirmwareSettings {
/**
* Sets if the homing direction should be inverted for the given axis
*
* @param axis the axis to make the setting for
* @param axis the axis to make the setting for
* @param inverted set to true if homing should be performed in a negative direction
*/
void setHomingDirectionInverted(Axis axis, boolean inverted) throws FirmwareSettingsException;
Expand Down Expand Up @@ -218,4 +218,11 @@ public interface IFirmwareSettings {
* @return the maximum rate in mm/min
*/
double getMaximumRate(Axis axis) throws FirmwareSettingsException;

/**
* Returns the controller max spindle speed
*
* @return the max spindle speed
*/
int getMaxSpindleSpeed() throws FirmwareSettingsException;
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
/*
Copyright 2022-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.fluidnc;

import com.willwinder.universalgcodesender.IController;
Expand All @@ -23,7 +41,11 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import java.util.stream.Stream;

/**
* @author Joacim Breiler
*/
public class FluidNCSettings implements IFirmwareSettings {
private static final Logger LOGGER = Logger.getLogger(FluidNCSettings.class.getName());

Expand All @@ -44,7 +66,7 @@ public void refresh() throws FirmwareSettingsException {
firmwareSettingsCommand.getSettings().keySet().forEach(key -> {
String value = firmwareSettingsCommand.getSettings().get(key);
FirmwareSetting firmwareSetting = new FirmwareSetting(key, value, "", "", "");
settings.put(key, firmwareSetting);
settings.put(key.toLowerCase(), firmwareSetting);
listeners.forEach(l -> l.onUpdatedFirmwareSetting(firmwareSetting));
});
}
Expand All @@ -61,6 +83,7 @@ public Optional<FirmwareSetting> getSetting(String key) {
@Override
public FirmwareSetting setValue(String key, String value) throws FirmwareSettingsException {
try {
key = key.toLowerCase();
if (!settings.containsKey(key) || !settings.get(key).getValue().equals(value)) {
FluidNCCommand systemCommand = new FluidNCCommand("$/" + key + "=" + value);
ControllerUtils.sendAndWaitForCompletion(controller, systemCommand);
Expand Down Expand Up @@ -200,7 +223,7 @@ public void setHardLimitsInverted(boolean inverted) throws FirmwareSettingsExcep
public void setSettings(List<FirmwareSetting> settings) throws FirmwareSettingsException {
settings.forEach(setting -> {
try {
setValue(setting.getKey(), setting.getValue());
setValue(setting.getKey().toLowerCase(), setting.getValue());
} catch (FirmwareSettingsException e) {
LOGGER.warning("Couldn't set the firmware setting " + setting.getKey() + " to value " + setting.getValue() + ". Error message: " + e.getMessage());
}
Expand All @@ -211,4 +234,24 @@ public void setSettings(List<FirmwareSetting> settings) throws FirmwareSettingsE
public double getMaximumRate(Axis axis) throws FirmwareSettingsException {
return 0;
}

private Optional<SpeedMap> getSpeedMap(String speedMapSetting) {
FirmwareSetting value = settings.get(speedMapSetting);
return Optional.ofNullable(value)
.map(FirmwareSetting::getValue)
.map(SpeedMap::new);
}

@Override
public int getMaxSpindleSpeed() throws FirmwareSettingsException {
return Stream.of(getSpeedMap("laser/speed_map"),
getSpeedMap("10V/speed_map"),
getSpeedMap("pwm/speed_map"),
getSpeedMap("besc/speed_map"))
.filter(Optional::isPresent)
.map(Optional::get)
.map(SpeedMap::getMax)
.findFirst()
.orElseThrow(() -> new FirmwareSettingsException("Could not find setting for max speed"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
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.fluidnc;

import java.util.HashMap;
import java.util.Map;

/**
* A class for parsing FluidNC speed maps
*
* @author Joacim Breiler
*/
public class SpeedMap {
private final Map<Integer, Double> speeds = new HashMap<>();

public SpeedMap(String speedMaps) {
String[] speeds = speedMaps.split(" ");
for (String speedMap : speeds) {
String[] split = speedMap.split("=");
if (split.length != 2) {
continue;
}

this.speeds.put(Integer.parseInt(split[0].trim()), Double.parseDouble(split[1].trim().replace("%", "")));
}
}

public int getMax() {
return speeds.keySet().stream()
.max((s1, s2) -> speeds.get(s1).compareTo(speeds.get(s2)))
.orElse(0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ private Map<String, String> flatten(Map<String, Object> mapToFlatten) {
.filter(Objects::nonNull)
.flatMap(this::flatten)
.collect(LinkedHashMap::new, (map, entry) ->
map.put(entry.getKey(), entry.getValue().toString()), LinkedHashMap::putAll);
map.put(entry.getKey().toLowerCase(), entry.getValue().toString()), LinkedHashMap::putAll);
}

private Stream<Map.Entry<String, Object>> flatten(Map.Entry<String, Object> entry) {
Expand All @@ -63,7 +63,7 @@ private Stream<Map.Entry<String, Object>> flatten(Map.Entry<String, Object> entr
if (value instanceof Map<?, ?>) {
Map<?, ?> properties = (Map<?, ?>) value;
return properties.entrySet().stream()
.flatMap(e -> flatten(new AbstractMap.SimpleEntry<>(entry.getKey() + "/" + e.getKey(), e.getValue())));
.flatMap(e -> flatten(new AbstractMap.SimpleEntry<>(entry.getKey().toLowerCase() + "/" + e.getKey().toString().toLowerCase(), e.getValue())));
}

return Stream.of(entry);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public class GrblFirmwareSettings implements ICommunicatorListener, IFirmwareSet
private static final String KEY_HARD_LIMITS_ENABLED = "$21";
private static final String KEY_HOMING_ENABLED = "$22";
private static final String KEY_HOMING_INVERT_DIRECTION = "$23";
private static final String KEY_MAX_SPINDLE_SPEED = "$30";
private static final String KEY_INVERT_DIRECTION = "$3";
private static final String KEY_INVERT_LIMIT_PINS = "$5";
private static final String KEY_STEPS_PER_MM_X = "$100";
Expand Down Expand Up @@ -370,6 +371,14 @@ public double getMaximumRate(Axis axis) throws FirmwareSettingsException {
}
}

@Override
public int getMaxSpindleSpeed() throws FirmwareSettingsException {
return getSetting(KEY_MAX_SPINDLE_SPEED)
.map(FirmwareSetting::getValue)
.map(Integer::valueOf)
.orElse(0);
}

private int getInvertDirectionMask() {
return getSetting(KEY_INVERT_DIRECTION)
.map(FirmwareSetting::getValue)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,11 @@ public double getMaximumRate(Axis axis) throws FirmwareSettingsException {
return 0;
}

@Override
public int getMaxSpindleSpeed() throws FirmwareSettingsException {
throw new FirmwareSettingsException("Not implemented");
}

/*
* IFirmwareSettingsListener
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.willwinder.universalgcodesender.firmware.fluidnc;

import static org.junit.Assert.*;
import org.junit.Test;

public class SpeedMapTest {

@Test
public void getMaxShouldReturnTheHundredPercentMaxSpindleSpeed() {
SpeedMap speedMap = new SpeedMap("0=0.00% 0=0.00% 5000=100.00%");
assertEquals(5000, speedMap.getMax());
}

@Test
public void getMaxShouldReturnTheMaxSpindleSpeedRegardlessOfOrder() {
SpeedMap speedMap = new SpeedMap("5000=100.00% 0=0.00% ");
assertEquals(5000, speedMap.getMax());
}

@Test
public void getMaxShouldReturnValueOfTheHighestPercent() {
SpeedMap speedMap = new SpeedMap("5000=99.00% 0=0.00% 4000=100%");
assertEquals(4000, speedMap.getMax());
}

@Test
public void speedMapShouldHandleExtraSpacing() {
SpeedMap speedMap = new SpeedMap("0=0.00% 5000=50.00% 10000=100.00%");
assertEquals(10000, speedMap.getMax());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public enum EntitySetting {
EntitySetting.ROTATION,
EntitySetting.START_DEPTH,
EntitySetting.TARGET_DEPTH,
EntitySetting.SPINDLE_SPEED,
EntitySetting.FEED_RATE,
EntitySetting.TEXT);

public static final List<EntitySetting> DEFAULT_LASER_SETTINGS = List.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.universalgcodesender.uielements.TextFieldWithUnit;
import net.miginfocom.swing.MigLayout;

import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
Expand All @@ -45,7 +46,7 @@ public class ToolSettingsPanel extends JPanel {
private JTextField depthPerPass;
private JTextField stepOver;
private JTextField safeHeight;
private JTextField spindleSpeed;
private JCheckBox detectMaxSpindleSpeed;
private TextFieldWithUnit laserDiameter;
private TextFieldWithUnit maxSpindleSpeed;

Expand All @@ -63,7 +64,14 @@ private void initComponents() {
toolDiameter = new TextFieldWithUnit(TextFieldUnit.MM, 3, controller.getSettings().getToolDiameter());
add(toolDiameter, TOOL_FIELD_CONSTRAINT);

add(new JLabel("Feed speed" ));
add(new JLabel("Tool step over" ));
stepOver = new TextFieldWithUnit(TextFieldUnit.PERCENT, 2,
controller.getSettings().getToolStepOver());
add(stepOver, TOOL_FIELD_CONSTRAINT);

add(new JSeparator(SwingConstants.HORIZONTAL), "spanx, grow, wrap, hmin 2" );

add(new JLabel("Default feed speed" ));
feedSpeed = new TextFieldWithUnit(TextFieldUnit.MM_PER_MINUTE, 0, controller.getSettings().getFeedSpeed());
add(feedSpeed, TOOL_FIELD_CONSTRAINT);

Expand All @@ -75,19 +83,15 @@ private void initComponents() {
depthPerPass = new TextFieldWithUnit(TextFieldUnit.MM, 2, controller.getSettings().getDepthPerPass());
add(depthPerPass, TOOL_FIELD_CONSTRAINT);

add(new JLabel("Step over" ));
stepOver = new TextFieldWithUnit(TextFieldUnit.PERCENT, 2,
controller.getSettings().getToolStepOver());
add(stepOver, TOOL_FIELD_CONSTRAINT);

add(new JLabel("Safe height" ));
safeHeight = new TextFieldWithUnit(TextFieldUnit.MM, 2, controller.getSettings().getSafeHeight());
add(safeHeight, TOOL_FIELD_CONSTRAINT);

add(new JSeparator(SwingConstants.HORIZONTAL), "spanx, grow, wrap, hmin 2" );
add(new JLabel("Spindle speed" ));
spindleSpeed = new TextFieldWithUnit(TextFieldUnit.ROTATIONS_PER_MINUTE, 0, controller.getSettings().getSpindleSpeed());
add(spindleSpeed, TOOL_FIELD_CONSTRAINT);

add(new JLabel("Detect max spindle speed" ));
detectMaxSpindleSpeed = new JCheckBox("", controller.getSettings().getDetectMaxSpindleSpeed());
add(detectMaxSpindleSpeed, TOOL_FIELD_CONSTRAINT);

add(new JLabel("Max spindle speed" ));
maxSpindleSpeed = new TextFieldWithUnit(TextFieldUnit.ROTATIONS_PER_MINUTE, 0, controller.getSettings().getMaxSpindleSpeed());
Expand Down Expand Up @@ -148,14 +152,6 @@ public double getSafeHeight() {
}
}

public double getSpindleSpeed() {
try {
return Utils.formatter.parse(spindleSpeed.getText()).doubleValue();
} catch (ParseException e) {
return controller.getSettings().getSpindleSpeed();
}
}

private double getLaserDiameter() {
try {
return Utils.formatter.parse(laserDiameter.getText()).doubleValue();
Expand All @@ -172,6 +168,10 @@ private double getMaxSpindleSpeed() {
}
}

private boolean getDetectMaxSpindleSpeed() {
return detectMaxSpindleSpeed.isSelected();
}

public Settings getSettings() {
Settings settings = new Settings();
settings.applySettings(controller.getSettings());
Expand All @@ -181,9 +181,9 @@ public Settings getSettings() {
settings.setToolDiameter(getToolDiameter());
settings.setToolStepOver(getStepOver());
settings.setPlungeSpeed(getPlungeSpeed());
settings.setSpindleSpeed(getSpindleSpeed());
settings.setLaserDiameter(getLaserDiameter());
settings.setMaxSpindleSpeed((int) getMaxSpindleSpeed());
settings.setDetectMaxSpindleSpeed(getDetectMaxSpindleSpeed());
return settings;
}
}
Loading

0 comments on commit d00d1b5

Please sign in to comment.