This is an old revision of the document!
Der untere p5.js-Sketch ermöglicht die schnelle Abschätzung grundlegender Fräsparameter für Hobby- und Labor-CNCs. Anstatt Vorschub, Zustelltiefe und Spindeldrehzahl nur aus Tabellenwerten zu übernehmen, kombiniert das Tool Materialauswahl, Materialdicke, Fräserdurchmesser und Fräser-Typ zu konsistenten Startwerten.
Für ein gewähltes Material (zum Beispiel Birkensperrholz, MDF, Kunststoffe oder Aluminium) und eine angegebene Materialdicke in Millimetern berechnet der Sketch unter anderem Vorschubgeschwindigkeit (Feed), Eintauchgeschwindigkeit (Plunge), Zustelltiefe pro Durchgang (Depth per pass), empfohlene Spindeldrehzahl sowie den Span pro Zahn (Chip Load). Zusätzlich wird zwischen Spiralnut-Aufwärtsfräsern (Upcut) und Fräsern mit gerader Schneide unterschieden, sodass die Hinweise praxisnahe Empfehlungen für typische Laborsituationen liefern. Das Tool ist bewusst konservativ ausgelegt und dient als Ausgangspunkt für eigene Testläufe an Reststücken.
https://ct-lab.info/cnc-helper/
P5.JS
// CNC feed suggestion helper with adjustable bit diameter // Includes spindle speed and chip load calculation let materialSelect; let thicknessInput; let bitDiameterInput; let bitTypeSelect; let calcButton; let resultDiv; function applyCustomStyles() { // Styles werden im HTML gesetzt; hier nur für Konsistenz. } function setup() { applyCustomStyles(); createCanvas(1, 1); noLoop(); select('canvas').style('display', 'none'); const container = select('#calculator-container'); const title = createDiv('CNC Feed & Chip-Load Rechner'); title.addClass('app-title'); title.parent(container); const subtitle = createDiv( 'Konservative Startwerte für Hobby-CNC-Router. Vor Serienfertigung immer an Reststücken testen.' ); subtitle.addClass('app-subtitle'); subtitle.parent(container); const layout = createDiv(); layout.addClass('layout'); layout.parent(container); const inputPanel = createDiv(); inputPanel.addClass('panel'); inputPanel.parent(layout); const inputTitle = createDiv('Eingaben'); inputTitle.addClass('panel-title'); inputTitle.parent(inputPanel); const matGroup = createDiv(); matGroup.addClass('field-group'); matGroup.parent(inputPanel); const matLabel = createSpan('Material (Material):'); matLabel.addClass('field-label'); matLabel.parent(matGroup); materialSelect = createSelect(); materialSelect.parent(matGroup); materialSelect.option('Birkensperrholz (Birch Plywood)'); materialSelect.option('Kiefer (Pine)'); materialSelect.option('Bambus (Bamboo)'); materialSelect.option('MDF (MDF)'); materialSelect.option('Kirschsperrholz (Cherry Plywood)'); materialSelect.option('Harter Ahorn (Hard Maple)'); materialSelect.option('Bubinga (Bubinga)'); materialSelect.option('HDPE (HDPE)'); materialSelect.option('2-Farb-HDPE (2-Color HDPE)'); materialSelect.option('Geschäumtes PVC (Expanded PVC)'); materialSelect.option('ABS (ABS)'); materialSelect.option('Gussacryl (Cast Acrylic)'); materialSelect.option('2-Farb-Acryl (2-Color Acrylic)'); materialSelect.option('Corian (Corian)'); materialSelect.option('Linoleum (Linoleum)'); materialSelect.option('Leiterplattenmaterial PCB (PCB)'); materialSelect.option('Aluminium (Aluminum)'); const thickGroup = createDiv(); thickGroup.addClass('field-group'); thickGroup.parent(inputPanel); const thickLabel = createSpan('Materialdicke [mm] (Material thickness):'); thickLabel.addClass('field-label'); thickLabel.parent(thickGroup); thicknessInput = createInput(''); thicknessInput.attribute('type', 'number'); thicknessInput.attribute('min', '0.1'); thicknessInput.attribute('step', '0.1'); thicknessInput.parent(thickGroup); const thickHint = createDiv('Typische Platten: 3 / 6 / 9 / 12 / 18 mm.'); thickHint.addClass('hint'); thickHint.parent(thickGroup); const toolRow = createDiv(); toolRow.addClass('field-row'); toolRow.parent(inputPanel); const bitGroup = createDiv(); bitGroup.addClass('field-group'); bitGroup.parent(toolRow); const bitLabel = createSpan('Fräserdurchmesser [mm] (Bit diameter):'); bitLabel.addClass('field-label'); bitLabel.parent(bitGroup); bitDiameterInput = createInput('2.5'); bitDiameterInput.attribute('type', 'number'); bitDiameterInput.attribute('min', '0.5'); bitDiameterInput.attribute('step', '0.1'); bitDiameterInput.parent(bitGroup); const typeGroup = createDiv(); typeGroup.addClass('field-group'); typeGroup.parent(toolRow); const typeLabel = createSpan('Fräser-Typ (End mill type):'); typeLabel.addClass('field-label'); typeLabel.parent(typeGroup); bitTypeSelect = createSelect(); bitTypeSelect.parent(typeGroup); bitTypeSelect.option('Spiralnut Aufwärts (Upcut end mill)'); bitTypeSelect.option('Gerade Schneide (Straight-cut end mill)'); const typeHint = createDiv( 'Upcut: starker Spanabtransport, mögliche Ausrisse oben. Gerade Schneide: ruhigere Kante, weniger Spanabtransport.' ); typeHint.addClass('hint'); typeHint.parent(inputPanel); calcButton = createButton('Vorschläge berechnen (Get suggestions)'); calcButton.parent(inputPanel); calcButton.mousePressed(updateSettings); const btnHint = createDiv( 'Alle Werte sind Startpunkte. Bei Geräusch, Vibration oder Brandspuren Parameter anpassen.' ); btnHint.addClass('hint'); btnHint.parent(inputPanel); const outputPanel = createDiv(); outputPanel.addClass('panel'); outputPanel.parent(container); const outputTitle = createDiv('Ergebnis'); outputTitle.addClass('panel-title'); outputTitle.parent(outputPanel); resultDiv = createDiv('Noch keine Berechnung durchgeführt.'); resultDiv.parent(outputPanel); const licenseDiv = createDiv( 'Creative Technologies Lab, FH Münster – Lizenz: Dieses Tool steht unter der Creative-Commons-Lizenz ' + '<a href="https://creativecommons.org/licenses/by-sa/3.0/" target="_blank" rel="noopener noreferrer">CC BY-SA 3.0</a>. ' + 'Es darf kopiert, geteilt und angepasst werden, solange die Urheberschaft genannt und abgeleitete Versionen unter denselben Bedingungen weitergegeben werden; ' + 'zusätzliche Einschränkungen oder abweichende Lizenzbedingungen dürfen nicht hinzugefügt werden.' ); licenseDiv.addClass('license-note'); licenseDiv.parent(container); } function updateSettings() { const mat = materialSelect.value(); const t = parseFloat(thicknessInput.value()); const bitD = parseFloat(bitDiameterInput.value()); const bitType = bitTypeSelect.value(); if (isNaN(t) || t <= 0) { resultDiv.html( '<div class="error-message">Bitte eine gültige Materialdicke in Millimetern eingeben.</div>' ); return; } if (isNaN(bitD) || bitD <= 0) { resultDiv.html( '<div class="error-message">Bitte einen gültigen Fräserdurchmesser in Millimetern eingeben.</div>' ); return; } const settings = computeSettings(mat, t, bitD, bitType); const passes = Math.ceil(t / settings.depthPerPass); const chipLoad = settings.feedRate / (settings.spindleRPM * settings.flutes); const summaryHtml = '<div class="summary-row">' + `<div class="summary-pill">Feed: ${Math.round(settings.feedRate)} mm/min</div>` + `<div class="summary-pill">Plunge: ${Math.round(settings.plungeRate)} mm/min</div>` + `<div class="summary-pill">Chip Load: ${roundTo(chipLoad, 4)} mm/Zahn</div>` + `<div class="summary-pill">Drehzahl: ${Math.round(settings.spindleRPM)} U/min</div>` + `<div class="summary-pill">Depth/Pass: ${roundTo(settings.depthPerPass, 2)} mm</div>` + `<div class="summary-pill">ca. ${passes} Durchgänge</div>` + '</div>'; const tableHtml = '<table id="result-table">' + '<tr>' + '<th>Material</th>' + '<th>Dicke [mm]</th>' + '<th>Ø Bit [mm]</th>' + '<th>Bit-Typ</th>' + '<th>Drehzahl [U/min]</th>' + '<th>Zähne</th>' + '<th>Chip Load [mm]</th>' + '<th>Feed [mm/min]</th>' + '<th>Plunge [mm/min]</th>' + '<th>Depth/Pass [mm]</th>' + '<th>Plunge-Art</th>' + '<th>Hinweise</th>' + '</tr>' + '<tr>' + `<td>${mat}</td>` + `<td>${roundTo(t, 1)}</td>` + `<td>${roundTo(bitD, 2)}</td>` + `<td>${bitType}</td>` + `<td>${Math.round(settings.spindleRPM)}</td>` + `<td>${settings.flutes}</td>` + `<td>${roundTo(chipLoad, 4)}</td>` + `<td>${Math.round(settings.feedRate)}</td>` + `<td>${Math.round(settings.plungeRate)}</td>` + `<td>${roundTo(settings.depthPerPass, 2)}</td>` + `<td>${settings.plungeType}</td>` + `<td>${settings.notes}</td>` + '</tr>' + '</table>'; resultDiv.html(summaryHtml + tableHtml); } function computeSettings(material, thickness, bitDiameter, bitType) { let baseFeed; let plunge; let depthFactor; let spindleRPM; let flutes; let plungeType = 'Rampe 5° (Ramp 5°)'; let notes; switch (material) { case 'Birkensperrholz (Birch Plywood)': case 'Bambus (Bamboo)': case 'MDF (MDF)': case 'Kirschsperrholz (Cherry Plywood)': baseFeed = 1800; plunge = 600; depthFactor = 0.32; spindleRPM = 16000; flutes = 2; notes = 'Standard-Holzeinstellung. Empfohlene Fräser: 2-Schneider-Spiralnut, ggf. Downcut oder Kompressionsfräser.'; break; case 'Kiefer (Pine)': baseFeed = 1900; plunge = 650; depthFactor = 0.32; spindleRPM = 16000; flutes = 2; notes = 'Weiches Nadelholz; etwas höhere Vorschubgeschwindigkeit möglich.'; break; case 'Harter Ahorn (Hard Maple)': case 'Bubinga (Bubinga)': baseFeed = 1300; plunge = 400; depthFactor = 0.24; spindleRPM = 16000; flutes = 2; notes = 'Hartes Holz; reduzierte Zustelltiefe. Empfohlene Fräser: sehr scharfe 2-Schneider-Spiralnut.'; break; case 'HDPE (HDPE)': case '2-Farb-HDPE (2-Color HDPE)': case 'Geschäumtes PVC (Expanded PVC)': case 'ABS (ABS)': baseFeed = 2200; plunge = 700; depthFactor = 0.32; spindleRPM = 18000; flutes = 2; notes = 'Weicher Kunststoff; höherer Feed hilft gegen Schmelzen. Empfohlen: polierte Spiralnut, 1–2 Schneiden.'; break; case 'Gussacryl (Cast Acrylic)': case '2-Farb-Acryl (2-Color Acrylic)': baseFeed = 1200; plunge = 400; depthFactor = 0.24; spindleRPM = 16000; flutes = 1; notes = 'Sprödes Acryl; konservative Zustelltiefe. Einzahn-Spiralnut mit polierten Schneiden ist oft vorteilhaft.'; break; case 'Corian (Corian)': baseFeed = 1200; plunge = 400; depthFactor = 0.24; spindleRPM = 16000; flutes = 2; notes = 'Dichter Mineralwerkstoff; ähnlich hartem Holz, gute Absaugung notwendig.'; break; case 'Linoleum (Linoleum)': baseFeed = 1900; plunge = 650; depthFactor = 0.4; spindleRPM = 16000; flutes = 2; notes = 'Weiches Material; größere Zustelltiefe möglich. Trägerschicht beachten.'; break; case 'Leiterplattenmaterial PCB (PCB)': baseFeed = 800; plunge = 250; depthFactor = 0.12; spindleRPM = 18000; flutes = 1; notes = 'Isolationsfräsen; sehr flache Zustellung. Häufig kleine Einzahnwerkzeuge (0,8–1,0 mm) mit V- oder Geradegeometrie.'; break; case 'Aluminium (Aluminum)': baseFeed = 700; plunge = 220; depthFactor = 0.1; spindleRPM = 12000; flutes = 2; notes = 'Metallbearbeitung; geringe Zustelltiefe, gute Spanntechnik und Schmierung notwendig. Empfohlen: 1–2-Schneider-Aluminiumfräser (Upcut).'; break; default: baseFeed = 1500; plunge = 500; depthFactor = 0.28; spindleRPM = 16000; flutes = 2; notes = 'Generische Einstellung; bitte an Reststück prüfen.'; break; } const refDiameter = 2.5; const feedScale = Math.sqrt(bitDiameter / refDiameter); let feed = baseFeed * feedScale; let depth = depthFactor * bitDiameter; depth = constrain(depth, 0.15, bitDiameter * 0.5); if (thickness < 4) { feed *= 1.05; notes += ' Dünnes Material: Feed leicht erhöht.'; } else if (thickness > 12 && thickness <= 20) { feed *= 0.9; notes += ' Dickes Material: Feed leicht reduziert.'; } else if (thickness > 20) { feed *= 0.85; notes += ' Sehr dickes Material: eher in mehreren Stufen bearbeiten, ggf. von beiden Seiten.'; } if (bitType === 'Spiralnut Aufwärts (Upcut end mill)') { notes += ' Gewählter Fräser: Upcut; sehr guter Spanabtransport, mögliche Ausrisse oben.'; } else if (bitType === 'Gerade Schneide (Straight-cut end mill)') { notes += ' Gewählter Fräser: gerade Schneide; gute Kantenqualität in Holz/Kunststoff, Spanabtransport geringer.'; } if (bitDiameter < 1.0 && flutes > 1) { flutes = 1; notes = 'Hinweis: Für Fräser unter 1.0 mm wird die Zahnzahl vorsorglich auf 1 gesetzt. ' + notes; } return { feedRate: feed, plungeRate: plunge, depthPerPass: depth, spindleRPM: spindleRPM, flutes: flutes, plungeType: plungeType, notes: notes }; } function roundTo(value, decimals) { return Number(value.toFixed(decimals)); }
html
<!doctype html> <html lang="de"> <head> <meta charset="utf-8"> <title>CNC Feed & Chip-Load Rechner – Creative Technologies Lab, FH Münster</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- p5.js library --> <script src="https://cdn.jsdelivr.net/npm/p5@1.9.0/lib/p5.min.js"></script> <style> * { box-sizing: border-box; } body { font-family: system-ui, -apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif; background-color: #f3f4f6; color: #111827; margin: 0; padding: 24px 0; } #calculator-container { max-width: 960px; margin: 0 auto; padding: 0 16px 24px 16px; } .app-title { font-size: 24px; font-weight: 600; margin-bottom: 4px; } .app-subtitle { font-size: 13px; color: #6b7280; margin-bottom: 18px; } .layout { display: block; } .panel { background-color: #ffffff; border-radius: 12px; padding: 16px 18px 18px 18px; box-shadow: 0 8px 20px rgba(15, 23, 42, 0.06); margin-bottom: 16px; } .panel-title { font-size: 16px; font-weight: 600; margin-bottom: 10px; } .field-group { margin-bottom: 10px; } .field-label { display: block; font-size: 13px; font-weight: 500; margin-bottom: 4px; } select, input[type="number"], button { font-family: inherit; font-size: 13px; } select, input[type="number"] { width: 100%; padding: 6px 8px; border-radius: 6px; border: 1px solid #d1d5db; background-color: #f9fafb; } select:focus, input[type="number"]:focus { outline: none; border-color: #2563eb; box-shadow: 0 0 0 1px #2563eb20; background-color: #ffffff; } .field-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; } @media (max-width: 600px) { .field-row { grid-template-columns: 1fr; } } button { margin-top: 6px; padding: 7px 14px; border-radius: 999px; border: none; background-color: #2563eb; color: #ffffff; font-weight: 500; cursor: pointer; } button:hover { background-color: #1d4ed8; } .hint { font-size: 11px; color: #6b7280; margin-top: 3px; } .error-message { color: #b91c1c; font-weight: 500; margin-top: 10px; padding: 8px 10px; border-radius: 6px; background-color: #fee2e2; border: 1px solid #fecaca; font-size: 12px; } .summary-row { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; } .summary-pill { padding: 4px 8px; border-radius: 999px; background-color: #eff6ff; border: 1px solid #bfdbfe; font-size: 11px; color: #1d4ed8; } #result-table { width: 100%; border-collapse: collapse; margin-top: 6px; } #result-table th, #result-table td { border: 1px solid #e5e7eb; padding: 4px 6px; font-size: 12px; text-align: left; vertical-align: top; } #result-table th { background-color: #f9fafb; font-weight: 600; } #result-table tr:nth-child(even) td { background-color: #f3f4f6; } .license-note { margin-top: 8px; font-size: 11px; color: #6b7280; line-height: 1.4; } .license-note a { color: #2563eb; text-decoration: none; } .license-note a:hover { text-decoration: underline; } </style> </head> <body> <div id="calculator-container"> <!-- Inhalt wird durch p5.js im Sketch erzeugt --> </div> <script> // CNC feed suggestion helper with adjustable bit diameter // Includes spindle speed and chip load calculation let materialSelect; let thicknessInput; let bitDiameterInput; let bitTypeSelect; let calcButton; let resultDiv; function applyCustomStyles() { // Styles werden im Kopfbereich gesetzt } function setup() { applyCustomStyles(); createCanvas(1, 1); noLoop(); select('canvas').style('display', 'none'); const container = select('#calculator-container'); const title = createDiv('CNC Feed & Chip-Load Rechner'); title.addClass('app-title'); title.parent(container); const subtitle = createDiv( 'Konservative Startwerte für Hobby-CNC-Router. Vor Serienfertigung immer an Reststücken testen.' ); subtitle.addClass('app-subtitle'); subtitle.parent(container); const layout = createDiv(); layout.addClass('layout'); layout.parent(container); const inputPanel = createDiv(); inputPanel.addClass('panel'); inputPanel.parent(layout); const inputTitle = createDiv('Eingaben'); inputTitle.addClass('panel-title'); inputTitle.parent(inputPanel); const matGroup = createDiv(); matGroup.addClass('field-group'); matGroup.parent(inputPanel); const matLabel = createSpan('Material (Material):'); matLabel.addClass('field-label'); matLabel.parent(matGroup); materialSelect = createSelect(); materialSelect.parent(matGroup); materialSelect.option('Birkensperrholz (Birch Plywood)'); materialSelect.option('Kiefer (Pine)'); materialSelect.option('Bambus (Bamboo)'); materialSelect.option('MDF (MDF)'); materialSelect.option('Kirschsperrholz (Cherry Plywood)'); materialSelect.option('Harter Ahorn (Hard Maple)'); materialSelect.option('Bubinga (Bubinga)'); materialSelect.option('HDPE (HDPE)'); materialSelect.option('2-Farb-HDPE (2-Color HDPE)'); materialSelect.option('Geschäumtes PVC (Expanded PVC)'); materialSelect.option('ABS (ABS)'); materialSelect.option('Gussacryl (Cast Acrylic)'); materialSelect.option('2-Farb-Acryl (2-Color Acrylic)'); materialSelect.option('Corian (Corian)'); materialSelect.option('Linoleum (Linoleum)'); materialSelect.option('Leiterplattenmaterial PCB (PCB)'); materialSelect.option('Aluminium (Aluminum)'); const thickGroup = createDiv(); thickGroup.addClass('field-group'); thickGroup.parent(inputPanel); const thickLabel = createSpan('Materialdicke [mm] (Material thickness):'); thickLabel.addClass('field-label'); thickLabel.parent(thickGroup); thicknessInput = createInput(''); thicknessInput.attribute('type', 'number'); thicknessInput.attribute('min', '0.1'); thicknessInput.attribute('step', '0.1'); thicknessInput.parent(thickGroup); const thickHint = createDiv('Typische Platten: 3 / 6 / 9 / 12 / 18 mm.'); thickHint.addClass('hint'); thickHint.parent(thickGroup); const toolRow = createDiv(); toolRow.addClass('field-row'); toolRow.parent(inputPanel); const bitGroup = createDiv(); bitGroup.addClass('field-group'); bitGroup.parent(toolRow); const bitLabel = createSpan('Fräserdurchmesser [mm] (Bit diameter):'); bitLabel.addClass('field-label'); bitLabel.parent(bitGroup); bitDiameterInput = createInput('2.5'); bitDiameterInput.attribute('type', 'number'); bitDiameterInput.attribute('min', '0.5'); bitDiameterInput.attribute('step', '0.1'); bitDiameterInput.parent(bitGroup); const typeGroup = createDiv(); typeGroup.addClass('field-group'); typeGroup.parent(toolRow); const typeLabel = createSpan('Fräser-Typ (End mill type):'); typeLabel.addClass('field-label'); typeLabel.parent(typeGroup); bitTypeSelect = createSelect(); bitTypeSelect.parent(typeGroup); bitTypeSelect.option('Spiralnut Aufwärts (Upcut end mill)'); bitTypeSelect.option('Gerade Schneide (Straight-cut end mill)'); const typeHint = createDiv( 'Upcut: starker Spanabtransport, mögliche Ausrisse oben. Gerade Schneide: ruhigere Kante, weniger Spanabtransport.' ); typeHint.addClass('hint'); typeHint.parent(inputPanel); calcButton = createButton('Vorschläge berechnen (Get suggestions)'); calcButton.parent(inputPanel); calcButton.mousePressed(updateSettings); const btnHint = createDiv( 'Alle Werte sind Startpunkte. Bei Geräusch, Vibration oder Brandspuren Parameter anpassen.' ); btnHint.addClass('hint'); btnHint.parent(inputPanel); const outputPanel = createDiv(); outputPanel.addClass('panel'); outputPanel.parent(container); const outputTitle = createDiv('Ergebnis'); outputTitle.addClass('panel-title'); outputTitle.parent(outputPanel); resultDiv = createDiv('Noch keine Berechnung durchgeführt.'); resultDiv.parent(outputPanel); const licenseDiv = createDiv( 'Creative Technologies Lab, FH Münster – Lizenz: Dieses Tool steht unter der Creative-Commons-Lizenz ' + '<a href="https://creativecommons.org/licenses/by-sa/3.0/" target="_blank" rel="noopener noreferrer">CC BY-SA 3.0</a>. ' + 'Es darf kopiert, geteilt und angepasst werden, solange die Urheberschaft genannt und abgeleitete Versionen unter denselben Bedingungen weitergegeben werden; ' + 'zusätzliche Einschränkungen oder abweichende Lizenzbedingungen dürfen nicht hinzugefügt werden.' ); licenseDiv.addClass('license-note'); licenseDiv.parent(container); } function updateSettings() { const mat = materialSelect.value(); const t = parseFloat(thicknessInput.value()); const bitD = parseFloat(bitDiameterInput.value()); const bitType = bitTypeSelect.value(); if (isNaN(t) || t <= 0) { resultDiv.html( '<div class="error-message">Bitte eine gültige Materialdicke in Millimetern eingeben.</div>' ); return; } if (isNaN(bitD) || bitD <= 0) { resultDiv.html( '<div class="error-message">Bitte einen gültigen Fräserdurchmesser in Millimetern eingeben.</div>' ); return; } const settings = computeSettings(mat, t, bitD, bitType); const passes = Math.ceil(t / settings.depthPerPass); const chipLoad = settings.feedRate / (settings.spindleRPM * settings.flutes); const summaryHtml = '<div class="summary-row">' + `<div class="summary-pill">Feed: ${Math.round(settings.feedRate)} mm/min</div>` + `<div class="summary-pill">Plunge: ${Math.round(settings.plungeRate)} mm/min</div>` + `<div class="summary-pill">Chip Load: ${roundTo(chipLoad, 4)} mm/Zahn</div>` + `<div class="summary-pill">Drehzahl: ${Math.round(settings.spindleRPM)} U/min</div>` + `<div class="summary-pill">Depth/Pass: ${roundTo(settings.depthPerPass, 2)} mm</div>` + `<div class="summary-pill">ca. ${passes} Durchgänge</div>` + '</div>'; const tableHtml = '<table id="result-table">' + '<tr>' + '<th>Material</th>' + '<th>Dicke [mm]</th>' + '<th>Ø Bit [mm]</th>' + '<th>Bit-Typ</th>' + '<th>Drehzahl [U/min]</th>' + '<th>Zähne</th>' + '<th>Chip Load [mm]</th>' + '<th>Feed [mm/min]</th>' + '<th>Plunge [mm/min]</th>' + '<th>Depth/Pass [mm]</th>' + '<th>Plunge-Art</th>' + '<th>Hinweise</th>' + '</tr>' + '<tr>' + `<td>${mat}</td>` + `<td>${roundTo(t, 1)}</td>` + `<td>${roundTo(bitD, 2)}</td>` + `<td>${bitType}</td>` + `<td>${Math.round(settings.spindleRPM)}</td>` + `<td>${settings.flutes}</td>` + `<td>${roundTo(chipLoad, 4)}</td>` + `<td>${Math.round(settings.feedRate)}</td>` + `<td>${Math.round(settings.plungeRate)}</td>` + `<td>${roundTo(settings.depthPerPass, 2)}</td>` + `<td>${settings.plungeType}</td>` + `<td>${settings.notes}</td>` + '</tr>' + '</table>'; resultDiv.html(summaryHtml + tableHtml); } function computeSettings(material, thickness, bitDiameter, bitType) { let baseFeed; let plunge; let depthFactor; let spindleRPM; let flutes; let plungeType = 'Rampe 5° (Ramp 5°)'; let notes; switch (material) { case 'Birkensperrholz (Birch Plywood)': case 'Bambus (Bamboo)': case 'MDF (MDF)': case 'Kirschsperrholz (Cherry Plywood)': baseFeed = 1800; plunge = 600; depthFactor = 0.32; spindleRPM = 16000; flutes = 2; notes = 'Standard-Holzeinstellung. Empfohlene Fräser: 2-Schneider-Spiralnut, ggf. Downcut oder Kompressionsfräser.'; break; case 'Kiefer (Pine)': baseFeed = 1900; plunge = 650; depthFactor = 0.32; spindleRPM = 16000; flutes = 2; notes = 'Weiches Nadelholz; etwas höhere Vorschubgeschwindigkeit möglich.'; break; case 'Harter Ahorn (Hard Maple)': case 'Bubinga (Bubinga)': baseFeed = 1300; plunge = 400; depthFactor = 0.24; spindleRPM = 16000; flutes = 2; notes = 'Hartes Holz; reduzierte Zustelltiefe. Empfohlene Fräser: sehr scharfe 2-Schneider-Spiralnut.'; break; case 'HDPE (HDPE)': case '2-Farb-HDPE (2-Color HDPE)': case 'Geschäumtes PVC (Expanded PVC)': case 'ABS (ABS)': baseFeed = 2200; plunge = 700; depthFactor = 0.32; spindleRPM = 18000; flutes = 2; notes = 'Weicher Kunststoff; höherer Feed hilft gegen Schmelzen. Empfohlen: polierte Spiralnut, 1–2 Schneiden.'; break; case 'Gussacryl (Cast Acrylic)': case '2-Farb-Acryl (2-Color Acrylic)': baseFeed = 1200; plunge = 400; depthFactor = 0.24; spindleRPM = 16000; flutes = 1; notes = 'Sprödes Acryl; konservative Zustelltiefe. Einzahn-Spiralnut mit polierten Schneiden ist oft vorteilhaft.'; break; case 'Corian (Corian)': baseFeed = 1200; plunge = 400; depthFactor = 0.24; spindleRPM = 16000; flutes = 2; notes = 'Dichter Mineralwerkstoff; ähnlich hartem Holz, gute Absaugung notwendig.'; break; case 'Linoleum (Linoleum)': baseFeed = 1900; plunge = 650; depthFactor = 0.4; spindleRPM = 16000; flutes = 2; notes = 'Weiches Material; größere Zustelltiefe möglich. Trägerschicht beachten.'; break; case 'Leiterplattenmaterial PCB (PCB)': baseFeed = 800; plunge = 250; depthFactor = 0.12; spindleRPM = 18000; flutes = 1; notes = 'Isolationsfräsen; sehr flache Zustellung. Häufig kleine Einzahnwerkzeuge (0,8–1,0 mm) mit V- oder Geradegeometrie.'; break; case 'Aluminium (Aluminum)': baseFeed = 700; plunge = 220; depthFactor = 0.1; spindleRPM = 12000; flutes = 2; notes = 'Metallbearbeitung; geringe Zustelltiefe, gute Spanntechnik und Schmierung notwendig. Empfohlen: 1–2-Schneider-Aluminiumfräser (Upcut).'; break; default: baseFeed = 1500; plunge = 500; depthFactor = 0.28; spindleRPM = 16000; flutes = 2; notes = 'Generische Einstellung; bitte an Reststück prüfen.'; break; } const refDiameter = 2.5; const feedScale = Math.sqrt(bitDiameter / refDiameter); let feed = baseFeed * feedScale; let depth = depthFactor * bitDiameter; depth = constrain(depth, 0.15, bitDiameter * 0.5); if (thickness < 4) { feed *= 1.05; notes += ' Dünnes Material: Feed leicht erhöht.'; } else if (thickness > 12 && thickness <= 20) { feed *= 0.9; notes += ' Dickes Material: Feed leicht reduziert.'; } else if (thickness > 20) { feed *= 0.85; notes += ' Sehr dickes Material: eher in mehreren Stufen bearbeiten, ggf. von beiden Seiten.'; } if (bitType === 'Spiralnut Aufwärts (Upcut end mill)') { notes += ' Gewählter Fräser: Upcut; sehr guter Spanabtransport, mögliche Ausrisse oben.'; } else if (bitType === 'Gerade Schneide (Straight-cut end mill)') { notes += ' Gewählter Fräser: gerade Schneide; gute Kantenqualität in Holz/Kunststoff, Spanabtransport geringer.'; } if (bitDiameter < 1.0 && flutes > 1) { flutes = 1; notes = 'Hinweis: Für Fräser unter 1.0 mm wird die Zahnzahl vorsorglich auf 1 gesetzt. ' + notes; } return { feedRate: feed, plungeRate: plunge, depthPerPass: depth, spindleRPM: spindleRPM, flutes: flutes, plungeType: plungeType, notes: notes }; } function roundTo(value, decimals) { return Number(value.toFixed(decimals)); } </script> </body> </html>
