TRƯỜNG ĐẠI HỌC GIAO THÔNG VẬN TẢI THÀNH PHỐ HỒ CHÍ MINH
KHOA ĐIỆN – ĐIỆN TỬ VIỄN THƠNG
ĐO LƯỜNG VÀ ĐIỀU KHIỂN BẰNG MÁY TÍNH
TRUYỀN THƠNG NỐI TIẾP GIỮA PC VÀ ARDUINO
SỬ DỤNG CẢM BIẾN GÓC NGHIÊNG MPU 6050
Giảng viên hướng dẫn: Th.S Lê Mạnh Thắng
Nhóm thực hiện: Nhóm 16
Trần Ngọc Sơn
2051050173 TD20D
Đồn Thành Đạt
2051050086 TD20A
Trần Xn Tín
2051050185 TD20D
Thành phố Hồ Chí Minh, ngày 08 tháng 04 năm 2023
1
MỤC LỤC
LỜI NĨI ĐẦU...............................................................................................................3
CHƯƠNG 1.
TÌM HIỂU VỀ CẢM BIẾN GY-521 6DOF IMU MPU6050..........4
1.1.
Giới thiệu về cảm biến GY-521 6DOF IMU MPU6050...................................4
1.2.
Thông số kỹ thuật cảm biến GY-521 6DOF IMU MPU6050...........................4
1.3.
Chức năng các chân cảm biến GY-521 6DOF IMU MPU6050........................5
1.4.
Ứng dụng cảm biến GY-521 6DOF IMU MPU6050........................................5
CHƯƠNG 2.
CODE LẬP TRÌNH ARDUINO.......................................................6
2.1.
Thư viện sử dụng...............................................................................................6
2.2.
Thời gian đọc và truyền dữ liệu.........................................................................6
2.3.
Khung dữ liệu truyền lên máy tính....................................................................6
2.4.
Code Arduino.....................................................................................................6
CHƯƠNG 3.
CODE C# VÀ GIAO DIỆN...............................................................8
3.1.
Code C# lập trình...............................................................................................8
3.2.
Giao diện Winforms.........................................................................................17
CHƯƠNG 4.
KẾT QUẢ THỰC HIỆN.................................................................18
4.1.
Hình ảnh thực tế...............................................................................................18
4.2.
Kiểm chứng kết quả và đánh giá sai số...........................................................18
4.3.
Video thuyết trình............................................................................................19
2
LỜI NĨI ĐẦU
Chúng ta có thể thấy rằng cảm biến góc nghiêng được ứng dụng trong nhiều lĩnh
vực. Ví dụ như hệ thống cân bằng trong drone, thước đo góc, tripod, các mơ hình trong
khơng gian 3D, v.v. Đề tài của nhóm em sẽ sử dụng cảm biến góc nghiêng MPU6050
dể khảo sát các trục X, Y, Z .Xem sai số của cảm biến so với thực tế và mức độ ảnh
hưởng lẫn nhau của 3 trục.
3
CHƯƠNG 1. TÌM HIỂU VỀ CẢM BIẾN GY-521 6DOF IMU MPU6050
1.1. Giới thiệu về cảm biến GY-521 6DOF IMU MPU6050
Cảm biến GY-521 6DOF IMU MPU6050 là IC tích hợp cảm biến tích gia tốc kế
và cảm biến từ trường. Nó thường được sử dụng để nhận biết 6 thông số: 3 trục Góc
quay (Gyro), 3 trục gia tốc hướng (Accelerometer). Ngoài ra, từ các giá trị này, người
ta cho đi qua các bộ lọc số (AHRS Kalman, v.v) để thu được giá trị đã loại bỏ nhiễu.
Hình 1. Cảm biến MPU 6050
Các giá trị này tiếp tục được dùng để xác định các giá trị thứ cấp như tốc độ dài,
tọa độ khơng gian, gia tốc góc, vận tốc góc, góc quay với độ chính xác lên tới 0.01 độ,
đo gia tốc, vận tốc chuyển động tịnh tiến.
Module cảm biến MPU 6050 có thể kết nối với vi điều khiển qua 1 trong 2 giao
thức là SPI hoặc I2C. MPU 6050 cịn có 1KB bộ nhớ để lưu trữ lệnh từ vi điều khiển
và dữ liệu sau khi nó tính toán xong các giá trị đo được.
Cảm biến MPU 6050 khơng có tính năng chuyển từ tín hiệu analog sang digital.
Cảm biến này nhận biết các tín hiệu giá trị gia tốc góc nghiêng. Sau đó, các tín hiệu
này sẽ được truyền sang vi mạch chuyển đổi tín hiệu trong MPU 6050 được gọi là
Digital Motion Processor (DMP). Thiết bị này tích hợp nhiều tính năng xử lý tín hiệu
và lưu trữ dữ liệu đa dạng. Nó tính tốn góc quay và gia tốc trong thời gian thực và
truyền dữ liệu này đến vi điều khiển thông qua giao tiếp I2C hoặc SPI. Các tín hiệu đi
qua DMP sẽ trở thành tín hiệu chuẩn hóa (dạng analog). Khi đó, nhờ vào tính năng
ADC của Arduino sẽ chuyển đổi tín hiệu từ dạng analog này sang digital.
1.2. Thông số kỹ thuật cảm biến GY-521 6DOF IMU MPU6050
Điện áp sử dụng: 3~5VDC.
Điện áp giao tiếp: 3~5VDC.
Chuẩn giao tiếp: I2C.
Giá trị góc quay (Gyroscopes):
Trục X: từ -250 đến +250 độ/giây.
Trục Y: từ -250 đến +250 độ/giây.
4
Trục Z: từ -250 đến +250 độ/giây.
Giá trị gia tốc (Acceleration):
Trục X: từ -2g đến +2g.
Trục Y: từ -2g đến +2g.
Trục Z: từ -2g đến +2g.
Giao tiếp: I2C, SPI.
Hỗ trợ AD 16 Bit.
1.3. Chức năng các chân cảm biến GY-521 6DOF IMU MPU6050
1.4.
VCC
GND
SCL
SDA
XDA
XCL
AD0
INT
5V/3V3
0V
Chân SCL trong giao tiếp I2C
Chân SDA trong giao tiếp I2C
Chân dữ liệu (kết nối với cảm biến khác)
Chân xung (kết nối với cảm biến khác)
Bit0 của địa chỉ I2C
Chân ngắt
Ứng
dụng
cảm
biến
GY521
6DOF IMU MPU6050
Đây là loại cảm biến gia tốc phổ biến nhất trên thị trường hiện nay. Các ứng
dụng và code dành cho nó rất nhiều và hầu như có trên mọi loại vi điều khiển.
MPU6050 sẽ là sự lựa chọn tối ưu cho các ứng dụng như:
Mơ hình như con lắc động.
Xe tự cân bằng.
Các thiết bị ổn định hình ảnh, chống rung.
Các ứng dụng điều khiển không tiếp xúc
Các ứng dụng nhận biết chuyển động.
Thiết bị game, ứng dụng cầm tay
Các thí nghiệm, đo lường.
5
CHƯƠNG 2. CODE LẬP TRÌNH ARDUINO
2.1. Thư viện sử dụng
MPU6050_tockn.h
Thư viện của cảm biến MPU 6050.
Wire.h
Thư viện dùng để gửi và nhận dữ liệu giữa cảm biến MPU 6050 và Arduino.
2.2. Thời gian đọc và truyền dữ liệu
Delay(200)
Lệnh delay mỗi 200ms arduino gửi giá trị lên 1 lần.
2.3. Khung dữ liệu truyền lên máy tính
mpu6050.update()
Lệnh update các giá trị của MPU 6050.
float x = mpu6050.getAngleX();
float y = mpu6050.getAngleY();
float z = mpu6050.getAngleZ();
Dùng float để định nghĩa số thực x,y,z, bằng các giá trị trục x,y,z.
Serial.println ("X" + String(x) + "Y" + String(y) + "Z" + String(z) )
Gửi lên pc chuỗi
2.4. Code Arduino
//include thư viện của mpu 6050
#include <MPU6050_tockn.h>
#include <Wire.h>
// thiết lập thư viện wire
void setup()
{
Serial.begin(9600);
Wire.begin();
mpu6050.begin();
mpu6050.calcGyroOffsets(false);
}
void loop()
{
6
// lệnh update các giá trị của mpu6050
mpu6050.update();
// dùng float để định nghĩa số thực x,y,z, bằng các giá trị trục x,y,z
float x = mpu6050.getAngleX();
float y = mpu6050.getAngleY();
float z = mpu6050.getAngleZ();
// gửi lên pc chuỗi
Serial.println ("X" + String(x) + "Y" + String(y) + "Z" + String(z) );
// vidu X0Y0Z0
//lệnh delay mỗi 200ms arduino gửi giá trị lên 1 lần
delay(200);
}
7
CHƯƠNG 3. CODE C# VÀ GIAO DIỆN
3.1. Code C# lập trình.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using System.Reflection.Emit;
using ZedGraph;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
#region Form
public Form1()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
string[] BaudRate = {"9600"};
cbxbaud.Items.AddRange(BaudRate);
}
private void Form1_Load(object sender, EventArgs e)
8
{
cbxtencom.DataSource = SerialPort.GetPortNames();
cbxbaud.Text = "9600";
// khoi tao bieu do goc X
GraphPane mypanel1 = zedGraphControl1.GraphPane;
mypanel1.Title.Text = "Giá trị góc nghiêng X";
mypanel1.YAxis.Title.Text = "Giá trị ";
mypanel1.XAxis.Title.Text = "Thời gian";
// khoi tao bieu do goc Y
GraphPane mypanel2 = zedGraphControl2.GraphPane;
mypanel2.Title.Text = "Giá trị góc nghiêng Y";
mypanel2.YAxis.Title.Text = "Giá trị ";
mypanel2.XAxis.Title.Text = "Thời gian";
// khoi tao bieu do goc Z
GraphPane mypanel3 = zedGraphControl3.GraphPane;
mypanel3.Title.Text = "Giá trị góc nghiêng Z";
mypanel3.YAxis.Title.Text = "Giá trị ";
mypanel3.XAxis.Title.Text = "Thời gian";
// khoi tao bieu do 3 goc X Y Z
GraphPane mypanel4 = zedGraphControl4.GraphPane;
mypanel4.Title.Text = "Giá trị góc nghiêgn X, Y, Z";
mypanel4.YAxis.Title.Text = "Giá trị ";
mypanel4.XAxis.Title.Text = "Thời gian";
//thiet lam muc list gia tri co the chay toi da 50000 so
RollingPointPairList list1 = new RollingPointPairList(50000);
RollingPointPairList list2 = new RollingPointPairList(50000);
RollingPointPairList list3 = new RollingPointPairList(50000);
RollingPointPairList list4 = new RollingPointPairList(50000);
RollingPointPairList list5 = new RollingPointPairList(50000);
RollingPointPairList list6 = new RollingPointPairList(50000);
9
//thiet lap duong line truc X, Y, Z add lan luot vao panel1,2,3 de hien thi
tren 3 do thi X Y Z
//do thi 1 la góc X
//do thi 2 la goc y
//do thi 3 la goc z
LineItem line1 = mypanel1.AddCurve("goc X", list1, Color.Red,
SymbolType.None);
LineItem line2 = mypanel2.AddCurve("goc Y", list2, Color.Blue,
SymbolType.None);
LineItem line3 = mypanel3.AddCurve("goc Z", list3, Color.Black,
SymbolType.None);
//thiet lap duong line x,y,Z vao do thi 4
//do thi 4 la do thi so sanh 3 goc xyz
LineItem line4 = mypanel4.AddCurve("goc X", list1, Color.Red,
SymbolType.None);
LineItem line5 = mypanel4.AddCurve("goc Y", list2, Color.Blue,
SymbolType.None);
LineItem line6 = mypanel4.AddCurve("goc Z", list3, Color.Black,
SymbolType.None);
//khoang cach cach trong bieu do truc X
mypanel1.YAxis.Scale.Min = -100;
mypanel1.YAxis.Scale.Max = 100;
mypanel1.YAxis.Scale.MinorStep = 10;
mypanel1.YAxis.Scale.MajorStep = 20;
zedGraphControl1.AxisChange();
//khoang cach cach trong bieu do truc y
10
mypanel2.YAxis.Scale.Min = -100;
mypanel2.YAxis.Scale.Max = 100;
mypanel2.YAxis.Scale.MinorStep = 10;
mypanel2.YAxis.Scale.MajorStep = 20;
zedGraphControl2.AxisChange();
//khoang cach cach trong bieu do truc z
mypanel3.YAxis.Scale.Min = -100;
mypanel3.YAxis.Scale.Max = 100;
mypanel3.YAxis.Scale.MinorStep = 10;
mypanel3.YAxis.Scale.MajorStep = 20;
zedGraphControl3.AxisChange();
//khoang cach cach trong bieu do goc so sanh xyz
mypanel4.YAxis.Scale.Min = -100;
mypanel4.YAxis.Scale.Max = 100;
mypanel4.YAxis.Scale.MinorStep = 10;
mypanel4.YAxis.Scale.MajorStep = 20;
zedGraphControl4.AxisChange();
}
int tong = 0;
public void draw1 (double line1) // ve duong x trong bieu do goc x
{
LineItem duongline1 = zedGraphControl1.GraphPane.CurveList[0] as
LineItem;
11
if (duongline1 == null )
{
return;
}
IPointListEdit list1 = duongline1.Points as IPointListEdit;
if (list1 == null)
{
return;
}
list1.Add(tong, line1);
zedGraphControl1.AxisChange();
zedGraphControl1.Invalidate();
tong += 2;
}
public void draw2(double line2)
{
LineItem duongline2 = zedGraphControl2.GraphPane.CurveList[0] as
LineItem;
if (duongline2 == null)
{
return;
}
IPointListEdit list2 = duongline2.Points as IPointListEdit;
if (list2 == null)
{
return;
}
list2.Add(tong, line2);
zedGraphControl2.AxisChange();
zedGraphControl2.Invalidate();
tong += 2;
}
12
public void draw3(double line3)
{
LineItem duongline3 = zedGraphControl3.GraphPane.CurveList[0] as
LineItem;
if (duongline3 == null)
{
return;
}
IPointListEdit list3 = duongline3.Points as IPointListEdit;
if (list3 == null)
{
return;
}
list3.Add(tong, line3);
zedGraphControl3.AxisChange();
zedGraphControl3.Invalidate();
tong += 2;
}
public void draw4(double line4)
{
LineItem duongline4 = zedGraphControl4.GraphPane.CurveList[0] as
LineItem;
if (duongline4 == null)
{
return;
}
IPointListEdit list4 = duongline4.Points as IPointListEdit;
if (list4 == null)
{
return;
}
list4.Add(tong, line4);
zedGraphControl4.AxisChange();
13
zedGraphControl4.Invalidate();
tong += 2;
}
public void draw5(double line5)
{
LineItem duongline5 = zedGraphControl4.GraphPane.CurveList[1] as
LineItem;
if (duongline5 == null)
{
return;
}
IPointListEdit list5 = duongline5.Points as IPointListEdit;
if (list5 == null)
{
return;
}
list5.Add(tong, line5);
zedGraphControl4.AxisChange();
zedGraphControl4.Invalidate();
tong += 2;
}
public void draw6(double line6)
{
LineItem duongline6 = zedGraphControl4.GraphPane.CurveList[2] as
LineItem;
if (duongline6 == null)
{
return;
}
IPointListEdit list6 = duongline6.Points as IPointListEdit;
if (list6 == null)
14
{
return;
}
list6.Add(tong, line6);
zedGraphControl4.AxisChange();
zedGraphControl4.Invalidate();
tong += 2;
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Escape:
{
Close();
break;
}
}
}
#endregion
private void btnconnect_Click(object sender, EventArgs e)
{
UART.PortName = cbxtencom.Text;
UART.Open();
if (UART.IsOpen)
{
MessageBox.Show("KET NOI COM THANH CONG");
}
}
15
private void btndisconnect_Click(object sender, EventArgs e)
{
UART.Close();
MessageBox.Show("NGAT KET NOI COM THANH CONG");
}
private
SerialDataReceivedEventArgs e)
void
UART_DataReceived(object
sender,
{
string Alldata = "";
Alldata = UART.ReadLine();// chuoi Alldata bang du lieu duoc gui len tu
arduino
Alldata = Alldata.Trim();//
int len = Alldata.Length;
if (len > 0)
{
//ham gui len co gia tri X0Y0Z0
int gcX = Alldata.IndexOf('X');// ham tim vi tri chu X
int gcY = Alldata.IndexOf('Y');// ham tim vi tri chu Y
int gcZ = Alldata.IndexOf('Z');// ham tim vi tri chu Z
//=> cac gia tri xyz gui len can xac dinh dung vi tri
//tach cac du lieu ra rieng
string gocx = Alldata.Substring(gcX + 1,gcY - gcX- 1);// chuoi se bat
dau tu sau chu x
string gocy = Alldata.Substring(gcY + 1,gcZ - gcY - 1);
string gocz = Alldata.Substring(gcZ + 1);
//=> tinh toan tach du lieu cac goc ra bang canh gia su bat dau tu goc x
// hien thi nhung du lieu vua tach ra text box
txbx.Text = gocx;// in goc x ra textbox
txby.Text = gocy;// in goc y ra textbox
16
txbz.Text = gocz;// in goc z ra textbox
// in du lieu ra do thi
Invoke(new MethodInvoker(() => draw1(Convert.ToDouble(gocx))));
Invoke(new MethodInvoker(() => draw2(Convert.ToDouble(gocy))));
Invoke(new MethodInvoker(() => draw3(Convert.ToDouble(gocz))));
Invoke(new MethodInvoker(() => draw4(Convert.ToDouble(gocx))));
Invoke(new MethodInvoker(() => draw5(Convert.ToDouble(gocy))));
Invoke(new MethodInvoker(() => draw6(Convert.ToDouble(gocz))));
}
}
}
3.2. Giao diện Winforms
Hình 2. Giao diện Winforms
17
CHƯƠNG 4. KẾT QUẢ THỰC HIỆN
4.1. Hình ảnh thực tế
Hình 3. Mơ hình thực tế
4.2. Kiểm chứng kết quả và đánh giá sai số
Dải đo 0 độ.
Trục X : kết quả góc đo trong khoảng 1.12 độ sai số khoảng 1.12 %.
Trục Y : kết quả góc đo trong khoảng 0.35 độ sai số khoảng 0.35 %
Trục Z : kết quả góc đo trong khoảng 0.67 độ sai số khoảng 0.67 %
Kết luận ở dải đo 0 độ
Các trục đo không giữ vững kết quả đo ở 0 độ, lý do có thể do đế đạt cảm
biến chưa đảm bảo chất lượng
Dải đo 45 độ.
Khi nghiêng trục X theo thước 45 độ
Trục X : kết quả góc đo giao động trong khoảng 43 độ sai số khoảng 4.4%.
Trục Y : thay đổi khoảng 0.3 độ.
Trục Z : thay đổi 1.5 độ.
Khi nghiêng trục Y theo thước 45 độ
Trục Y : kết quả góc đo giao động trong khoảng 43.5 độ sai số khoảng
3.3%.
Trục X : thay đổi khoảng 0.45 độ.
Trục Z : thay đổi 2 độ.
Khi nghiêng trục Z theo thước 45 độ
18
Trục Z : kết quả góc đo giao động trong khoảng 44.7 độ sai số khoảng
0.67%.
Trục X : thay đổi khoảng 0.2 độ.
Trục Y : thay đổi 0.12 độ.
Kết luận ở dải đo 45 độ
Sai số của cảm biến so với thực tế là khoảng, lý do có thể là do vật liêu làm
đế cảm biến ( test boar không đảm bảo chất lượng) và khi nghiêng cảm biến
bị di chuyển vị trí các góc.
Các trục X,Y,Z không bị ảnh hượng lẫn nhau nhiều
Dải đo 90 độ.
Khi nghiêng trục X theo thước 90 độ
Trục X : kết quả góc đo giao động trong khoảng 85 độ sai số khoảng 5.5%.
Trục Y : thay đổi khoảng 0.4 độ.
Trục Z : thay đổi 2.5 độ.
Khi nghiêng trục Y theo thước 90 độ
Trục Y : kết quả góc đo giao động trong khoảng 84.2 độ sai số khoảng
6.3%.
Trục X : thay đổi khoảng 0.5 độ.
Trục Z : thay đổi 1 độ.
Khi nghiêng trục Z theo thước 90 độ
Trục Z : kết quả góc đo giao động trong khoảng 92.2 độ sai số khoảng
1.33%.
Trục X : thay đổi khoảng 0.4 độ.
Trục Y : thay đổi 1.12 độ.
Kết luận ở dải đo 90 độ
Thấy rằng sai số ở mức đo 90 độ cao hơn một chút so mới mức đo 45 độ
Mức độ ảnh hưởng lẫn nhau của các trục không thay đổi nhiều
Kết luận sau ba dải đo
Thấy rằng ở dải đo càng cao thì sai số cho ra càng lớn
Mức độ ảnh hưởng lẫn nhau của các trục khi trục khác hoạt dộng không
nhiều
19
4.3. Video thuyết trình
/>%A7nXu%C3%A2nT%C3%ADn
20