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 60[.]
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 MỤC LỤC LỜI NÓI ĐẦU .3 CHƯƠNG TÌM HIỂU VỀ CẢM BIẾN GY-521 6DOF IMU MPU6050 1.1 Giới thiệu cảm biến GY-521 6DOF IMU MPU6050 1.2 Thông số kỹ thuật cảm biến GY-521 6DOF IMU MPU6050 1.3 Chức chân cảm biến GY-521 6DOF IMU MPU6050 1.4 Ứng dụng cảm biến GY-521 6DOF IMU MPU6050 CHƯƠNG CODE LẬP TRÌNH ARDUINO .6 2.1 Thư viện sử dụng .6 2.2 Thời gian đọc truyền liệu .6 2.3 Khung liệu truyền lên máy tính 2.4 Code Arduino CHƯƠNG 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 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 đánh giá sai số 18 4.3 Video thuyết trình 19 LỜI NÓI ĐẦU Chúng ta thấy cảm biến góc nghiêng ứng dụng nhiều lĩnh vực Ví dụ hệ thống cân drone, thước đo góc, tripod, mơ hình khơng gian 3D, v.v Đề tài nhóm em sử dụng cảm biến góc nghiêng MPU6050 dể khảo sát trục X, Y, Z Xem sai số cảm biến so với thực tế mức độ ảnh hưởng lẫn trục CHƯƠNG TÌM HIỂU VỀ CẢM BIẾN GY-521 6DOF IMU MPU6050 1.1 Giới thiệu cảm biến GY-521 6DOF IMU MPU6050 Cảm biến GY-521 6DOF IMU MPU6050 IC tích hợp cảm biến tích gia tốc kế cảm biến từ trường Nó thường sử dụng để nhận biết thơng số: trục Góc quay (Gyro), trục gia tốc hướng (Accelerometer) Ngoài ra, từ giá trị này, người ta cho qua lọc số (AHRS Kalman, v.v) để thu giá trị loại bỏ nhiễu Hình Cảm biến MPU 6050 Các giá trị tiếp tục dùng để xác định giá trị thứ cấp 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 độ 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 kết nối với vi điều khiển qua giao thức SPI I2C MPU 6050 cịn có 1KB nhớ để lưu trữ lệnh từ vi điều khiển liệu sau tính tốn xong giá trị đo Cảm biến MPU 6050 khơng có tính chuyển từ tín hiệu analog sang digital Cảm biến nhận biết tín hiệu giá trị gia tốc góc nghiêng Sau đó, tín hiệu truyền sang vi mạch chuyển đổi tín hiệu MPU 6050 gọi Digital Motion Processor (DMP) Thiết bị tích hợp nhiều tính xử lý tín hiệu lưu trữ liệu đa dạng Nó tính tốn góc quay gia tốc thời gian thực truyền liệu đến vi điều khiển thông qua giao tiếp I2C SPI Các tín hiệu qua DMP trở thành tín hiệu chuẩn hóa (dạng analog) Khi đó, nhờ vào tính ADC Arduino chuyển đổi tín hiệu từ dạng analog 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 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 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 giao tiếp I2C Chân SDA giao tiếp I2C Chân 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 địa I2C Chân ngắt Ứng dụng cảm biến GY521 6DOF IMU MPU6050 Đây loại cảm biến gia tốc phổ biến thị trường Các ứng dụng code dành cho nhiều có loại vi điều khiển MPU6050 lựa chọn tối ưu cho ứng dụng như: Mơ lắc động Xe tự cân 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 CHƯƠNG CODE LẬP TRÌNH ARDUINO 2.1 Thư viện sử dụng MPU6050_tockn.h Thư viện cảm biến MPU 6050 Wire.h Thư viện dùng để gửi nhận liệu cảm biến MPU 6050 Arduino 2.2 Thời gian đọc truyền liệu Delay(200) Lệnh delay 200ms arduino gửi giá trị lên lần 2.3 Khung liệu truyền lên máy tính mpu6050.update() Lệnh update giá trị 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, 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 mpu 6050 #include #include // thiết lập thư viện wire void setup() { Serial.begin(9600); Wire.begin(); mpu6050.begin(); mpu6050.calcGyroOffsets(false); } void loop() { // lệnh update giá trị mpu6050 mpu6050.update(); // dùng float để định nghĩa số thực x,y,z, 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 200ms arduino gửi giá trị lên lần delay(200); } CHƯƠNG 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) { cbxtencom.DataSource = SerialPort.GetPortNames(); cbxbaud.Text = "9600"; // khoi tao bieu 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 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 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 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); //thiet lap duong line truc X, Y, Z add lan luot vao panel1,2,3 de hien thi tren thi X Y Z //do thi la góc X //do thi la goc y //do thi 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 thi //do thi la thi so sanh 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 bieu 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 bieu 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 bieu 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 bieu 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 bieu 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 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 bang canh gia su bat dau tu goc x // hien thi nhung du lieu vua tach text box txbx.Text = gocx;// in goc x textbox txby.Text = gocy;// in goc y textbox 16 txbz.Text = gocz;// in goc z textbox // in du lieu 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 Giao diện Winforms 17 CHƯƠNG KẾT QUẢ THỰC HIỆN 4.1 Hình ảnh thực tế Hình Mơ hình thực tế 4.2 Kiểm chứng kết đánh giá sai số Dải đo độ Trục X : kết góc đo khoảng 1.12 độ sai số khoảng 1.12 % Trục Y : kết góc đo khoảng 0.35 độ sai số khoảng 0.35 % Trục Z : kết góc đo khoảng 0.67 độ sai số khoảng 0.67 % Kết luận dải đo độ Các trục đo không giữ vững kết đo độ, lý 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 góc đo giao động 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 góc đo giao động khoảng 43.5 độ sai số khoảng 3.3% Trục X : thay đổi khoảng 0.45 độ Trục Z : thay đổi độ Khi nghiêng trục Z theo thước 45 độ 18 Trục Z : kết góc đo giao động 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ảm biến so với thực tế khoảng, lý vật liêu làm đế cảm biến ( test boar không đảm bảo chất lượng) nghiêng cảm biến bị di chuyển vị trí góc Các trục X,Y,Z khơng bị ảnh hượng lẫn nhiều Dải đo 90 độ Khi nghiêng trục X theo thước 90 độ Trục X : kết góc đo giao động 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 góc đo giao động khoảng 84.2 độ sai số khoảng 6.3% Trục X : thay đổi khoảng 0.5 độ Trục Z : thay đổi độ Khi nghiêng trục Z theo thước 90 độ Trục Z : kết góc đo giao động 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 sai số mức đo 90 độ cao chút so mức đo 45 độ Mức độ ảnh hưởng lẫn trục không thay đổi nhiều Kết luận sau ba dải đo Thấy dải đo cao sai số cho lớn Mức độ ảnh hưởng lẫn trục trục khác hoạt dộng không nhiều 19 4.3 Video thuyết trình https://www.youtube.com/watch?v=CIE71Qjjjx4&ab_channel=Tr%E1%BA %A7nXu%C3%A2nT%C3%ADn 20