Open AndyCXL opened 3 years ago
You are using Grbl-Mega-5x right? It is not fully implemented in UGS to support multiple axises yet.
It should preferably have its own controller implementation that would detect how many axises that the hardware is configured with and then add that capability. It would then be shown automatically in the DRO: https://github.com/winder/Universal-G-Code-Sender/blob/master/ugs-platform/ugs-platform-plugin-dro/src/main/java/com/willwinder/ugs/nbp/dro/panels/DROPopup.java#L42
Here is an example on how its done with Grbl-ESP32: https://github.com/winder/Universal-G-Code-Sender/blob/master/ugs-core/src/com/willwinder/universalgcodesender/GrblEsp32Controller.java#L75
I think we have had suggestions on making it possible to change the visualization of the axises in the DRO where ABC should be shown in degrees by default. But I'm not sure how the visualization of the gcode should be done if it weren't rotational...
Yes, Grbl Mega 5X on my Carbide 3D ShapeOKO 3XL with VFD spindle and a rotary axis upgrade. I have studied the Mega 5XL source in some detail and know the following:
Comments towards the visualisation:
I have a working instance of GrblMega5XController up and successfully connecting. During this I extract from the status strings the AxisOrder as reported from Mega5X and have instantiated a call (duly instantiated through the override layers) to obtain this string as it is needed in GrblUtils.java to correctly sequence and assign the MPos etc positions. For this last part to work, I need a lightweight way of getting the current controller instance, so I can call the new getAxisLetterOrder() method. GrblUtils has no current objects relating to the Controller - as I know I am deep in the bowels of the code here, I would appreciate a pointer as to how to achieve this...?
Thanks for the clarification about the status reports!
I think that you can create your own GrblMega5XUtils.java
that is specialized in handling the status messages from GrblMega5X as it has deviated from Grbl. The util methods for parsing the status report would need the state of the controller configuration so I figure that those could be sent along as well.
So for instance, the previous method for parsing the status message in Grbl is done using GrblUtils.getStatusFromStatusStringV1
:
/**
* Parses a GRBL status string in in the v1.x format:
* 1.x: <status|WPos:1,2,3|Bf:0,0|WCO:0,0,0>
* @param lastStatus required for the 1.x version which requires WCO coords
* and override status from previous status updates.
* @param status the raw status string
* @param reportingUnits units
* @return the parsed controller status
*/
public static ControllerStatus getStatusFromStatusStringV1(ControllerStatus lastStatus, String status, Units reportingUnits)
The new method for GrblMega5XUtils could be something like:
/**
* Parses a GrblMega5X status string: <status|WPos:1,2,3,N|Bf:0,0|WCO:0,0,0,N>
*
* @param lastStatus required for WCO coords
* and override status from previous status updates.
* @param status the raw status string
* @param reportingUnits units
* @param axisOrder a list of axises that will be reported by the controller. Normally [X, Y, Z] but could also be [X, Y, Z, Y] when the Y-axis is mirrored.
* @return the parsed controller status
*/
public static ControllerStatus getStatusFromStatusStringV1(ControllerStatus lastStatus, String status, Units reportingUnits, List<Axis> axisOrder)
Your explanation allowed me to understand the structure of the code and classes better, and I can now see what is needed. First pass at this is written and builds. Now to test.
I have explored this idea to the limit of my (limited) architectural knowledge of Java and UGS, and don't believe the weave within the UGS structure is within my grasp to code to incorporate a GrblMega5X method. That said, I have worked out the various individual pieces of code in order to do this... which someone can hopefully take and either frame-out the architectural needs so I can finish it, or take onboard themselves to do this.
In the meantime I have a dirty hack that makes what I need work, it's just not suitable for incorporation as-is and cannot deal with any arbitrary choice of axis sequencing coming from the GrblMega5X controller board.
New version of function within GrblUtils.java (or a new GrblMega5XUtils) that will be required: Adds axisOrder to the call, and through the call tree to be able to correctly interpret the axis report data
static private Position getPositionFromStatusString(final String status, final Pattern pattern, Units reportingUnits, String axisOrder) { / GrblMega5XController knows the reported Axis order, eg: XYZ or XYA or XYZYA // and added capabilities according to each unique axis letter, even if the count // of axes was greater (XYZYA is 4 distinct letters 5 positions). Position reporting // is per physical axis, so XYZYA is the string order even though Y is duplicated / Matcher matcher = pattern.matcher(status);
// Do we have any matches, if so assign them to axes
if (matcher.find()) {
// Is Axis ordering default, or dictated by the controller
// String axisOrder defines the order
if ("".equals(axisOrder)) {
axisOrder = "XYZABC";
}
// pX contains the integer position of X in axisOrder
// indexOf returns 0th index of first match, or -1 if no match
int pX = axisOrder.indexOf("X")+1;
int pY = axisOrder.indexOf("Y")+1;
int pZ = axisOrder.indexOf("Z")+1;
int pA = axisOrder.indexOf("A")+1;
int pB = axisOrder.indexOf("B")+1;
int pC = axisOrder.indexOf("C")+1;
// Position is a fixed order structure, indexOf bridges to axisOrder
Position result = new Position(
pX > 0 ? Double.parseDouble(matcher.group(pX)) : 0.00D,
pY > 0 ? Double.parseDouble(matcher.group(pY)) : 0.00D,
pZ > 0 ? Double.parseDouble(matcher.group(pZ)) : 0.00D,
reportingUnits
);
result.a = pA > 0 ? Double.parseDouble(matcher.group(pA)) : 0.00D;
result.b = pB > 0 ? Double.parseDouble(matcher.group(pB)) : 0.00D;
result.c = pC > 0 ? Double.parseDouble(matcher.group(pC)) : 0.00D;
return result;
}
// No match, default return null
return null;
}
New version of functions in GrblController.java (or a new GrblMega5XController.java) that will be required: this extracts the GrblMega5X controller's reported axis order and makes it available to other modules in addition to updating the capabilities
static String axisOrder = "XYZABC"; static Pattern axisCountPattern = Pattern.compile("\[AXS:(\d):([XYZABC])]");
Optional
Optional
// Parse axis details from status string - AndyCXL
private void parseAxesFromStatus(final String response) {
/
[VER:1.1t.20210510:]
[AXS:5:XYZYA]
[OPT:VNMGPH,25,255,48]
/
Optional
if (axes.isPresent()) {
this.capabilities.removeCapability(X_AXIS);
this.capabilities.removeCapability(Y_AXIS);
this.capabilities.removeCapability(Z_AXIS);
this.capabilities.removeCapability(A_AXIS);
this.capabilities.removeCapability(B_AXIS);
this.capabilities.removeCapability(C_AXIS);
/* Axes defines the number of distinct axes, Order defines the
// sequence and any duplication, eg: dual-Y or dual-X configs
// eg: 3=XYZ 3 distinct, 3=XYA 3 distinct, or 5=XYZYA 4 distinct
// Ignore for now that Mega 5X allows letters other than ABC
//
// Strategy for coping with non XYZABC order, and duplicates:
// Iterate 1..axes.get()
// Obtain nth axis letter from order
// Test if this.capabilities.hasCapability(n_AXIS) already exists
// and addCapability() if not
//
// Capabilities now added for each distinct axis letter, potentially
// different (fewer) than the number of physical axes Mega5X reports
*/
char nthChar;
for (int n=0; n < axes.get(); n++) {
nthChar = order.get().charAt(n);
switch(nthChar) {
case 'X':
if (!this.capabilities.hasCapability(X_AXIS))
this.capabilities.addCapability(X_AXIS);
break;
case 'Y':
if (!this.capabilities.hasCapability(Y_AXIS))
this.capabilities.addCapability(Y_AXIS);
break;
case 'Z':
if (!this.capabilities.hasCapability(Z_AXIS))
this.capabilities.addCapability(Z_AXIS);
break;
case 'A':
if (!this.capabilities.hasCapability(A_AXIS))
this.capabilities.addCapability(A_AXIS);
break;
case 'B':
if (!this.capabilities.hasCapability(B_AXIS))
this.capabilities.addCapability(B_AXIS);
break;
case 'C':
if (!this.capabilities.hasCapability(C_AXIS))
this.capabilities.addCapability(C_AXIS);
break;
}
}
// Record Axis ordering as a capability
if (order.isPresent()) {
axisOrder = order.get();
this.capabilities.addCapability(AXIS_ORDERING);
} else {
axisOrder = "XYZABC";
}
// Log outcome, and to aid machine and setup diagnostics
logger.log(Level.CONFIG, "Axes:{0} Order:{1}",
new Object[] {axes.get(), order.get()}
);
}
}
Additions to CapabilitiesConstants.java that will be required:
public static final String A_AXIS = "A_AXIS"; public static final String B_AXIS = "B_AXIS"; public static final String C_AXIS = "C_AXIS"; public static final String AXIS_ORDERING = "AXIS_ORDERING";
Is your feature request related to a problem? Please describe.Show all Enabled Axes in DRO from XYZABC not just Linear Axes
Describe the solution you'd like Right-click in DRO only shows XYZ and whether disabled. If XYZABC were all able to be enabled or disabled this way, then any 'has capability' axis from the actual machine could be displayed in DRO. If an axis is rotational, it would be nice if some visual distinction could be made versus a linear axis.
Describe alternatives you've considered I have hacked axisutils to declare A axis as Linear and thus show in DRO. This demonstrates that the underlying code and data reporting are there and able to work, so a 'formal' solution is likely not that difficult.
Additional context