Skip to content

Commit 4f779e6

Browse files
committed
Enhanced basic materials support and added import of LinuxCNC and SheetCam style material files.
Added support for setting feedrate via named parameter set from value in selected material.
1 parent 429c27f commit 4f779e6

File tree

7 files changed

+751
-122
lines changed

7 files changed

+751
-122
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ add_library(plasma INTERFACE)
22

33
target_sources(plasma INTERFACE
44
${CMAKE_CURRENT_LIST_DIR}/thc.c
5+
${CMAKE_CURRENT_LIST_DIR}/linuxcnc.c
6+
${CMAKE_CURRENT_LIST_DIR}/sheetcam.c
57
)
6-
7-
target_include_directories(plasma INTERFACE ${CMAKE_CURRENT_LIST_DIR})

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,24 @@ The Q-word for M67 and M68 is the percentage of the programmed feed rate the act
8282
The minimum percentage allowed is 10%, values below this will be set to 10%.
8383
The maximum percentage allowed is 100%, values above this will be set to 100%.
8484

85+
#### Materials
86+
87+
The plugin can load and partially make use of LinuxCNC and/or SheetCam style material files. Loading is from either a SD card or from root mounted littlefs file system.
88+
89+
The following files are currently loaded from if present:
90+
* LinuxCNC: _/linuxcnc/material.cfg_
91+
* SheetCam: _/sheetcam/default.tools_
92+
93+
Additionally materials can be modified or added by LinuxCNC style _magic_ [gcode comments](https://linuxcnc.org/docs/html/plasma/qtplasmac.html#plasma:magic-comments).
94+
95+
To select the material to use `M190P<n>` where `<n>` is the material number.
96+
If NGC parameter support is enabled in the controller the feedrate from the selected material can be set by adding `F#<_hal[plasmac.cut-feed-rate]>` to the gcode file.
97+
98+
Currently loaded materials can be output to the sender console with the `$EM` command, the output is in a machine readable format.
99+
100+
> [!NOTE]
101+
> Settings updated via _magic_ comments are currently _not_ written back to the material file.
102+
85103
#### Dependencies:
86104

87105
Driver must support a number of auxiliary I/O ports, at least one digital input for the arc ok signal.
@@ -92,4 +110,4 @@ Some drivers support the MCP3221 I2C ADC, when enabled it can be used for the ar
92110
LinuxCNC documentation linked to above.
93111

94112
---
95-
2024-01-26
113+
2025-02-23

linuxcnc.c

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
3+
linuxcnc.c - plasma cutter tool height control plugin
4+
5+
Part of grblHAL
6+
7+
Copyright (c) 2025 Terje Io
8+
9+
grblHAL is free software: you can redistribute it and/or modify
10+
it under the terms of the GNU General Public License as published by
11+
the Free Software Foundation, either version 3 of the License, or
12+
(at your option) any later version.
13+
14+
grblHAL is distributed in the hope that it will be useful,
15+
but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
GNU General Public License for more details.
18+
19+
You should have received a copy of the GNU General Public License
20+
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
21+
22+
*/
23+
24+
#include "thc.h"
25+
26+
#if PLASMA_ENABLE
27+
28+
#include <math.h>
29+
#include <stdio.h>
30+
#include <stdint.h>
31+
#include <stdbool.h>
32+
#include <string.h>
33+
34+
#include "grbl/vfs.h"
35+
#include "grbl/strutils.h"
36+
37+
static on_vfs_mount_ptr on_vfs_mount;
38+
39+
static void load_tools (const char *path, const vfs_t *fs)
40+
{
41+
// NOTE: must match layout of material_t
42+
static const char params[] = "PIERCE_HEIGHT,PIERCE_DELAY,CUT_SPEED,CUT_HEIGHT,CUT_VOLTS,PAUSE_AT_END,KERF_WIDTH,CUT_AMPS,GAS_PRESSURE,CUT_MODE,PUDDLE_JUMP_HEIGHT,PUDDLE_JUMP_DELAY,-,NAME,THC";
43+
44+
char c, *eq, buf[100];
45+
uint_fast8_t idx = 0;
46+
vfs_file_t *file;
47+
status_code_t status = Status_GcodeUnusedWords;
48+
49+
material_t material;
50+
51+
if((file = vfs_open("/linuxcnc/material.cfg", "r"))) {
52+
53+
while(vfs_read(&c, 1, 1, file) == 1) {
54+
55+
if(c == ASCII_CR || c == ASCII_LF) {
56+
57+
buf[idx] = '\0';
58+
59+
if(*buf == '[') {
60+
61+
if(status == Status_OK && plasma_material_is_valid(&material))
62+
plasma_material_add(&material, true);
63+
64+
status = Status_GcodeUnusedWords;
65+
66+
if((eq = strchr(buf, ']'))) {
67+
68+
*eq = '\0';
69+
70+
if((eq = strrchr(buf, '_'))) {
71+
uint32_t id;
72+
uint_fast8_t cc = 1;
73+
if((status = read_uint(eq, &cc, &id)) == Status_OK) {
74+
material.id = (int32_t)id;
75+
material.thc_status = true; //?
76+
*material.name = '\0';
77+
for(idx = 0; idx < sizeof(material.params) / sizeof(float); idx++)
78+
material.params[idx] = NAN;
79+
}
80+
}
81+
}
82+
}
83+
84+
if(status == Status_OK && (eq = strchr(buf, '='))) {
85+
86+
int32_t p;
87+
88+
*eq++ = '\0';
89+
90+
while(*eq == ' ')
91+
eq++;
92+
93+
switch((p = strlookup(strtok(buf, " "), params, ','))) {
94+
95+
case 13:
96+
strncpy(material.name, eq, sizeof(material.name) - 1);
97+
material.name[sizeof(material.name) - 1] = '\0';
98+
break;
99+
100+
case 14:
101+
material.thc_status = *eq != '0';
102+
break;
103+
104+
default:
105+
{
106+
uint_fast8_t cc = 0;
107+
if(!read_float(eq, &cc, &material.params[p]))
108+
status = Status_BadNumberFormat;
109+
}
110+
break;
111+
}
112+
}
113+
idx = 0;
114+
} else if(idx < sizeof(buf))
115+
buf[idx++] = c;
116+
}
117+
118+
if(status == Status_OK && plasma_material_is_valid(&material))
119+
plasma_material_add(&material, true);
120+
121+
vfs_close(file);
122+
}
123+
124+
if(on_vfs_mount)
125+
on_vfs_mount(path, fs);
126+
}
127+
128+
void linuxcnc_init (void)
129+
{
130+
on_vfs_mount = vfs.on_mount;
131+
vfs.on_mount = load_tools;
132+
}
133+
134+
#endif // PLASMA_ENABLE

powermax.c

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*
2+
3+
powermax.c - PowerMax plasma cutter RS-485 communication
4+
5+
Part of grblHAL
6+
7+
Copyright (c) 2025 Terje Io
8+
9+
grblHAL is free software: you can redistribute it and/or modify
10+
it under the terms of the GNU General Public License as published by
11+
the Free Software Foundation, either version 3 of the License, or
12+
(at your option) any later version.
13+
14+
grblHAL is distributed in the hope that it will be useful,
15+
but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
GNU General Public License for more details.
18+
19+
You should have received a copy of the GNU General Public License
20+
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
21+
22+
*/
23+
24+
#include "thc.h"
25+
26+
#if PLASMA_ENABLE && 0
27+
28+
#include <math.h>
29+
#include <string.h>
30+
31+
#include "../spindle/modbus_rtu.h"
32+
33+
static uint32_t modbus_address = 1;
34+
35+
static void rx_packet (modbus_message_t *msg);
36+
static void rx_exception (uint8_t code, void *context);
37+
38+
static const modbus_callbacks_t callbacks = {
39+
.retries = 5,
40+
.retry_delay = 50,
41+
.on_rx_packet = rx_packet,
42+
.on_rx_exception = rx_exception
43+
};
44+
45+
static bool set_cut_mode (uint16_t mode)
46+
{
47+
modbus_message_t rpm_cmd = {
48+
.context = (void *)Plasma_SetMode,
49+
.crc_check = false,
50+
.adu[0] = modbus_address,
51+
.adu[1] = ModBus_WriteRegister,
52+
.adu[2] = 0x20,
53+
.adu[3] = 0x93,
54+
.adu[4] = mode >> 8,
55+
.adu[5] = mode & 0xFF,
56+
.tx_length = 8,
57+
.rx_length = 8
58+
};
59+
60+
return modbus_send(&rpm_cmd, &callbacks, true);
61+
}
62+
63+
static bool set_amperage (float a)
64+
{
65+
uint16_t amps = (uint16_t)(a * 64);
66+
67+
modbus_message_t rpm_cmd = {
68+
.context = (void *)Plasma_SetCurrent,
69+
.crc_check = false,
70+
.adu[0] = modbus_address,
71+
.adu[1] = ModBus_WriteRegister,
72+
.adu[2] = 0x20,
73+
.adu[3] = 0x94,
74+
.adu[4] = amps >> 8,
75+
.adu[5] = amps & 0xFF,
76+
.tx_length = 8,
77+
.rx_length = 8
78+
};
79+
80+
return modbus_send(&rpm_cmd, &callbacks, true);
81+
}
82+
83+
static bool set_gas_pressure (float psi)
84+
{
85+
uint16_t pressure = (uint16_t)(psi * 128);
86+
87+
modbus_message_t mode_cmd = {
88+
.context = (void *)Plasma_SetPressure,
89+
.crc_check = false,
90+
.adu[0] = modbus_address,
91+
.adu[1] = ModBus_WriteRegister,
92+
.adu[2] = 0x20,
93+
.adu[3] = 0x96,
94+
.adu[4] = pressure >> 8,
95+
.adu[5] = pressure & 0xFF,
96+
.tx_length = 8,
97+
.rx_length = 8
98+
};
99+
100+
return modbus_send(&mode_cmd, &callbacks, true);
101+
}
102+
103+
static void rx_packet (modbus_message_t *msg)
104+
{
105+
if(!(msg->adu[0] & 0x80)) {
106+
/*
107+
switch((vfd_response_t)msg->context) {
108+
109+
case VFD_GetRPM:
110+
spindle_validate_at_speed(spindle_data, f2rpm((msg->adu[3] << 8) | msg->adu[4]));
111+
break;
112+
113+
case VFD_GetMinRPM:
114+
freq_min = (msg->adu[3] << 8) | msg->adu[4];
115+
break;
116+
117+
case VFD_GetMaxRPM:
118+
freq_max = (msg->adu[3] << 8) | msg->adu[4];
119+
spindle_hal->cap.rpm_range_locked = On;
120+
spindle_hal->rpm_min = f2rpm(freq_min);
121+
spindle_hal->rpm_max = f2rpm(freq_max);
122+
break;
123+
124+
default:
125+
break;
126+
}
127+
*/
128+
}
129+
}
130+
131+
static void rx_exception (uint8_t code, void *context)
132+
{
133+
// raise alarm?
134+
}
135+
136+
/*
137+
static void onReportOptions (bool newopt)
138+
{
139+
on_report_options(newopt);
140+
141+
if(!newopt)
142+
report_plugin("PowerMax RS-485", "0.01");
143+
}
144+
*/
145+
146+
void powermax_init (void)
147+
{
148+
cutter.set_cut_mode = set_cut_mode;
149+
cutter.set_current = set_amperage;
150+
cutter.set_pressure = set_gas_pressure;
151+
}
152+
153+
#endif

0 commit comments

Comments
 (0)