1. Trang chủ
  2. » Giáo Dục - Đào Tạo

BÁO cáo bài tập lớn kỹ thuật lập trình trong cơ điện tử đề tài hệ thống cảnh báo nhiệt độ

32 22 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Hệ thống cảnh báo nhiệt độ
Tác giả Nhóm 11
Người hướng dẫn Ts. Dương Văn Lạc
Trường học Trường Đại học Bách Khoa Hà Nội
Chuyên ngành Cơ điện tử
Thể loại Báo cáo bài tập lớn
Năm xuất bản 2022
Thành phố Hà Nội
Định dạng
Số trang 32
Dung lượng 590,08 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Cấu trúc

  • PHẦN I LẬP KẾ HOẠCH THỰC HIỆN PHẦN MỀM (4)
    • I. LẬP KẾ HOẠCH (4)
      • 1. Khởi tạo dự án (4)
      • 2. Phân tích tính khả thi (4)
    • II. LỊCH BIỂU DIỄN CÔNG VIỆC (4)
      • 1. Thành viên (4)
      • 2. Thời gian tổng thể (5)
    • PHẦN 2: PHÂN TÍCH HỆ THỐNG (6)
      • 1. SƠ ĐỒ THIẾT KẾ (6)
      • 2. LINH KIỆN SỬ DỤNG (6)
      • 3. LẬP TRÌNH ADRUINO (11)
      • 4. LẬP TRÌNH GIAO DIỆN C# (12)
    • PHẦN 3: THỬ NGHIỆM VÀ KẾT LUẬN (14)
      • 1. THỬ NGHIỆM (14)
      • 2. KẾT LUẬN (15)
    • Phần 4: Bài học kinh nghiệm (0)
      • 1. Về triển khai kế hoạch bài tập lớn (15)
      • 2. Về thiết kế hệ thống (15)
      • 3. Về lập trình Arduino (0)
      • 4. Về lập trình GUI (0)

Nội dung

Nắm bắt được xu hướng đó, trong khuôn khổ nội dung của chương trình học học phần Kĩ thuật lập trình trong Cơ điện tử, nhóm chúng em đã quyết định tìm hiểu và xây dựng một đề tài đơn giản

LẬP KẾ HOẠCH THỰC HIỆN PHẦN MỀM

LẬP KẾ HOẠCH

Mong muốn có một sản phẩm có thể quản lí nhiệt độ, độ ẩm nhằm nâng cao hiệu quả quản lý để đạt được những yêu cầu đầu ra của đối tượng, nhóm sinh viên chúng em đã nghiên cứu và xây dựng đề tài X để hỗ trợ các người quản lý và nhân viên của họ trong công việc quản lý nhiệt độ, độ ẩm một cách hiện đại và chuyên nghiệp Sản phẩm sẽ giúp tiết kiệm một lượng lớn thời gian đo đạc thủ công cũng như thống kê khảo sát tình hình của môi trường trong thời gian thực.

2 Phân tích tính khả thi

2.1 Tính khả thi về mặt kỹ thuật

- Sản phẩm được phát triển dựa trên công cụ C# và Adruino là công cụ hỗ trợ thông dụng, mạnh để lập trình giao diện và lập trình vi điều khiển.

- Sản phầm được thiết kế chạy trên nền window đảm bảo phù hợp với đa số người dùng.

- Linh kiện không quá phức tạp.

2.2 Tính khả thi về mặt kinh tế

- Linh kiện không khó để tìm kiếm và không đắt đỏ.

2.3 Tính khả thi về mặt tổ chức

- Phần mềm sau khi hoàn thành dễ dàng sử dụng, thân thiện với người dung, ngay cả người mới.

LỊCH BIỂU DIỄN CÔNG VIỆC

1 Trần Quang Trung (TN) 20134191 KT ĐT-TT 06 K58

2 Trịnh Hữu Trường 20134237 KT ĐT-TT 07 K58

3 Nguyễn Đăng Anh Tú 20136796 CN-Điện tử TT 02 K58

4 Nguyễn Thị Cẩm Tú 20134495 KT ĐT-TT 09 K58

5 Phạm Mạnh Tuấn 20134328 KT ĐT-TT 06 K58

Tổng thời gian dự kiến là 15-17 tuần (kéo dài trong thời gian học) hoàn thành trước thời hạn bàn giao phần mềm là 1 tuần được phân bổ như sau:

+ Phân tích và thiết kế hệ thống phần mềm : 4-5 tuần.

+ Lập trình, kiểm thử các hệ thống phần mềm, sửa lỗi, nộp báo cáo : 11-12 tuần.

PHÂN TÍCH HỆ THỐNG

2 LINH KIỆN SỬ DỤNG a) Adruino Uno R3

Thông số kỹ thuật Adruino Uno R3

Vi điều khiển ATmega328 họ 8bit Điện áp hoạt động 5 - 12V DC ( khuyên dùng )

Tần số hoạt động 16 MHz

Dòng tiêu thụ Khoảng 30mA Điện áp vào giới hạn 19V DC

Số chân Digital I/O 14 ( 6 chân PWM )

Số chân Analog 6 ( độ phân giải 10bit )

Dòng tối đa trên mỗi chân I/O 30 mA

Dòng ra tối đa ( 5V ) 500 mA

Dòng ra tối đa ( 3.3 ) 50 mA

Bộ nhớ Flash 32 KB ( ATmega328 ) với 0.5 KB dùng bởi bootloader

Khối lượng 25 gram b) Cảm biến nhiệt độ, độ ẩm DHT11

Cảm biến nhiệt độ, độ ẩm DHT11

Thông số kỹ thuật Cảm biến nhiệt độ độ ẩm DHT 11

 Dòng sử dụng: 2.5mA max (khi truyền dữ liệu).

 Khoảng đo độ ẩm: 20%-90% RH (sai số 5%RH)

 Khoảng đo nhiệt độ: 0-50°C (sai số 2°C)

 Tần số lấy mẫu tối đa: 1Hz (1 giây / lần)

 Kích thước 15mm x 12mm x 5.5mm.

Cảm biến độ ẩm và nhiệt độ DHT11 Temperature Humidity Sensor là cảm biến rất thông dụng hiện nay vì chi phí rẻ và rất dễ lấy dữ liệu thông qua giao tiếp 1 wire (giao tiếp digital 1 dây truyền dữ liệu duy nhất) Bộ tiền xử lý tín hiệu tích hợp trong cảm biến giúp bạn có được dữ liệu chính xác mà không phải qua bất kỳ tính toán nào So với cảm biến đời mới hơn là DHT22 thì DHT11 cho khoảng đo và độ chính xác kém hơn rất nhiều. c) Màn hình LCD 16x2 và giao tiếp I2C

LCD 16×2 được sử dụng để hiển thị trạng thái hoặc các thông số.

 LCD 16×2 có 16 chân trong đó 8 chân dữ liệu (D0 – D7) và 3 chân điều khiển (RS, RW, EN).

 5 chân còn lại dùng để cấp nguồn và đèn nền cho LCD 16×2.

 Các chân điều khiển giúp ta dễ dàng cấu hình LCD ở chế độ lệnh hoặc chế độ dữ liệu.

 Chúng còn giúp ta cấu hình ở chế độ đọc hoặc ghi.

LCD 16×2 có thể sử dụng ở chế độ 4 bit hoặc 8 bit tùy theo ứng dụng ta đang làm.

LCD có quá nhiều nhiều chân gây khó khăn trong quá trình đấu nối và chiếm dụng nhiều chân trên vi điều khiển

Module I2C LCD ra đời và giải quyết vấn để này cho bạn.

Thay vì phải mất 6 chân vi điều khiển để kết nối với LCD 16×2 (RS,

EN, D7, D6, D5 và D4) thì module IC2 bạn chỉ cần tốn 2 chân (SCL, SDA) để kết nối.

Module I2C hỗ trợ các loại LCD sử dụng driver HD44780(LCD 16×2, LCD 20×4, …) và tương thích với hầu hết các vi điều khiển hiện nay. Ưu điểm

 Tiết kiệm chân cho vi điều khiển.

 Dễ dàng kết nối với LCD.

 Điện áp hoạt động: 2.5-6V DC.

 Hỗ trợ màn hình: LCD1602,1604,2004 (driver HD44780).

 Địa chỉ mặc định: 0X27 (có thể điều chỉnh bằng ngắn mạch chân A0/A1/A2).

 Tích hợp Jump chốt để cung cấp đèn cho LCD hoặc ngắt.

 Tích hợp biến trở xoay điều chỉnh độ tương phản cho LCD. Để sử dụng màn hình LCD giao tiếp I2C sử dụng Arduino thì ta cần cài đặt thư viện Liquidcrystal_I2C

Sử dụng công cụ lập trình Arduino IDE. o Ưu điểm

- Phần mềm lập trình mã nguồn mở miễn phí

- Sử dụng ngôn ngữ lập trình C/C++ thân thiện với các lập trình viên

- Hỗ trợ lập trình tốt cho bo mạch Arduino

- Thư viện hỗ trợ phong phú (~700 thư viện)

- Giao diện đơn giản dễ sử dụng

- Hỗ trợ đa nền tảng như Windows, MacOS, Linux

Arduino IDE là một phần mềm được phân phối chính hãng, tải miễn phí và giao diện thân thiện với người dùng Phần mềm liên tục được nhà phát hành cập nhật dưới sự giúp đỡ của Cộng đồng người dùng Arduino đông đảo nên độ bảo mật là rất cao Arduino IDE là phần mềm nên sử dụng nhất để tải code vào bo mạch Arduino.

Sử dụng công cụ lập trình C# và môi trường Visual Studio. o Ưu điểm:

- Giao diện và cấu trúc gần gũi, phổ biến, dễ dàng tiếp cận

- C# có thể biên dịch trên nhiều nền tảng máy tính khác nhau Nhờ sự hỗ trợ của NET

- Cải tiến các khuyết điểm trước kia của C++ và Java

- Đồng thời, dựa trên các nền tảng ngôn ngữ lập trình có sẵn, C++ được thừa hưởng những thế mạnh trước đó của các ngôn ngữ C++, Java, Pascal o Nhược điểm:

- C# là chỉ chạy trên nền tảng Windows và có cài NET Framework Nên đây được xem là nhược điểm lớn nhất của C#

- Thao tác với phần cứng hầu hết phải dựa vào Windows

C#, QT là một trong những phần mềm thông dụng để lập trình giao diện GUI trên Windows Với những sự thừa kế của các ngôn ngữ lập trình tiền than, C# rất than thiện với người lập trình.

THỬ NGHIỆM VÀ KẾT LUẬN

1 THỬ NGHIỆM a Sơ đồ mạch b Giao diện điều khiển

(1)Thanh công cụ: a COM: cổng kết nối với thiệt bị b Connect: Kết nối với thiết bị c Run: Khởi động thiết bị d Pause: Tạm dừng e Clear: Xóa dữ liệu, trở về cài đặt gốc f Save: Lưu các giá trị ở bảng (2) về file Excel g Exit: Thoát (2)Bảng hiện thời gian thực và giá trị độ ẩm/nhiệt độ (3)Biểu đồ giá trị độ ẩm/nhiệt độ theo thời gian thực c Các bước tiến hành

1 Kết nối Kit Arduino với cổng COM, sau đó nhấn Connect để xác nhận kết nối

2 Nhấn Run để khởi động hệ thống

Bài học kinh nghiệm

- Linh kiện hệ thống rẻ, dễ dàng mua được

- Hệ thống Cơ điện tử đã được hoàn thiện

- Giao diện được thiết kế thông qua Visual Studio dựa theo kiến thức học được

- Sản phẩm được chạy bình thường và theo yêu cầu đề ra b Khó khăn:

- Độ nhạy của cảm biến chưa thực sự cao c Phương hướng phát triển:

- Có thể ứng dụng vào trong công nghiệp như đo nhiệt độ, độ ẩm trong môi trường khép kín

- Thêm thiết bị điều khiển nhiệt độ, độ ẩm như máy sưởi, quạt, máy phun sương để đạt được yêu cầu nhiệt độ độ ẩm mong muốn

- Thay thế cảm biến tốt hơn để tăng tốc độ xử lý

- Thay thế bộ vi xử lí để giảm giá thành, tăng bộ nhớ

Phần 4: Bài học kinh nghiệm:

1 Về triển khai kế hoạch bài tập lớn

Cả nhóm cần nhanh chóng thống nhất được đề tài sớm hơn, vì mỗi người có một ý tưởng nhưng lại chưa tìm hiểu rõ đề tài của mình để bảo vệ ý tưởng, dẫn đến mất một thời gian mới chốt được đề tài.

Cả nhóm nên có chia nhỏ những kế hoạch với thời gian cụ thể và thôi thúc các thành viên hoàn thành đúng tiến độ.

2 Về thiết kế hệ thống

Cần phải chỉn chu hơn nữa để có thể tối ưu đường dây dẫn, nhìn khoa học hơn, bắt mắt hơn.

3 Về lập trình Arduino

Trang web wokwi.com là một trang web rất hữu ích để giả lập nghiệm sản phẩm mà độ hiệu quả mang lại khá tốt Có thể thử trước khi quyết định thêm một linh kiện để xem tính khả thi của nó như thế nào.

4 Về lập trình GUI

Có thể sử dụng QT hoặc C# để lập trình giao diện Việc học lập trình giao diện trở nên dễ dàng hơn khi có sự hướng dẫn của giáo viên, nhiều phương tiện tìm hiểu và sự giúp đỡ của những thành viên trong nhóm Sản phẩm trên không phải là sản phẩm tốt nhất nhưng sẽ là nền tảng tốt để tiếp tục học tập, nghiên cứu và phát triển liên quan đến ngành Cơ điện tử trong tương lai.

Chúng em xin chân thành cảm ơn thầy Dương Văn Lạc đã tận tình hướng dẫn , giải đáp thắc mắc và chỉ bảo nhóm em trong suốt thời gian nhóm em hoàn thành bài tập lớn

Mặc dù đã cố gắng hoàn thành đề tài tốt nhất nhưng do thời gian và kiến thức còn có hạn nên chúng em sẽ không thể tránh khỏi những thiếu sót nhất định, rất mong nhận được sự cảm thông, chia sẻ và tận tình đóng góp chỉ bảo của thầy cũng như các bạn.

#include const int DHTPIN = 7; const int DHTTYPE = DHT11; DHT dht(DHTPIN, DHTTYPE);

}; int state = 0; long time_now = 0; long time_start = 0; float gettemp(); float data = 0; void setup() {

Serial.begin(9600); dht.begin(); lcd.init(); lcd.backlight(); lcd.print("Nhiet do: "); lcd.setCursor(0,1); lcd.print("Do am: "); lcd.createChar(1, degree); pinMode(2,OUTPUT);

// Điều khiển Arduino qua giá trị của biến state if(Serial.available())

{ char temp = Serial.read(); if(temp == '0') state = 0; if(temp == '1') state = 1; if(temp == '2') state = 2;

// state = 0: dừng Arduino case 0: break; case 1: gettemp();

Serial.println(round(data)); break;

// state = 2: Reset dữ liệu và thời gian về 0 case 2: data = 0; time_now = 0; state = 0; break;

} float h = dht.readHumidity(); float t = dht.readTemperature(); if (t > 33)

} else { lcd.setCursor(10,0); lcd.print(round(t)); lcd.print(" "); lcd.write(1); lcd.print("C"); lcd.setCursor(10,1); lcd.print(round(h)); lcd.print(" %");

{ time_start = millis(); data = dht.readTemperature(); delay(100); time_now = time_now + millis() - time_start;}

Code lập trình giao diện 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; using System.IO.Ports; using System.Xml; using ZedGraph; namespace GraphRealTime

{ public partial class Form1 : Form

{ string SDatas = String.Empty; // Khai báo chuỗi để lưu dữ liệu cảm biến gửi qua Serial string SRealTime = String.Empty; // Khai báo chuỗi để lưu thời gian gửi qua Serial int status = 0; // Khai báo biến để xử lý sự kiện vẽ đồ thị double realtime = 0; //Khai báo biến thời gian để vẽ đồ thị double datas = 0; //Khai báo biến dữ liệu cảm biến để vẽ đồ thị public Form1()

} private void Form1_Load(object sender, EventArgs e)

{ comboBox1.DataSource = SerialPort.GetPortNames(); // Lấy nguồn cho comboBox là tên của cổng COM comboBox1.Text = Properties.Settings.Default.ComName;

GraphPane myPane = zedGraphControl1.GraphPane; myPane.Title.Text = "Đồ thị dữ liệu theo thời gian"; myPane.XAxis.Title.Text = "Thời gian (s)"; myPane.YAxis.Title.Text = "Dữ liệu";

LineItem curve = myPane.AddCurve("Dữ liệu", list, Color.Red, SymbolType.None); myPane.XAxis.Scale.Min = 0; myPane.XAxis.Scale.Max = 30; myPane.XAxis.Scale.MinorStep = 1; myPane.XAxis.Scale.MajorStep = 5; myPane.YAxis.Scale.Min = -100; myPane.YAxis.Scale.Max = 100; myPane.AxisChange();

// Hàm Tick này sẽ bắt sự kiện cổng Serial mở hay không private void timer1_Tick(object sender, EventArgs e)

// Hàm này lưu lại cổng COM đã chọn cho lần kết nối private void SaveSetting()

Properties.Settings.Default.ComName = comboBox1.Text;

// Nhận và xử lý string gửi từ Serial private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)

{ string[] arrList = serialPort1.ReadLine().Split('|'); // Đọc một dòng của Serial, cắt chuỗi khi gặp ký tự gạch đứng

SRealTime = arrList[0]; // Chuỗi đầu tiên lưu vào SRealTime

SDatas = arrList[1]; // Chuỗi thứ hai lưu vào SDatas double.TryParse(SDatas, out datas); // Chuyển đổi sang kiểu double double.TryParse(SRealTime, out realtime); realtime = realtime / 1000.0; // Đối ms sang s status = 1; // Bắt sự kiện xử lý xong chuỗi, đổi starus về 1 để hiển thị dữ liệu trong ListView và vẽ đồ thị

// Hiển thị dữ liệu trong ListView private void Data_Listview()

ListViewItem item = new ListViewItem(realtime.ToString()); // Gán biến realtime vào cột đầu tiên của ListView item.SubItems.Add(datas.ToString()); listView1.Items.Add(item); // Gán biến datas vào cột tiếp theo của ListView

// Không nên gán string SDatas vì khi xuất dữ liệu sang Excel sẽ là dạng string, không thực hiện các phép toán được listView1.Items[listView1.Items.Count - 1].EnsureVisible(); // Hiện thị dòng được gán gần nhất ở ListView, tức là mình cuộn ListView theo dữ liệu gần nhất đó

// Vẽ đồ thị private void Draw()

LineItem curve = zedGraphControl1.GraphPane.CurveList[0] as LineItem; if (curve == null) return;

IPointListEdit list = curve.Points as IPointListEdit; if (list == null) return; list.Add(realtime, datas); // Thêm điểm trên đồ thị

Scale xScale = zedGraphControl1.GraphPane.XAxis.Scale;

Scale yScale = zedGraphControl1.GraphPane.YAxis.Scale;

// Tự động Scale theo trục x if (realtime > xScale.Max - xScale.MajorStep)

{ xScale.Max = realtime + xScale.MajorStep; xScale.Min = xScale.Max - 30;

// Tự động Scale theo trục y if (datas > yScale.Max - yScale.MajorStep)

{ yScale.Max = datas + yScale.MajorStep;

} else if (datas < yScale.Min + yScale.MajorStep)

{ yScale.Min = datas - yScale.MajorStep;

} zedGraphControl1.AxisChange(); zedGraphControl1.Invalidate(); zedGraphControl1.Refresh();

// Xóa đồ thị, với ZedGraph thì phải khai báo lại như ở hàm Form1_Load, nếu không sẽ không hiển thị private void ClearZedGraph()

{ zedGraphControl1.GraphPane.CurveList.Clear(); // Xóa đường zedGraphControl1.GraphPane.GraphObjList.Clear(); // Xóa đối tượng zedGraphControl1.AxisChange(); zedGraphControl1.Invalidate();

GraphPane myPane = zedGraphControl1.GraphPane; myPane.Title.Text = "Đồ thị dữ liệu theo thời gian"; myPane.XAxis.Title.Text = "Thời gian (s)"; myPane.YAxis.Title.Text = "Dữ liệu";

LineItem curve = myPane.AddCurve("Dữ liệu", list, Color.Red, SymbolType.None); myPane.XAxis.Scale.Min = 0; myPane.XAxis.Scale.Max = 30; myPane.XAxis.Scale.MinorStep = 1; myPane.XAxis.Scale.MajorStep = 5; myPane.YAxis.Scale.Min = -100; zedGraphControl1.AxisChange();

// Hàm xóa dữ liệu private void ResetValue()

SRealTime = String.Empty; status = 0; // Chuyển status về 0

// Hàm lưu ListView sang Excel private void SaveToExcel()

Microsoft.Office.Interop.Excel.Application xla = new

Microsoft.Office.Interop.Excel.Application(); xla.Visible = true;

Microsoft.Office.Interop.Excel.Workbook wb xla.Workbooks.Add(Microsoft.Office.Interop.Excel.XlSheetType.xlWorksheet);

Microsoft.Office.Interop.Excel.Worksheet ws (Microsoft.Office.Interop.Excel.Worksheet)xla.ActiveSheet;

// Đặt tên cho hai ô A1 B1 lần lượt là "Thời gian (s)" và "Dữ liệu", sau đó tự động dãn độ rộng

Microsoft.Office.Interop.Excel.Range rg (Microsoft.Office.Interop.Excel.Range)ws.get_Range("A1", "B1"); ws.Cells[1, 1] = "Thời gian (s)"; ws.Cells[1, 2] = "Dữ liệu"; rg.Columns.AutoFit();

// Lưu từ ô đầu tiên của dòng thứ 2, tức ô A2 int i = 2; int j = 1; foreach (ListViewItem comp in listView1.Items)

{ ws.Cells[i, j] = comp.Text.ToString(); foreach (ListViewItem.ListViewSubItem drv in comp.SubItems)

{ ws.Cells[i, j] = drv.Text.ToString(); j++;

} private void btConnect_Click(object sender, EventArgs e)

{ serialPort1.Write("2"); //Gửi ký tự "2" qua Serial, tương ứng với state = 2 serialPort1.Close(); btConnect.Text = "Kết nối"; btExit.Enabled = true;

SaveSetting(); // Lưu cổng COM vào ComName

{ serialPort1.BaudRate = 9600; // Baudrate là 9600, trùng với baudrate của Arduino try

{ serialPort1.Open(); btConnect.Text = "Ngắt kết nối"; btExit.Enabled = false;

MessageBox.Show("Không thể mở cổng" + serialPort1.PortName, "Lỗi", MessageBoxButtons.OK, MessageBoxIcon.Error);

} private void btExit_Click(object sender, EventArgs e)

DialogResult traloi; traloi = MessageBox.Show("Bạn có chắc muốn thoát?", "Thoát",

MessageBoxButtons.OKCancel, MessageBoxIcon.Warning); if (traloi == DialogResult.OK)

Application.Exit(); // Đóng ứng dụng

} private void btSave_Click(object sender, EventArgs e)

DialogResult traloi; traloi = MessageBox.Show("Bạn có muốn lưu số liệu?", "Lưu",

MessageBoxButtons.OKCancel, MessageBoxIcon.Warning); if (traloi == DialogResult.OK)

SaveToExcel(); // Thực thi hàm lưu ListView sang Excel

} private void btRun_Click(object sender, EventArgs e)

{ serialPort1.Write("1"); //Gửi ký tự "1" qua Serial, chạy hàm tạo Random ở Arduino } else

MessageBox.Show("Bạn không thể chạy khi chưa kết nối với thiết bị", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Error);

} private void btPause_Click(object sender, EventArgs e)

{ serialPort1.Write("0"); //Gửi ký tự "0" qua Serial, Dừng Arduino

MessageBox.Show("Bạn không thể dừng khi chưa kết nối với thiết bị", "Thông báo", MessageBoxButtons.OK, MessageBoxIcon.Error);

} private void btClear_Click(object sender, EventArgs e)

DialogResult traloi; traloi = MessageBox.Show("Bạn có chắc muốn xóa?", "Xóa dữ liệu",

Ngày đăng: 01/11/2022, 05:17

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w