Skip to content

Commit

Permalink
ConfigGen: properly support pretuned sensorless configs, set sensorle…
Browse files Browse the repository at this point in the history
…ss as default on mk3
  • Loading branch information
miklschmidt committed Dec 27, 2024
1 parent b60c6fa commit 79319f1
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 23 deletions.
4 changes: 2 additions & 2 deletions configuration/printers/prusa-mk3s/printer-definition.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
"partFan": "4pin-dedicated",
"hotendFan": "4pin-dedicated",
"probe": "superpinda",
"xEndstop": "endstop",
"yEndstop": "endstop"
"xEndstop": "sensorless",
"yEndstop": "sensorless"
}
],
"rails": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ position_max: 255
homing_speed: 25
homing_retract_dist: 0

[tmc2130 stepper_x]
driver_SGT: 0

[stepper_y]
endstop_pin: tmc2130_stepper_y:virtual_endstop
position_endstop: -4
Expand All @@ -21,6 +24,9 @@ position_max: 212.5
homing_speed: 25
homing_retract_dist: 0

[tmc2130 stepper_y]
driver_SGT: 0

[stepper_z]
endstop_pin: probe:z_virtual_endstop
position_min: -5
Expand Down
4 changes: 2 additions & 2 deletions src/__tests__/fixtures/prusa-mk3s.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"hotend": "v6",
"thermistor": "ATC Semitec 104GT-2",
"extruder": "mk3s",
"xEndstop": "endstop",
"yEndstop": "endstop",
"xEndstop": "sensorless",
"yEndstop": "sensorless",
"hotendFan": "4pin-dedicated",
"partFan": "4pin-dedicated",
"nozzle": {
Expand Down
47 changes: 39 additions & 8 deletions src/__tests__/server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,15 @@ const serializedConfigFromDefaults = (printer: PrinterDefinition): SerializedPri

const loadConfig = async (path: string) => {
const config = await loadSerializedConfig(path);
const res: string = (await getFilesToWrite(config)).find((f) => f.fileName === 'RatOS.cfg')?.content ?? '';
const files = await getFilesToWrite(config);
const res: string = files.find((f) => f.fileName === 'RatOS.cfg')?.content ?? '';
const splitRes = res.split('\n');
const annotatedLines = splitRes.map((l: string, i: number) => `Line-${i + 1}`.padEnd(10, '-') + `|${l}`);
return {
splitRes,
annotatedLines,
config,
files,
};
};

Expand Down Expand Up @@ -242,16 +244,16 @@ describe('server', async () => {
}
});
});
describe('can generate a config without resonance tester', async () => {
describe('can generate a valid mk3s config', async () => {
const prusaMk3sConfigPath = path.join(__dirname, 'fixtures', 'prusa-mk3s.json');
const { splitRes, annotatedLines, config } = await loadConfig(prusaMk3sConfigPath);
const gcodeBlocks: number[] = [];
splitRes.forEach((l, i) => l.includes('[resonance_tester]') && gcodeBlocks.push(i));
const { splitRes, annotatedLines, config, files } = await loadConfig(prusaMk3sConfigPath);
test('produces valid config', async () => {
expectValidConfig(config, splitRes, annotatedLines);
});
const resonanceTesterBlocks: number[] = [];
splitRes.forEach((l, i) => l.includes('[resonance_tester]') && resonanceTesterBlocks.push(i));
test('does not include resonance tester in the config', async () => {
for (const block of gcodeBlocks) {
for (const block of resonanceTesterBlocks) {
try {
expect(splitRes[block].includes('[resonance_tester]')).toBeFalsy();
} catch (e) {
Expand All @@ -261,6 +263,31 @@ describe('server', async () => {
}
}
});
const sensorlessBlocks: number[] = [];
const endstopBlocks: number[] = [];
splitRes.forEach((l, i) => l.includes('[include sensorless-homing') && sensorlessBlocks.push(i));
splitRes.forEach((l, i) => l.includes('variable_homing_x: "endstop"') && endstopBlocks.push(i));
splitRes.forEach((l, i) => l.includes('variable_homing_y: "endstop"') && endstopBlocks.push(i));
test('correctly configures sensorless homing', async () => {
try {
expect(endstopBlocks.length).toBeLessThan(1);
} catch (e) {
throw new Error(
`Found endstop configuration:\n${annotatedLines.slice(endstopBlocks[0] - 4, endstopBlocks[0] + 5).join('\n')}`,
);
}
expect(sensorlessBlocks.length).toBe(2);
});
test('correctly comments out generated sensorless defaults', async () => {
expect(files.find((f) => f.fileName === 'sensorless-homing-x.cfg')?.content).toContain(
'#variable_sensorless_x_current: ',
);
expect(files.find((f) => f.fileName === 'sensorless-homing-y.cfg')?.content).toContain(
'#variable_sensorless_y_current: ',
);
expect(files.find((f) => f.fileName === 'sensorless-homing-x.cfg')?.content).toContain('#driver_SGT: 0');
expect(files.find((f) => f.fileName === 'sensorless-homing-y.cfg')?.content).toContain('#driver_SGT: 0');
});
});
describe('can generate another idex config', async () => {
const config = await loadSerializedConfig(path.join(__dirname, 'fixtures', 'another-idex.json'));
Expand Down Expand Up @@ -408,8 +435,12 @@ describe('server', async () => {
test.concurrent('can render sensorless homing files', async () => {
const config = await loadSerializedConfig(path.join(__dirname, 'fixtures', 'hybrid-config.json'));
const utils = await constructKlipperConfigUtils(config);
const x = sensorlessXTemplate(config, utils);
const y = sensorlessYTemplate(config, utils);
const x = sensorlessXTemplate(config, utils, false);
const y = sensorlessYTemplate(config, utils, false);
expect(x).toContain('variable_sensorless_x_current:');
expect(y).toContain('variable_sensorless_y_current:');
expect(x).toContain('driver_SGTHRS:');
expect(y).toContain('driver_SGTHRS:');
});
});
describe('can generate v-minion config', async () => {
Expand Down
11 changes: 6 additions & 5 deletions src/server/helpers/klipper-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export const constructKlipperConfigUtils = async (config: PrinterConfiguration)
getAxisDriverHomingCurrent(axis: PrinterAxis, factor: number) {
const rail = this.getRail(axis);
factor = Math.max(0, Math.min(1, factor));
return rail.stepper.maxPeakCurrent * 0.71 * factor;
return Math.round(rail.stepper.maxPeakCurrent * 0.71 * factor * 1000) / 1000;
},
getExtruderPinPrefix(tool: ToolOrAxis = 0) {
const th = this.getToolhead(tool);
Expand Down Expand Up @@ -382,19 +382,19 @@ export const constructKlipperConfigExtrasGenerator = (config: PrinterConfigurati
return [`[save_variables]`, `filename: ${path.join(environment.KLIPPER_CONFIG_PATH, f.fileName)}`].join('\n');
});
},
generateSensorlessHomingIncludes() {
generateSensorlessHomingIncludes(hasPretunedConfig: boolean) {
const filesToWrite: WritableFiles = [];
if (utils.isSensorless(PrinterAxis.x)) {
filesToWrite.push({
fileName: 'sensorless-homing-x.cfg',
content: sensorlessXTemplate(config, utils),
content: sensorlessXTemplate(config, utils, hasPretunedConfig),
overwrite: false,
});
}
if (utils.isSensorless(PrinterAxis.y)) {
filesToWrite.push({
fileName: 'sensorless-homing-y.cfg',
content: sensorlessYTemplate(config, utils),
content: sensorlessYTemplate(config, utils, hasPretunedConfig),
overwrite: false,
});
}
Expand Down Expand Up @@ -1009,8 +1009,9 @@ export const constructKlipperConfigHelpers = async (
))
) {
result.push(`[include ${pretunedSensorlessConfig}]`);
result.push(extrasGenerator.generateSensorlessHomingIncludes(true));
} else {
result.push(extrasGenerator.generateSensorlessHomingIncludes());
result.push(extrasGenerator.generateSensorlessHomingIncludes(false));
}
}
if (utils.getToolheads().every((th) => th.getProbe() == null)) {
Expand Down
24 changes: 18 additions & 6 deletions src/templates/extras/sensorless-homing.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { KlipperConfigUtils } from '@/server/helpers/klipper-config';
import { PrinterAxis } from '@/zods/motion';
import { PrinterConfiguration } from '@/zods/printer-configuration';
export const sensorlessXTemplate = (config: PrinterConfiguration, utils: KlipperConfigUtils) => `
export const sensorlessXTemplate = (
config: PrinterConfiguration,
utils: KlipperConfigUtils,
hasPretunedConfig: boolean,
) => `
# Sensorless homing.
#
# Tune the sensorless_x_current variable and the SGTHRS/SGT value in this file untill you get reliable homing.
Expand All @@ -16,18 +20,24 @@ export const sensorlessXTemplate = (config: PrinterConfiguration, utils: Klipper
[${utils.getAxisDriverSectionName(PrinterAxis.x)}]
${utils.getAxisDriverDiagConfig(PrinterAxis.x)}
${utils.getAxisDriverStallGuardThreshold(PrinterAxis.x, 0.5)}
${hasPretunedConfig ? '# Printer has a pretuned sensorless homing config, uncomment the next line to override it' : ''}
${hasPretunedConfig ? '#' : ''}${utils.getAxisDriverStallGuardThreshold(PrinterAxis.x, 0.5)}
[${utils.getAxisStepperName(PrinterAxis.x)}]
endstop_pin: ${utils.getAxisVirtualEndstop(PrinterAxis.x)}
homing_retract_dist: 0
[gcode_macro RatOS]
variable_homing_x: "sensorless"
variable_sensorless_x_current: ${utils.getAxisDriverHomingCurrent(PrinterAxis.x, 0.35)}
${hasPretunedConfig ? '# Printer has a pretuned sensorless homing config, uncomment the next line to override it' : ''}
${hasPretunedConfig ? '#' : ''}variable_sensorless_x_current: ${utils.getAxisDriverHomingCurrent(PrinterAxis.x, 0.35)}
`;

export const sensorlessYTemplate = (config: PrinterConfiguration, utils: KlipperConfigUtils) => `
export const sensorlessYTemplate = (
config: PrinterConfiguration,
utils: KlipperConfigUtils,
hasPretunedConfig: boolean,
) => `
# Sensorless homing.
#
# Tune the current variable and the SGTHRS value in the included file(s) untill you get reliable homing.
Expand All @@ -42,13 +52,15 @@ export const sensorlessYTemplate = (config: PrinterConfiguration, utils: Klipper
[${utils.getAxisDriverSectionName(PrinterAxis.y)}]
${utils.getAxisDriverDiagConfig(PrinterAxis.y)}
${utils.getAxisDriverStallGuardThreshold(PrinterAxis.y, 0.5)}
${hasPretunedConfig ? '# Printer has a pretuned sensorless homing config, uncomment the next line to override it' : ''}
${hasPretunedConfig ? '#' : ''}${utils.getAxisDriverStallGuardThreshold(PrinterAxis.y, 0.5)}
[stepper_y]
endstop_pin: ${utils.getAxisVirtualEndstop(PrinterAxis.y)}
homing_retract_dist: 0
[gcode_macro RatOS]
variable_homing_y: "sensorless"
variable_sensorless_y_current: ${utils.getAxisDriverHomingCurrent(PrinterAxis.y, 0.51)}
${hasPretunedConfig ? '# Printer has a pretuned sensorless homing config, uncomment the next line to override it' : ''}
${hasPretunedConfig ? '#' : ''}variable_sensorless_y_current: ${utils.getAxisDriverHomingCurrent(PrinterAxis.y, 0.51)}
`;

0 comments on commit 79319f1

Please sign in to comment.