You are on page 1of 65

TRƯỜNG ĐẠI HỌC SƯ PHẠM KỸ THUẬT TP.

HCM

KHOA ĐIỆN – ĐIỆN TỬ

BỘ MÔN KỸ THUẬT MÁY TÍNH – VIỄN THÔNG

===== ● =====

ĐỒ ÁN MÔN HỌC 2

THIẾT KẾ KEYBOARD GAME

GVHD : PGS.TS Phan Văn Ca

SVTH : Đào Minh Thuấn 15119138


Nguyễn Văn Phú 15119118
Ngành : Công nghệ kỹ thuật máy tính

Tp. Hồ Chí Minh, tháng 5 năm 2019


PHIẾU NHẬN XÉT CỦA GIẢNG VIÊN

Họ và tên Sinh viên: Đào Minh Thuấn MSSV: 15119138


Nguyễn Văn Phú MSSV: 15119118
Ngành: Công nghệ kỹ thuật máy tính.
Tên đề tài: Thiết kế KeyBoard Game.
Họ và tên Giáo viên phản biện: .......................................................................................
..................................................................................................................................................
NHẬN XÉT
1. Về nội dung đề tài & khối lượng thực hiện:
..................................................................................................................................................
..................................................................................................................................................
2. Ưu điểm:
..................................................................................................................................................
..................................................................................................................................................
3. Khuyết điểm:
..................................................................................................................................................
..................................................................................................................................................
4. Đề nghị cho bảo vệ hay không?
..................................................................................................................................................
5. Đánh giá loại:
..................................................................................................................................................
6. Điểm:………….(Bằng chữ: ...........................................................................................)
..................................................................................................................................................
Tp. Hồ Chí Minh, ngày tháng năm 2019
Giảng viên phản biện
MỤC LỤC
DANH MỤC HÌNH ------------------------------------------------------------------------------i
DANH MỤC BẢNG ---------------------------------------------------------------------------- ii
LỜI MỞ ĐẦU----------------------------------------------------------------------------------- iii
LỜI CẢM ƠN----------------------------------------------------------------------------------- iv
DANH SÁCH CÁC TỪ VIẾT TẮT ---------------------------------------------------------- v
CHƯƠNG 1 : TỔNG QUAN ------------------------------------------------------------------ 1
1.1. Tình hình nghiên cứu hiện nay -------------------------------------------------------- 1
1.2. Lý do chọn đề tài------------------------------------------------------------------------ 1
1.3. Mục tiêu của đề tài---------------------------------------------------------------------- 1
1.4. Đối tượng nghiên cứu ------------------------------------------------------------------ 2
1.5. Phương pháp nghiên cứu --------------------------------------------------------------- 2
1.6. Bố cục đồ án----------------------------------------------------------------------------- 2
CHƯƠNG 2 : CƠ SỞ LÝ THUYẾT --------------------------------------------------------- 4
2.1. Tổng quan về chuẩn truyền I2C -------------------------------------------------------- 4
2.2. Tổng quan về chuẩn truyền UART---------------------------------------------------- 5
2.3. Tổng quan về RTOS -------------------------------------------------------------------- 6
2.4. Ngôn ngữ PYTHON -------------------------------------------------------------------- 7
2.5. Tương tác với cơ sở dữ liệu ------------------------------------------------------------ 9
2.6. Chip ST32F103C8T6 ----------------------------------------------------------------- 10
2.7. Module Joystick----------------------------------------------------------------------- 11
2.8. Module MPU6050 -------------------------------------------------------------------- 12
2.9. Mạch sạc TP4056 --------------------------------------------------------------------- 13
2.10. Module Bluetooth HC05 ----------------------------------------------------------- 14
2.11. IC nguồn LM1117T 3v3 ----------------------------------------------------------- 16
CHƯƠNG 3 : THIẾT KẾ VÀ XÂY DỰNG HỆ THỐNG ------------------------------ 17
3.1. Giới thiệu và tóm tắt ------------------------------------------------------------------ 17
3.1.1. Yêu cầu chung của hệ thống-------------------------------------------------- 17
3.1.2. Đặc tả hệ thống ---------------------------------------------------------------- 17
3.2. Sơ đồ khối ----------------------------------------------------------------------------- 17
3.3. Thiết kế phần cứng ------------------------------------------------------------------- 21
3.3.1. Khối cảm biến ----------------------------------------------------------------- 21
3.3.2. Khối giao tiếp ------------------------------------------------------------------ 21
3.3.3. Khối nguồn --------------------------------------------------------------------- 22
3.3.4. Khối xử lý trung tâm ---------------------------------------------------------- 22
3.4. Thiết kế phần mềm ------------------------------------------------------------------- 23
3.4.1. Các thành phần ---------------------------------------------------------------- 23
3.4.2. Lưu đồ giải thuật phần mềm-------------------------------------------------- 24
CHƯƠNG 4: KẾT QUẢ THỰC HIỆN ---------------------------------------------------- 27
4.1. Phần cứng ------------------------------------------------------------------------------- 27
4.1.1. Các công cụ sử dụng ---------------------------------------------------------- 27
4.1.2. Schematic ---------------------------------------------------------------------- 27
4.1.3. Mạch PCB---------------------------------------------------------------------- 28
4.2. Giao diện phần mềm trên máy tính ------------------------------------------------- 28
4.3. Database ------------------------------------------------------------------------------- 29
CHƯƠNG 5: KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN -------------------------------- 30
5.1. Kết luận ---------------------------------------------------------------------------------- 30
5.2. Hướng phát triển ---------------------------------------------------------------------- 30
TÀI LIỆU THAM KHẢO ------------------------------------------------------------------- 31
PHỤ LỤC--------------------------------------------------------------------------------------- 32
DANH MỤC HÌNH
Hình 2.1. Giao tiếp I2C.-------------------------------------------------------------------------- 4
Hình 2.2. Giao tiếp UART ----------------------------------------------------------------------- 5
Hình 2.3.1. CPU xử lý các Task----------------------------------------------------------------- 6
Hình 2.3.2. Trạng thái các Task ----------------------------------------------------------------- 7
Hình 2.4. Logo Python --------------------------------------------------------------------------- 8
Hình 2.5. Ví dụ về 1 cơ sở dữ liệu. ------------------------------------------------------------- 9
Hình 2.6. STM32F103C8T6 Pinout. ---------------------------------------------------------- 10
Hình 2.7. Module Joystick --------------------------------------------------------------------- 12
Hình 2.8. Module MPU6050.------------------------------------------------------------------ 12
Hình 2.9. Mạch sạc TP4056 ------------------------------------------------------------------- 13
Hình 2.10. Module HC05 ---------------------------------------------------------------------- 14
Hình 2.11. IC nguồnLM1117T. --------------------------------------------------------------- 16

Hình 3.1. Sơ đồ khối của hệ thống. ---------------------------------------------------------- 18


Hình 3.2. Lưu đồ-------------------------------------------------------------------------------- 25
Hình 4.1.1. Schematic. ------------------------------------------------------------------------- 27
Hình 4.1.2. PCB. -------------------------------------------------------------------------------- 28
Hình 4.1.3. Mô hình hoàn thiện. -------------------------------------------------------------- 28
Hình 4.2. Giao diện phần mềm ---------------------------------------------------------------- 29
Hình 4.3. Giao diện database. ----------------------------------------------------------------- 29

i
DANH MỤC BẢNG
Bảng 3.2.1. So sánh các dòng vi xử lý. ------------------------------------------------------- 19
Bảng 3.2.2. So sánh các công nghệ không dây.---------------------------------------------- 20

ii
LỜI MỞ ĐẦU
Trên thị trường hiện tại có rất nhiều tay cầm kết nối không dây chơi game, chúng
thì được thiết kế khá nhỏ gọn phù hợp với người chơi. Tuy nhiên thường những tay cầm
này có giá thành rất cao, kèm theo đó là chỉ có thể chơi một số game nhất định, với lại
trong các game thường thì người chơi hay cấu hình game theo ý của mình nhưng đối với
các tay cầm hiện tại hầu như không có tính năng là thay đổi cấu hình để phù hợp cấu
hình game mà người chơi đã cấu hình trước đó điều này phần nào dẫn đến cảm giác khó
chịu khi đang chơi game.

Vì những lý do này, nhóm thực hiện đã chọn đề tài “ THIẾT KẾ KEY BOARD
GAME" trong quá trình thực hiện đề tài này, không tránh khỏi những sai sót do kiến
thức có giới hạn, cũng như tham khảo từ nhiều nguồn tài liệu từ internet, sách, báo,…
Rất mong nhận được sự đóng góp của quý thầy cô và bạn bè để đề tài thực hiện thành
công và phát triển hơn nữa.

iii
LỜI CẢM ƠN
Đầu tiên, nhóm thực hiện đề tài xin gửi lời cảm ơn sâu sắc và chân thành đến thầy
PHAN VĂN CA đã tận tình giúp đỡ, chỉ bảo, hướng dẫn nhóm thực hiện trong suốt quá
trình thực hiện đề tài này. Trong thời gian làm việc với thầy, nhóm không những tiếp
thu thêm nhiều kiến thức bổ ích mà còn học tập được tinh thần làm việc, thái độ nghiên
cứu khoa học nghiêm túc hiệu quả của thầy. Đây là những điều cần thiết cho nhóm trong
quá trình học tập và công tác sau này.

Nhóm thực hiện cũng xin chân thành cảm ơn các bạn ngành công nghệ kỹ thuật
máy tính lớp 151191A , đã luôn đồng hành, giúp đỡ để nhóm có thể thực hiện đề tài này
thành công.

Quá trình biên soạn báo cáo khó có thể tránh hoàn toàn các sai phạm. Kính mong
nhận được lời góp ý mang tính xây dựng từ mọi người.

Người thực hiện

Đào Minh Thuấn

Nguyễn Văn Phú

iv
DANH SÁCH CÁC TỪ VIẾT TẮT
TỪ VIẾT TẮT TỪ TIẾNG ANH Ý NGHĨA

I2C Inter-Integrated Circuit Giao tiếp một thiết bị chủ


với nhiều thiết bị tớ.

UART Universal Asynchronous Bộ truyền nhận nối tiếp bất


Receiver Transmitter đồng bộ

ARM Acorn RISC Machine Là 1 loại cấu trúc vi xử lý


32 bit kiểu RISC (thuộc
kiến trúc Harvard, tập lệnh
rút gọn).

API Application Programming Giao diện lập trình ứng


Interface dụng.

v
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

CHƯƠNG 1 : TỔNG QUAN


1.1. Tình hình nghiên cứu hiện nay
Hiện nay, xã hội ngày phát triển và khoa học kỹ thuật ngày càng tiên tiến hơn thì
nhu cầu về kỹ thuật càng được quan tâm và phát triển hơn. Đặc biệt là những công trình
nghiên cứu khoa học nhằm thiết kế ra những sản phẩm ứng dụng có ý nghĩa thiết thực vào
cuộc sống.

1.2. Lý do chọn đề tài


Trong quá trình học tập thì chúng em đã học được nhiều loại vi điều khiển như: avr,
pic, 8051,…Và trên hết là chip Arm cụ thể là dòng arm cortex m3 đại diện là chip
STM32F103C8T6. Ngoài ra cũng được làm việc với nhiều module, cảm biến. Và bây giờ
thông qua đồ án môn học 2 này, nhóm thực hiện muốn tạo ra một sản phẩm sử dụng các
tính năng của chip STM32F103C8T6 và các module, cũng như khả năng hàn chip dán.
Nên nhóm quyết định chọn đề tài: “Thiết kế Keyboard Game”.

1.3. Mục tiêu của đề tài


Đề tài triển khai nghiên cứu hướng tới mục tiêu sau:

 Theo dõi các giá trị góc nghiêng thông qua cảm biến MPU6050, tử các góc nghiêng
đó sẽ bắt đầu gửi các lệnh tương ứng.
 Điều khiển led RGB.
 Điều khiển module Joystick.
 Điều khiển các nút nhấn.
 Gửi các chuỗi điều khiển thông qua Bluetooth.
 Phần mềm trên máy tính sau khi nhận được các chuỗi sẽ tiến hành gửi các lệnh điều
khiển tương ứng để điều khiển game.
 Phần mềm có thể thiết lập cấu hình game và lưu thiết lập đó trên database.

1
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

1.4. Đối tượng nghiên cứu


 Chip STM32F103C8T6, Module Joystick, cảm biến MPU6050, module HC05,
nút nhấn, LM1117T 3v3, mạch sạc TP4056.
 Chuẩn giao thiếp I2C.
 Chuẩn giao tiếp UART.
 RTOS.
 Ngôn ngữ Python.
 Tương tác với cơ sở dữ liệu.

1.5. Phương pháp nghiên cứu


Trong đề tài này, nhóm đã sử dụng các phương pháp nghiên cứu sau:

 Phương pháp tham khảo tài liệu: bằng cách thu thập thông tin từ sách, tạp chí về
điện tử, truy cập từ mạng internet.
 Phương pháp quan sát: khảo sát một số mạch điện từ mạng internet, khảo sát các
tay cầm người ta tự chế.
 Phương pháp khảo sát và thực nghiệm: từ những ý tưởng và kiến thức của nhóm,
kết hơp sự hướng dẫn của giáo viên, nhóm đã thiết kế thử nghiệm thành công
tay cầm chơi game.

1.6. Bố cục đồ án

Chương 1: Tổng quan

Giới thiệu sơ lược về tình hình nghiên cứu hiện nay cũng như đối tượng
nghiên cứu, phương pháp nghiên cứu.

Chương 2: Cơ sở lý thuyết

Nêu các lý thuyết cần thiết của các cảm biến, chuẩn giao tiếp, giao thức sử
dụng trong đề tài.

Chương 3: Thiết kế và xây dựng hệ thống

Trình bày sơ đồ hệ thống và giải thích hoạt động của hệ thống.


2
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

Đưa ra các phương pháp lựa chọn phần cứng và xác định lựa chọn phù hợp
với yêu cầu của đề tài.

Chương 4: Kết quả thực hiện

Tính toán đưa ra giải thuật, thuật toán phần mềm.

Trình bày kết quả đã thực hiện về phần cứng và phần mềm.

Chương 5: Kết luận và hướng phát triển


Nêu các ưu điểm và các điểm cần cải thiện của đề tài, hướng khắc phục và
hướng phát triển trong tương lại.

3
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

CHƯƠNG 2 : CƠ SỞ LÝ THUYẾT
Để tiến hành thiết kế phần cứng cũng như phần mềm nhóm đã tìm hiểu một số khái niệm
sau:

2.1. Tổng quan về chuẩn truyền I2C


I2C là một loại bus nối tiếp được phát triển bởi hãng sản xuất linh kiện điện tử
Philips. Ban đầu, loại bus này chỉ được dùng trong các linh kiện điện tử của Philips. Sau
đó, do tính ưu việt và đơn giản của nó, I2C đã được chuẩn hóa và được dùng rộng rãi
trong các module truyền thông nối tiếp của vi mạch tích hợp ngày nay. . Địa chỉ của thiết
bị tớ thường do nhà chế tạo thiết bị thiết lập sẵn.
I2C sử dụng hai đường truyền tín hiệu: một đường xung nhịp đồng hồ (SCL) có
chức năng cấp xung clock để dịch chuyển dữ liệ và một đường dữ liệu (SDA) có chức
năng truyền tải dữ liệu. SCL và SDA luôn được kéo lên nguồn bằng một điện trở kéo lên
có giá trị xấp xỉ 4,7 KOhm. Các chế độ hoạt động của I²C bao gồm:
 Chế độ chuẩn (standard mode) hoạt động ở tốc độ 100 Kbit/s.
 Chế độ tốc độ thấp (low-speed mode) hoạt động ở tốc độ 10 Kbit/s.
Trong hệ thống truyền dữ liệu I²C, thiết bị nào cấp xung clock được gọi là thiết bị
chủ (master), thiết bị nhận xung clock được gọi là tớ (slave). Thiết bị chủ có 1, thiết bị tớ
có nhiều, mỗi thiết bị tớ có 1 địa chỉ độc lập, chuẩn truyền ban đầu dung địa chỉ 7 bit nên
có thể giao tiếp với 128 thiết bị tớ. Các thiết bị sau này được tang số bit địa chỉ lên nên
giao tiếp nhiều thiết bị hơn.

Hình 2.1. Giao tiếp I2C.

4
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

2.2. Tổng quan về chuẩn truyền UART


UART là “Universal Asynchronous Receiver / Transmitter”. Nó là một vi mạch sẵn
có trong một vi điều khiển nhưng không giống như giao thức truyền thông (I2C & SPI).
Chức năng chính của UART là truyền dữ liệu nối tiếp. Trong UART, giao tiếp giữa hai
thiết bị có thể được thực hiện theo hai cách là giao tiếp dữ liệu nối tiếp và giao tiếp dữ liệu
song song.

Hình 2.2. Giao tiếp UART


Trong giao tiếp dữ liệu nối tiếp, dữ liệu có thể được truyền qua một đường dây.
Truyền thông dữ liệu nối tiếp không đắt khi chúng ta so sánh với giao tiếp song song. Nó
đòi hỏi rất ít mạch cũng như dây.

Trong giao tiếp này, có hai loại UART có sẵn là truyền UART và nhận UART và
giao tiếp giữa hai loại này có thể được thực hiện trực tiếp với nhau. Đối với điều này, chỉ
cần hai cáp để giao tiếp giữa hai UART. Luồng dữ liệu sẽ từ cả hai chân truyền (Tx) và
nhận (Rx) của UARTs. Trong UART, việc truyền dữ liệu từ Tx UART sang Rx UART có
thể được thực hiện không đồng bộ.

Ưu điểm và nhược điểm của UART

 Những ưu và nhược điểm của UART bao gồm những điều sau đây
 Nó chỉ cần hai dây để truyền dữ liệu
 Tín hiệu CLK là không cần thiết.
 Nó bao gồm một bit chẵn lẻ để cho phép kiểm tra lỗi
 Sắp xếp gói dữ liệu có thể được sửa đổi vì cả hai mặt được sắp xếp
 Kích thước khung dữ liệu tối đa là 9 bit
 Nó không chứa một số hệ thống phụ (hoặc)
 Tốc độ truyền của UART phải ở mức 10% của nhau

5
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

2.3. Tổng quan về RTOS


Hệ điều hành thời gian thực – RealTime Operating Systems(RTOS), là phần mềm
điều khiển chuyên dụng thường được dùng trong những ứng dụng nhúng có tài nguyên bộ
nhớ hạn chế và yêu cầu ngặt nghèo về thời gian đáp ứng tức thời, tính sẵn sàng cao và khả
năng tự kiểm soát một cách chính xác.

Một hệ điều hành có thể:

 Cho phép nhiều chương trình chạy cùng 1 lúc (multi-tasking).


 Có quản lý tài nguyên về phần cứng và cung cấp các dịch vụ cho các chương trình khác .

 Khi nào bạn cần sử dụng RTOS ?

Các ứng dụng không cần dùng RTOS

 Ứng dụng đơn (ứng dụng chỉ có 1 chức năng).


 Ứng dụng có vòng lặp đơn giản.
 Ứng dụng <32kB.

Nếu ứng dụng của bạn mà kích thước chương trình lớn dần và độ phức tạp tăng lên thì
RTOS sẽ rất hữu dụng trong trường hợp này, lúc đó RTOS sẽ chia các ứng dụng phức tạp
thành các phần nhỏ hơn và dễ quản lý hơn.

Tại sao lại phải dùng RTOS ?

 Chia sẻ tài nguyên một cách đơn giản: cung cấp cơ chế để phân chia các yêu cầu về bộ
nhớ và ngoại vi của MCU.
 Dễ debug và phát triển: Mọi người trong nhóm có thể làm việc một cách độc lập, các
lập trình viên thì có thể tránh được các tương tác với ngắt, timer, với phần cứng (cái
này mình không khuyến khích lắm vì hiểu được phần cứng vẫn sẽ tốt hơn nhiều).
 Tăng tính linh động và dễ dàng bảo trì: thông qua API của RTOS,….

Các khái niệm cơ bản

Kernel

Hình 2.3.1. CPU xử lý các Task

6
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

Kernel sẽ có nhiệm vụ quản lý nhiều task cùng chạy 1 lúc, mỗi task thường chạy mất vài
ms. Tại lúc kết thúc task thường:

 Lưu trạng thái task


 Thanh ghi CPU sẽ load trạng thái của task tiếp theo
 Task tiếp theo cần khoảng vài ms để thực hiện
Vì CPU thực hiện tác vụ rất nhanh nên dưới góc nhìn người dùng thì hầu như các task là
được thực hiện 1 cách liên tục.
Task state

Một task trong RTOS thường có các trạng thái như sau

Hình 2.3.2. Trạng thái các Task

RUNNING: đang thực thi.


READY: sẵn sàng để thực hiện.
WAITING: chờ sự kiện.
INACTIVE: không được kích hoạt.
2.4. Ngôn ngữ PYTHON
Python là một ngôn ngữ lập trình hướng đối tượng rất thông dụng dùng để viết các
tiện ích hệ thống và các đoạn mã trên Internet. Nó cũng được sử dụng như ngôn ngữ kết
dính đóng vai trò tích hợp C và C++. Được tạo ra bởi Guido van Rossum tại Amsterdam
năm 1990. Python hoàn toàn tạo kiểu động và dùng cơ chế cấp phát bộ nhớ tự động. Python
được phát triển trong một dự án mã mở, do tổ chức phi lợi nhuận Python Software
Foundation quản lý. Phiên bản mới nhất của Python hiện tại (thời điểm viết bài) là bản
3.4.x.

7
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

Hình 2.4. Logo Python


Python là ngôn ngữ có hình thức khá đơn giản và rõ ràng, do đó tạo nên sự dễ dàng
tiếp cânh cho những lập trình viên mới bắt đầu.

Ban đầu, Python được phát triển để chạy trên nền Unix. Nhưng rồi theo thời gian,
nó đã "bành trướng" sang mọi hệ điều hành từ MS-DOS đến Mac OS, OS/2, Windows,
Linux và các hệ điều hành khác thuộc họ Unix. Mặc dù sự phát triển của Python có sự đóng
góp của rất nhiều cá nhân, nhưng Guido van Rossum hiện nay vẫn là tác giả chủ yếu của
Python. Ông giữ vai trò chủ chốt trong việc quyết định hướng phát triển của Python.

Một số tính chất của Python

Python is Interpreted: Nhờ chức năng thông dịch mà trình thông dịch (Interpreter) của
Python có thể xử lý lệnh tại thời điểm chạy chương trình (runtime). Nhờ đó mà ta không
cần biên dịch chương trình trước khi thực hiện nó (tương tự như Perl và PHP).

Python is Interactive: Tính năng tương tác của Python giúp ta có thể tương tác trực tiếp với
trình thông dịch của nó ngay tại dấu nhắc lệnh. Cụ thể: Ta có thể thực hiện lệnh một cách
trực tiếp tại dấu nhắc của Python.

Python is Object-Oriented: Python hỗ trợ mạnh cho phong cách lập trình hướng đối tương
và kỹ thuật lập trình gói mã trong đối tượng.

Python is a Beginner's Language: Mặc dầu Python được xem là ngôn ngữ lập trình dành
cho những ai mới làm quen với việc lập trình trên máy tính, nhưng nó hỗ trợ mạnh cho
việc phát triển nhiều loại ứng dụng khác nhau, từ các chương trình xử lý văn bản đơn giản
đến các ứng dụng web, đến các chương trình game,…

Tính năng
Python là một ngôn ngữ lập trình dễ học, dễ đọc. Python tăng cường sử dụng từ khóa
tiếng Anh, hạn chế các kí hiệu và cấu trúc cú pháp so với các ngôn ngữ khác.
Mã nguồn của Python là tương đối dễ để bảo trì và duy trì và có khả năng mở rộng.
Python có một tiêu chuẩn thư viện rộng, có nền tảng tương thích trên nhiều hệ điều hành
hiện nay như: UNIX, Windows, and Macintosh. Đây cũng là một trong những điểm mạnh
đáng kể của Python.
8
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

Python có thể được sử dụng như ngôn ngữ script, hoặc ngôn ngữ biên dịch, nhờ đó mà ta
có thể buil các chương trình lớn trên nó.
Khi chế độ Interactive, ta có thể nhập kết quả từ các đầu cuối khác nhau vào chương trình
Python,do đó mà việc test hay debug lỗi code trở nên đơn giản hơn.
Python cho phép người dùng tích hợp vào các module để có thể sử dụng trong các chương
trình khác. Nó cũng cung cấp sẵn một tập hợp các modules chuẩn mà lập trình viên có thể
sử dụng lại trong chương trình của họ. Các module này cung cấp nhiều chức năng hữu ích,
như các hàm truy xuất tập tin, các lời gọi hệ thống, trợ giúp lập trình mạng (socket),…
Python cung cấp giao diện cho tất cả các cơ sở dữ liệu thương mại lớn.

Có thế dễ dàng tích hợp với C, C++, COM, CORBA, ActiveX, Java.
2.5. Tương tác với cơ sở dữ liệu
Cơ sở dữ liệu là tập hợp dữ liệu được tổ chức có cấu trúc liên quan với nhau và được
lưu trữ trong máy tính.CSDL được thiết kế, xây dựng cho phép người dùng lưu trữ dữ liệu,
truy xuất thông tin hoặc cập nhật dữ liệu.CSDL được tổ chức có cấu trúc. Các dữ liệu được
lưu trữ có cấu trúc thành các bản ghi (record), các trường dữ liệu (field). Các dữ liệu lưu
trữ có mối quan hệ (relation) với nhauCSDL được cấu trúc để dễ dàng truy cập, quản lý và
cập nhật.

Hình 2.5. Ví dụ về 1 cơ sở dữ liệu.


Quản lý dữ liệu là quản lý một số lượng lớn dữ liệu, bao gồm cả việc lưu trữ và cung cấp
cơ chế cho phép Thao tác (thêm, sửa, xóa dữ liệu) và Truy vấn dữ liệu. Hai phương pháp
quản lý dữ liệu: Hệ thống quản lý bằng file và Hệ thống quản lý bằng CSDL

Quản lý dữ liệu bằng file

Dữ liệu được lưu trữ trong các file riêng biệt. Ví dụ: các chương trình lưu trữ thông
tin bằng hệ thống các file dạng text.
9
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

Nhược điểm của việc quản lý bằng file:

 Dư thừa và mâu thuẫn dữ liệu.


 Kém hiệu quả trong truy xuất ngẫu nhiên hoặc xử lý đồng thời.
 Dữ liệu lưu trữ rời rạc.
 Gặp vấn đề về an toàn và bảo mật

Quản lý dữ liệu bằng CSDL

Quản lý dữ liệu bằng CSDL giúp dữ liệu được lưu trữ một cách hiệu quả và có tổ
chức, cho phép quản lý dữ liệu nhanh chóng và hiệu quả.

Thao tác với dữ liệu

Sử dụng các câu lệnh SELECT,INSERT, UPDATE, DELETE để tương tác với dữ
liệu trong cơ sở dữ liệu.

2.6. Chip ST32F103C8T6

Hình 2.6. STM32F103C8T6 Pinout.

Thông số kỹ thuật:

 Chip STM32F103C8T6 có kích thước core: 32 bit (bộ xử lý 32 bit).


 Kích thước bộ nhớ lưu trữ chương bộ nhớ chương trình: 64kB và là kiểu bộ nhớ
FLASH.
 Kích thước RAM: 20K x 8.
 Số chân I/O: 37.

10
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

 Tốc độ 72Mhz.
 Hoạt động ở nhiệt độ từ - 40 đến 85 độ C.
 Liên kết: CAN, I&sup2;C, IrDA, LIN, SPI, UART/USART, USB.
 Ngoại vi: DMA, Motor Control PWM, PDR, POR, PVD, PWM, Temp Sensor, WDT.
 Nguồn cung cấp: 2.6 ~ 3.6V.
 Bộ ADC 12 bit.

Một số ưu nhược điểm của chip.

Ưu điểm:

 Giá rẻ.
 Nhỏ gọn.
 Siêu tiết kiệm điện.
 GPU mạnh.
 Phục vụ cho nhiều mục đích.
 Khả năng hoạt động liên tục 24/7.
 Khả năng debug chương trình mạnh. Vì sử dụng chuẩn nạp code JATG.
Nhược điểm:
 Không phù hợp với hệ thống lớn, phức tạp.
 Cấu hình còn thấp.
2.7. Module Joystick
Mạch điều khiển Joysticks được thiết kế để có thể giúp bạn điều khiển các thiết bị
theo mong muốn. Tương tự như trên các tay cầm game, nó sử dụng 2 biến trở trên 2 trục
X và Y, nhờ đó xuất mức điện áp đưa đến đầu vào analog của các vi điều khiển, nhờ đó dễ
dàng xử lý các tín hiệu này để điều khiển các thiết bị chấp hành theo mong muốn. Hơn nữa,
mạch Joystick còn cung cấp thêm 1 nút nhấn và có thể sử dụng nó với chức năng
accept/enter.

11
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

Hình 2.7. Module Joystick


Sơ đồ chân của module Joystick:
 5V: Chân cấp nguồn 5V.
 GND: Chân nối đất.
 VRX: Chân này trả về giá trị ADC trên trục x.
 VRY: Chân này trả về giá trị ADC trên trục y.
 SW: Trả về giá trị nút nhấn.
Thông số kỹ thuật:

 Kích thước: 34x27x35mm.


 5 chân kết nối.
 1 Nút nhấn.
 2 hướng điều khiển X và Y.
 Điện áp vào: 5V hoặc 3v3.

2.8. Module MPU6050

Hình 2.8. Module MPU6050.


Cảm biến GY-521 6DOF IMU MPU6050 được sử dụng để đo 6 thông số: 3 trục
Góc quay (Gyro), 3 trục gia tốc hướng (Accelerometer), là loại cảm biến gia tốc phổ biến
nhất trên thị trường hiện nay.

12
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

Sơ đồ chân của MPU6050:


 VCC: Chân cấp nguồn từ 3 – 5V.
 GND: Chân nối đất.
 SCL: Chân này có chức năng nhận xung clock từ phía bên Master.
 SDA: Chân này có chức năng truyền tải dữ liệu thông qua I2C.
 XDA (Auxiliary Serial Data), XCL (Auxiliary Serial Clock): Nó có thể được sử dụng
cho giao diện khác mô-đun I2C khác với MPU6050.
 AD0: Nếu có nhiều hơn một MPU6050 được sử dụng một MCU, thì pin này có thể
được sử dụng để thay đổi địa chỉ.
 INT: Chân này được sử dụng để chỉ ra rằng dữ liệu có sẵn để MCU đọc.
Thông tin kỹ thuật:
 Điện áp sử dụng: 3~5VDC.
 Điện áp giao tiếp: 3~5VDC.
 Chuẩn giao tiếp: I2C.
 Giá trị Gyroscopes trong khoảng: +/- 250 500 1000 2000 degree/sec.
 Giá trị Acceleration trong khoảng: +/- 2g, +/- 4g, +/- 8g, +/- 16g.
Chức năng: Trả về giá trị Accelerometer 3 trục x,y,z. Từ đó ta tính các góc nghiêng, và từ
các góc đó sẽ có những chuỗi lệnh truyền tương ứng đến máy tính. Chúng ta chỉ dùng đại
lượng gia tốc hướng (Accelerometer) còn đại lượng còn lại không dùng.

2.9. Mạch sạc TP4056

Hình 2.9. Mạch sạc TP4056


Mạch sạc pin Lithium TP4056 (1A) V2 là phiên bản nâng cấp của Mạch sạc pin
Lithium TP4056 (1A) thêm chức năng ngắt tải bảo vệ pin khi điện áp xuống quá thấp để
tránh làm hư hỏng pin (chai pin), mạch được sử dụng để sạc cho các loại pin Lithium có
điện áp 3.7~4.2VDC (Pin Lipo, Pin 18650,...), mạch có kích thước nhỏ gọn với cổng USB

13
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

kết nối tiện dụng, đèn báo đang sạc và sạc đầy hiển thị trạng thái pin, thích hợp cho các
ứng dụng sử dụng pin sạc: Robot, mạch cảm biến không dây,...

Sơ đồ chân của mạch sạc TP4056

 IN+,IN-: Là ngõ vào cấp nguồn từ 4.5 đến 8V.


 Cổng USB: Ngõ vào cấp nguồn 5VDC.
 B+,B-: Là ngõ ra dùng để sạc pin.
 OUT+,OUT-: Nối với tải.
Lưu ý: Khi cấp nguồn thì chỉ duy nhất sử dụng cổng INT+,INT- hoặc cổng USB không
được sử dụng cả 2.

Thông sỗ kỹ thuật:

 IC chính: TP4056
 Nguồn đầu vào:
o 4.5~8VDC: Chân nguồn vào + / -
o 5VDC qua cổng Micro USB.
 Nguồn sạc đầy: 4.2VDC
 Dòng sạc: 1A có thể biến đổi theo trạng thái pin.
 Chức năng ngắt tải bảo vệ pin khi điện áp xuống quá thấp để tránh làm hư hỏng pin
(chai pin).
 Đèn trạng thái sạc:
o Đèn đỏ: đang sạc, chưa đầy
o Đèn xanh lá: Đã sạc đầy.
 Kích thước: 17x22x5mm.
2.10. Module Bluetooth HC05

Hình 2.10. Module HC05

14
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

Bluetooth là chuẩn truyền thông không dây để trao đổi dữ liệu ở khoảng cách
ngắn.Chuẩn truyền thông này sử dụng sóng radio ngắn(UHF radio) trong dải tần số ISM
(2.4 tới 2.485 GHz). Khoảng cách truyền của module này vào khoảng 10m. Module này
được thiết kế dựa trên chip BC417. Con chip này khá phức tạp và sử dụng bộ nhớ flash
ngoài 8Mbit. Nhưng việc sử dụng module này hoàn toàn đơn giản bởi nhà sản xuất đã tích
hợp mọi thứ cho bạn trên module HC-05.

Sơ đồ chân của module gồm có:

 KEY: là chân chọn chế độ hoạt động ATMode hay DataMode.


 VCC: Chân này có thể cấp nguồn từ 3.6 – 6V bên trong module đã có IC nguồn chuyển
đổi về điện áp 3v3 cấp cho chip BC417.
 GND: Nối với chân GND.
 TXD, RXD: Đây là 2 chân UART dùng để giao tiếp hoạt động mức điện áp 3v3.
 STATE: Chân trạng thái, không quan tâm nên thả nổi.

Module thu phát bluetooth HC-05 dùng để thiết lập kết nối Serial giữa 2 thiết bị
bằng sóng bluetooth. Điểm đặc biệt của module bluetooth HC-05 là module có thể hoạt
động được ở 2 chế độ: MASTER hoặc SLAVE. Trong khi đó, bluetooth module HC-06
chỉ hoạt động ở chế độ SLAVE.

+ Ở chê độ SLAVE: bạn cần thiết lập kết nối từ smartphone, laptop, usb bluetooth để dò
tìm module sau đó pair với mã PIN là 1234. Sau khi pair thành công, bạn đã có 1 cổng
serial từ xa hoạt động ở baud rate 9600.

+ Ở chế độ MASTER: module sẽ tự động dò tìm thiết bị bluetooth khác (1 module


bluetooth HC-06, usb bluetooth, bluetooth của laptop...) và tiến hành pair chủ động mà
không cần thiết lập gì từ máy tính hoặc smartphone.

Thông số kỹ thuật:

 Điện áp hoạt động: 3.3 - 5V.


 Dòng điện khi hoạt động: khi Pairing 30 mA, sau khi pairing hoạt động truyền nhận
bình thường 8 mA.
 Baudrate UART có thể chọn được: 1200, 2400, 4800, 9600, 19200, 38400, 57600,
115200.
 Kích thước của module chính: 28 mm x 15 mm x 2.35 mm.

15
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

2.11. IC nguồn LM1117T 3v3

Hình 2.11. IC nguồnLM1117T.


Được sử dụng làm mạch ổn áp.

Sơ đồ chân của IC nguồn:

Hình 2.11.1. Sơ đồ chân

 INPUT: Chân cấp nguồn vào 5V.


 OUTPUT: Ngõ ra 3v3.
 GND: Nối đất.

Thông số kỹ thuật:

 Dải áp đầu vào nằm trong khoảng 4.25V – 5.25V.


 Áp đầu ra: 3v3.
 Công suất cực đại 5W.
 Dòng điện đầu ra cực đại 1,5A.
 Dải nhiệt độ hoạt động: 0 đến 125 độ.

16
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

CHƯƠNG 3 : THIẾT KẾ VÀ XÂY DỰNG HỆ THỐNG


Sau khi nhóm đã tìm hiểu một số khái niệm liên quan cần thiết, nhóm tiến hành thiết kế
và xây dựng phần cứng cũng như phần mềm.
3.1.Giới thiệu và tóm tắt
3.1.1. Yêu cầu chung của hệ thống
Với tiêu chi thiết kế, làm một tay cầm có thể chơi được nhiều loại game. Hệ thống
có các tính năng như sau:

 Tay cầm chơi game kết nối không dây.


 Tương tác với máy tính.
 Tốc độ xử lý nhanh, tiết kiệm năng lượng.
 Giá cả hợp lý.
 Kích thước nhỏ gọn.
 Chơi được nhiều loại game: nhập vai hành động, đua xe. Ví dụ: Samurai, Đấu
trường thú, Asphalt,…
 Có thể thiết lập được chức năng của mỗi nút trên tay cầm thông qua phần mềm.
 Lựa chọn thể loại game , hoặc xem lại thiết lập trước đó thông qua phần mềm kết
nối với cơ sở dữ liệu.

3.1.2. Đặc tả hệ thống


Với các yêu cầu của hệ thống trên nhóm đã tiến hành đề ra các phương án thiết kế
cho phần cứng như sau:
 Khối nguồn: cung cấp cho toàn bộ hệ thống.
 Khối giao tiếp: truyền tín hiệu điều khiển điến khối xự lý trung tâm.
 Khối xử lý trung tâm: đọc các giá trị từ các khối gaio tiếp và cảm biển sau đó gửi
qua máy tính xử lý thông qua khối truyền thông.
 Khối cảm biến: Gửi các giá trị góc nghiêng đến khối xử lý trung tâm
 Khối truyền thông: Gửi các dữ liệu từ khối cảm biến và khối giao tiếp đến máy
tính. Sau đó máy tính sẽ xử lý các dữ liệu thông qua driver.
Với các yêu cầu của hệ thống trên nhóm đã tiến hành đề ra các phương án thiết kế
cho phần mềm như sau:

17
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

 Sử dụng ngôn ngữ Python để lập trình phần mềm trên máy tính và chọn SQLite làm
cơ sở dữ liệu lưu trữ thông tin cấu hình game.
3.2.Sơ đồ khối

Hình 3.1. Sơ đồ khối của hệ thống.


 Khối nguồn: Cấp nguồn nuôi chip với cấp nguồn cho toàn bộ hệ thống.
 Khối xử lý trung tâm: Nhận dữ liệu truyền về từ khối cảm biến cũng như khối giao
tiếp sau đó truyền đến máy tính thông qua khối truyền thông.
Bộ vi xử lý cần phải đáp ứng các tiêu chuẩn: tiết kiệm năng lượng, thời gian nhanh,
kích thước nhỏ gọn, đáp ứng thời gian thực, chi phi thiết kế thiết kế thấp.

Vi điều khiển STM32F103C8T6 là họ vi điều khiển 32 bit với 64-128 Kb bộ nhớ


Flash, USB 2.0 full-speed, 2 bộ ADC và 9 giao diện kết nối.

Lõi : ARM 32 bit Cortex-M3 Tần số hoạt động lên tới 72 Mhz

ADC : 2×12 bit, tần số lấy mẫu 1Mhz DMA : Điều khiển 7 kênh DMA

Giao diện kết nối : 2xI2C, 3xUSART, 2xSPI, CAN, USB 2.0 full-speed.

+ Các thiết bị ngoại vi có thể được cấu hình một cách thích hợp. Lõi của bộ vi xử lý Cortex-
M3 được thiết kế để đáp ứng yêu cầu bộ nhớ tối thiểu, năng lượng tiêu thụ thấp và thiết kế
nhỏ gọn.

+ Tần số hoạt động lên tới 72 Mhz cho phép sử lý các tập lệnh nhanh chóng.

18
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

+ Bộ ADC của ARM có độ phân giải 12 bits tức là giá trị đọc về nằm trong khoảng 0 -

>2^12= 4096. (Độ phân giải PIC, AVR= 8/10 bits).

+ Có bộ DMA để đẩy cao thời gian truyền nhận.

+ Có nhiều chuẩn kết nối phù hợp trong việc phát triển cho hệ thống sau này.

8051 PIC AVR ARM

Bus Width 8 bit cho core 8/16/32- bit 8/32-bit Hầu như 32bit,
chuẩn số ít 64 bit

Chuẩn truyền UART, UART, UART, UART,


thông USART, SPI, USART, SPI, USART, SPI, USART, SPI,
I2C I2S, LIN, I2C, (AVR hỗ I2S, LIN,
CAN, trợ CAN, CAN,
ETHERNET ETHERNET) ETHERNET,
I2C, DSP, SAI,
IrDA

Tốc độ 12 clock/ chu 4 clock/ chu kỳ 1 clock/ chu kỳ 1 clock/ chu kỳ


kỳ lệnh lệnh lệnh lệnh

Bộ nhớ ROM, SRAM, FLASH, FLASH,


SRAM,FLASH FLASH SRAM, SDRAM,
EEPROM EEPROOM

ISA CLSC 1 vài tính năng RISC RISC


của RISC

Kiến trúc bộ Von Neumann Harvard Tùy chỉnh Havard tùy


nhớ chỉnh

Năng tương Trung bình Thấp Thấp Thấp


tiêu thụ

Chi phí Rất thấp Trung bình Trung bình Thấp

Bảng 3.2.1. So sánh các dòng vi xử lý.


Từ những lợi ích ở trên nhóm đã quyết định chọn ARM cụ thể hơn là chip
STM32F103C8T6 làm khối xử lý trung tâm.

19
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

 Khối cảm biến: Thu thập dữ liệu từ các cảm biến rồi gửi về khối xử lý trung tâm.
 Khối truyền thông:

CÔNG NGHỆ KHÔNG DÂY

Zigbee Bluetooth Wifi NFC

RF 868/915 MHz 2.4 GHz 2.4Ghz,5.8Ghz 13.56Mhz


Frequency – 2.4GHz
Data Rate 250 Kbits/s 723Kbit/s 11-105Mbits/s 100-420Kbit/s

Range 10-300m 10m 10-100m 1cm-10cm

Power Very Low Low High Very Low

Bảng 3.2.2. So sánh các công nghệ không dây.


 Wifi : Năng lượng tiêu thụ của nó cao, tốc độ truyền dữ liệu cao.
 NFC (Near-Field Communication: Công nghệ giao tiếp trường gần) là công nghệ kết
nối sử dụng cảm ứng từ để thực hiện kết nối giữa 2 thiết bị. Cái này loại vì khoảng cách
nó quá ngắn tối đa 10cm trên lý thuyết thực tế thì chỉ có 4cm chúng ta không thể chơi
game với khoảng cách đó.
 Zigbee vì tuy nó đáp ứng được yêu cầu đặt ra nhưng giá thành của zigbee cao hơn rất
nhiều so với Bluetooth. Một điểm nữa là tốc độ truyền dữ liệu của Bluetooth cao hơn
so với zigbee.
 Bluetooth. Nó đáp ứng được yêu cầu khoảng cách chơi game từ màn hình đến người
chơi game, giá thành phù hợp và công suất thấp.

 Chọn Bluetooth.
Nguyên lý hoạt động chung:

Bộ xử lý trung tâm sau khi nhận được dữ liệu được gửi về từ cảm biến,từ đó sẽ gửi
các chuỗi thông qua Bluetooth kết nối với máy tính, phần mềm trên máy tính sẽ tiến hành
so sánh nếu đúng là chuỗi gửi, thì tương ứng từng chuỗi sẽ xuất lệnh điều khiển tương ứng
với cấu hình game.

20
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

3.3.Thiết kế phần cứng


Theo sơ đồ khối ta sẽ thiết kế phần cứng bao gồm 6 phần:
 Khối xử lý trung tâm: Chip STM32F103C8T6.
 Khối cảm biến: MPU6050. .
 Khối giao tiếp: Nút nhấn, Joystick.
 Khối nguồn: Mạch sạc TP4056, IC nguồn LM117T, pinNokia.

3.3.1. Khối cảm biến


 Yêu cầu thiết kế
Cập nhật giá trị liên tục gia tốc góc.
Lựa chọn phần cứng
Để ứng dụng vào việc lấy các giá trị góc nghiêng nên nhóm đã chọn cảm biến
góc nghiêng MPU6050.
Kết nối với STM32F103C8T6
Cảm biến này có 7 chân nhưng chỉ sử dụng 4 chân: VCC, GND, SDA, SCL.
Các chân lần lượt nối vào chân VCC3v3, GND, PB6,PB7.
 Giải thích nguyên lý
Khi nghiêng tay cầm thì lập tức cảm biến sẽ trả về giá trị gia tốc góc 3 trục
từ 3 giá trị này dùng công thức tính ra các giá trị góc nghiêng.

3.3.2. Khối giao tiếp


 Yêu cầu thiết kế
Nút nhấn phải ăn có chống dội, Joystick trả về giá trị ADC liên tục khi sử
dụng.
 Lựa chọn phần cứng
Sử dụng nút nhấn 2 chân, và module Joystick.
 Kết nối
• Joystick: Có 4 chân VCC, GND, VRX, VRY. Trong đó 2 chân VRX
và VRY lần lượt nối vào 2 chân PA4 và PA5.

21
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

• Nút nhấn: Có 6 nút nhấn nối lần lượt nối vào các chân PA12, PA11,
PA10, PA9, PA8, PB15.
 Giải thích nguyên lý
• Joystick: Khi sử dụng sẽ trả về giá trị ADC trên 2 trục,bộ xử lý trung
tâm sẽ gửi các chuỗi lệnh tương ứng từ các giá trị này.
• Nút nhấn: Khi nhấn thì bộ xử lý trung tâm sẽ gửi chuỗi tương ứng
từng nút.

3.3.3. Khối nguồn


 Yêu cầu thiết kế
Phải có chức năng sạc.
 Lựa chọn phần cứng
Sử dụng mạch sạc TP4056 và IC nguồn LM1117T 3v3, pin Nokia.
 Giải thích nguyên lý
• Khi sạc: Dòng điện đi vào thông qua cổng USB, sau đó đi ra 2 chân
OUT+ và OUT-. OUT+ sẽ là ngõ ra chân INPUT của LM11177T ngõ ra
lúc này sẽ có điện áp là 3v3, điện áp nuôi chip cũng như các cảm biến.
• Khi không sạc: Dòng điện được lấy từ pin Nokia.

3.3.4. Khối xử lý trung tâm


 Yêu cầu thiết kế
Khối xử lý trung tâm được lập trình để:
 Giao tiếp với MPU6050 để lấy các giá trị gia tốc góc.
 Giao tiếp với module Bluetooth.
 Giao tiếp với Joystick và nút nhấn .
 Giao tiếp với led RGB.
Phương án lựa chọn

22
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

Để thực hiện được những công việc điều khiển như trên ta có thể sử dụng các loại vi
điều khiển như 8051, AVR, PIC… Tuy nhiên những dòng vi xử lý trên có bộ vi xử lý
thấp chỉ có 8bit cũng có thể xử lý được nhưng hiệu suất không cao.
Lựa chọn
Trong đề tài này ta sử dụng chip STM32F103C8T6 vì:
 chip STM32F103C8T6 hiện là đang là vi điều khiển được phát triển rộng rãi và sử
dụng phổ biến.
 chip STM32F103C8T6 tiết kiệm năng lượng.
 Tốc độ xử lý cao với bộ xử lý 32 bit.

3.4.Thiết kế phần mềm


3.4.1. Các thành phần
3.4.1.1. Giao diện
Được chia thành 3 frame: Frame_1, Frame_mid, Frame_2, tương đương với 3 cột
 Frame_1: 9 Label, 8 Entry , 1 ComboBox, 1 CheckBox.
• 9 Lable: LU, UP, UR, RIGHT, RD, DOWN, DL, LEFT định nghĩa cho các Entry.
• 8 Entry này người dùng có thể điền vào các ký tự mong muốn để thiết lập các
hướng cho JoyStick.
• 1 ComboBox: lựa chọn hiệu ứng Led trên bàn phím chơi game.
• 1 CheckBox :Tùy thuộc vào thể loại game mà người dùng có thể bật/tắt cảm biến
MPU6050,
 Frame_2: 7 nút nhấn, 8 Label, 6 Entry.
• 7 nút nhấn: 6 nút nhấn trên cùng được đặt tên BUTTON 1, BUTTON 2,…BUTTON
6 nhằm cho người dùng mô hình hóa nó là các nút nhấn trên KeyBoard game. Nút
nhấn còn lại được đặt tên SELECT GAME với mục đích lựa chọn thể loại game,
hoặc xem lại thiết lập trước đó bằng việc truy vấn trên SQLite.
• 8 Label : 2 Label(BUTTON, CHARACTER): định nghĩa các trường cho 6 Lable và
6 Entry ,6 Label còn lại được đặt tên BUTTON 1, BUTTON 2,…BUTTON 6 : nhằm
định nghĩa cho các 6 Entry sẽ được đề cập bên dưới đây.
• 6 Entry: Người dùng có thể điền vào các ký tự mong muốn để thiết lập các ký tự
cho 6 nút nhấn.

23
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

 Frame_mid: gồm các Label và 1 nút nhấn.


• Các Label với mục đích định nghĩa và hiện thị 2 thông số chính gồm thể loại game
và ngày giờ cập nhật được điều khiển bởi nút nhấn SELECT GAME ở Frame_2.
• 1 nút nhấn: được đặt tên UPDATE dùng để cập nhật các thiết đặt của người dùng
lên SQLite.

3.4.1.2. Database
Bảng trên gồm có hàng , 18 cột:
• Hàng chứa các thiết đặt của các game khác nhau
• 18 cột là các trường bao gồm: tên game(GAME),thời gian thiết đặt (TIME), hiệu ứng
led(LED), trạng thái MPU6050(MPU), các nút nhấn, các hướng của Joystick.
Lựa chọn:
Có rất nhiều hệ cơ sở dữ liệu nổi tiếng hiện tại như MSAccess, SQL Server, MySQL,
Oracle,…Ở đây đối với đề tài này chúng em cần đến database là chỉ để lưu trữ và cho phép
truy vấn các thiết lập cấu hình trong game nên không cần sử dụng đến các hệ cở sở dữ liệu
lớn chỉ cần sử dụng SQLite hoặc MSAccess là đủ. Nhóm quyết định chọn SQLite làm
database cho đề tài này.

Chức năng: Lưu trữ và cho phép truy vấn các thiết lập game.

3.4.2. Lưu đồ giải thuật phần mềm

24
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

Hình 3.2. Lưu đồ

25
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

Giải thích lưu đồ:


 Đầu tiên hởi tạo các thư viện hỗ trợ, khởi tạo các biến sử dụng trong chương trình.
Sau khi xây dựng kết nối bluetooth giữa máy tính và keyboard game , chúng ta sẽ
thiết kế giao diện front-end cho phần mềm thông qua thư viện Tkinter.
 Tạo Database để lưu trữ các thiết lập và sử dụng database để dùng hiện thị các thiết
lập cũ trước đó.
 Xác định data và xử lý: Khi keyboard game hoạt động, chúng sẽ gửi data -kí tự cho
Pc thông qua bluetooth . Lúc này nếu có kí tự của nút nhấn/joystic/MPU trên
keyboard game gửi về PC, hệ thống sử dụng Thread xác định các kí từ này và tự
động giả lập bàn phím trên PC dựa vào các thiết lập lưu trên Database.
 Thiêt lập game vào các Entry: lúc này chúng ta đã có giao diện, hệ thống sẽ cho
phép chúng ta nhập các kí tự mong muốn trên bàn phím bao gồm: joystic, button,
chế độ led, bật tắt MPU
 Nút SELECT: nếu chúng ta có nhấn nút SELECT trên giao diện thì hệ thống sẽ hiển
thị tên game mà chúng ta cần thiết lập và cũng cho phép chúng ta thiết lập vào các
Entry nếu muốn. Ngoài ra hệ thống cũng lưu trữ lịch sử thời gian thiết lập trước đó
được lấy từ Database và hiện thị trên lable ở Frame mid.
 Sau cùng là Nút UPDATE: Nút UPDATE sẽ cập nhật dữ liệu thiết đặt lên database.

26
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

CHƯƠNG 4: KẾT QUẢ THỰC HIỆN


4.1. Phần cứng
4.1.1. Các công cụ sử dụng
 Đồng hồ VOM.
 Chì hàn, mỏ hàn.
 Chuẩn bị các module có sẵn theo thiết kế.
 Chuẩn bị các linh kiện như sơ đồ nguyên lý.
 Chuẩn bị các phần mềm cần thiết.

4.1.2. Schematic
Sau khi thiết kế sơ đồ khối, sơ đồ nguyên lí toàn mạch ta tiến hành vẽ mạch in đã
thiết kế.

Hình 4.1.1. Schematic.

27
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

4.1.3. Mạch PCB


Từ schematic ở trên nhóm đã vẽ ra PCB.

Hình 4.1.2. PCB.


Mô hình hoàn thiện

Hình 4.1.3. Mô hình hoàn thiện.


4.2. Giao diện phần mềm trên máy tính

28
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

Hình 4.2. Giao diện phần mềm


4.3. Database

Hình 4.3. Giao diện database.

29
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

CHƯƠNG 5: KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN


5.1. Kết luận
Sau thời gian thực hiện đề tài đến nay nhóm đã hoàn thành các yêu cầu đặt ra, đã thiết
kế và thi công thành công tay cầm.

Hoàn thành đề tài này đã giúp cho nhóm nắm thêm được nhiều kiến thức bổ ích như:

 Hiểu về lập trình Arm.


 Hiểu thêm về các chuẩn và phương thức giao tiếp thường gặp với vi điều khiển như:
I2C, UART,…
 Hiểu thêm về ngôn ngữ Python.
 Nguyên lý hoạt động của cảm biến.
 Nâng cao khả năng hàn chip dán.
 Cách tương tác với cơ sở dữ liệu.

Bên cạnh đó do thời gian cũng như kiến thức còn hạn hẹp nên cũng không tránh khỏi
một số khuyết điểm như:
 Kỹ thuật hàn còn thấp.
 Bố trí chưa đẹp lắm.
 Tư duy viết code còn nhiều sai sót.

5.2. Hướng phát triển

Qua các khuyết điểm cần cải thiện được nêu ra đề tài có thể được phát triển theo các
hướng rộng hơn và hoàn thiện hơn như:

 Tích hợp, thay thế thêm nhiều cảm biến để nâng tính ổn định, thông minh cho hệ thống.
 Làm thêm các hiệu ứng cho đẹp sản phầm.
 Kết hợp thêm các tấm pin năng lượng mặt trời nhỏ để khi hết điện chỉ cần để ngoài
nắng là có thể tự động sạc được.

30
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

TÀI LIỆU THAM KHẢO


[1]. https://hocarm.org/serie-video-hoc-lap-trinh-arm-stm32f103/

[2]. Giáo trình “THỰC TẬP VI ĐIỀU KHIỂN PIC – Nguyễn Đình Phú” – Đại Học Sư
Phạm Kỹ Thuật Tp.HCM tháng 8/2015.

[3]. Giáo trình “VI XỬ LÝ NÂNG CAO STM32 – Thầy Phan Vân Hoàn” – Đại Học Sư
Phạm Kỹ Thuật Tp.HCM.

[4]. https://hocarm.org/hoc-rtos/

[5].https://advancecad.edu.vn/su-khac-biet-giua-vi-dieu-khien-avr-arm-8051-va-
pic/?fbclid=IwAR2lgZMCATRdsp9bRA2cu43O6WDil9Y3NumwrGH02tUfRd3rBC68o
khlwbg

31
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

PHỤ LỤC
Code điều khiển phần cứng.

#include "main.h"
#include "stm32f1xx_hal.h"
#include "cmsis_os.h"
#include "sd_hal_mpu6050.h"
#include "math.h"

ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;

I2C_HandleTypeDef hi2c1;
I2C_HandleTypeDef hi2c2;

UART_HandleTypeDef huart2;

osThreadId BUTTON_TASKHandle;
osThreadId JOYSTICK_TASKHandle;
osThreadId MPU6050_TASKHandle;
osThreadId RGB_TASKHandle;

uint8_t rx_buffer[100],rx_index=0,rx_data[2],Transfer_cplt,len,len1;
uint16_t ADC_value[2];
uint16_t x,y;
int stop = 0;
int sp = 0;
unsigned char buffer[100];
char Buffer[100];
SD_MPU6050 mpu1;
int16_t g_x,g_y,g_z,a_x,a_y,a_z;
int minVal=265;
int maxVal=402;
double rad_to_deg = 180/3.141592654;
double Acc_angle_x;
uint8_t data[14];

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_ADC1_Init(void);
static void MX_I2C1_Init(void);
static void MX_I2C2_Init(void);
void BUTTON(void const * argument);// TASK BUTTON
void JOYSTICK(void const * argument);// TASK JOYSTICK
void MPU6050(void const * argument);// TASKMPU6050
void RGB(void const * argument);//TASK LED RGB

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)


{
if(huart->Instance==USART2)
{

32
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

// Nếu dữ liệu không có, thì sẽ clear mảng buffer


if(rx_index==0)
{
for(int i=0;i<100;i++)
rx_buffer[i]=0;
}
if(rx_data[0]!=13)
rx_buffer[rx_index++]=rx_data[0];
else
{
rx_index=0;
Transfer_cplt=1;
}
HAL_UART_Receive_IT(&huart2,(uint8_t *)&rx_data,1);// Nhận
ký tự (chỉ duy nhất 1 lý tự 1 lần)
}
}

//TẠO HÀM ÁNH XẠ


uint16_t map(uint16_t x, uint16_t in_min, uint16_t in_max, uint16_t out_min,
uint16_t out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
/* USER CODE END 0 */

/**
* @brief The application entry point.
*
* @retval None
*/
int main(void)
{

HAL_Init();

SystemClock_Config();

MX_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
MX_ADC1_Init();
MX_I2C1_Init();
MX_I2C2_Init();

osThreadDef(BUTTON_TASK, BUTTON, osPriorityNormal, 0, 64);


BUTTON_TASKHandle = osThreadCreate(osThread(BUTTON_TASK), NULL);

/* definition and creation of JOYSTICK_TASK */


osThreadDef(JOYSTICK_TASK, JOYSTICK, osPriorityNormal, 0, 64);
JOYSTICK_TASKHandle = osThreadCreate(osThread(JOYSTICK_TASK), NULL);

/* definition and creation of MPU6050_TASK */


osThreadDef(MPU6050_TASK, MPU6050, osPriorityNormal, 0, 64);
MPU6050_TASKHandle = osThreadCreate(osThread(MPU6050_TASK), NULL);

/* definition and creation of RGB_TASK */

33
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

osThreadDef(RGB_TASK, RGB, osPriorityIdle, 0, 64);


RGB_TASKHandle = osThreadCreate(osThread(RGB_TASK), NULL);

osKernelStart();

while (1)
{ }

void SystemClock_Config(void)
{

RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;

/**Initializes the CPU, AHB and APB busses clocks


*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

/**Initializes the CPU, AHB and APB busses clocks


*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)


{
_Error_Handler(__FILE__, __LINE__);
}

PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

/**Configure the Systick interrupt time


*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

34
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

/**Configure the Systick


*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

/* SysTick_IRQn interrupt configuration */


HAL_NVIC_SetPriority(SysTick_IRQn, 15, 0);
}

/* ADC1 init function */


static void MX_ADC1_Init(void)
{

ADC_ChannelConfTypeDef sConfig;

/**Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 2;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

/**Configure Regular Channel


*/
sConfig.Channel = ADC_CHANNEL_4;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

/**Configure Regular Channel


*/
sConfig.Rank = ADC_REGULAR_RANK_2;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

/* I2C1 init function */


static void MX_I2C1_Init(void)
{

hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 0;

35
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

/* I2C2 init function */


static void MX_I2C2_Init(void)
{

hi2c2.Instance = I2C2;
hi2c2.Init.ClockSpeed = 400000;
hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c2.Init.OwnAddress1 = 0;
hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c2.Init.OwnAddress2 = 0;
hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

/* USART2 init function */


static void MX_USART2_UART_Init(void)
{

huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}

/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */

36
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

__HAL_RCC_DMA1_CLK_ENABLE();

/* DMA interrupt init */


/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

//CẤU HÌNH CHÂN


static void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/* GPIO Ports Clock Enable */


__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();

/*Configure GPIO pin Output Level */


HAL_GPIO_WritePin(GPIOB, G2_Pin|R2_Pin|B2_Pin|BT6_Pin
|G1_Pin|R1_Pin|B1_Pin, GPIO_PIN_RESET);

/*Configure GPIO pin Output Level */


HAL_GPIO_WritePin(GPIOA, BT5_Pin|BT4_Pin|BT3_Pin|BT2_Pin
|BT1_Pin, GPIO_PIN_RESET);

/*Configure GPIO pins : G2_Pin R2_Pin B2_Pin BT6_Pin


G1_Pin R1_Pin B1_Pin */
GPIO_InitStruct.Pin = G2_Pin|R2_Pin|B2_Pin|BT6_Pin
|G1_Pin|R1_Pin|B1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/*Configure GPIO pins : BT5_Pin BT4_Pin BT3_Pin BT2_Pin


BT1_Pin */
GPIO_InitStruct.Pin = BT5_Pin|BT4_Pin|BT3_Pin|BT2_Pin
|BT1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

//BUTTON

void BUTTON(void const * argument)


{
for(;;)
{
// KIỂM TRA NHẤN PHÍM
if(!HAL_GPIO_ReadPin(BT1_GPIO_Port,BT1_Pin))

37
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

{
//CHỐNG DỘI
osDelay(30);
if(!HAL_GPIO_ReadPin(BT1_GPIO_Port,BT1_Pin)) // TIẾP TỤC KIẾM TRA
NHẤN PHÍM
{
// NẾU CÓ NHẤN THÌ TIẾN HÀNH ĐƯA CHUỖI "1U" VÀO MẢNG BUFFER
//HÀM SPRINTF CHỨC NĂNG TRẢ VỀ SỐ KÝ TỰ TRONG MẢNG BUFFER
TỨC ĐỘ DÀI CỦA CHUỖI TRUYỀN
len1 = sprintf((char *)Buffer, "1U|");
//TRUYỀN MẢNG BUFFER CHỨA CHUỖI ĐIỀU KHIỂN
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
// CHỞ NHÀ NÚT NHẤN
while(!HAL_GPIO_ReadPin(BT1_GPIO_Port,BT1_Pin))
{
osDelay(1);
}
// SAU KHI NHẢ NÚT THÌ LƯU CHUỖI "1D" VÀO MẢNG
len1 = sprintf((char *)Buffer, "1D|");
//TRUYỀN MẢNG BUFFER CHỨA CHUỖI "1D"
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
}
}
//TƯƠNG TỰ CHO CÁC NÚT NHẤN CÒN LẠI
else if(!HAL_GPIO_ReadPin(BT2_GPIO_Port,BT2_Pin))
{
osDelay(30);
if(!HAL_GPIO_ReadPin(BT2_GPIO_Port,BT2_Pin))
{
len1 = sprintf((char *)Buffer, "2U|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
while(!HAL_GPIO_ReadPin(BT2_GPIO_Port,BT2_Pin))
{
osDelay(1);
}
len1 = sprintf((char *)Buffer, "2D|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
}
}
////
else if(!HAL_GPIO_ReadPin(BT3_GPIO_Port,BT3_Pin))
{
osDelay(30);
if(!HAL_GPIO_ReadPin(BT3_GPIO_Port,BT3_Pin))
{
len1 = sprintf((char *)Buffer, "3U|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
while(!HAL_GPIO_ReadPin(BT3_GPIO_Port,BT3_Pin))
{
osDelay(1);
}
len1 = sprintf((char *)Buffer, "3D|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
}
}
/////
else if(!HAL_GPIO_ReadPin(BT3_GPIO_Port,BT3_Pin))

38
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

{
osDelay(30);
if(!HAL_GPIO_ReadPin(BT2_GPIO_Port,BT2_Pin))
{
len1 = sprintf((char *)Buffer, "3U|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
while(!HAL_GPIO_ReadPin(BT2_GPIO_Port,BT2_Pin))
{
osDelay(1);
}
len1 = sprintf((char *)Buffer, "3D|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
}
}
/////
else if(!HAL_GPIO_ReadPin(BT4_GPIO_Port,BT4_Pin))
{
osDelay(30);
if(!HAL_GPIO_ReadPin(BT4_GPIO_Port,BT4_Pin))
{
len1 = sprintf((char *)Buffer, "4U|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
while(!HAL_GPIO_ReadPin(BT4_GPIO_Port,BT4_Pin))
{
osDelay(1);
}
len1 = sprintf((char *)Buffer, "4D|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
}
}
/////
else if(!HAL_GPIO_ReadPin(BT5_GPIO_Port,BT5_Pin))
{
osDelay(30);
if(!HAL_GPIO_ReadPin(BT5_GPIO_Port,BT5_Pin))
{
len1 = sprintf((char *)Buffer, "5U|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
while(!HAL_GPIO_ReadPin(BT5_GPIO_Port,BT5_Pin))
{
osDelay(1);
}
len1 = sprintf((char *)Buffer, "5D|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
}
}
/////
else if(!HAL_GPIO_ReadPin(BT6_GPIO_Port,BT6_Pin))
{
osDelay(30);
if(!HAL_GPIO_ReadPin(BT6_GPIO_Port,BT6_Pin))
{
len1 = sprintf((char *)Buffer, "6U|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
while(!HAL_GPIO_ReadPin(BT6_GPIO_Port,BT6_Pin))
{
osDelay(1);

39
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

}
len1 = sprintf((char *)Buffer, "6D|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
}
}
osDelay(1);
}
/* USER CODE END 5 */
}

//JOYSTICK
void JOYSTICK(void const * argument)
{
/* USER CODE BEGIN JOYSTICK */
/* Infinite loop */
for(;;)
{
//ĐỌC GIÁ TRỊ ADC GỬI VỀ TỪ JOYSTICK
/**
* @param hadc: hadc1 VÌ SỬ DỤNG BỘ ADC1
@param pData: NƠI LƯU TRỮ DỮ LIỆU ĐỌC VỀ, Ở ĐÂY LÀ ĐỊA CHỈ MẢNG
ADC_value
@param length: ĐỘ DÀI DỮ LIỆU ĐƯỢC TRUYỀN VỀ TỪ ADC NGOẠI VI ĐẾN
BỘ NHỚ CHIP
*/

HAL_ADC_Start_DMA(&hadc1,(uint32_t*)&ADC_value,2);
osDelay(30);
//KẾT THÚC QUÁ TRÌNH ĐỌC ADC
HAL_ADC_Stop_DMA(&hadc1);
// GIÁ TRỊ ADC TRỤC X SẼ ĐƯỢC LƯU VÀO PHẦN TỬ ĐẦU TIÊN CỦA MẢNG
ADC_value
y = ADC_value[0];
// GIÁ TRỊ ADC TRỤC X SẼ ĐƯỢC LƯU VÀO PHẦN TỬ TH Ứ 2 CỦA MẢNG
ADC_value
x = ADC_value[1];
// SỬ DỤNG HÀM MAP ĐỂ CHUYỂN ĐỔI GIÁ TRỊ TỪ 0 ĐẾN 1023 THÀNH 0 ĐẾN
3200
x=map(x,0,1023,0,3200);
x=map(y,0,1023,0,3200);
// NẾU x>3000
if (x > 3000)
//TIẾP TỤC KIỂM TRA NẾU y>3000
if (y > 3000)
{
//LƯU CHUỖI "DR" VÀO TRONG MẢNG buffer TRẢ VỀ ĐỘ DÀI
CHUỖI LƯU TRONG BIẾN len1
len1 = sprintf((char *)Buffer, "DR|");
// TRUYỀN CUỖI ĐÓ
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1,
1000);
stop= 0;
}
//TƯƠNG TỰ CHO CÁC TRƯỜNG HỢP CÒN LẠI
else if (y<1000)
{

40
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

len1 = sprintf((char *)Buffer, "UR|");


HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1,
1000);
stop= 0;
}
else
{
len1 = sprintf((char *)Buffer, "RT|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1,
1000);
stop= 0;
}
else if (x < 1000)
if (y > 3000)
{
len1 = sprintf((char *)Buffer, "DL|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1,
1000);
stop= 0;
}
else if (y<1000)
{
len1 = sprintf((char *)Buffer, "UL|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1,
1000);
stop= 0;
}
else
{
len1 = sprintf((char *)Buffer, "LT|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1,
1000);
stop= 0;
}
else
if (y > 3000)
{
len1 = sprintf((char *)Buffer, "DW|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
stop= 0;
}
else if (y<1000)
{
len1 = sprintf((char *)Buffer, "UP|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
stop= 0;
}
// NGƯỢC LẠI THÌ DỪNG
else
{

if (stop == 0)
{
stop = 1;
len1 = sprintf((char *)Buffer, "ST|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1,
1000);

41
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

}
}
osDelay(1);
}
/* USER CODE END JOYSTICK */
}

//MPU6050
void MPU6050(void const * argument)
{
/* USER CODE BEGIN MPU6050 */
/* Infinite loop */
for(;;)
{

osDelay(2);

SD_MPU6050_ReadTemperature(&hi2c1,&mpu1);
float temper = mpu1.Temperature;
//ĐỌC GIÁ TRỊ GÓC QUAY VÀ LƯU VÀO 3 BIẾN TƯƠNG ỨNG VỚI 3 TRỤC
SD_MPU6050_ReadGyroscope(&hi2c1,&mpu1);
g_x = mpu1.Gyroscope_X;
g_y = mpu1.Gyroscope_Y;
g_z = mpu1.Gyroscope_Z;

SD_MPU6050_ReadAccelerometer(&hi2c1,&mpu1);
//ĐỌC GIÁ TRỊ GIA TỐC GÓC VÀ LƯU VÀO 3 BIẾN TƯƠNG ỨNG VỚI 3 TRỤC
a_x = mpu1.Accelerometer_X;
a_y = mpu1.Accelerometer_Y;
a_z = mpu1.Accelerometer_Z;
// TỪ 3 GIÁ TRỊ NÀY TÍNH RA GÓC NGHIÊNG
Acc_angle_x = (atan((a_y)/sqrt(pow((a_x),2) +
pow((a_z),2)))*rad_to_deg);
//KIỂM TRA NẾU GÓC NGHIÊNG LỚN HƠN 30 ĐỘ THÌ TRUYỀN CHUỖI ĐIỀU KHIỂN RP
if (Acc_angle_x > 30)
{
len1 = sprintf((char *)Buffer, "RP|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
sp = 1;
}
//KIỂM TRA NẾU GÓC NGHIÊNG NHỎ HƠN -30 ĐỘ THÌ TRUYỀN CHUỖI ĐIỀU
KHIỂN LP
else if (Acc_angle_x <-30)
{
len1 = sprintf((char *)Buffer, "LP|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
sp =1;
}
//NGƯỢC LẠI THÌ DỪNG
else
{
if(sp==1)
{
len1 = sprintf((char *)Buffer, "SP|");
HAL_UART_Transmit(&huart2, (uint8_t*)Buffer, len1, 1000);
sp = 0;

42
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

}
}
}
}
/* USER CODE END MPU6050 */

//LED RGB
void RGB(void const * argument)
{
/* USER CODE BEGIN RGB */
/* Infinite loop */
for(;;)
{
HAL_GPIO_WritePin(GPIOB,R1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,G1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,B1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,R2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,G2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,B2_Pin,GPIO_PIN_SET);
osDelay(500);

HAL_GPIO_WritePin(GPIOB,R1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,G1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,B1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,R2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,G2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,B2_Pin,GPIO_PIN_SET);
osDelay(500);

HAL_GPIO_WritePin(GPIOB,R1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,G1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,B1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,R2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,G2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,B2_Pin,GPIO_PIN_RESET);
osDelay(500);

HAL_GPIO_WritePin(GPIOB,R1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,G1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,B1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,R2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,G2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,B2_Pin,GPIO_PIN_RESET);
osDelay(500);

HAL_GPIO_WritePin(GPIOB,R1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,G1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,B1_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,R2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,G2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,B2_Pin,GPIO_PIN_SET);
osDelay(500);

HAL_GPIO_WritePin(GPIOB,R1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,G1_Pin,GPIO_PIN_SET);

43
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

HAL_GPIO_WritePin(GPIOB,B1_Pin,GPIO_PIN_RESET);

HAL_GPIO_WritePin(GPIOB,R2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,G2_Pin,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB,B2_Pin,GPIO_PIN_RESET);
osDelay(500);

HAL_GPIO_WritePin(GPIOB,R1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,G1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,B1_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,R2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,G2_Pin,GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB,B2_Pin,GPIO_PIN_RESET);
osDelay(500);
}
/* USER CODE END RGB */
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)


{
/* USER CODE BEGIN Callback 0 */

/* USER CODE END Callback 0 */


if (htim->Instance == TIM4) {
HAL_IncTick();
}

void _Error_Handler(char *file, int line)


{

while(1)
{
}
/* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT

void assert_failed(uint8_t* file, uint32_t line)


{

}
#endif /* USE_FULL_ASSERT */

Chương trình phần mềm trên máy tính

from tkinter import *


import calendar
import time
from tkinter.ttk import Combobox
import sqlite3
from threading import Thread

44
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

import pyautogui
import serial

bt1 = 0
bt2 = 0
bt3 = 0
bt4 = 0
bt5 = 0
bt6 = 0
bt_up = 0
bt_down = 0
bt_right = 0
bt_left = 0
up ='W'
right ='D'
down ='S'
left='A'
command = ""
val_btn1 = 'U'
val_btn2 = 'I'
val_btn3 = 'O'
val_btn4 = 'J'
val_btn5 = 'K'
val_btn6 = 'L'
val_RP='right'
val_LP='left'
RP=0
LP=0

def doSomething():

global bt1,bt2,bt3,bt4,bt5,bt6,bt_down,bt_left
global bt_right,bt_up
global up,right,down,left
global val_btn1,val_btn2,val_btn3,val_btn4,val_btn5,val_btn6
global val_LP,val_RP
global command
global LP,RP

sr = serial.Serial('com8',baudrate=115200,parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS,timeout=0)
time.sleep(3)
while(True):
#try:
#

a = sr.read().decode('utf-8')
command = command + a
if (a == '|'):
print(command[0:len(command)-1])
command = command[0:len(command)-1]
#Button1 nhấn
if(command == "1U" ):
if(bt1 == 0):
pyautogui.keyDown(val_btn1) #Holds down the val_btn1
key
bt1 = 1;

45
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

#Button1 nhả
elif(command == "1D" ):
if(bt1 == 1):
pyautogui.keyUp(val_btn1) #Lets go of the val_btn1
key
bt1 =0;

#Button2 nhấn
elif(command == "2U" ):
if(bt2 == 0):
pyautogui.keyDown(val_btn2)
bt2 = 1;
#Button2 nhả
elif(command == "2D" ):
if(bt2 == 1):
pyautogui.keyUp(val_btn2)
bt2 =0;

#Button3 nhấn
elif(command == "3U" ):
if(bt3 == 0):
pyautogui.keyDown(val_btn3)
bt3 = 1;
#Button3 nhả
elif(command == "3D" ):
if(bt3 == 1):
pyautogui.keyUp(val_btn3)
bt3 =0;

#Button4 nhấn
elif(command == "4U" ):
if(bt4 == 0):
pyautogui.keyDown(val_btn4)
bt4 = 1;
#Button4 nhả
elif(command == "4D" ):
if(bt4 == 1):
pyautogui.keyUp(val_btn4)
bt4 =0;

#Button5 nhấn
elif(command == "5U" ):
if(bt5 == 0):
pyautogui.keyDown(val_btn5)
bt5 = 1;
#Button5 nhả
elif(command == "5D" ):
if(bt5 == 1):
pyautogui.keyUp(val_btn5)
bt5 =0;

#Button6 nhấn
elif(command == "6U" ):
if(bt6 == 0):
pyautogui.keyDown(val_btn6)
bt6 = 1;
#Button6 nhả

46
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

elif(command == "6D" ):
if(bt6 == 1):
pyautogui.keyUp(val_btn6)
bt6 =0;
#Joystick UP
elif(command == "UP"):
if(bt_up == 0 ):
pyautogui.keyDown(up)
bt_up = 1
if(bt_left==1):
pyautogui.keyUp(left)
bt_left = 0
if(bt_right == 1):
pyautogui.keyUp(right)
bt_right = 0
if(bt_down == 1):
pyautogui.keyUp(down)
bt_down = 0
#Joystick DOWN
elif(command == "DW"):
if(bt_down == 0 ):
pyautogui.keyDown(down)
bt_down = 1
if(bt_left==1):
pyautogui.keyUp(left)
bt_left = 0
if(bt_right == 1):
pyautogui.keyUp(right)
bt_right = 0
if(bt_up==1):
pyautogui.keyUp(up)
bt_up = 0
#Joystick RIGHT
elif(command == "RT"):
if(bt_right == 0 ):
pyautogui.keyDown(right)
bt_right = 1
if(bt_up==1):
pyautogui.keyUp(up)
bt_up = 0
if(bt_down == 1):
pyautogui.keyUp(down)
bt_down = 0
if(bt_left==1):
pyautogui.keyUp(left)
bt_left = 0
#Joystick LEFT
elif(command == "LT"):
if(bt_left == 0 ):
pyautogui.keyDown(left)
bt_left = 1
if(bt_up==1):
pyautogui.keyUp(up)
bt_up = 0
if(bt_down == 1):
pyautogui.keyUp(down)
bt_down = 0

47
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

if(bt_right == 1):
pyautogui.keyUp(right)
bt_right = 0
#Joystick DOWN + LEFT
elif(command == "DL"):
if(bt_left == 0 ):
pyautogui.keyDown(left)
bt_left = 1
if(bt_down == 0 ):
pyautogui.keyDown(down)
bt_down = 1
if(bt_up==1):
pyautogui.keyUp(up)
bt_up = 0
if(bt_right == 1):
pyautogui.keyUp(right)
bt_right = 0
#Joystick UP + LEFT
elif(command == "UL"):
if(bt_left == 0 ):
pyautogui.keyDown(left)
bt_left = 1
if(bt_up == 0 ):
pyautogui.keyDown(up)
bt_up = 1
if(bt_down==1):
pyautogui.keyUp(down)
bt_down = 0
if(bt_right == 1):
pyautogui.keyUp(right)
bt_right = 0
#Joystick UP + RIGHT
elif(command == "UR"):
if(bt_right == 0 ):
pyautogui.keyDown(right)
bt_right = 1
if(bt_up == 0 ):
pyautogui.keyDown(up)
bt_up = 1
if(bt_down==1):
pyautogui.keyUp(down)
bt_down = 0
if(bt_left == 1):
pyautogui.keyUp(left)
bt_left = 0
#Joystick DOWN + RIGHT
elif(command == "DR"):
if(bt_right == 0 ):
pyautogui.keyDown(right)
bt_right = 1
if(bt_down == 0 ):
pyautogui.keyDown(down)
bt_down = 1
if(bt_up==1):
pyautogui.keyUp(up)
bt_up = 0
if(bt_left == 1):

48
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

pyautogui.keyUp(left)
bt_left = 0
#Joystick do nothing
elif(command == "ST"):
if(bt_right == 1):
pyautogui.keyUp(right)
bt_right = 0
if(bt_down==1):
pyautogui.keyUp(down)
bt_down = 0
if(bt_up==1):
pyautogui.keyUp(up)
bt_up = 0
if(bt_left == 1):
pyautogui.keyUp(left)
bt_left = 0
#MPU sensor right
elif(command == "RP"):
if(RP == 0):
pyautogui.keyDown(val_RP)
RP = 1
if(LP == 1):
pyautogui.keyUp(val_LP)
LP = 0
#MPU sensor left
elif(command == "LP"):
if(LP == 0):
pyautogui.keyDown(val_LP)
LP = 1
if(RP == 1):
pyautogui.keyUp(val_RP)
RP = 0
#MPU sensor stop
elif(command == "SP"):
if(RP == 1):
pyautogui.keyUp(val_RP)
RP = 0
if(LP == 1):
pyautogui.keyUp(val_LP)
LP = 0

command = ""
#except:
# print("error")
# time.sleep(1)
def runThread():
myThread = Thread(target=doSomething)
myThread.start()

runThread()
root = Tk()
root.title("DRIVER GAME") # Đat ten cho cua so
root.resizable(height=True,width=True) # cho phep thay doi chieu rong va
chieu cao cua cua so
root.minsize(height=545,width=880) #xat chieu cao, chieu rong cua so
root.update_idletasks()
width = root.winfo_width()

49
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

height = root.winfo_height()
x = (root.winfo_screenwidth() // 2) - (width // 2)
y = (root.winfo_screenheight() // 2) - (height // 2)
root.geometry('{}x{}+{}+{}'.format(width, height, x, y))
Label(root,text="SAVE MY WORLD",bg="#009896",font="NONE 15").pack(fill=X)

#lựa chọn game đã được thiết lập và hiển thị cài đặt( mặc đinh ban đầu hoặc lần
cập nhật sau cùng)
def customizeGame():
global game,var1
game = game + 1
lable_blu_2 = Label(frame_mid, width="11", height="3", bg="#A1C1DA")
lable_blu_2.grid(row=6, column=2, sticky="WE")
if game == 1:
lable_blu_2["text"] = "LOL"
var1=IntVar(value=1)
elif game == 2:
lable_blu_2["text"] = "FIFA"
var1 = IntVar(value=1)
elif game == 3:
lable_blu_2["text"] = "SAMURAI"
var1 = IntVar(value=1)
elif game == 4:
lable_blu_2["text"] = "RACING"
var1 = IntVar(value=0)
elif game == 5:
game = 0
Checkbutton(frame_1, text="IS MPU ACTIVE ?", height="3", width="45",
variable=var1, bg="#A1C1DA").place(x=0,y=320)
if lable_blu_2["text"]== "LOL":
conn = sqlite3.connect('tutorial_rac26_1.db')
c = conn.cursor()
c.execute(
"SELECT
GAME,TIME,LED,MPU,BUTTON1,BUTTON2,BUTTON3,BUTTON4,BUTTON5,BUTTON6"
",LEFT_UP,UP,UP_RIGHT,RIGHT,RIGHT_DOWN,DOWN,DOWN_LEFT,LEFT from
stuffToPlot where GAME='LOL'")
elif lable_blu_2["text"]== "FIFA":
conn = sqlite3.connect('tutorial_rac26_1.db')
c = conn.cursor()
c.execute(
"SELECT
GAME,TIME,LED,MPU,BUTTON1,BUTTON2,BUTTON3,BUTTON4,BUTTON5,BUTTON6"
",LEFT_UP,UP,UP_RIGHT,RIGHT,RIGHT_DOWN,DOWN,DOWN_LEFT,LEFT from
stuffToPlot where GAME='FIFA'")
elif lable_blu_2["text"] == "SAMURAI":
conn = sqlite3.connect('tutorial_rac26_1.db')
c = conn.cursor()
c.execute(
"SELECT
GAME,TIME,LED,MPU,BUTTON1,BUTTON2,BUTTON3,BUTTON4,BUTTON5,BUTTON6"
",LEFT_UP,UP,UP_RIGHT,RIGHT,RIGHT_DOWN,DOWN,DOWN_LEFT,LEFT from
stuffToPlot where GAME='SAMURAI'")
elif lable_blu_2["text"] == "RACING":
conn = sqlite3.connect('tutorial_rac26_1.db')
c = conn.cursor()
c.execute(

50
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

"SELECT
GAME,TIME,LED,MPU,BUTTON1,BUTTON2,BUTTON3,BUTTON4,BUTTON5,BUTTON6"
",LEFT_UP,UP,UP_RIGHT,RIGHT,RIGHT_DOWN,DOWN,DOWN_LEFT,LEFT from
stuffToPlot where GAME='RACING'")
for row in c:
entry_btn1.delete(0, END) # xóa ki tự trong ô entry
entry_btn1.insert(0,row[4]) #btn1 # chèn giá
trị chứa trong row vào entry
entry_btn2.delete(0, END)
entry_btn2.insert(0,row[5]) #btn2
entry_btn3.delete(0, END)
entry_btn3.insert(0,row[6]) ##btn3
entry_btn4.delete(0, END)
entry_btn4.insert(0,row[7]) #btn4
entry_btn5.delete(0, END)
entry_btn5.insert(0,row[8]) #btn5
entry_btn6.delete(0, END)
entry_btn6.insert(0,row[9]) #btn6
entry_1.delete(0,END)
entry_1.insert(0,row[10]) #lu
entry_2.delete(0, END)
entry_2.insert(0, row[11]) #up
entry_3.delete(0, END)
entry_3.insert(0, row[12]) #ur
entry_4.delete(0, END)
entry_4.insert(0, row[13]) #right
entry_5.delete(0, END)
entry_5.insert(0, row[14]) #rd
entry_6.delete(0, END)
entry_6.insert(0, row[15]) #down
entry_7.delete(0, END)
entry_7.insert(0, row[16]) #DL
entry_8.delete(0, END)
entry_8.insert(0, row[17]) #LEFT

# hiệu ứng led tương ứng với mỗi biến


def ledeffect():
global port,led
port=combo.get()
if port == "ĐỎ":
led=1
elif port == "CAM":
led=2
elif port == "VÀNG":
led=3
elif port == "LỤC":
led=4
elif port == "LAM":
led=5
elif port == "CHÀM":
led=6
elif port == "TÍM":
led=7
elif port == "TRẮNG":
led=8
elif port == "ĐỔI MÀU":
led=9

51
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

elif port == "TẮT LED":


led=10
# Hàm này để tạo in các
#1. 6 biến button , 8 biến joystick, 1 biến port các giá trị của port
tùy thuộc vào mình chọn trong giao diện
#2. tạo database, lưu dữ liệu trên sqlite
def fn2():
#xủ lý trên fram_mid
global val_btn1, val_btn2, val_btn3, val_btn4, val_btn5,
val_btn6,tmp,port,led
localtime = time.asctime(time.localtime(time.time()))
lable_blu_6["text"] = localtime
#xử lý trên frame_2
val_btn1 = entry_btn1.get()
val_btn2 = entry_btn2.get()
val_btn3 = entry_btn3.get()
val_btn4 = entry_btn4.get()
val_btn5 = entry_btn5.get()
val_btn6 = entry_btn6.get()
print("BUTTON 1 =",val_btn1)
print("BUTTON 2 =",val_btn2)
print("BUTTON 3 =",val_btn3)
print("BUTTON 4 =",val_btn4)
print("BUTTON 5 =",val_btn5)
print("BUTTON 6 =",val_btn6)
#Xử lý trên frame_1

lu = entry_1.get()
up = entry_2.get()
ur = entry_3.get()
right = entry_4.get()
rd = entry_5.get()
down = entry_6.get()
dl = entry_7.get()
left = entry_8.get()
port= combo.get()
ledeffect()
print("LU = ", lu)
print("UP = ", up)
print("UR = ", ur)
print("RIGHT = ", right)
print("RD = ", rd)
print("DOWN = ", down)
print("DL = ", dl)
print("LEFT = ", left)
print("port, LED :" ,port,led)
print("var1 = ",str(var1.get()))
# database
conn = sqlite3.connect('tutorial_rac26_1.db')
c = conn.cursor()
c.execute(
"CREATE TABLE IF NOT EXISTS stuffToPlot(GAME TEXT,TIME TEXT,LED
TEXT,MPU TEXT,BUTTON1 TEXT,BUTTON2 TEXT,BUTTON3 TEXT,BUTTON4 TEXT,BUTTON5
TEXT,BUTTON6 TEXT,LEFT_UP TEXT,UP TEXT,UP_RIGHT TEXT,RIGHT TEXT,RIGHT_DOWN
TEXT,DOWN TEXT,DOWN_LEFT TEXT,LEFT TEXT)")
# cập nhật giá trị cho bảng
if (game == 1):

52
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

nameofgame = 'LOL'
elif(game == 2):
nameofgame = 'FIFA'
elif (game == 3):
nameofgame = 'SAMURAI'
elif (game == 4):
nameofgame = 'RACING'
c.execute("UPDATE stuffToPlot set
TIME='"+localtime+"',LED='"+port+"',MPU='"+str(var1.get())+"',BUTTON1 =
'"+val_btn1+"',BUTTON2 = '"+val_btn2+"',BUTTON3 = '"+val_btn3+"',BUTTON4 =
'"+val_btn4+"',BUTTON5 = '"+val_btn5+"',BUTTON6 =
'"+val_btn6+"',LEFT_UP='"+lu+"',UP = '"+up+"',UP_RIGHT='"+ur+"',RIGHT =
'"+right+"',RIGHT_DOWN = '"+rd+"',DOWN = '"+down+"',DOWN_LEFT = '"+dl+"',LEFT
= '"+left+"' where GAME = '"+nameofgame+"'")

conn.commit()

# tạo các frame


frame_1 = Frame(root, width=400, height=100,bg="white")
frame_1.pack(side=LEFT,fill=Y)
frame_mid = Frame(root, width=200, height=20, bg="white")
frame_mid.pack(side=LEFT, fill=Y)
frame_2= Frame(root, width=200, height=20,bg="white")
frame_2.pack(side=LEFT,fill=Y)

#khai báo các biến global


val_btn1=""
val_btn2=""
val_btn3=""
val_btn4=""
val_btn5=""
val_btn6=""
game=1
port=StringVar()
led=0
localtime = time.asctime( time.localtime(time.time()))

#sử dung combobox de chon thể loai game


#v = ["LOL","BUBG","FIFA","SAMURAI"]
#combo = Combobox(frame_mid, values=v, width=12)
#combo.set("select")
#combo.grid(row=7, column=2, sticky="WESN")

# tạo các Label, Entry cho fram_2


label_btn =Label(frame_2,text=" BUTTON
",bg="orange").grid(row=4,column=0)
label_select = Label(frame_2, text=" CHARACTER ",bg="orange").grid(row=4,
column=1)
lable_btn1 = Label(frame_2, text="BUTTON 1").grid(row=5,column=0)
lable_btn2 = Label(frame_2, text="BUTTON 2").grid(row=6, column=0)
lable_btn3 = Label(frame_2, text="BUTTON 3").grid(row=7, column=0)
lable_btn4 = Label(frame_2, text="BUTTON 4").grid(row=8, column=0)
lable_btn5 = Label(frame_2, text="BUTTON 5").grid(row=9, column=0)
lable_btn6 = Label(frame_2, text="BUTTON 6").grid(row=10, column=0)
entry_btn1 = Entry(frame_2,width=5)
entry_btn1.grid(row=5, column=1)

53
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

entry_btn2 = Entry(frame_2,width=5)
entry_btn2.grid(row=6, column=1)
entry_btn3 = Entry(frame_2,width=5)
entry_btn3.grid(row=7, column=1)
entry_btn4 = Entry(frame_2,width=5)
entry_btn4.grid(row=8, column=1)
entry_btn5 = Entry(frame_2,width=5)
entry_btn5.grid(row=9, column=1)
entry_btn6 = Entry(frame_2,width=5)
entry_btn6.grid(row=10, column=1)

# nhấn nút để chọn thể loại game


btn_SETUP = Button(frame_mid, text="UPDATE", width=45,
height=25,bg="#64b8a1",padx=0, pady=0, command=fn2).place(x=0, y=50)

#XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXxx
#XỬ LÝ TRÊN frame_1
# tạo các lable và entry cho Joystic
# 3 lable hàng 0
#lable_1=Label(frame_1,text="LU",width="10",height="3",bg="white",foreground=
"#859751").grid(row=0, column=0)
lable_2=Label(frame_1,text="UP",width="10",height="3",bg="white",foreground="
#00a4c7" ).grid(row=0, column=2)
#lable_3=Label(frame_1,text="UR",width="10",height="3",bg="white",foreground=
"orange" ).grid(row=0, column=4)

#3 entry hàng 1
entry_1=Entry(frame_1,width=5,bg="#fef2f6")
#entry_1.grid(row=1, column=1)
entry_2=Entry(frame_1,width=5,bg="#fef2f6")
entry_2.grid(row=1, column=2)
entry_3=Entry(frame_1,width=5,bg="#fef2f6")
#entry_3.grid(row=1, column=3)

# 2 lable, 2 entry hàng 2


lable_4=Label(frame_1,text="LEFT",width="10",height="3",bg="white"
,foreground="red").grid(row=2, column=0)
entry_8=Entry(frame_1,width=5,bg="#fef2f6")
entry_8.grid(row=2, column=1)
entry_4=Entry(frame_1,width=5,bg="#fef2f6")
entry_4.grid(row=2, column=3)
lable_5=Label(frame_1,text="RIGHT",width="10",height="3",bg="white",foregroun
d="purple" ).grid(row=2, column=4)

# 3 entry hàng 3
entry_7=Entry(frame_1,width=5,bg="#fef2f6")
#entry_7.grid(row=3, column=1)
entry_6=Entry(frame_1,width=5,bg="#fef2f6")
entry_6.grid(row=3, column=2)
entry_5=Entry(frame_1,width=5,bg="#fef2f6")
#entry_5.grid(row=3, column=3)

# 3 lable hàng 4
#lable_6=Label(frame_1,text="DL",width="10",height="3",bg="white"
,foreground="#c55805").grid(row=4, column=0)
lable_7=Label(frame_1,text="DOWN",width="10",height="3",bg="white"
).grid(row=4, column=2)

54
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

#lable_8=Label(frame_1,text="RD",width="10",height="3",bg="white",foreground=
"green").grid(row=4, column=4)

# 1 lable để chọn port serial


Lable_9=Label(frame_1,text=" LED EFFECT",width="42",height="2",bg="#A1C1DA"
).grid(row=8, columnspan=5)

# 1 combobox để chọn port serial


v = ["ĐỎ","CAM","VÀNG","LỤC","LAM","CHÀM","TÍM","TRẮNG","ĐỔI MÀU","TẮT LED"]
combo = Combobox(frame_1, values=v, width=30)
combo.set("select")
combo.grid(row=9, columnspan=5)

#XỬ LÝ TRÊN frame_2


#tạo các button , Lable, entry
#hàng 0
button_1=Button(frame_2,text="BUTTON
1",width="10",height="3",bg="#FFE40F").grid(row=0,column=0)
button_2=Button(frame_2,text="BUTTON
2",width="10",height="3",bg="#00a4c7").grid(row=0,column=1)

#hàng 1
button_3=Button(frame_2,text="BUTTON
3",width="10",bg="#00a4c7",height="3").grid(row=1,column=0)
button_4=Button(frame_2,text="BUTTON
4",width="10",bg="#FFE40F",height="3").grid(row=1,column=1)

#hàng 2
button_5=Button(frame_2,text="BUTTON
5",width="10",bg="#FFE40F",height="3").grid(row=2,column=0)
button_6=Button(frame_2,text="BUTTON
6",width="10",bg="#00a4c7",height="3").grid(row=2,column=1)
#hang 3: khi click để chọn thể loại game
Btn_CUSTOM=Button(frame_2,text="SELECT GAME",
width=18,height=3,bg="#64b8a1",padx=10,pady=10,command=customizeGame).grid(co
lumnspan=2)

#Xử lý trên frame_mid


lable_blu_1=Label(frame_mid,text="YOU ARE IN GAME
:",width="30",height="3",bg="#A1C1DA").grid(row=6,sticky=W)
lable_blu_2=Label(frame_mid,text="RACING",width="11",height="3",bg="#A1C1DA" )
lable_blu_2.grid(row=6, column=2)
lable_blu_6 = Label(frame_mid, width="11", height="3", bg="#A1C1DA")
lable_blu_6.grid(row=8, column=2,sticky="WESN")
lable_blu_5=Label(frame_mid,text="DAY SETUP
:",width="30",height="3",bg="#A1C1DA").grid(row=8,sticky=W)
#1 Checkbox để kiểm tra cảm biến góc nghiêng có hoạt động hay không
var1 = IntVar()
Checkbutton(frame_1, text="IS MPU ACTIVE ?",
height="3",width="45",variable=var1,bg="#A1C1DA").place(x=0, y=320)

customizeGame()

root.mainloop()

55
ĐỒ ÁN 2: THIẾT KẾ KEYBOARD GAME GVHD: PGS.TS PHAN VĂN CA

56

You might also like