Hiệu chỉnh độ chính xác máy CNC, máy laser tự chế: bước/mm, vuông góc, độ rơ, phay phẳng, dò Z
Đo và hiệu chỉnh máy CNC, máy laser tự chế: số bước mỗi milimét, độ vuông góc bằng hai đường chéo, độ rơ bằng đồng hồ so, phay phẳng tấm lót, dò Z bằng G38.2, kèm chương trình Python.
Máy CNC hay máy laser vừa lắp xong chạy được chưa có nghĩa là chạy đúng: hình vuông 100 mm có thể ra 99,2 mm, góc vuông thành 89,8°, lỗ tròn méo, đáy hốc chỗ sâu chỗ nông. Bài này hướng dẫn đo và hiệu chỉnh năm thứ quyết định độ chính xác của máy tự chế: số bước mỗi milimét, độ vuông góc giữa hai trục, độ rơ, độ phẳng của tấm lót và cách đặt Z = 0 bằng tấm dò.
Kèm theo bài là một chương trình Python nhỏ chạy trên máy tính, tính sẵn các con số cần sửa và sinh G-code phay phẳng tấm lót.
1. Thứ tự hiệu chỉnh

- Cơ khí trước, con số sau. Siết lại toàn bộ ốc, căng đai, chỉnh bánh xe V, căn vít me thẳng hàng (bài 17, 18 của loạt). Hiệu chỉnh trên máy còn lỏng thì mỗi lần đo ra một số khác.
- Gửi
$$và lưu toàn bộ thông số hiện tại vào một file trước khi sửa, để quay lại được khi cần.
2. Chương trình tính hiệu chỉnh
Chương trình chỉ dùng thư viện chuẩn của Python 3. Lưu thành hieu_chinh.py, mở cửa sổ dòng lệnh ở thư mục đó và chạy theo các ví dụ trong từng mục bên dưới.
# PYWORLD.VN - Tính hiệu chỉnh cho máy CNC, máy laser chạy GRBL: bước/mm, độ vuông góc, độ rơ, G-code phay phẳng tấm lót
# Đơn vị mm. Chỉ dùng thư viện chuẩn của Python 3, chạy trên máy tính.
# Chạy: python hieu_chinh.py <việc> ... (xem ví dụ ở cuối file hoặc gõ python hieu_chinh.py -h)
import argparse
import math
import statistics
def so(v, le=3):
"""Số gọn: 30.0 -> 30, 2.50 -> 2.5"""
return f"{v:.{le}f}".rstrip("0").rstrip(".")
# ---------------------------------------------------------------- 1. bước/mm
def buoc_mm_moi(hien_tai, lenh, do_duoc):
"""Máy được lệnh chạy `lenh` mm nhưng đo được `do_duoc` mm: bước/mm mới = cũ × lệnh ÷ đo."""
return hien_tai * lenh / do_duoc
# ---------------------------------------------------------------- 2. vuông góc
def vuong_goc(canh_x, canh_y, cheo_1, cheo_2):
"""Hình chữ nhật khắc thử có cạnh đo được canh_x, canh_y.
cheo_1: đường chéo từ góc gốc (X nhỏ, Y nhỏ) tới góc đối diện; cheo_2: đường chéo còn lại.
Hai trục làm với nhau góc theta: cheo_1² - cheo_2² = 4·x·y·cos(theta).
Trả về (góc giữa hai trục, độ lệch so với 90°, độ xô X khi chạy Y 100 mm), góc tính bằng độ."""
cos_t = (cheo_1 ** 2 - cheo_2 ** 2) / (4 * canh_x * canh_y)
theta = math.degrees(math.acos(cos_t))
return theta, 90 - theta, 100 * cos_t
# ---------------------------------------------------------------- 3. độ rơ
def do_ro(cac_lan_doc):
"""Số đọc đồng hồ so sau khi đổi chiều và quay về điểm 0, đo nhiều lần."""
return statistics.mean(cac_lan_doc), max(cac_lan_doc)
# ---------------------------------------------------------------- 4. G-code phay phẳng tấm lót
def buoc_ngang(dai, mui, chong):
"""Số lượt và bước ngang thật: bước không lớn hơn mui × (1 - chong), chia đều để lượt cuối nằm đúng mép."""
buoc = mui * (1 - chong)
so_luot = math.ceil(dai / buoc - 1e-9) + 1 # trừ 1e-9: 180 / 7.2 ra 25.000000000000004 khi tính bằng số thực
return so_luot, dai / (so_luot - 1)
def phay_phang(rong, dai, mui, chong, sau, toc_cat, vong_quay, z_an_toan=5.0):
"""Đường dao zig-zag theo X phủ vùng rong × dai (tính theo tâm dao, gốc ở góc trái dưới).
`chong` là phần đường kính mũi chồng lên lượt trước, ví dụ 0.4 = 40 %."""
so_luot, buoc = buoc_ngang(dai, mui, chong)
dong = [f"(PYWORLD.VN - phay phang tam lot {so(rong)} x {so(dai)} mm, mui {so(mui)} mm, buoc ngang {so(buoc)} mm)",
"G21 G90 G17",
f"G0 Z{so(z_an_toan)}",
"G0 X0 Y0",
f"M3 S{vong_quay}",
"G4 P3",
f"G1 Z{so(-sau)} F{max(50, toc_cat // 4)}"]
for i in range(so_luot):
y = i * buoc
x_cuoi = rong if i % 2 == 0 else 0
if i > 0:
dong.append(f"G1 Y{so(y)}")
dong.append(f"G1 X{so(x_cuoi)} F{toc_cat}")
dong += [f"G0 Z{so(z_an_toan)}", "M5", "G0 X0 Y0", "M30"]
return dong
def main():
p = argparse.ArgumentParser(description="Tinh hieu chinh may CNC, may laser chay GRBL")
viec = p.add_subparsers(dest="viec", required=True)
a = viec.add_parser("buoc-mm", help="tinh lai buoc/mm ($100, $101, $102)")
a.add_argument("--hien-tai", type=float, required=True, help="gia tri $10x dang dung")
a.add_argument("--lenh", type=float, required=True, help="quang da ra lenh chay (mm)")
a.add_argument("--do", type=float, required=True, help="quang do duoc (mm)")
b = viec.add_parser("vuong-goc", help="do lech vuong goc tu hai duong cheo")
b.add_argument("--x", type=float, required=True, help="canh theo X do duoc (mm)")
b.add_argument("--y", type=float, required=True, help="canh theo Y do duoc (mm)")
b.add_argument("--cheo1", type=float, required=True, help="duong cheo tu goc goc toi goc doi dien (mm)")
b.add_argument("--cheo2", type=float, required=True, help="duong cheo con lai (mm)")
c = viec.add_parser("do-ro", help="do ro tu cac so doc dong ho so (mm)")
c.add_argument("doc", type=float, nargs="+")
d = viec.add_parser("phay-phang", help="sinh G-code phay phang tam lot")
d.add_argument("--rong", type=float, required=True, help="chieu X cua vung phay (mm)")
d.add_argument("--dai", type=float, required=True, help="chieu Y cua vung phay (mm)")
d.add_argument("--mui", type=float, required=True, help="duong kinh mui phay (mm)")
d.add_argument("--chong", type=float, default=0.4, help="phan chong len luot truoc, mac dinh 0.4")
d.add_argument("--sau", type=float, default=0.3, help="do an sau (mm), mac dinh 0.3")
d.add_argument("--f", type=int, default=800, help="toc do cat (mm/phut)")
d.add_argument("--s", type=int, default=1000, help="toc do spindle S")
d.add_argument("--ra", default="phay_phang.nc", help="ten file G-code")
k = p.parse_args()
if k.viec == "buoc-mm":
moi = buoc_mm_moi(k.hien_tai, k.lenh, k.do)
sai = (k.do - k.lenh) / k.lenh * 100
print(f"Sai lech: {sai:+.2f} %")
print(f"Buoc/mm moi: {moi:.3f} (gui lenh $100={moi:.3f} cho truc X, $101 cho Y, $102 cho Z)")
if abs(sai) > 10:
print("Sai qua 10 %: kiem tra lai vi buoc, buoc tien vit me, so rang puly truoc khi sua.")
elif k.viec == "vuong-goc":
theta, lech, xo = vuong_goc(k.x, k.y, k.cheo1, k.cheo2)
print(f"Goc giua hai truc: {theta:.3f} do (lech {lech:+.3f} do so voi 90)")
print(f"Chay Y 100 mm thi dau dao xo theo X: {xo:+.3f} mm")
elif k.viec == "do-ro":
tb, lon = do_ro(k.doc)
print(f"Do ro trung binh: {tb:.3f} mm, lon nhat: {lon:.3f} mm ({len(k.doc)} lan do)")
else:
dong = phay_phang(k.rong, k.dai, k.mui, k.chong, k.sau, k.f, k.s)
with open(k.ra, "w", encoding="ascii") as f:
f.write("\n".join(dong) + "\n")
print(f"Da ghi {len(dong)} dong vao {k.ra}")
if __name__ == "__main__":
main()
# Ví dụ:
# python hieu_chinh.py buoc-mm --hien-tai 400 --lenh 100 --do 99.2
# python hieu_chinh.py vuong-goc --x 100 --y 100 --cheo1 141.70 --cheo2 141.13
# python hieu_chinh.py do-ro 0.06 0.05 0.07
# python hieu_chinh.py phay-phang --rong 300 --dai 180 --mui 12 --sau 0.3 --f 600 --s 1000
3. Số bước mỗi milimét

- Đặt giá trị lý thuyết trước: 80 bước/mm cho đai GT2 puly 20 răng, 400 bước/mm cho vít me bước tiến 8 mm, cùng vi bước 1/16 (bài 8, bài 18).
- Đánh dấu vị trí đầu: máy CNC gắn mũi nhọn hoặc bút vào spindle; máy laser khắc một vạch ngắn ở công suất thấp.
- Chạy một quãng dài nhất có thể, ví dụ
G91 G1 X100 F500, rồi đánh dấu vị trí cuối. - Đo khoảng cách giữa hai dấu bằng thước kẹp. Với laser, đo giữa tâm hai vạch để bề rộng tia không làm sai số đo.
- Tính và gửi giá trị mới:
python hieu_chinh.py buoc-mm --hien-tai 400 --lenh 100 --do 99.2
Sai lech: -0.80 %
Buoc/mm moi: 403.226 (gui lenh $100=403.226 cho truc X, $101 cho Y, $102 cho Z)
- Đo lại sau khi sửa. Luôn đi tới điểm đo theo cùng một chiều để độ rơ không lẫn vào kết quả.
- Máy dây đai thường lệch nhỏ do đai và puly, sửa số là hợp lý. Máy vít me thường khớp giá trị lý thuyết: lệch nhiều là do mất bước, độ rơ hoặc đo sai, không nên sửa số để che lỗi.
- Lệch gần gấp đôi, một nửa: vi bước khác với giả định, xem jumper dưới driver (bài 7).
4. Độ vuông góc giữa X và Y

- Khắc hoặc phay một hình chữ nhật càng lớn càng tốt (ít nhất 100 × 100 mm), sau khi đã chỉnh xong bước/mm.
- Đo hai cạnh và hai đường chéo. Chéo 1 nối góc gốc (X nhỏ, Y nhỏ) với góc đối diện, chéo 2 là đường còn lại.
- Tính độ lệch:
python hieu_chinh.py vuong-goc --x 100 --y 100 --cheo1 141.70 --cheo2 141.13
Goc giua hai truc: 89.769 do (lech +0.231 do so voi 90)
Chay Y 100 mm thi dau dao xo theo X: +0.403 mm
- GRBL không bù độ vuông góc bằng phần mềm: phải chỉnh cơ khí.
- Máy hai động cơ Y (máy laser khung hở, máy cổng di chuyển): tắt máy, nới vít puly ở một bên, đẩy bên đó tiến hoặc lùi một chút để cổng vuông với ray Y, siết lại rồi khắc thử lần nữa. Dùng FluidNC với hai công tắc riêng cho hai động cơ Y thì firmware có thể tự kéo vuông cổng khi về gốc (xem phần squaring trong tài liệu FluidNC).
- Máy một động cơ Y, máy 3018: chỉnh ke giữa dầm X và cột cổng, hoặc vị trí cột cổng trên khung đế.
5. Độ rơ

Độ rơ là quãng trục không chạy khi động cơ đổi chiều: khe hở giữa đai ốc và vít me, đai chùng, puly hoặc khớp nối lỏng. Độ rơ làm lỗ tròn méo và hai cạnh song song cắt theo hai chiều lệch nhau.
- Gắn đồng hồ so lên khung máy, mũi đồng hồ tì vào xe trượt theo phương trục cần đo.
- Tiến tới điểm đo theo chiều dương, chỉnh mặt đồng hồ về 0.
- Gửi
G91 G1 X1 F100: đồng hồ phải chỉ 1,00 mm. - Gửi
G91 G1 X-1 F100: số đồng hồ còn lại (chưa về 0) là độ rơ. Đo vài lần:
python hieu_chinh.py do-ro 0.06 0.05 0.07
Do ro trung binh: 0.060 mm, lon nhat: 0.070 mm (3 lan do)
- GRBL 1.1 không có bù độ rơ. Giảm độ rơ bằng cơ khí: đai ốc chống rơ có lò xo, siết chặt đai ốc vào giá, căng đai, siết vít puly và khớp nối vào mặt phẳng của trục.
- Không có đồng hồ so: bật driver (động cơ đang giữ), đẩy kéo xe trượt bằng tay; nghe tiếng lạch cạch hoặc thấy xe xê dịch là có độ rơ cần xử lý.
6. Phay phẳng tấm lót

Mặt bàn máy CNC tự chế hiếm khi song song tuyệt đối với mặt phẳng chạy dao. Cách làm quen thuộc là bắt một tấm lót (MDF) lên bàn rồi cho chính máy phay phẳng mặt tấm lót, sau đó kẹp phôi lên trên.
- Bắt tấm lót bằng vít đầu chìm, đầu vít thấp hơn hẳn chiều sâu sẽ phay.
- Dùng mũi phay mặt hoặc mũi đầu bằng lớn nhất mà collet kẹp được. Spindle nhỏ thì ăn sâu ít (0,2–0,5 mm mỗi lần).
- Đặt gốc X, Y ở góc tấm lót, đặt Z = 0 ở mặt tấm lót (mục 7), rồi sinh G-code:
python hieu_chinh.py phay-phang --rong 300 --dai 180 --mui 12 --sau 0.3 --f 600 --s 1000
Da ghi 62 dong vao phay_phang.nc
Mười hai dòng đầu của file:
(PYWORLD.VN - phay phang tam lot 300 x 180 mm, mui 12 mm, buoc ngang 7.2 mm)
G21 G90 G17
G0 Z5
G0 X0 Y0
M3 S1000
G4 P3
G1 Z-0.3 F150
G1 X300 F600
G1 Y7.2
G1 X0 F600
G1 Y14.4
G1 X300 F600
- Xem thử file bằng phần mềm mô phỏng G-code trước khi chạy (bài 15). Vùng phay rộng hơn đường tâm dao một bán kính mũi về mỗi phía.
- Còn vùng chưa chạm dao thì hạ Z thêm 0,2–0,3 mm và chạy lại tới khi cả mặt được phay.
- Mặt phay có gờ nhỏ giữa các lượt là spindle bị nghiêng so với bàn. Gắn đồng hồ so lên một thanh kẹp ở collet, quay tay spindle đo bốn phía; chỉnh giá kẹp spindle tới khi số đo bằng nhau rồi phay lại.
- Máy laser không phay phẳng được: đặt cữ tiêu cự ở bốn góc vùng khắc để kiểm tra mặt bàn, kê chỉnh khung nếu lệch.
7. Đặt Z = 0 bằng tấm dò

- GRBL đọc tấm dò ở chân A5: mạch kín (mũi phay chạm tấm đồng) thì lệnh
G38.2dừng và ghi lại vị trí. - Đo độ dày tấm dò bằng thước kẹp, thay vào số 1.6 trong lệnh
G10. - Mỗi lần thay mũi phay phải dò lại Z, vì chiều dài mũi trong collet thay đổi.
ALARM:4: tấm dò đã ở trạng thái chạm trước khi bắt đầu (kẹp cá sấu chạm tấm, dây chập).ALARM:5: chạy hết quãng dò mà không chạm. Sau báo động, gửi$Xđể mở khóa, kiểm tra lại dây.
G91 G38.2 Z-20 F50
G10 L20 P1 Z1.6
G91 G0 Z5
G90
8. Kiểm tra lại bằng mẫu thử
- Phay hoặc khắc một mẫu có hình vuông 100 mm và một lỗ tròn đường kính 50 mm.
- Cạnh vuông sai: xem lại bước/mm. Hai đường chéo khác nhau: xem lại vuông góc.
- Lỗ tròn đo theo X và theo Y ra hai số khác nhau, hoặc có vết bậc ở bốn điểm đổi chiều: độ rơ.
- Xong thì gửi
$$và lưu lại bộ thông số đã hiệu chỉnh.
9. Xử lý lỗi
| Hiện tượng | Nguyên nhân hay gặp | Cách xử lý |
|---|---|---|
| Mỗi lần đo bước/mm ra một số khác | máy còn lỏng, mất bước, đo theo hai chiều khác nhau | siết lại cơ khí, giảm tốc độ đo, luôn tới điểm đo theo một chiều |
| Sửa bước/mm rồi mà hình vẫn sai dần theo thời gian chạy | mất bước, không phải sai bước/mm | giảm tốc độ, gia tốc; chỉnh VREF (bài 7, bài 12) |
| Hình vuông thành hình bình hành | cổng hoặc dầm X không vuông với trục Y | chỉnh cơ khí theo mục 4 |
| Lỗ tròn méo, có bậc ở bốn điểm | độ rơ | đai ốc chống rơ, căng đai, siết puly và khớp nối |
| Mặt phay có gờ giữa các lượt | spindle nghiêng | chỉnh giá kẹp spindle, phay lại |
Lệnh dò báo ALARM:4 hoặc ALARM:5 | tấm dò chạm sẵn, hoặc dò không tới | kiểm tra dây A5, GND; hạ dao gần tấm hơn trước khi dò |
10. Xem thêm
- Bài trước trong loạt: Tự lắp máy CNC mini cỡ 3018. Bài sau: Sửa lỗi và nâng cấp máy CNC, máy laser tự chế.
- Các bài nền của loạt: truyền động (bài 8), cấu hình GRBL (bài 12), phần mềm CAM và mô phỏng G-code (bài 15).
- Hiệu chuẩn đồng hồ so: đồng hồ so dùng để đo độ rơ cũng cần được kiểm tra.
Xem thêm