Tải bản đầy đủ (.pdf) (58 trang)

Giới thiệu về chức năng nhiệm vụ của hệ thống

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.07 MB, 58 trang )

CHƯƠNG 1. Tổng quan về hệ thống cơ điện tử
1.1 Giới thiệu về chức năng nhiệm vụ của hệ thống
1.1.1

Khái niệm Cơ Điện Tử và hệ Cơ Điện Tử

Cơ điện tử là một hệ thống cơ cấu máy có thiết bị điều khiển đã được lập
trình và có khả năng hoạt động một cách linh hoạt. Ứng dụng trong sinh hoạt,
trong công nghiệp, trong lĩnh vực nghiên cứu như máy lạnh, tủ lạnh, máy giặt,
modul sản xuất linh hoạt, tự động hóa q trình sản xuất hoặc cá thiết bị hỗ trợ
nghiên cứu như các thiết bị đo trong các hệ thống kiểm tra.
Khái niệm cơ điện tử được mở ra từ định nghĩa ban đầu của công ty
Yasakawa Electric, theo sau đó là những định nghĩa khác nhau của các nhà khoa
học khác trên toàn thế giới. Tất cả những định nghĩa và phát biểu đó đều xác
đắng và giàu thông tin, tuy nhiên nếu đứng riêng lẻ lại không định nghĩa được
đầy đủ thuật ngữ Cơ Điện Tử.
Hệ thống Cơ Điện Tử là một lĩnh vực đa ngành của khoa học kĩ thuật, hình
thành từ các ngành mũi nhọn như Cơ khí, Điện – Điện tử, Tin học. Tuy nhiên,
trên thực thế hệ thống Cơ Điện Tử không có một định nghĩa rõ ràng. Nó được
tách biệt hồn toàn ở cá phần riêng biệt nhưng được kết hợp trong quá trình thực
hiện.
Các phần tử cơ bản cấu thành nên hệ thống Cơ Điện Tử:
 Hệ thống thông tin
 Hệ thống điện
 Hệ thống cơ khí
 Hệ thống máy tính
 Cảm biến
 Cơ cấu chấp hành / cơ cấu tác động
 Giao tiếp thời gian thực (HMI/GUI)

Hình 1.1 Các thành phần cơ bản của hệ thống Cơ Điện Tử



Giải pháp cơ điện tử trong thiết kế kĩ thuật liên quan đến việc cung cấp
một cấu trúc trong đó có sự tích hợp thành một hệ thống thống nhất của các công
nghệ khác nhau được thiết lập và đánh giá. Sơ đồ khối về toàn bộ hệ thống (một

1


sản phẩm cơ điện tử) trên cơ sở các khối hoặc các modun thành phần được thể
hiện như trên hình 1.2

Hình 1.2 Cấu trúc theo modul hệ Cơ Điện Tử

1.1.2

Hệ thống Cơ Điện Tử được sử dụng hiện nay

Hệ Cơ Điện Tử được phân loại đa dạng và được ứng dụng rộng rãi trong
cuộc sống:
- Trong y học: Các thiết bị máy cắt lớp, các máy chụp X-quang, các thiết bị
mổ nội soi,…
- Trong công nghiệp: Hệ thống FMS, robot công nghiệp, hệ thống phân
loại, kho hàng tự động, …
- Trong văn phịng: Hệ thống mạng cơng tác, có sử dụng máy tính, các thiết
bị văn phịng (máy in, máy fax,…)
- Trong sinh hoạt gia đình: Các sản phẩm tiêu dùng (máy giặt, điện thoại,
tivi,…) hệ thống giám sát bảo vệ ngôi nhà, …
1.1.3

Đề tài hệ thống đo và cảnh báo khí gas


Hệ thống cảnh báo rị rỉ khí là hệ thống có chức năng phát hiện sự hiện diện của
một loại khí trong một khu vực nhất định nào đó, hệ thống này thường là một phần của
hệ thống an toàn của nhà máy hoặc khu vực dễ chịu ảnh hưởng của những loại khí độc
hại. Hệ thống này gồm 2 phần chính, phần thứ nhất là đầu rị khí có tác dụng phát hiện
khí bị rị rỉ. Phần thứ 2 là thiết bị cảnh báo, có chng cảnh báo, đèn cảnh báo, màn hình
hiển thị nồng độ khí. Sau khi đầu rị phát hiện khí, nó sẽ truyền tín hiệu cho bộ phận
cảnh báo để đưa ra cảnh báo và ngắt nguồn khí, chạy các hệ thống ngăn ngừa cháy nổ.


Phát hiện rị rỉ khí là q trình xác định rị rỉ khí có khả năng gây nguy hiểm hay
khơng. Việc tiếp xúc với khí độc cũng có thể xảy ra trong các hoạt động như sợ, khử
trùng, đổ nhiên liệu, vận hành bãi chôn lấp,… Các cảm biến thông thường bao gồm cảm
biến khí cháy, thiết bị dị quang phổ, cảm biến bán dẫn,… Những loại cảm biến này
được sử dụng cho nhiều ứng dụng và có thể tìm thấy trong các nhà máy, xí nghiệp hay
như kiểm tra chất lượng và nhà ở.
Sau khi tiến hành lắp đặt thì tất cả đầu rị khí ohair được hiệu chỉnh lần đầu và
định kì hiệu chỉnh theo chu kì để cho hệ thống được hoạt động ổn định và ít xảy ra sai
sót nhất có thể.
Trong thực tế, hệ thống này đã được ứng dụng rộng rãi trong các hộ gia đình sử
dụng gas hay như trong khách sạn, nhà hàng và những khu công nghiệp như là biện
pháp an tồn bắt buộc.

Hình 1.3 Hệ thống cảnh báo rị rỉ khí Acetylene C2H2 ngắt van tự động

1.2 Mục tiêu hồn thành của đề tài
- Thiết kế mơ hình và đo cảnh báo khí gas sử dụng kit Arduino UNO với những
-

chức năng cơ bản của hệ thống.

Thiết kế giao diện người dùng GUI phù hợp có thể kết nối với máy tính
Kết suất bản vẽ sơ đồ điện hệ thống


CHƯƠNG 2. Các thành phần cơ bản của hệ thống cơ điện
2.1 Các phần tử đầu vào
Trong đề tài này, phần tử đầu vào của hệ thống nhóm chọn và sử dụng là
cảm biến khí gas MQ-2 do mức độ phổ biến và dễ tiếp cận của nó. Cảm biến
MQ-2 là cảm biến khí gas thơng dụng trong các dịng cảm biến MQ. Cảm biến
MQ-2 thuộc dòng cảm biến bán dẫn, nó sử dụng một mẩu chất bán dẫn oxit kim
loại (MOS) làm thành phần nhạy để xác định sự thay đổi của khí. Sự có mặt của
các chất khí khác ngồi khơng khí sẽ làm thay đổi điện trở của chất bán dẫn, từ
đó làm thay đổi điện áp, và từ đây ta có thể xác định được sự thay đổi của khí.
Cảm biến MQ-2 hoạt động dưới điện áp 5V và cơng suất trung bình khoảng
800mW. Nó có thể phát hiện các loại khí như LPG, khói, Alcohol, Propane,
Hydrogen, Methane và Cacbon monoxide từ 200 cho đến 10000ppm.

Một vài thông số kĩ thuật liên quan được thể hiện trong bảng 1.
Bảng 1. Các thơng số chính cảm biến MQ2

Kí hiệu

Tên thơng số

Thơng số

Ghi chú

VC
VH

RL
RH

Điện áp mạch
Điện áp làm nóng
Điện trở tải
Điện trở làm nóng

5V±0.1
5V±0.1
Có thể điều chỉnh
33Kohm±5%

AC hoặc DC
AC hoặc DC
10Kohm ±5%
Nhiệt độ phịng

PH

Cơng suất làm
nóng

≤800mW

TO
TS
RH
O2


Nhiệt độ hoạt động
Nhiệt độ bảo quản
Độ ẩm hoạt động
Nồng độ oxy

RS
α
Điều kiện
tiêu chuẩn
Thời gian
chuẩn bị

-20 ℃ - 50 ℃
-20 ℃ - 70 ℃
≤95%
21% (Điều kiện tiêu
chuẩn) Nồng độ Oxy có
thể ảnh hưởng đến độ
nhạy.
Điện trở cảm biến
3Kohm-30Kohm
(1000 ppm iso-butane)
Hệ số góc
≤0.6
Nhiệt độ: 20±2 ℃ , điện áp 5V±0.1
Độ ẩm: 65% ± 5%
Trên 24 giờ

Tối thiểu là 2%


Nồng độ phát hiện:
200-5000ppm LPG
và Propane
300-5000ppm
Butane
5000-20000ppm
Methane
300-5000ppm H2
100-2000ppm
Alcohol


Hình 2.4 Thơng số kích thước module MQ – 2

Hình 2.5 Sơ đồ điện module MQ – 2

2.2 Các phần tử đầu ra
-

Trình bày về các thơng tin cơ bản của mỗi phần tử đầu ra:
Chức năng, nguyên lý hoạt động
Thơng số kỹ thuật: điện áp hoạt động, dạng tín hiệu điều khiển, ký hiệu phần tử.

Các phần tử đầu ra là thành phần thực hiện các kết quả sau khi bộ điều khiển xử lý
xong các tín hiệu của phần tử đầu vào. Trong đề tài này thì các phần tử đầu ra chính là
các cơ cấu chấp hành cụ thể chính là động cơ bước và cịi báo động.

2.2.1

Động cơ bước 28BYJ-48 5V


Động cơ bước 5VDC là động cơ bước 4 pha, 5 dây điều khiển. 4 trong 5
dây này được kết nối với 4 cuộn dây trong động cơ và 1 dây là dây nguồn chung
cho cả 4 cuộn dây. Mỗi bước của động cơ quét 1 góc 5.625 độ, vậy để quay 1
vịng động cơ phải thực hiện 64 bước.
Rated voltage : 5VDC
Number of Phase : 4
Speed Variation Ratio : 1/64
Stride Angle : 5.625° /64
Frequency : 100Hz
DC resistance : 50Ω±7%(25℃)


Hình 2.6 Thơng số kích thước động cơ bước 28BỴ - 48 5V

Động cơ bước hoạt động kèm theo với IC ULN2003 để có thể điều khiển
bước góc xoay. Như chúng ta thấy có bốn cuộn dây trong động cơ và một đầu
của tất cả các cuộn dây được gắn với + 5V (Đỏ) và các đầu còn lại (Cam, Hồng,
Vàng và Xanh) được đưa ra ngoài như dây. Dây Đỏ luôn được cung cấp nguồn +
5V không đổi và + 5V này sẽ đi qua (cung cấp năng lượng) cho cuộn dây chỉ khi
đầu kia của cuộn dây được nối đất. Động cơ bước chỉ có thể quay nếu các cuộn
dây được cấp điện (nối đất) theo một trình tự hợp lý. Chuỗi logic này có thể được
lập trình bằng vi điều khiển hoặc bằng cách thiết kế mạch kỹ thuật số. Trình tự
mà mỗi cuộn dây sẽ được kích hoạt được hiển thị trong bảng dưới đây. Ở đây “1”
đại diện cho cuộn dây được giữ ở + 5V, vì cả hai đầu của cuộn dây đều ở + 5V
(màu đỏ và các đầu khác), cuộn dây sẽ không được cung cấp năng lượng. Tương
tự “0” đại diện cho cuộn dây được giữ dưới đất, bây giờ một đầu sẽ là + 5V và
đầu kia được nối đất để cuộn dây sẽ được cung cấp năng lượng.

Hình 2.7 Sơ đồ dây động cơ



Bảng 2 Tín hiệu góc quay động cơ
Màu cuộn dây
Cam
Vàng
Hồng
Xanh dương
Đỏ

2.2.2

Bước
1
0
1
1
1
1

Trình tự xoay theo hướng kim đồng hồ
Bước Bước Bước Bước Bước Bước
2
3
4
5
6
7
0
1

1
1
1
1
0
0
0
1
1
1
1
1
0
0
0
1
1
1
1
1
0
0
1
1
1
1
1
1

Bước

8
0
1
1
0
1

Còi báo động SFM – 27 12V

Còi Báo Động SFM-27 12V là loại còi thường được dùng trong báo cháy,
báo sự cố dân dụng và công nghiệp. Loại còi này tạo ra âm thanh liên tục với
cường độ >90dB
Thơng số kỹ th •t:
- Mã sản phẩm: LOA09
- Điện áp hoạt động: 3- 24V
- Dòng điện tiêu thụ: 100mA
- Khối lượng: 8g

Hình 2.8 Cịi báo động


2.3 Bộ điều khiển

Hình 2.9 Kit Arduino UNO

Thơng số kỹ thuật của Arduino UNO R3
Thông số kỹ thuật của Arduino Uno R3 là tiêu chuẩn, các biến thể gần
như có thông số tương đương.
Arduino Uno được xây dựng với phần nhân là vi điều khiển
ATmega328P, sử dụng thạch anh có chu kì dao động là 16 MHz. Với vi điều

khiển này, tổng cộng có 14 pin (ngõ) ra / vào được đánh số từ 0 tới 13 (trong đó
có 6 pin PWM, được đánh dấu ~ trước mã số của pin). Song song đó, có thêm 6
pin nhận tín hiệu analog được đánh kí hiệu từ A0 - A5, 6 pin này cũng có thể sử
dụng được như các pin ra / vào bình thường (như pin 0 - 13). Ở các pin được đề
cập, pin 13 là pin đặc biệt vì nối trực tiếp với LED trạng thái trên board. Trên
board cịn có 1 nút reset, 1 ngõ kết nối với máy tính qua cổng USB và 1 ngõ cấp
nguồn sử dụng jack 2.1mm lấy năng lượng trực tiếp từ AC-DC adapter hay thông
qua ắc-quy nguồn.
Khi làm việc với Arduino board, một số thuật ngữ sau cần lưu ý:
 Flash Memory: bộ nhớ có thể ghi được, dữ liệu khơng bị mất ngay cả khi
tắt điện. Về vai trị, có thể hình dung bộ nhớ này như ổ cứng để chứa dữ
liệu trên board. Chương trình được viết cho Arduino sẽ được lưu ở đây.
Kích thước của vùng nhớ này dựa vào vi điều khiển được sử dụng, ví dụ
như ATmega8 có 8KB flash memory. Loại bộ nhớ này có thể chịu được
khoảng 10.000 lần ghi / xố.
 RAM: tương tự như RAM của máy tính, mất dữ liệu khi ngắt điện, bù lại
tốc độ đọc ghi xoá rất nhanh. Kích thước nhỏ hơn Flash Memory nhiều
lần.
 EEPROM: một dạng bộ nhớ tương tự như Flash Memory nhưng có chu kì
ghi / xố cao hơn - khoảng 100.000 lần và có kích thước rất nhỏ. Để đọc /
ghi dữ liệu có thể dùng thư viện EEPROM của Arduino.
Ngồi ra, Arduino board còn cung cấp cho các pin khác nhau như pin cấp
nguồn 3.3V, pin cấp nguồn 5V, pin GND, ...
Thơng số kỹ thuật của Arduino board được tóm tắt trong bảng 2:


Bảng 3 Thơng số kĩ thuật chính của Arduino UNO R3

Chip điều khiển


Atmega328P

Điện áp hoạt động

5V

Điện áp đầu vào (khuyên dùng)

7-12V

Điện áp đầu vào (giới hạn)

6-20V

Số chân Digital

14 (trong đó có 6 chân hỗ trợ chỉnh xung
PWM)

Số chân PWM Digital

6

Số chân Analog

6

Dòng điện DC trên mỗi chân I/O

20mA


Dòng điện DC trên trên 3.3V

50mA

Flash Memory

32KB (0.5KB sử dụng để khởi động)

SRAM

2KB (chip Atmega328P)

EEPROM

1KB (chip Atmega328P)

Xung nhịp chip

16MHz

LED_BUILT_IN

PIN13

Chiều dài

68.6mm

Chiều rộng


53.4mm

Khối lượng

25g

2.4 Các dạng giao tiếp được sử dụng
Để kết nối giữa kit Arduino với GUI trên máy tính, nhóm sử dụng chuẩn
truyền thông UART, đây là bộ truyền nhận nối tiếp bất đồng bộ có sẵn với mọi
bộ kit Arduino hiện nay.
Các khái niệm quan trọng trong chuẩn truyền thông UART:
Baudrate: Số bit truyền được trong 1s, ở truyền nhận không đồng bộ thì ở
các bên truyền và nhận phải thống nhất Baudrate. Các thông số tốc độ Baudrate
thường hay sử dụng dể giao tiếp với máy tính là
600,1200,2400,4800,9600,14400,19200,38400,56000,57600,115200.


Frame: Ngoài việc giống nhau của tốc độ baud 2 thiết bị truyền nhận thì
khung truyền của bên cũng được cấu hình giống nhau. Khung truyền quy định số
bit trong mỗi lần truyền, bit bắt đầu “Start bit”, các bit kết thúc (Stop bit), bit
kiểm tra tính chẵn lẻ (Parity), ngồi ra số bit quy định trong một gói dữ liệu cũng
được quy định bởi khung truyền. Có thể thấy, khung truyền đóng một vai trị rất
quan trọng trong việc truyền thành công dữ liệu.
- Idle frame: Đường truyền UART ở mức “1”, để xác nhận hiện tại đường
truyền dữ liệu trống, khơng có frame nào đang được truyền đi.
- Break frame: Đường truyền UART ở mức “0”, để xác nhận hiện tại trên
đường truyền đang truyền dữ liệu, có frame đang được truyền đi.

Hình 2.10 Cấu trúc gói dữ liệu


Start bit: Bit đầu tiên được truyền trong một frame, bit này có chức năng
báo cho bên nhận rằng sắp có một gói dữ liệu truyền đến. Đường truyền UART
ln ở trạng thái cao mức “1” cho đến khi chip muốn truyền dữ liệu đi thì nó gởi
bit start bằng cách kéo xuống mức “0”. Như vậy start bit giá trị điện áp 0V và
phải bắt buộc có bit start trong khung truyền.
Data: Data hay dữ liệu là thông tin mà chúng ta nhận được trong quá trình
truyền và nhận. Data trong STM32 có quy định khung truyền là 8bit hoặc 9bit.
Trong q trình truyền UART, bit có trọng số thấp nhất (LSB – least significant
bit – bên phải) sẽ được truyền trước và cuối cùng là bit có ảnh hưởng cao nhất
(MSB – most significant bit – bên trái)
Parity bit: Parity dùng để kiểm tra dữ liệu truyền có đúng hay khơng. Có 2
loại Parity đó là Parity chẵn (even parity) và parity lẽ (odd parity). Parity chẵn
nghĩa là số bit 1 trong trong data truyền cùng với bit Parity luôn là số chẵn,
ngược lại nếu Parity lẽ nghĩa là số bit 1 trong data truyền cùng với bit Parity
luôn là số lẽ. Bit Parity không phải là bit bắt buộc và vì thế chúng ta có thể loại
bỏ bit này ra khỏi khung truyền.


Stop bits: Stop bits là một bit báo cáo để cho bộ truyền/nhận biết được gói
dữ liệu đã được gởi xong. Stop bits là bit bắt buộc phải có trong khung truyền.
Stop bits có thể là 1bit, 1.5bit, 2bit, 0.5bit tùy thuộc vào ứng dụng UART của
người sử dụng.


CHƯƠNG 3. Hệ thống điều khiển của hệ thống cơ điện tử
3.1 Sơ đồ mạch điện
Notes: Thiết kế sơ đồ kết nối mạch điện cho các phần tử điều khiển với Bộ
điều khiển.



3.2 Chương trình điều khiển
Chức năng chính của mơ hình là đo nồng độ các chất khí xung quanh nên
chương trình điều khiển sẽ tập trung các thành phần này. Với việc sử dụng cảm
biến MQ – 2 sẽ tồn tại những bài tốn sau:
-

Tính tốn điện trở của cảm biến khi có tác động của khí
Hiệu chỉnh cảm biến lúc ban đầu
Quy đổi giá trị đo của cảm biến sang đơn vị ppm

Tính tốn điện trở của cảm biến khi có tác động của khí: Cảm biến và điện trở
tải tạo thành một bộ phân áp. Với điện áp trên điện trở tải và điện trở của nó, điện
trở của cảm biến có thể được tính tốn.
Hiệu chỉnh cảm biến: Chức năng này giả định rằng cảm biến đang ở trong
khơng khí sạch. Nó sử dụng hàm MQResistanceCalculation để tính tốn điện trở
của cảm biến trong khơng khí sạch và sau đó chia nó với
RO_CLEAN_AIR_FACTOR, giá trị này là khác nhau với các cảm biến khác
nhau.
Quy đổi giá trị đo của cảm biến: Bằng cách sử dụng độ dốc và một điểm của
đường thẳng. Giá trị x (giá trị logarit của ppm) của dịng có thể được tính nếu y
(rs_ro_ratio) được cung cấp. Vì nó là một tọa độ logarit, nên lũy thừa 10 được sử
dụng để chuyển đổi kết quả thành một giá trị không phải logarit. Đây là giá trị
ppm của khí cần cảnh báo.
3.3 Giao diện điều khiển
Notes:
-

Sử dụng ngơn ngữ lập trình nào? (C++)


-

Ứng dụng chạy trên thiết bị nào? (laptop)

-

Trình bày chức năng của các phần tử trên giao diện điều khiển.

-

Hướng dẫn cách bước kết nối, cài đặt và sử dụng giao diện điều khiển và
hệ thống cơ điện tử.



CHƯƠNG 4. Kết luận và phương hướng phát triển
Note:
-

Đúc kết và thảo luận những kết quả đã đạt được.
Nêu phương hướng có thể tiếp tục cần phát triển của đề tài trong tương lai.


Phụ lục
4.1 Chương trình điều khiển cảm biến MQ -2
#include "Stepper.h"
// ĐỘNG CƠ
//
const int so_buoc_tren_1_vong = 2048;
Stepper stepper(so_buoc_tren_1_vong, 8, 10, 9, 11);

// CẢM BIẾN MQ2
//
#define MQ_PIN
#define RL_VALUE

(A0)
(5)

#define RO_CLEAN_AIR_FACTOR

(9.83)

#define CALIBARAION_SAMPLE_TIMES

(20)

#define CALIBRATION_SAMPLE_INTERVAL (500)
#define READ_SAMPLE_INTERVAL
#define READ_SAMPLE_TIMES

(5)

#define GAS_LPG

(0)

#define GAS_CO

(1)


#define GAS_SMOKE
float LPGCurve1 = 2.3;
float LPGCurve2 = 0.21;
float LPGCurve3 = -0.47;
float COCurve1 = 2.3;
float COCurve2 = 0.72;
float COCurve3 = -0.34;
float SmokeCurve1 = 2.3;
float SmokeCurve2 = 0.53;
float SmokeCurve3 = -0.44;
float Ro = 10;
float gas=0;
float Threshold=0.19;
// ĐÈN LED, CÒI BÁO
//
int redLED =7;
int greenLED=6;
int buzzer=5;

(10)

(2)


//CỬA THƠNG GIĨ
//
int i=0;
int i1=0;
int goc_mo=0;
int goc_mo_1=0;

int c1=0;
int c2=456;
void setup()
{
Serial.begin(9600);
pinMode(redLED, OUTPUT);
pinMode(greenLED, OUTPUT);
pinMode(buzzer, OUTPUT);
Ro = MQCalibration(MQ_PIN);
stepper.setSpeed(15);
}
void loop()
{
// ĐO VÀ KIỂM TRA SỰ TĂNG GIẢM CỦA NỒNG ĐỘ KHÍ GAS
//
float bgas=gas;
float dataSensor1=MQGetGasPercentage(MQRead(MQ_PIN)/Ro,GAS_LPG);
float dataSensor2=MQGetGasPercentage(MQRead(MQ_PIN)/Ro,GAS_CO);
float dataSensor3=MQGetGasPercentage(MQRead(MQ_PIN)/Ro,GAS_SMOKE);
gas=dataSensor1+dataSensor2+dataSensor3;
// NỒNG ĐỘ VƯỢT MỨC
//
if(gas>=Threshold){
digitalWrite(redLED, HIGH);
digitalWrite(greenLED, LOW);
tone(buzzer, 5000, 200);
// ĐIỀU KHIỂN CỬA THƠNG GIĨ DỰA VÀO CẢM BIẾN
//
if(gas<0.25) i=57;
if(0.25<=gas<0.3) i=114;

if(0.35<=gas<0.4) i=171;
if(0.45<=gas<0.5) i=223;
if(0.55<=gas<0.6) i=285;
if(0.65<=gas<0.7) i=342;
if(0.75<=gas<0.8) i=399;
if(0.85<=gas) i=456;


if(gas>bgas){
if(i<=c2){
c2-=i;
}
else {
i=c2;
c2=0;
}
c1=456-c2;
if(goc_mo_1==0) {
stepper.step(-i);
}
}
else{
i=0;
stepper.step(0);
}
goc_mo+=i*10/57;
}
// AN TỒN, ĐĨNG CỬA THƠNG GIĨ
//
else{

digitalWrite(redLED, LOW);
digitalWrite(greenLED, HIGH);
noTone(buzzer);
i=-c1;
if(goc_mo_1==0){
stepper.step(-i);
}
c1=0;
c2=456;
goc_mo=0;
// ĐIỀU KHIỂN CỬA THƠNG GIĨ THEO Ý MUỐN CỦA NGƯỜI SỬ DỤNG
//
int b_goc_mo_1=goc_mo_1;
String sign=Serial.readString();
int sign1=sign.toInt();
goc_mo_1=sign1*57/10;
i1=goc_mo_1 - b_goc_mo_1;
stepper.step(-i1);
}
Serial.print((String) dataSensor1 + "C" +dataSensor2 + "S" + dataSensor3 + "A" + goc_mo + "B" +
bgas + " " + gas + " i= "+i+" c1: "+c1+", c2: " + c2 + " sign: "+goc_mo_1+ "\n");
delay(1000);


}
// QUY ĐỔI GIÁ TRỊ ANALOG VỀ PPM CỦA CÁC 3 LOẠI KHÍ LPG, CO, KHĨI
//
float MQResistanceCalculation(int raw_adc)
{
return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc));

}

float MQCalibration(int mq_pin)
{
int i;
float val=0;
for (i=0;ival += MQResistanceCalculation(analogRead(mq_pin));
delay(CALIBRATION_SAMPLE_INTERVAL);
}
val = val/CALIBARAION_SAMPLE_TIMES;
val = val/RO_CLEAN_AIR_FACTOR;

return val;
}
float MQRead(int mq_pin)
{
int i;
float rs=0;
for (i=0;irs += MQResistanceCalculation(analogRead(mq_pin));
delay(READ_SAMPLE_INTERVAL);
}
rs = rs/READ_SAMPLE_TIMES;
return rs;
}

float MQGetGasPercentage(float rs_ro_ratio, int gas_id)
{
if ( gas_id == GAS_LPG ) {



return MQGetPercentage(rs_ro_ratio,LPGCurve1,LPGCurve2,LPGCurve3);
} else if ( gas_id == GAS_CO ) {
return MQGetPercentage(rs_ro_ratio,COCurve1,COCurve2,COCurve3);
} else if ( gas_id == GAS_SMOKE ) {
return MQGetPercentage(rs_ro_ratio,SmokeCurve1,SmokeCurve2,SmokeCurve3);
}
return 0;
}

float MQGetPercentage(float rs_ro_ratio, float pcurve1,float pcurve2,float pcurve3)
{
return pow(10,( ((log(rs_ro_ratio)-pcurve2)/pcurve3) + pcurve1));
}

4.2 Chương trình GUI
#pragma once
namespace Nhóm17 {
using namespace std;
using namespace System;
using namespace System::Collections::Generic;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Threading::Tasks;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Text;
using namespace System::Drawing;
using namespace System::IO::Ports;

using namespace System::IO;
using namespace System::Xml;
using namespace System::Windows::Forms::DataVisualization::Charting;
using namespace System::Drawing::Drawing2D;

public ref class MyForm : public System::Windows::Forms::Form
{
public:
MyForm(void)
{
InitializeComponent();
findPorts();
}
protected:
~MyForm()
{


if (components)
{
delete components;
}
}
private: System::ComponentModel::IContainer^ components;
protected:
private: System::Windows::Forms::Panel^ panel3;
private: System::Windows::Forms::TextBox^ textBox1;
private: System::Windows::Forms::Panel^ panel5;
private: System::IO::Ports::SerialPort^ serialPort1;
private: System::Windows::Forms::Timer^ timer1;

private: System::Windows::Forms::DataVisualization::Charting::Chart^ chart1;
private: System::Windows::Forms::Panel^ panel8;
private: System::Windows::Forms::Label^ label18;
private: System::Windows::Forms::Label^ label17;
private: System::Windows::Forms::Label^ label16;
private: System::Windows::Forms::Label^ label15;
private: System::Windows::Forms::Label^ label14;
private: System::Windows::Forms::Label^ label19;
private: System::Windows::Forms::Label^ label21;
private: System::Windows::Forms::Label^ label20;
private: System::Windows::Forms::Panel^ panel9;
private: Color onBackColor = Color::MediumSlateBlue;
private: Color onToggleColor = Color::WhiteSmoke;
private: Color offBackColor = Color::Gray;
private: Color offToggleColor = Color::Gainsboro;
private: Bunifu::Framework::UI::BunifuGradientPanel^ panel12;
private: Bunifu::Framework::UI::BunifuiOSSwitch^ Switch2;
private: Bunifu::Framework::UI::BunifuiOSSwitch^ Switch1;
private: System::Windows::Forms::ComboBox^ comboBox1;
private: System::Windows::Forms::ComboBox^ comboBox2;
private: System::Windows::Forms::Label^ label2;
private: System::Windows::Forms::Label^ label3;
private: Bunifu::Framework::UI::BunifuGradientPanel^ panel11;
private: System::Windows::Forms::Label^ label1;
private: Bunifu::Framework::UI::BunifuThinButton2^ button4;
private: Bunifu::Framework::UI::BunifuGradientPanel^ panel10;
private: Bunifu::Framework::UI::BunifuThinButton2^ button6;
private: System::Windows::Forms::Panel^ panel4;
private: System::Windows::Forms::Label^ label6;
private: System::Windows::Forms::Button^ button3;

private: System::Windows::Forms::Panel^ panel2;
private: System::Windows::Forms::Label^ label5;
private: System::Windows::Forms::Button^ button2;
private: System::Windows::Forms::Panel^ panel1;
private: System::Windows::Forms::Label^ label4;


private: System::Windows::Forms::Button^ button1;
private: Bunifu::Framework::UI::BunifuCircleProgressbar^ CircleProgressbar1;
private: Bunifu::Framework::UI::BunifuCircleProgressbar^ CircleProgressbar3;
private: Bunifu::Framework::UI::BunifuCircleProgressbar^ CircleProgressbar2;
private: System::Windows::Forms::Label^ label9;
private: System::Windows::Forms::Label^ label8;
private: System::Windows::Forms::Label^ label7;
private: System::Windows::Forms::TrackBar^ trackBar1;
private: System::Windows::Forms::Label^ label10;
private: Bunifu::Framework::UI::BunifuThinButton2^ button5;
private: Bunifu::Framework::UI::BunifuThinButton2^ button8;
private: System::Windows::Forms::CheckBox^ checkBox3;
private: System::Windows::Forms::CheckBox^ checkBox2;
private: System::Windows::Forms::CheckBox^ checkBox1;
private: Bunifu::Framework::UI::BunifuDropdown^ Dropdown1;
private: System::Windows::Forms::Label^ label13;
private: System::Windows::Forms::Label^ label12;
private: System::Windows::Forms::Label^ label11;
private: System::Windows::Forms::Timer^ timer2;
private: Bunifu::Framework::UI::BunifuGauge^ Gauge1;
private: System::Windows::Forms::Label^ label24;
private: System::Windows::Forms::Label^ label23;
private: System::Windows::Forms::Label^ label22;

private: System::Windows::Forms::Label^ label25;
private: System::Windows::Forms::RadioButton^ radioButton1;
private: System::Windows::Forms::TrackBar^ trackBar2;
private: System::Windows::Forms::Label^ label28;
private: System::Windows::Forms::Label^ label27;
private: System::Windows::Forms::Label^ label26;
private: System::Windows::Forms::RadioButton^ radioButton2;
String^ item1 = "GAS";
String^ item2 = "Lpg, Co, Smoke";
#pragma region Windows Form Designer generated code
void InitializeComponent(void)
{
this->components = (gcnew System::ComponentModel::Container());
System::ComponentModel::ComponentResourceManager^ resources = (gcnew
System::ComponentModel::ComponentResourceManager(MyForm::typeid));
System::Windows::Forms::DataVisualization::Charting::ChartArea^ chartArea1 = (gcnew
System::Windows::Forms::DataVisualization::Charting::ChartArea());
System::Windows::Forms::DataVisualization::Charting::Legend^ legend1 = (gcnew
System::Windows::Forms::DataVisualization::Charting::Legend());
System::Windows::Forms::DataVisualization::Charting::Series^ series1 = (gcnew
System::Windows::Forms::DataVisualization::Charting::Series());
System::Windows::Forms::DataVisualization::Charting::Series^ series2 = (gcnew
System::Windows::Forms::DataVisualization::Charting::Series());


System::Windows::Forms::DataVisualization::Charting::Series^ series3 = (gcnew
System::Windows::Forms::DataVisualization::Charting::Series());
System::Windows::Forms::DataVisualization::Charting::Series^ series4 = (gcnew
System::Windows::Forms::DataVisualization::Charting::Series());
this->panel3 = (gcnew System::Windows::Forms::Panel());

this->button8 = (gcnew Bunifu::Framework::UI::BunifuThinButton2());
this->label19 = (gcnew System::Windows::Forms::Label());
this->textBox1 = (gcnew System::Windows::Forms::TextBox());
this->panel5 = (gcnew System::Windows::Forms::Panel());
this->Dropdown1 = (gcnew Bunifu::Framework::UI::BunifuDropdown());
this->chart1 = (gcnew System::Windows::Forms::DataVisualization::Charting::Chart());
this->label13 = (gcnew System::Windows::Forms::Label());
this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components));
this->timer1 = (gcnew System::Windows::Forms::Timer(this->components));
this->panel8 = (gcnew System::Windows::Forms::Panel());
this->label28 = (gcnew System::Windows::Forms::Label());
this->label27 = (gcnew System::Windows::Forms::Label());
this->label26 = (gcnew System::Windows::Forms::Label());
this->radioButton2 = (gcnew System::Windows::Forms::RadioButton());
this->label25 = (gcnew System::Windows::Forms::Label());
this->radioButton1 = (gcnew System::Windows::Forms::RadioButton());
this->trackBar2 = (gcnew System::Windows::Forms::TrackBar());
this->label24 = (gcnew System::Windows::Forms::Label());
this->label23 = (gcnew System::Windows::Forms::Label());
this->label22 = (gcnew System::Windows::Forms::Label());
this->Gauge1 = (gcnew Bunifu::Framework::UI::BunifuGauge());
this->label12 = (gcnew System::Windows::Forms::Label());
this->label11 = (gcnew System::Windows::Forms::Label());
this->label10 = (gcnew System::Windows::Forms::Label());
this->trackBar1 = (gcnew System::Windows::Forms::TrackBar());
this->Switch2 = (gcnew Bunifu::Framework::UI::BunifuiOSSwitch());
this->Switch1 = (gcnew Bunifu::Framework::UI::BunifuiOSSwitch());
this->label21 = (gcnew System::Windows::Forms::Label());
this->label20 = (gcnew System::Windows::Forms::Label());
this->label17 = (gcnew System::Windows::Forms::Label());

this->label16 = (gcnew System::Windows::Forms::Label());
this->label15 = (gcnew System::Windows::Forms::Label());
this->label14 = (gcnew System::Windows::Forms::Label());
this->label18 = (gcnew System::Windows::Forms::Label());
this->panel9 = (gcnew System::Windows::Forms::Panel());
this->panel12 = (gcnew Bunifu::Framework::UI::BunifuGradientPanel());
this->panel4 = (gcnew System::Windows::Forms::Panel());
this->checkBox3 = (gcnew System::Windows::Forms::CheckBox());
this->label9 = (gcnew System::Windows::Forms::Label());
this->CircleProgressbar3 = (gcnew Bunifu::Framework::UI::BunifuCircleProgressbar());
this->label6 = (gcnew System::Windows::Forms::Label());
this->button3 = (gcnew System::Windows::Forms::Button());


this->panel2 = (gcnew System::Windows::Forms::Panel());
this->checkBox2 = (gcnew System::Windows::Forms::CheckBox());
this->label8 = (gcnew System::Windows::Forms::Label());
this->CircleProgressbar2 = (gcnew Bunifu::Framework::UI::BunifuCircleProgressbar());
this->label5 = (gcnew System::Windows::Forms::Label());
this->button2 = (gcnew System::Windows::Forms::Button());
this->panel1 = (gcnew System::Windows::Forms::Panel());
this->checkBox1 = (gcnew System::Windows::Forms::CheckBox());
this->label7 = (gcnew System::Windows::Forms::Label());
this->CircleProgressbar1 = (gcnew Bunifu::Framework::UI::BunifuCircleProgressbar());
this->label4 = (gcnew System::Windows::Forms::Label());
this->button1 = (gcnew System::Windows::Forms::Button());
this->comboBox1 = (gcnew System::Windows::Forms::ComboBox());
this->comboBox2 = (gcnew System::Windows::Forms::ComboBox());
this->label2 = (gcnew System::Windows::Forms::Label());
this->label3 = (gcnew System::Windows::Forms::Label());

this->panel11 = (gcnew Bunifu::Framework::UI::BunifuGradientPanel());
this->label1 = (gcnew System::Windows::Forms::Label());
this->button4 = (gcnew Bunifu::Framework::UI::BunifuThinButton2());
this->panel10 = (gcnew Bunifu::Framework::UI::BunifuGradientPanel());
this->button5 = (gcnew Bunifu::Framework::UI::BunifuThinButton2());
this->button6 = (gcnew Bunifu::Framework::UI::BunifuThinButton2());
this->timer2 = (gcnew System::Windows::Forms::Timer(this->components));
this->panel3->SuspendLayout();
this->panel5->SuspendLayout();
(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->chart1))->BeginInit();
this->panel8->SuspendLayout();
(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->trackBar2))->BeginInit();
(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->trackBar1))->BeginInit();
this->panel9->SuspendLayout();
this->panel12->SuspendLayout();
this->panel4->SuspendLayout();
this->panel2->SuspendLayout();
this->panel1->SuspendLayout();
this->panel11->SuspendLayout();
this->panel10->SuspendLayout();
this->SuspendLayout();
//
// panel3
//
this->panel3->BackColor = System::Drawing::SystemColors::Control;
this->panel3->BorderStyle = System::Windows::Forms::BorderStyle::Fixed3D;
this->panel3->Controls->Add(this->button8);
this->panel3->Controls->Add(this->label19);
this->panel3->Controls->Add(this->textBox1);
this->panel3->Location = System::Drawing::Point(18, 358);

this->panel3->Margin = System::Windows::Forms::Padding(2);


this->panel3->Name = L"panel3";
this->panel3->Size = System::Drawing::Size(458, 238);
this->panel3->TabIndex = 1;
//
// button8
//
this->button8->ActiveBorderThickness = 1;
this->button8->ActiveCornerRadius = 20;
this->button8->ActiveFillColor = System::Drawing::SystemColors::MenuHighlight;
this->button8->ActiveForecolor = System::Drawing::Color::White;
this->button8->ActiveLineColor = System::Drawing::SystemColors::MenuHighlight;
this->button8->BackColor = System::Drawing::SystemColors::Control;
this->button8->BackgroundImage = (cli::safe_cast<System::Drawing::Image^>(resources>GetObject(L"button8.BackgroundImage")));
this->button8->ButtonText = L"Clear";
this->button8->Cursor = System::Windows::Forms::Cursors::Hand;
this->button8->Font = (gcnew System::Drawing::Font(L"Century Gothic", 14.25F,
System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(0)));
this->button8->ForeColor = System::Drawing::SystemColors::ActiveCaptionText;
this->button8->IdleBorderThickness = 1;
this->button8->IdleCornerRadius = 20;
this->button8->IdleFillColor = System::Drawing::Color::White;
this->button8->IdleForecolor = System::Drawing::SystemColors::ActiveCaptionText;
this->button8->IdleLineColor = System::Drawing::Color::DodgerBlue;
this->button8->Location = System::Drawing::Point(378, 5);
this->button8->Margin = System::Windows::Forms::Padding(4);
this->button8->Name = L"button8";

this->button8->Size = System::Drawing::Size(71, 41);
this->button8->TabIndex = 2;
this->button8->TextAlign = System::Drawing::ContentAlignment::MiddleCenter;
this->button8->Click += gcnew System::EventHandler(this, &MyForm::button8_Click);
//
// label19
//
this->label19->AutoSize = true;
this->label19->Font = (gcnew System::Drawing::Font(L"Century Gothic", 14.25F,
System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(0)));
this->label19->ForeColor = System::Drawing::SystemColors::ActiveCaptionText;
this->label19->Location = System::Drawing::Point(16, 12);
this->label19->Margin = System::Windows::Forms::Padding(2, 0, 2, 0);
this->label19->Name = L"label19";
this->label19->Size = System::Drawing::Size(259, 22);
this->label19->TabIndex = 1;
this->label19->Text = L"- HIỂN THỊ THÔNG TIN THỰC:";
//


×