วันจันทร์ที่ 12 กันยายน พ.ศ. 2559

การเขียนโปรแกรมอ่านค่า Joystick USB เพื่อนำไปควบคุมหุ่นยนต์ครับ (read data from USB gamepad Sent to Serial port)

วันนี้ผมจะมา นำเสนอวิธีการเขียนโปรแกรมเพื่ออ่านค่า USB GamePad(joystick) ซึ่งในการเขียนอ่านค่านั้นจำเป็นต้องใช่ library ของ Microsoft DirectX ซึ่งจะเป็นตัว DirectInput นั้นจะทำหน้าที่ในการ ประมวลผลข้อมูลที่มาจาก keybord,Mouse และสำคัญที่สุดสำเราบทความนี้ คือ Joystick หรือเกมส์คอนโทรลเลออื่นๆ ก็สามารถทำได้
      โดยท่านผู้อ่านสามารถหาข้อมูลเพิ่มเติมเกี่ยวกับการใช้งาน Class และ Method การใช้งานต่างๆได้เพิ่มเติมที่  https://msdn.microsoft.com/en-us/library/windows/desktop/bb318766(v=vs.85).aspx
หน้าตาโปรแกรมที่ออกแบบครับ

รออัพเดท วิดีโอ และ eport ตัว exe

ซึ่งในที่นี้ ผมจะทำการสร้างโปรเจคขึ้นมาเป็นแบบ Window Form Application โดย library ที่ใช่

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX.DirectInput;
// หลักการทำงานของ joyStick หลักหลักเลยจะใช้งาน DirectX ของ microsoft ที่เป็น DirectInput 
// ตัว DirectInput มันจะเป็นการทำงานเกี่ยวกับการประมวลผลข้อมูลที่มาจาก joystick keybord mouse เป็นต้น 
//โดยข้อมูลเพิ่มเติมสามารถหาได้จาก  https://msdn.microsoft.com/en-us/library/windows/desktop/bb318766(v=vs.85).aspx 
  1. ทำการเชื่อมต่อ joystucโดย Method ที่งานเริ่มต้นคือทำการ ค้นหา Joystick คือ InitDevice()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 private void InitDevices()
        {
            
            //create joystick device สั่งให้ วนลูบหา Device ที่เชื่อมต่อแเข้ามาในเครื่องคอมพิวเตอร์ โดย Class ที่ใช่ get ค่า device คือ manager class 
            // manager class มี methode ในการทำงาน ได้หลายอย่างเช่น getDevice() findDevice() 
            //paramitor ที่อยู่ใน GetDevice มีสองตัว คือ 1 actionformat หมายถึง format ของ Device ที่ get เข้ามา มี keybord,gamecontrol  เป็นต้น 
            // paramitor ตัวที่สอง คือ flag จะต้องขึ้นต้นด้วย enumDeviceFlag เสมอ methode ที่สามารถใช่งานได้ คือ attachedOnly หมายถึงตัวที่มีการเชื่อมต่อมาเท่านั้น 
            foreach (DeviceInstance di in Manager.GetDevices(DeviceClass.GameControl,EnumDevicesFlags.AttachedOnly))
            {
                joystick = new Device(di.InstanceGuid); // เก็บค่าไว้ใน object joystick 
                break; 
            }

            if (joystick == null) // ถ้าวนหา แล้วไม่เจอ joystick สั่ง massegboxshow 
            {
                //Throw exception if joystick not found.
                MessageBox.Show("หา joyStick ไม่เจอ โปรดมั่นใจว่าคุณได้เสียบ joystick แล้ว");
                return;
            }

            //หลังจากที่เราแนบ device ไว้ใน object joystick แล้ว เราจะทำการ ค้าหาเข้าไปในตัว object อีกว่ามี อะไรอยู๋ในตัว object บ้าง 
            foreach (DeviceObjectInstance doi in joystick.Objects) 
            {
                if ((doi.ObjectId & (int)DeviceObjectTypeFlags.Axis) != 0) // objectid มี ค่า และ axis ค่าแกนของ object joystick มีค่าไม่เท่ากับ 0
                {
                    // ทำการ set range โดย paramitorhow หมายความว่าเราจะ set rang โดย fillter ค่าของอะไรเป็นหลัก ใน ที่นี้ ผมเลือก byid มีอย่างอื่นด้วยคือ byDevice 
                    //paramitor ตัวต่อมา คือ ทำการ ใส่ ตัว object ของเราลงไป โดยเลือกเป็น by id เหมือนกัน 
                    // paramitor ตัวสุดท้าย inputRange ผมเซ็ตให้มันมีค่า 0-1600 
                    joystick.Properties.SetRange(ParameterHow.ById,doi.ObjectId,new InputRange(0, 1600));
                }
            }

            joystick.Properties.AxisModeAbsolute = true;      // ทำให้ค่าที่ออกมาจาก joystick เป็นค่าที่ไม่ติดลบ

            //set cooperative level.
            joystick.SetCooperativeLevel(
            this,
            CooperativeLevelFlags.NonExclusive |
            CooperativeLevelFlags.Background);

            //Acquire devices for capturing.
            joystick.Acquire();                             // ทำการใส่ค่าที่รับมาจาก joystick ไปใน object

        }

2. วิธีการรับค่าข้อมูลโดยเราจะใช่การรับค่าของ Device ที่เราเชื่อมต่อมา ตาม code ด้านล่าง ซึ่งอาจจะต้อง Method ไปวางไว้ใน timer ให้เป็น loopเวลา คอยรับค่าที่ส่งมาจาก Joystick โดย ใน บรรทัดที่ 20 เราได้ทำการ สร้าง Object  button ขึ้นมาโดย buttonนั้น จะถูกแบ่งออกเป็น Array เช่น button[0] ก็จะเท่ากับ ตัวเลข 1 ที่อยู่ฝั่งขวาของ joystick เป็นต้น
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
  private void UpdateJoystick()   // อัพเดทการทำงานของ 
        {
            if (joystick != null)
            {
                string info = "Joystick: ";
                JoystickState state = joystick.CurrentJoystickState;    // รับค่าสถานะของ device ที่เรา get ค่ามา

                //Capture Position.
                info += "X:" + state.X + " ";
                info += "Y:" + state.Y + " ";
                info += "Z:" + state.Z + " ";
                info += "no:" + state.ARx + "";
                trackBar1.Value = state.X;
                trackBar2.Value = state.Y;
                

                label2.Text = "แกน X :" + state.X;
                label3.Text = "แกน Y :" + state.Y;
                //Capture Buttons.
                byte[] buttons = state.GetButtons();
          }
}

3. การใช้งาน button ค่าที่ออกมาจาก joystick นั้น ถ้าปุ่มถูกกดค่าจะถูก ส่งออกมาเป็นค่า128 ถ้าไม่ถูกกด ค่าจะถูกส่งออกมาเป็น 0 ตามโค็ดตัวอย่าง
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 byte[] buttons = state.GetButtons();
                // MessageBox.Show("" + buttons[0]);
                if (buttons[0] == 0)
                {
                    //ไม่ต้องทำอะไร
                    
                }
                if (buttons[0] == 128)
                {
                    MessageBox.Show("ปุ่ม 1 ถูกกด");
                }

ไม่มีความคิดเห็น:

แสดงความคิดเห็น