Feeds and Speeds
Overview
Machining is governed by three linked numbers, and keeping straight which one controls what is the difference between a quiet, tool-friendly cut and a screeching, burnt one:
- Surface speed
v = π d N(m/min) — the speed of the cutting edge through the material. It is the main driver of tool wear: too fast and the edge overheats and dulls in seconds. Each material family has a surface-speed range its cutters tolerate. - Chip load
f_z = F/(N·z)(m/tooth) — the thickness each cutting edge bites off. It is the main driver of cutting force and surface finish: too much and the tool deflects or breaks; too little and the edge rubs instead of cutting. - Spindle speed
N = v/(πd)and feed rateF— what you actually program into the machine’s spindle and axis drives.
Rasmah exposes these exact relations plus catalog recommendations per material group, so you can plan a cut before touching metal.
using RasmahThe kinematics
Given a cutter diameter and spindle speed, the surface speed follows v = π d N; the inverse gives the spindle speed for a target surface speed:
d, N = 0.006, 10000.0 # 6 mm cutter at 10 000 rpm
v = surface_speed(d, N)
println("surface speed v = ", round(v; digits = 2), " m/min (analytic π·d·N = ", round(π * d * N; digits = 2), ")")
println("spindle round-trip N = ", round(spindle_rpm(v, d); digits = 1))surface speed v = 188.5 m/min (analytic π·d·N = 188.5)
spindle round-trip N = 10000.0
Chip load and feed
A three-flute end mill advancing at F metres per minute removes F/(N·z) per edge per revolution:
feed, teeth = 0.25, 3
chip = chip_load(feed, N, teeth)
println("chip load = ", round(chip * 1e3; digits = 3), " mm/tooth (feed/(N·teeth) = ", round(feed / (N * teeth) * 1e3; digits = 3), ")")
println("feed round-trip = ", round(feed_rate(chip, N, teeth); digits = 3))chip load = 0.008 mm/tooth (feed/(N·teeth) = 0.008)
feed round-trip = 0.25
Planning a cut for a real machine
Put the three relations to work on a concrete job: slotting aluminium with a 6 mm carbide end mill. First pick the tool — the built-in catalog gives the standard diameter and its typical flute count:
d_tool, z = tool_catalog_entry(0.006)
println("catalog: ", d_tool * 1e3, " mm cutter, ", z, " flutes")catalog: 6.0 mm cutter, 3 flutes
recommended_cut turns the material group’s handbook surface-speed range and chip load into a complete (rpm, feed, surface speed) plan:
rpm_al, feed_al, sfm_al = recommended_cut(:aluminum, d_tool; teeth = z)
println("aluminum: ", round(rpm_al; digits = 0), " rpm, ", round(feed_al; digits = 2),
" m/min feed, ", round(sfm_al; digits = 0), " m/min SFM")aluminum: 10610.0 rpm, 3.18 m/min feed, 200.0 m/min SFM
200 m/min is a typical carbide-in-aluminium surface speed, giving ≈10 600 rpm on a 6 mm tool — within reach of most CNC spindles. But the same surface speed on a small cutter can outrun the machine. A typical hobby spindle tops out at 24 000 rpm; check a 2 mm cutter:
N_max = 24000.0
rpm_2, feed_2, sfm_2 = recommended_cut(:aluminum, 0.002; teeth = 2)
println("2 mm cutter wants ", round(rpm_2; digits = 0), " rpm — over the machine's ", N_max, " rpm limit")
rpm_cap = min(rpm_2, N_max) # clamp to the spindle limit
feed_cap = feed_rate(1.0e-4, rpm_cap, 2) # keep the same chip load
println("capped at ", round(rpm_cap; digits = 0), " rpm → feed ", round(feed_cap; digits = 2), " m/min")2 mm cutter wants 31831.0 rpm — over the machine's 24000.0 rpm limit
capped at 24000.0 rpm → feed 4.8 m/min
The right response to a spindle limit is to slow down and keep the chip load — reducing the chip load instead would make the edge rub.
The material group changes everything. Run the identical job in titanium:
rpm_ti, feed_ti, sfm_ti = recommended_cut(:titanium, d_tool; teeth = z)
println("titanium: ", round(rpm_ti; digits = 0), " rpm, ", round(feed_ti; digits = 2),
" m/min feed, ", round(sfm_ti; digits = 0), " m/min SFM — ",
round(feed_al / feed_ti; digits = 1), "× slower")titanium: 2387.0 rpm, 0.21 m/min feed, 45.0 m/min SFM — 14.8× slower
Titanium keeps its strength at cutting temperature and conducts heat poorly, so its surface-speed range is 30–60 m/min against aluminium’s 100–300 — the same tool must crawl. The real cost shows up in the material removal rate MRR = F · a_p · a_e (feed × axial depth × radial width). Slotting at 3 mm deep with the full 6 mm width:
ap, ae = 0.003, 0.006 # axial depth, radial width (m)
mrr_al = feed_al * ap * ae
mrr_ti = feed_ti * ap * ae
println("MRR aluminum = ", round(mrr_al * 1e6; digits = 1), " cm³/min")
println("MRR titanium = ", round(mrr_ti * 1e6; digits = 1), " cm³/min")
V = 50.0e-6 # a 50 cm³ pocket
println("pocket time: aluminum ", round(V / mrr_al; digits = 2), " min, titanium ",
round(V / mrr_ti; digits = 1), " min")MRR aluminum = 57.3 cm³/min
MRR titanium = 3.9 cm³/min
pocket time: aluminum 0.87 min, titanium 12.9 min
The same pocket costs ≈52 s in aluminium and ≈13 min in titanium — that 15× difference is what machinists mean when they say titanium is expensive to machine. machining_materials() lists every material group the catalog knows:
println(machining_materials())[:aluminum, :brass, :cast_iron, :copper, :inconel, :magnesium, :plastic, :stainless, :steel, :titanium, :tool_steel, :wood]
Catalog recommendations
recommended_rpm/recommended_feed/recommended_cut return a starting point for a material from the built-in tool catalog:
rpm = recommended_rpm(:steel, 0.01)
fd = recommended_feed(:steel, 0.01, rpm, 2)
println("steel: ", round(rpm; digits = 0), " rpm, feed ", round(fd; digits = 3), " m/min")steel: 2865.0 rpm, feed 0.344 m/min
Treat catalog values as a baseline: they assume carbide tooling, rigid workholding, and flood coolant — derate for flimsy fixtures or dry cutting, and adjust by listening to the cut.
Next steps
- CNC toolpaths — applying the feeds to a toolpath.
- Feature-based machining — picking tools per feature.
