Xe điều khiển bằng tay game Dual Shock3 thông qua Bluetooth

Vừa bắt đầu với arduino được hơn 1 tuần, có tham khảo qua các nguồn từ "trung ương đến địa phương", nắm được 1 số kiến thức cơ bản nên mình bắt đầu thực hiện 1 sản phẩm để đúc kết kinh nghiệm. Trong số đó thì xe điều khiển là dễ nhất. Kết hợp với cái tay game ps3 nằm lăn lóc ở góc nhà. Thế là có 1 chiếc xe điều khiển từ xa. Bắt đầu nhé heart!

I. Chuẩn bị

Tất cả các linh kiện trên các bạn có thể search và mua trên các cửa hàng điện tử. Cửa hàng thì các bạn tự lựa chọn mình không nêu ra ở đây.

II. Tiến hành

1. Ráp module USB host shield vào board Arduino

Sau đó ráp Motor shield vào trên USB (nghe như làm bánh sandwitch wink)

2. Nối 2 động cơ vào chân M1 và M2 cho 

3. Nối động cơ servo

4. Nguồn cho cả hệ thống

Mình dùng cục pin dự phòng nên cắt cọng dây USB, dây đỏ nối cực dương và dây đen nối cực âm

5. Tađa

Đã xong phần lắp ráp. Tổng thể của chiếc xe như hình bên dưới

Chuyển sang phần code nhe!

III. Lập trình

1. Thư viện

Hiện tại mình sử dụng thư viện:

AFMotor: https://learn.adafruit.com/adafruit-motor-shield/library-install (mirror)

USB host shield: https://github.com/felis/USB_Host_Shield_2.0

Tất cả đều có example các bạn tự tham khảo nhe.

2. Cách kết nối USB Dongle với tay game ps3

Mình nói sơ sơ nhé:

  1. Đầu tiên mở nguồn.
  2. Cắm usb dongle vào usb host shield đợi 5 -> 10s, sau đó rút ra.
  3. Cắm dây kết nối tay game ps3 với usb host shield, nhấn nút kết nối trên tay game ps3, đợi 5 -> 10s rồi rút dây ra.
  4. Đợi tí xíu nữa khi nào còn 1 đèn là nó đã kết nối rồi đó.

3. Ý tưởng code như sau

Mình sử dụng cần analog bên trái để điều khiển: tới - lùi - trái - phải

Theo thư viện nhúng vào thì cần analog trên tay game ps3 nó định nghĩa như sau:

  • Từ trái -> phải <=> 0 -> 255
  • Từ trên -> dướng <=> 0 -> 255

Dùng hàm map để điều chỉnh như sau:

  • Tiến / lùi: dùng map để tăng tốc tiến / lùi cho motor.
  • Trái / phải: dùng map để tình góc cho động cơ servo.

Thực tế thì khi dùng giá trị trả về của cần analog thì giá trị luôn bị dao động tại 1 vị trí (ở đây là vị trí xe đứng im và bánh hướng phía trước mình gọi là vị trí cân bằng), ko biết có nên sử dụng bộ lọc ko nhưng theo các của mình thì mình sẽ tăng khoảng cách của vị trí cân bằng. Mình chia 1 hành trình của cần analog làm 3 đoạn: 0->117; 117->135; 135->255.

Đây là thành quả của mình

Hiện tại USB host shield và Arduino motor shield giá thành cũng khá mắc. Các bạn có thể thay thế bằng module Bluetooth HC-06 và module L298.

4. Code

#include <AFMotor.h>
#include <Servo.h>
 
#include <PS3BT.h>
#include <usbhub.h>
 
// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#include <SPI.h>
#endif
 
USB Usb;
//USBHub Hub1(&Usb); // Some dongles have a hub inside
 
BTD Btd(&Usb); // You have to create the Bluetooth Dongle instance like so
/* You can create the instance of the class in two ways */
PS3BT PS3(&Btd); // This will just create the instance
//PS3BT PS3(&Btd, 0x00, 0x15, 0x83, 0x3D, 0x0A, 0x57); // This will also store the bluetooth address - this can be obtained from the dongle when running the sketch
 
AF_DCMotor motor1(1); //Khai báo động cơ 1
AF_DCMotor motor2(2); //Khai báo động cơ 4
Servo servo1;
void setup() {
  Serial.begin(115200); //Mở cổng Serial
  
  #if !defined(__MIPSEL__)
  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
  if (Usb.Init() == -1) {
    Serial.print(F("\r\nOSC did not start"));
    while (1); //halt
  }
  Serial.print(F("\r\nPS3 Bluetooth Library Started"));
    
    motor1.setSpeed(255);//Đặt tốc độ động cơ
    motor2.setSpeed(255);
    motor1.run(RELEASE);
    motor2.run(RELEASE);
    servo1.attach(9);
}
 
void loop() 
{
  Usb.Task();
  if(PS3.getAnalogHat(LeftHatY) >= 0 && PS3.getAnalogHat(LeftHatY) < 117){ //UP
      motor1.run(FORWARD);
      motor2.run(FORWARD);
      int iSpeed = map(PS3.getAnalogHat(LeftHatY), 117, 0, 0, 255);
      motor1.setSpeed(iSpeed);
      motor2.setSpeed(iSpeed);
      delay(5);
  }
  if(PS3.getAnalogHat(LeftHatY) > 137 && PS3.getAnalogHat(LeftHatY) <= 255){ //DOWN
      motor1.run(BACKWARD);
      motor2.run(BACKWARD);
      int iSpeed = map(PS3.getAnalogHat(LeftHatY), 137, 255, 0, 255);
      motor1.setSpeed(iSpeed);
      motor2.setSpeed(iSpeed);
      delay(5);
  }
  
  if(PS3.getAnalogHat(LeftHatX) >= 0 && PS3.getAnalogHat(LeftHatX) < 117){ //LEFT
      int iRad = map(PS3.getAnalogHat(LeftHatX), 0, 117, 135, 90);
      servo1.write(iRad);
      delay(5);
  }
  if(PS3.getAnalogHat(LeftHatX) > 137 && PS3.getAnalogHat(LeftHatX) <= 255){ //RIGHT
      int iRad = map(PS3.getAnalogHat(LeftHatX), 137, 255, 90, 45);
      servo1.write(iRad);
      delay(5);
  }
  if(PS3.getAnalogHat(LeftHatY) >= 117 && PS3.getAnalogHat(LeftHatY) <= 137){ //STOP
      motor1.run(RELEASE);
      motor2.run(RELEASE);
  }
  if(PS3.getAnalogHat(LeftHatX) >= 121 && PS3.getAnalogHat(LeftHatX) <= 134){ //STOP
      servo1.write(90);
  }
  if (PS3.getButtonClick(CROSS))//Dung dong co
  {
      Serial.println("STOP!");
      motor1.run(RELEASE);
      motor2.run(RELEASE);
      servo1.write(90);
      delay(5);
  }
  delay(5);
}

Hy vọng sau bài này các bạn sẽ có những ý tưởng mới.

Chào đoàn kết và quyết thắng.  

Bài viết truyền cảm hứng: 
lên
15 thành viên đã đánh giá bài viết này hữu ích.
Các dự án được truyền cảm hứng

Select any filter and click on Apply to see results