GRBL Probe (G38.2–G38.5) คืออะไร?

คำสั่ง Probe ใน GRBL เป็นฟีเจอร์ที่ใช้วัดตำแหน่งของชิ้นงานด้วยการ "แตะ" (Touch) แทนการกะด้วยตา ทำให้เราทราบพิกัดจริงของผิวชิ้นงานได้อย่างแม่นยำ ตั้งแต่ G38.2 ถึง G38.5

บทความนี้จะพาไปรู้จักคำสั่ง Probe ของ GRBL และวิธีนำมาประยุกต์ใช้สร้าง เครื่องวัดพิกัด 3 แกน (CMM — Coordinate Measuring Machine) ด้วย Python โดยให้ Python ทำหน้าที่เป็น Controller/Sequencer ส่ง G-code ผ่าน Serial Port อ่านค่าพิกัดเมื่อหัววัดแตะชิ้นงาน แล้วบันทึกเป็น Point Cloud เพื่อนำไปวิเคราะห์ต่อ

ใช้ได้กับเครื่อง Minicnc / เครื่องกัดที่ขับด้วย GRBL และหัววัดแบบ 3D Touch Probe (DIYO / ชุด XYZ three coordinate probe)

หัววัด 3D Touch Probe คืออะไร

หัววัด 3D Touch Probe (หรือที่เรียกกันว่า XYZ Three Coordinate Probe) เป็นอุปกรณ์ที่ใช้หาตำแหน่งขอบและผิวชิ้นงานแบบ 3 แกน มีสไตลัส (Stylus) เป็นก้านปลายมน เมื่อปลายสัมผัสชิ้นงาน จะเกิดสัญญาณไฟฟ้าส่งไปยังบอร์ดควบคุมทันที

การต่อสายหัววัด (Wiring)

หัววัด DIY0 มี 3 สายตามแผนภาพผู้ผลิต:

สีสายชื่อความหมายต่อกับ
แดง (Red)VCCจ่ายไฟ 5–24 Vแหล่งจ่ายไฟ + (5–24 V)
เหลือง (Yellow)IO / OUTสัญญาณออก — ระดับ High เท่ากับ VCCขา A5 ของ GRBL (Probe Input)
ดำ (Black)GNDกราวด์ / 0 VGND และ COM– / DCM ของบอร์ดควบคุม

แผนภาพการต่อสายหัววัด DIY0 — VCC / IO(OUT) / GND

ภาพที่ 1: แผนภาพการต่อสายหัววัด DIY0 — ตัวต้านทาน 10K pull-up ภายใน, VCC = 5–24 V, IO = สัญญาณออก, GND = กราวด์

ลักษณะหัววัดและชุดอุปกรณ์

DIY0 3D Touch Probe (XYZ three coordinate probe) พร้อมกล่องและสายสัญญาณ

ภาพที่ 2: ชุดหัววัด 3D Touch Probe (DIY0) — กล่อง, ตัวหัววัดสไตลัส และสายสัญญาณ

พฤติกรรมของสัญญาณไฟแสดงสถานะ

สภาวะไฟ LEDระดับสัญญาณ IO
จ่ายไฟแล้ว ยังไม่แตะชิ้นงาน (ปกติ)🟢 เขียว ติดค้างHigh (เท่ากับ VCC)
หัววัดแตะชิ้นงาน (Trigger)🔴 แดง ติดLow (0 V)

หมายเหตุสำคัญ: ระดับลอจิกเป็นแบบ Active Low — เมื่อแตะชิ้นงานแล้ว IO จะ ดึงลงเป็น Low ทำให้ GRBL รับรู้ว่าเกิดการ Trigger

หลักการทำงานของ GRBL Probing

ความหมายของคำสั่ง G38.2 – G38.5

คำสั่งความหมาย
G38.2Probe ไปยังเป้าหมาย — หยุดเมื่อแตะ (Error ถ้าไม่แตะ)
G38.3Probe ไปยังเป้าหมาย — หยุด/ไม่หยุด (ไม่ Error ถ้าไม่แตะ)
G38.4Probe ถอยออกจากชิ้นงาน — หยุดเมื่อหลุดสัมผัส (Error ถ้าไม่หลุด)
G38.5Probe ถอยออก — หยุดเมื่อหลุดสัมผัส (ไม่ Error)

ตัวอย่าง: G38.2 Z-20 F50 หมายถึง ให้แกน Z เคลื่อนที่ลงไปถึงพิกัด Z = –20 ด้วยอัตราป้อน (Feed rate) 50 mm/min จนกว่าสวิตช์ Probe จะแตะชิ้นงาน

การตอบกลับของ GRBL

  • แตะสำเร็จ: GRBL หยุดเคลื่อนที่ทันที และตอบกลับ [PRB:X,Y,Z:1] — เลข 1 ท้ายสุดหมายถึงแตะสำเร็จ
  • ไม่แตะ: GRBL ส่ง Alarm/Error กลับมา พร้อมค่า [PRB:X,Y,Z:0] — เลข 0 หมายถึงล้มเหลว

สร้างเครื่อง CMM ด้วย Python

ใช้ไลบรารี pyserial เชื่อมต่อกับบอร์ด GRBL โดยตรง โครงสร้างคลาสหลักมีดังนี้

import serial
import time
import re

class GRBL_CMM:
    def __init__(self, port='COM3', baudrate=115200):
        self.ser = serial.Serial(port, baudrate, timeout=1)
        time.sleep(2)  # รอ GRBL รีเซ็ตระบบ
        self.ser.flushInput()
        print("Connected to GRBL CMM")

        # Unlock GRBL (ถ้าติด Alarm อยู่)
        self.send_command("$X")
        # ตั้งค่าหน่วยเป็นมิลลิเมตร (G21) และ Absolute Coordinates (G90)
        self.send_command("G21 G90")

    def send_command(self, cmd):
        """ส่งคำสั่ง G-code และรอคำตอบกลับ 'ok'"""
        self.ser.write(f"{cmd}\n".encode('utf-8'))
        response_lines = []
        while True:
            line = self.ser.readline().decode('utf-8', errors='ignore').strip()
            if line:
                response_lines.append(line)
            if line == 'ok' or 'error' in line:
                break
        return response_lines

    def probe_point(self, target_axis, target_dist, feed_rate=50):
        """
        ส่งคำสั่ง G38.2 เพื่อแตะหาจุดสัมผัส
        target_axis: 'X', 'Y' หรือ 'Z'
        target_dist: ระยะเป้าหมายในการ Probe (เช่น -10)
        """
        cmd = f"G38.2 {target_axis}{target_dist} F{feed_rate}"
        lines = self.send_command(cmd)

        # ดึงค่า PRB:x,y,z จากการตอบกลับของ GRBL
        for line in lines:
            if line.startswith("[PRB:"):
                match = re.search(r"\[PRB:([-\d\.]+),([-\d\.]+),([-\d\.]+):(\d)\]", line)
                if match:
                    x, y, z, success = match.groups()
                    if success == '1':
                        return float(x), float(y), float(z)
                    else:
                        print("Probe failed to touch the target.")
                        return None
        return None

    def retract(self, axis, distance, feed_rate=200):
        """ถอยแกนออกจากจุดสัมผัสชิ้นงาน (Relative Mode G91)"""
        self.send_command("G91")
        self.send_command(f"G0 {axis}{distance}")
        self.send_command("G90")

    def close(self):
        self.ser.close()

ตัวอย่าง: Grid Surface Scanning

สแกนพื้นผิวแบบตาราง (Grid) เพื่อเก็บ Point Cloud แล้วบันทึกเป็นไฟล์ CSV

if __name__ == "__main__":
    # เปลี่ยนชื่อ Serial Port ให้ตรงตามบอร์ด (เช่น 'COM3' หรือ '/dev/ttyUSB0')
    cmm = GRBL_CMM(port='COM3', baudrate=115200)

    # กำหนดขอบเขตพื้นที่ที่ต้องการสแกน (Grid)
    x_start, x_end, x_step = 0, 20, 10   # พิกัด X: 0, 10, 20
    y_start, y_end, y_step = 0, 20, 10   # พิกัด Y: 0, 10, 20

    z_safe = 5.0       # ระยะ Z ปลอดภัยก่อนขยับไปจุดถัดไป
    z_probe_min = -15  # ระยะลึกสุดที่จะ Probe หาชิ้นงาน

    point_cloud = []

    try:
        # ยก Z ไปที่ระยะปลอดภัยก่อนเริ่ม
        cmm.send_command(f"G0 Z{z_safe}")

        for x in [x_start + i * x_step for i in range(int((x_end - x_start) / x_step) + 1)]:
            for y in [y_start + j * y_step for j in range(int((y_end - y_start) / y_step) + 1)]:
                # 1. ขยับไปยังพิกัด X, Y
                cmm.send_command(f"G0 X{x} Y{y}")

                # 2. เริ่มยิง Probe ลงแกน Z
                pt = cmm.probe_point('Z', z_probe_min, feed_rate=40)

                if pt:
                    print(f"Measured Point -> X: {pt[0]:.3f}, Y: {pt[1]:.3f}, Z: {pt[2]:.3f}")
                    point_cloud.append(pt)

                    # 3. ถอย Z ขึ้นเล็กน้อยเพื่อปลดสวิตช์ Probe
                    cmm.retract('Z', 2.0)

                # 4. ยก Z กลับไปที่ Safe Height
                cmm.send_command(f"G0 Z{z_safe}")

        # บันทึก Point Cloud เป็นไฟล์ CSV
        with open("cmm_points.csv", "w") as f:
            f.write("X,Y,Z\n")
            for p in point_cloud:
                f.write(f"{p[0]},{p[1]},{p[2]}\n")

        print("CMM Scanning Completed. Saved to cmm_points.csv")

    finally:
        cmm.close()

หมายเหตุ: โค้ดต้นฉบับมีข้อผิดพลาดเล็กน้อยในลูป for y (ใช้ตัวแปร i แทน j) — ในบทความนี้แก้ไขเป็น j แล้วเพื่อให้สแกนได้ครบทุกแถว

ขั้นตอนการใช้งานจริง

  1. เตรียมความปลอดภัย — ตรวจว่าหัววัดและชิ้นงานยึดแน่น, ปิดสปินเดิล, ตรวจว่ามือไม่เข้าเขตเครื่อง
  2. ต่อสายหัววัด — ตามตารางด้านบน (VCC → ไฟเลี้ยง, IO → A5, GND → GND/COM–)
  3. จ่ายไฟเลี้ยงหัววัด — ตรวจว่าไฟเขียวติดค้าง = ปกติ
  4. ต่อ Serial — ตรวจ COM port และ baudrate (GRBL มาตรฐาน = 115200)
  5. Unlock + ตั้งค่าเริ่มต้น — ส่ง $X แล้วตามด้วย G21 G90
  6. Home เครื่อง — ส่ง $H เพื่อให้พิกัดอ้างอิงถูกต้อง (จำเป็น ก่อนวัดทุกครั้ง)
  7. ทดสอบแตะมือ — ใช้มือกดปลายสไตลัสเบาๆ ระหว่างรัน แล้วดูว่าไฟแดงติดและระบบหยุด = วงจรทำงาน
  8. รัน Grid Scan — กำหนดขอบเขตและ step แล้วรันสคริปต์
  9. ตรวจผล — เปิดไฟล์ cmm_points.csv ตรวจว่าจำนวนจุดตรงกับที่คาดไว้
  10. เกษียณงาน — ยก Z ขึ้น Safe Height, ปิดไฟเลี้ยงหัววัด, ปิดการเชื่อมต่อ

ข้อควรระวังและแนวทางเพิ่มความแม่นยำ

1. Probe Signal Debounce (ด้านฮาร์ดแวร์)

ขาสัญญาณ Probe (ปกติคือ A5 บน Arduino UNO / GRBL 0.9–1.1) มีความไวต่อสัญญาณรบกวนสูงมาก ควรเพิ่ม:

  • RC Low-Pass Filter — ตัวต้านทาน Pull-up + ตัวเก็บประจุ กรองสัญญาณรบกวนความถี่สูง
  • Optocoupler Isolation — แยกกราวด์ของหัววัดออกจากกราวด์มอเตอร์ ป้องกันการเกิด False Trigger ขณะมอเตอร์สเตปเปอร์ทำงาน

2. Double Probing Technique (เพิ่มความแม่นยำ)

ใช้การ Probe 2 รอบต่อ 1 จุด:

รอบความเร็วจุดประสงค์
รอบที่ 1F100 (ปานกลาง)หาตำแหน่งชิ้นงานอย่างรวดเร็ว แล้วถอยออก
รอบที่ 2F5 – F10 (ต่ำมาก)อ่านค่าพิกัดจริง ลดความคลาดเคลื่อนจาก Infiltration / Overshoot ของกลไก

3. Probe Tip Radius Compensation

ค่าที่ได้จาก [PRB:] เป็นพิกัด จุดศูนย์กลางของหัวทัชโพรบ (Stylus Ball) ไม่ใช่ผิวสัมผัสจริง — หากต้องการความแม่นยำระดับไมครอน ต้องนำ รัศมีของหัวโพรบ (Ball Radius Offset) ไปหักลบออกจากค่าที่วัดได้ ตามทิศทางที่แตะ

4. ข้อควรระวังอื่นๆ

หัวข้อข้อควรระวัง
การแยกไฟเลี้ยงอย่าใช้ไฟเลี้ยงเดียวกับมอเตอร์สเตปเปอร์ — ไฟกระชากทำให้เกิด False Trigger
Safe Heightต้องยก Z ก่อนขยับ X/Y ทุกครั้ง ไม่งั้นหัววัดจะครูดชิ้นงาน
ระยะ Probeตั้ง z_probe_min ให้ลึกพอกับชิ้นงาน แต่ไม่ชน Bed — ถ้า Alarm ทุกจุดแปลว่าลึกไม่พอ
ความเร็วรอบ 1อย่าใช้เร็วเกิน 100 mm/min เพราะ Overshoot มาก ทำให้ค่าคลาดเคลื่อน
อุณหภูมิวัดหลายชั่วโมงต้องรอให้เครื่องอุณหภูมิคงที่ก่อน (Thermal Drift) หรือ Re-home ระหว่างวัด

สรุป

GRBL Probe (G38.2–G38.5) ไม่ได้มีไว้แค่หาจุด Zero ของงาน แต่ยังสามารถต่อยอดเป็น เครื่องวัดพิกัด 3 แกน (CMM) ระดับงานอดิเรกได้ด้วย Python เพียงไม่กี่สิบบรรทัด โดยอาศัยค่า [PRB:] ที่ GRBL ส่งกลับมาเป็นหัวใจหลัก

สิ่งที่จะทำให้ผลลัพธ์แม่นยำขึ้นจริงคือ ฮาร์ดแวร์ (กรองสัญญาณรบกวน) และ เทคนิคการวัด (Double Probing + ชดเชยรัศมีหัววัด) ไม่ใช่ตัวโค้ดเพียงอย่างเดียว


เอกสารอ้างอิง: GRBL Official Wiki — Commands: https://github.com/gnea/grbl/wiki/Grbl-v1.1-Commands

หมวด: เริ่มต้น CNC — PanmaneeCNC · ปรับปรุงล่าสุด: ตุลาคม 2026