กวาดเซอร์โวแบบนุ่มนวล
N32G031_SERVO_SMOOTH
บทนำ
โปรเจกต์ระดับเริ่มต้นที่ออกแบบมาเพื่อสอนการควบคุมเซอร์โวมอเตอร์โดยใช้ไมโครคอนโทรลเลอร์ N32G031 โดยเน้นเป็นพิเศษที่การเคลื่อนไหวที่ราบรื่นไร้การกระตุก (Smooth Sweep) โปรเจกต์นี้ทำหน้าที่เป็นเครื่องมือการเรียนรู้พื้นฐานที่ยอดเยี่ยมสำหรับวิทยาการหุ่นยนต์และการประยุกต์ใช้ For Loop ที่ออกแบบมาสำหรับเด็กและผู้เริ่มต้น โปรเจกต์นี้ได้รับการปรับแต่งอย่างสมบูรณ์แบบสำหรับเวิร์กโฟลว์ข้ามแพลตฟอร์มโดยใช้ UnityMbed
วิดีโอสาธิตการทำงาน
การต่อวงจร
| อุปกรณ์ | สาย / ขาอุปกรณ์ (Pin) | ขาบอร์ด N32G031 | หมายเหตุ & คำแนะนำ |
|---|---|---|---|
| เซอร์โวมอเตอร์ (เช่น SG90) | น้ำตาล / ดำ | GND | กราวด์ร่วมของระบบ (Common System Ground) |
| เซอร์โวมอเตอร์ (เช่น SG90) | แดง (VCC) | 5V | แหล่งจ่ายไฟหลักของมอเตอร์ (Motor Power Supply) |
| เซอร์โวมอเตอร์ (เช่น SG90) | ส้ม / เหลือง | PA1 | ขาสัญญาณควบคุม (Control Signal Pin - PWM Bit-Banging) |
การทำงาน & ลอจิกการทำงาน
เมื่อเปิดเครื่องและจ่ายไฟ แขนกลเซอร์โวจะกวาดองศาอย่างต่อเนื่องตามลูป 4 จังหวะดังต่อไปนี้:
กวาดแขนจาก 0° ไปยัง 45°
ค่อยๆ กวาดแขนจาก 0 ไปยัง 45 องศา (PULSE_0_DEG ➔ PULSE_45_DEG) และหน่วงเวลาพักตำแหน่ง
กวาดแขนจาก 45° ไปยัง 90°
ค่อยๆ กวาดแขนจาก 45 ไปยัง 90 องศา (PULSE_45_DEG ➔ PULSE_90_DEG) และหน่วงเวลาพักตำแหน่ง
กวาดแขนกลับจาก 90° มายัง 45°
ค่อยๆ กวาดแขนกลับจาก 90 มายัง 45 องศา (PULSE_90_DEG ➔ PULSE_45_DEG) และหน่วงเวลาพักตำแหน่ง
กวาดแขนกลับจาก 45° มายัง 0°
ค่อยๆ กวาดแขนกลับจาก 45 มายัง 0 องศา (PULSE_45_DEG ➔ PULSE_0_DEG) และหน่วงเวลาพักตำแหน่ง ก่อนเริ่มรอบใหม่
// UnityMbed — Smooth Servo Sweep Control @ N32G031
#include "n32g031.h"
#include "n32g031_gpio.h"
#include "n32g031_rcc.h"
/* ====================================================================
* [โซนปรับแต่งฮาร์ดแวร์ / Hardware Calibration Zone]
* ค่า Pulse width สำหรับกำหนดตำแหน่งองศาต่างๆ
* ==================================================================== */
#define PULSE_0_DEG 2250 // 0 องศา (หันซ้ายสุด / Far Left)
#define PULSE_45_DEG 3325 // 45 องศา (กึ่งกลางซ้าย / Mid-Left)
#define PULSE_90_DEG 4400 // 90 องศา (ตั้งฉาก/ตรงกลาง / Perpendicular / Center)
/* ฟังก์ชันหน่วงเวลาแบบลูป */
void Delay_Loop(volatile uint32_t count) {
while(count--) { __NOP(); }
}
/* ====================================================================
* ฟังก์ชันย่อย: ขยับทีละก้าว (ส่งสัญญาณ PWM 1 รอบคลื่น)
* ==================================================================== */
void Servo_Step(uint32_t pulse_width) {
GPIO_SetBits(GPIOA, GPIO_PIN_1);
Delay_Loop(pulse_width);
GPIO_ResetBits(GPIOA, GPIO_PIN_1);
Delay_Loop(100000);
}
/* ====================================================================
* ฟังก์ชันหลัก: ขยับแบบนุ่มนวลจากมุมหนึ่งไปอีกมุมหนึ่ง (Smooth Movement)
* ==================================================================== */
void Smooth_Move(uint32_t start_pulse, uint32_t end_pulse) {
// ถ้าจุดหมายอยู่ไกลกว่า ให้ค่อยๆ เพิ่มค่า Pulse
if (start_pulse < end_pulse) {
for (uint32_t p = start_pulse; p <= end_pulse; p += 20) {
Servo_Step(p);
}
}
// ถ้าจุดหมายอยู่น้อยกว่า ให้ค่อยๆ ลดค่า Pulse
else {
for (uint32_t p = start_pulse; p >= end_pulse; p -= 20) {
Servo_Step(p);
}
}
}
/* ====================================================================
* จุดเริ่มต้นการทำงานหลัก: ลูปกวาดองศาแบบนุ่มนวลเป็นรอบ (Periodic Smooth Sweep)
* ==================================================================== */
int main(void) {
/* กำหนดค่าเริ่มต้นฮาร์ดแวร์ GPIOA Pin 1 เป็น Push-Pull Output */
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
GPIO_InitType GPIO_InitStructure;
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_1;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
while(1) {
/* 1. ค่อยๆ กวาดแขนจาก 0 ไป 45 องศา */
Smooth_Move(PULSE_0_DEG, PULSE_45_DEG);
Delay_Loop(5000000); // พักตำแหน่ง
/* 2. ค่อยๆ กวาดแขนจาก 45 ไป 90 องศา */
Smooth_Move(PULSE_45_DEG, PULSE_90_DEG);
Delay_Loop(5000000);
/* 3. ค่อยๆ กวาดแขนกลับจาก 90 มา 45 องศา */
Smooth_Move(PULSE_90_DEG, PULSE_45_DEG);
Delay_Loop(5000000);
/* 4. ค่อยๆ กวาดแขนกลับจาก 45 มา 0 องศา เพื่อเริ่มรอบใหม่ */
Smooth_Move(PULSE_45_DEG, PULSE_0_DEG);
Delay_Loop(5000000);
}
}ไอเดียการเรียนรู้ & ต่อยอดด้วย AI
นักเรียนและผู้เรียนสามารถใช้ AI Assistant ใน UnityMbed เพื่อช่วยสำรวจ แก้ไขบั๊ก และปรับปรุงฟังก์ชันของโปรเจกต์นี้:
การเคลื่อนไหวแบบสมูท (Smooth Movement)
ทำความเข้าใจความแตกต่างระหว่างการสั่งให้หุ่นยนต์กระโดดไปตำแหน่งปลายทางทันที กับการขยับทีละก้าวอย่างต่อเนื่องด้วยฟังก์ชัน Smooth_Move เพื่อสร้างแอนิเมชันที่ดูเป็นธรรมชาติ
การปรับจูนฮาร์ดแวร์ (Hardware Calibration)
สัมผัสประสบการณ์จริงในการปรับแต่งค่าพารามิเตอร์ฮาร์ดแวร์ (Pulse Width) เพื่อตั้งศูนย์และเทียบมุม 0, 90 และ 180 องศาให้ตรงกับเซอร์โวมอเตอร์จริงแต่ละตัว
การประยุกต์ใช้ For Loop ในการเขียนโปรแกรม
เห็นภาพการทำงานของคำสั่ง For Loop อย่างชัดเจนผ่านการมองเห็นแขนกลขยับทีละขั้นตอนเมื่อค่าตัวแปรในลูปเพิ่มขึ้นหรือลดลง
ความท้าทายเรื่องความเร็ว
ลองปรับค่า step increment ใน Smooth_Move (เช่น p += 20 และ p -= 20) — ถ้าเปลี่ยนเป็น += 50 แขนจะหมุนเร็วขึ้นหรือไม่? หรือถ้าเปลี่ยนเป็น += 5 จะได้เอฟเฟกต์ Slow Motion หรือไม่?
คู่มือการ Build และ Flash
เปิดโปรเจกต์ (Open Project): เปิดโฟลเดอร์โปรเจกต์นี้ใน IDE โดยตรง
Build & Flash: เพียงคลิกปุ่ม Build และ Flash บนแถบเครื่องมือของอินเทอร์เฟซ