⚙️ หลักการ ของหุ่นยนต์บังคับด้วย Wireless Joystick PS2

🎮 1. Human to Machine Interface (HMI)

จากปลายนิ้วมนุษย์ สู่การขยับของหุ่นยนต์แบบเรียลไทม์
จอย PS2 คือสะพานเชื่อมระหว่างมนุษย์กับเครื่องจักร ผู้ควบคุมเพียงกดปุ่มหรือโยกอนาล็อก สัญญาณไฟฟ้าก็ถูกส่งไปยังบอร์ด Arduino เพื่อสั่งให้หุ่นยนต์ขยับทันที คล้ายกับเราผสมน้ำมนต์แห่งการควบคุมเข้าไปในเครื่องจักรให้มันเคลื่อนไหวตามเรา


📡 2. Wireless Signal Translation – ภาษาลับระหว่างจอยกับหุ่นยนต์

จอย PS2 แบบไร้สายจะส่งข้อมูลผ่านคลื่นวิทยุไปยังตัวรับ (Receiver) ที่เสียบอยู่กับ Arduino ข้อมูลนี้เป็นรูปแบบดิจิทัล เช่น

  • UP = เดินหน้า
  • X Button = เพิ่มสปีด
  • Analog Left = เลี้ยวซ้ายแบบนุ่มนวล

Arduino จึงทำหน้าที่เหมือนล่ามดิจิทัล แปล “ภาษาของจอย” ให้กลายเป็นคำสั่ง “ภาษาของหุ่นยนต์”


⚡ 3. Input → Processing → Output คือหัวใจของระบบอัตโนมัติ

หุ่นยนต์ทั้งระบบสามารถสรุปให้เท่ ๆ ได้ใน 3 ขั้นตอน:

  1. Input: จอย PS2 ส่งค่าปุ่มและตำแหน่งอนาล็อก
  2. Processing: Arduino ประมวลผล ตัดสินใจว่าจะให้หุ่นยนต์ทำอะไร
  3. Output: สั่งงานมอเตอร์ให้หมุน เดินหน้า ถอยหลัง เลี้ยว หรือหยุด

นี่คือกลไกเดียวกับที่ใช้ในระบบหุ่นยนต์อุตสาหกรรม เครื่องบินโดรน หรือแม้กระทั่งยานสำรวจดาวอังคาร


🔁 4. PWM (Pulse Width Modulation) – ศิลปะการควบคุมความเร็วแบบดิจิทัล

แทนที่จะเพิ่มลดแรงดันไฟตรง ๆ Arduino ใช้เทคนิค PWM ส่งสัญญาณ “เปิด-ปิดเร็วมาก ๆ” เพื่อควบคุมความเร็วของมอเตอร์ ลองนึกภาพเหมือนเราเปิดปิดวาล์วน้ำเร็ว ๆ เพื่อควบคุมปริมาณน้ำที่ไหลออก — มันดูพื้นฐานแต่ทรงพลังสุด ๆ ในโลกอิเล็กทรอนิกส์


⚙️ 5. H-Bridge Motor Driver – สวิตช์กลับทิศพลังงาน

การสั่งให้มอเตอร์หมุนไปข้างหน้า/ถอยหลัง เกิดจากการกลับขั้วไฟฟ้า ซึ่งมอเตอร์ไดร์เวอร์ (เช่น L298N) ทำหน้าที่เหมือน “สะพานสวิตช์ 4 ทิศทาง” ให้ไฟไหลได้ทิศทางที่เราต้องการ คล้ายระบบเกียร์ของรถ แต่ควบคุมด้วยไฟฟ้าทั้งหมด


🤖 6. Modular Design – หุ่นยนต์ที่อัปเกรดได้เหมือนเกม

หุ่นยนต์ PS2 Control ถูกออกแบบแบบแยกส่วน (Modular) เช่น

ส่วน Sensors (เพิ่มภายหลังได้)
จึงสามารถอัปเกรดได้ เช่น เพิ่มเซนเซอร์หลบสิ่งกีดขวาง, ใส่กล้อง FPV, หรือควบคุมผ่าน IoT — เรียกได้ว่าเริ่มจากของเล่นแต่ไปจบที่ของจริงได้เลย

ส่วนควบคุม (Control Unit)

ส่วนขับเคลื่อน (Motor Unit)


🔌 อุปกรณ์ที่ใช้



ขั้นตอนการสร้าง


1.ประกอบหุ่นยนต์และเชื่อมต่อวงจร


บัดกรีสายมอเตอร์ โดย สายสีแดงอยู่ด้านบน และ สายสีดำอยู่ด้านล่าง ทั้ง 4 ตัว



ยึดมอเตอร์เข้ากับโครงหุ่นยนต์ (ด้านล่าง)



ยึดเสา 6 ต้น สำหรับใส่โครงหุ่นยนต์ด้านบน


การต่อวงจร



ประกอบ sensor shield v 5.0 เข้า กับ Arduino Uno R3

Arduino Shield เวอร์ชัน 5 บอร์ดขยายพอร์ท Arduino สำหรับเสียบกับสายเซนเซอร์ หรืออุปกรณ์ต่อพ่วงต่าง ๆ ได้อย่างสะดวก

Arduino ทุกเวอร์ชั่น (ยกเว้นพวกที่เป็น SMD และ เวอร์ชั่นที่ทำขึ้นกันเอง) จะถูกออกแบบให้มี Layout ของ Pin ต่างๆในรูปแบบเดียวกัน เพื่อให้สามารถใช้อุปกรณ์เสริมหลายๆอย่างร่วมกันได้ โดยวิธี Plug n’ play หมายถึงแค่เสียบลงไปแล้วก็นำไปใช้งานได้เลย …. ทำให้อุปกรณ์เสริมที่นำมาใช้ต่อพ่วงร่วมกันเรียกว่า Shield (ซึ่งหมายถึง เกราะ หรืออะไรประมาณนั้น ประมาณว่า สวมเกราะเสร็จ ออกไปรบได้เลย)


หมายเหตุ : ถ้ามี Jumper อยู่ที่ขา ENA และ ENB ของ บอร์ด L298N  ให้ถอดออก



การเชื่อมต่อระหว่าง บอร์ด Arduino Sensor Shield V5.0 กับ บอร์ด L298N  



เชื่อมต่อ มอเตอร์ ทั้ง 4 ตัวเข้ากับ โมดูลขับมอเตอร์


(ตรวจสอบการต่อสายแต่ละคู่ของมอเตอร์ ต้องเป็นขั้วเดียวกัน แล้วจึงไปแก้ไข สลับขั้วการต่อกับโมดูลขับมอเตอร์ ตอนทดสอบ การเคลื่อนที่ของหุ่นยนต์ ถ้ายังวิ่งไม่ถูกทิศทาง)

เชื่อมต่อบอร์ด Arduino กับ PS2 PS3 Adapter 

  • PS2 PS3 Adapter              Arduino Board
  •          +5V                       +5V
  •          DATA                     D 12
  •          CMD                      D 11 
  •          CLK                       D 13
  •          ATT                       D 10
  •          GND                      GND


2.ติดตั้ง Arduino IDE

ดาวน์โหลด Arduino IDE จากที่นี่

https://www.arduino.cc/en/software


3. ทดสอบ การเคลื่อนที่ของหุ่นยนต์


การทดสอบนี้ เป็นการตรวจสอบการต่อสายต่างๆ เช่น การเชื่อมต่อสายของมอเตอร์ ทั้ง 4 ตัว รวมทั้งสายอื่นๆ ของหุ่นยนต์ที่เราสร้าง ว่าถูกต้องหรือไม่ ถ้าถูกต้องหุ่นยนต์จะดำเนินการดังนี้

คือ เดินหน้า -> ถอยหลัง -> เลี้ยวซ้าย -> เลี้ยวขวา


และนี่คือโค้ดที่ใช้ทดสอบ

// Motor A pins (enableA = enable motor, pinA1 = forward, pinA2 = backward)
int enableA = 3;
int pinA1 = 6;
int pinA2 = 7;

//Motor B pins (enabledB = enable motor, pinB2 = forward, pinB2 = backward)
int enableB = 5;
int pinB1 = 8;
int pinB2 = 9;

void setup() {
  pinMode(enableA, OUTPUT);
  pinMode(pinA1, OUTPUT);
  pinMode(pinA2, OUTPUT);

  pinMode(enableB, OUTPUT);
  pinMode(pinB1, OUTPUT);
  pinMode(pinB2, OUTPUT);
}
void loop() {

  delay(2000);
  enableMotors();
  //Go forward
  forward(1000);
  coast(200);
  //Go backward
  backward(1000);
  coast(200);
  //Turn left
  turnLeft(400);
  coast(200);
  //Turn right
  turnRight(400);
  coast(200);
}

//Define high-level H-bridge commands

void enableMotors() {
  motorAOn();
  motorBOn();
}

void disableMotors() {
  motorAOff();
  motorBOff();
}

void forward(int time) {
  motorAForward();
  motorBForward();
  delay(time);
}

void backward(int time) {
  motorABackward();
  motorBBackward();
  delay(time);
}

void turnLeft(int time) {
  motorABackward();
  motorBForward();
  delay(time);
}

void turnRight(int time) {
  motorAForward();
  motorBBackward();
  delay(time);
}

void coast(int time) {
  motorACoast();
  motorBCoast();
  delay(time);
}

void brake(int time) {
  motorABrake();
  motorBBrake();
  delay(time);
}
//Define low-level H-bridge commands

//enable motors
void motorAOn() {
  digitalWrite(enableA, HIGH);
}

void motorBOn() {
  digitalWrite(enableB, HIGH);
}

//disable motors
void motorAOff() {
  digitalWrite(enableB, LOW);
}

void motorBOff() {
  digitalWrite(enableA, LOW);
}

//motor A controls
void motorAForward() {
  digitalWrite(pinA1, HIGH);
  digitalWrite(pinA2, LOW);
}

void motorABackward() {
  digitalWrite(pinA1, LOW);
  digitalWrite(pinA2, HIGH);
}

//motor B controls
void motorBForward() {
  digitalWrite(pinB1, HIGH);
  digitalWrite(pinB2, LOW);
}

void motorBBackward() {
  digitalWrite(pinB1, LOW);
  digitalWrite(pinB2, HIGH);
}

//coasting and braking
void motorACoast() {
  digitalWrite(pinA1, LOW);
  digitalWrite(pinA2, LOW);
}

void motorABrake() {
  digitalWrite(pinA1, HIGH);
  digitalWrite(pinA2, HIGH);
}

void motorBCoast() {
  digitalWrite(pinB1, LOW);
  digitalWrite(pinB2, LOW);
}

void motorBBrake() {
  digitalWrite(pinB1, HIGH);
  digitalWrite(pinB2, HIGH);
}

ไปที่ Tools -> Board -> Arduino AVR Boards -> Arduino Uno



เลือก Port โดยไปที่ Tools -> Port -> COM19
(โดย COM19 แต่ละเครื่องจะไม่เหมือนกัน ให้เลือกตามที่ปรากฎ)



คลิกที่ Upload



รอจนกระทั่งขึ้น Done uploading. ที่แถบด้านล่าง แสดงว่าเราอัพโหลดโปรแกรมลงบอร์ดได้สำเร็จแล้ว



วิดีโอผลลัพธ์การทำงาน การเคลื่อนที่ของหุ่นยนต์


4. อัพโหลดโค้ด หุ่นยนต์ บังคับ ด้วย Wireless Joystick PS2


ต้องมีการเพิ่มไลบรารี่ PS2X

ไลบรารี่ PS2X เป็น ไลบรารี่ ฟังก์ชัน ที่มีผู้พัฒนาเตรียมพร้อมไว้ให้เราแล้ว

🔧 ขั้นตอนการเพิ่มไลบรารี่ PS2X ลงใน Arduino IDE

  • ดาวน์โหลดไฟล์ไลบรารี่ PS2X
  • ไปที่ลิงก์ GitHub (ลิงก์ต้นฉบับของ Bill Porter):
    👉 https://github.com/madsci1016/Arduino-PS2X
  • กดปุ่มสีเขียว “Code” → “Download ZIP”
  • เปิด Arduino IDE
  • ไปที่เมนู Sketch → Include Library → Add .ZIP Library…
  • เลือกไฟล์ ZIP ที่โหลดมา
  • เลือกไฟล์ Arduino-PS2X-master.zip ที่โหลดไว้ แล้วกด Open
  • ตรวจสอบการติดตั้ง
  • ไปที่ Sketch → Include Library แล้วดูในรายการ ถ้ามีชื่อ PS2X_lib แสดงว่าติดตั้งสำเร็จแล้ว ✅



จากนั้นจึง Upload โค้ด โปรเจค หุ่นยนต์บังคับ ด้วย Wireless Joystick PS2 ไปยัง บอร์ด Arduino UNO R3

#include <PS2X_lib.h>   // ไลบรารีสำหรับจอย PS2

PS2X ps2x;

// กำหนดขาเชื่อมต่อ PS2
#define PS2_CLK  13
#define PS2_CMD  11
#define PS2_ATT  10
#define PS2_DAT  12

// กำหนดขามอเตอร์
int enableA = 3; // Motor A Speed (PWM)
int pinA1   = 6; // Motor A Forward
int pinA2   = 7; // Motor A Backward

int enableB = 5; // Motor B Speed (PWM)
int pinB1   = 8; // Motor B Forward
int pinB2   = 9; // Motor B Backward

void setup() {
  Serial.begin(9600);

  // ตั้งค่าขามอเตอร์
  pinMode(enableA, OUTPUT);
  pinMode(pinA1,   OUTPUT);
  pinMode(pinA2,   OUTPUT);

  pinMode(enableB, OUTPUT);
  pinMode(pinB1,   OUTPUT);
  pinMode(pinB2,   OUTPUT);

  // เปิดมอเตอร์เริ่มต้น
  motorAOn();
  motorBOn();

  // ตั้งค่าเชื่อมต่อจอย PS2
  int error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_ATT, PS2_DAT, true, true);

  if(error == 0) Serial.println("✅ PS2 Controller Connected!");
  else Serial.println("❌ PS2 Controller Error, เช็คสายต่อ");
}

void loop() {
  ps2x.read_gamepad(false, 0); // อ่านค่าจอย PS2 ทุก Loop

  // ควบคุมด้วยปุ่ม D-Pad
  if(ps2x.Button(PSB_PAD_UP)) {
    forward();
    Serial.println("เดินหน้า");
  }
  else if(ps2x.Button(PSB_PAD_DOWN)) {
    backward();
    Serial.println("ถอยหลัง");
  }
  else if(ps2x.Button(PSB_PAD_LEFT)) {
    turnLeft();
    Serial.println("เลี้ยวซ้าย");
  }
  else if(ps2x.Button(PSB_PAD_RIGHT)) {
    turnRight();
    Serial.println("เลี้ยวขวา");
  }
  else {
    coast();  // หยุดเมื่อไม่กดปุ่ม
    // brake(); // ถ้าอยากให้หยุดแบบเบรกทันทีให้ใช้ฟังก์ชันนี้แทน
  }

  delay(50);
}

//---------------- Motor Control Functions ----------------//

void forward() {
  analogWrite(enableA, 200);
  analogWrite(enableB, 200);
  motorAForward();
  motorBForward();
}

void backward() {
  analogWrite(enableA, 200);
  analogWrite(enableB, 200);
  motorABackward();
  motorBBackward();
}

void turnLeft() {
  analogWrite(enableA, 200);
  analogWrite(enableB, 200);
  motorABackward();
  motorBForward();
}

void turnRight() {
  analogWrite(enableA, 200);
  analogWrite(enableB, 200);
  motorAForward();
  motorBBackward();
}

void coast() {
  motorACoast();
  motorBCoast();
}

void brake() {
  motorABrake();
  motorBBrake();
}

//---------------- Low-Level Motor Functions ----------------//

void motorAOn()  { digitalWrite(enableA, HIGH); }
void motorBOn()  { digitalWrite(enableB, HIGH); }
void motorAOff() { digitalWrite(enableA, LOW);  }
void motorBOff() { digitalWrite(enableB, LOW);  }

void motorAForward()  { digitalWrite(pinA1, HIGH); digitalWrite(pinA2, LOW);  }
void motorABackward() { digitalWrite(pinA1, LOW);  digitalWrite(pinA2, HIGH); }

void motorBForward()  { digitalWrite(pinB1, HIGH); digitalWrite(pinB2, LOW);  }
void motorBBackward() { digitalWrite(pinB1, LOW);  digitalWrite(pinB2, HIGH); }

void motorACoast() { digitalWrite(pinA1, LOW);  digitalWrite(pinA2, LOW);  }
void motorBCoast() { digitalWrite(pinB1, LOW);  digitalWrite(pinB2, LOW);  }

void motorABrake() { digitalWrite(pinA1, HIGH); digitalWrite(pinA2, HIGH); }
void motorBBrake() { digitalWrite(pinB1, HIGH); digitalWrite(pinB2, HIGH); }

หลักการทำงาน

ปุ่มบนจอย PS2การทำงานของรถ
กดปุ่ม UPเดินหน้า
กดปุ่ม DOWNถอยหลัง
กดปุ่ม LEFTเลี้ยวซ้าย
กดปุ่ม RIGHTเลี้ยวขวา
ปล่อยทุกปุ่มหยุดรถ (Coast/Brake)



วิดีโอผลลัพธ์การทำงาน หุ่นยนต์บังคับ ด้วย Wireless Joystick PS2

Leave a Reply

Your email address will not be published. Required fields are marked *