You are on page 1of 51

TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI

VIỆN CƠ KHÍ
-------------

BÁO CÁO BÀI TẬP LỚN


Môn học: KỸ THUẬT LẬP TRÌNH TRONG CƠ ĐIỆN TỬ
Đề tài: Hệ thống tưới cây tự động

Giảng viên hướng dẫn: TS. Dương Văn Lạc


Nhóm :19 – Mã Lớp: 132785
Danh sách nhóm:

STT Họ và tên MSSV


1. Nguyễn Quốc Hùng 20195036
2. Võ Nhật Khang 20195055
3. Tạ Duy Ngọc 20195118

Hà Nội, ngày tháng năm


MỤC LỤC
Mục lục ....................................................................................................................1
Tóm tắt sản phẩm......................................................................................................2
Chương I: Tổng quan về hệ thống tưới cây tự động.................................................3
Chương II: Các phần tử của mạch điều khiển hệ thống tưới cây tự động................5
2.1.Mạch điều khiển: Kit Arduino Leonardo........................................................6
2.2.Cảm biến độ ẩm đất.........................................................................................7
2.3.Cảm biến nhiệt độ LM35................................................................................8
2.4.Module thời gian thực(DS1307).....................................................................9
2.5.Màn hình LCD 20x04(I2C)..........................................................................11
2.6.Rơ-le(5VDC)................................................................................................12
2.7.Máy bơm chìm mini.....................................................................................13
2.8 Nguồn...........................................................................................................14
Chương III: Thiết kế hệ thống tưới cây..................................................................15
3.1 Sơ đồ nối mạch.............................................................................................15
3.2 Sơ đồ thuật toán............................................................................................22
Chương IV.Lập trình..............................................................................................23
4.1.Code Adruino...............................................................................................23
4.2.Code chương trình điều khiển......................................................................30
Chương V:Kết luận................................................................................................49
Tài liệu tham khảo..................................................................................................50

1
Tóm tắt sản phẩm
1.Tên sản phẩm :Máy tưới cây tự động
2.Chức năng
- Đảm bảo cung cấp đây đủ nước cho cây trồng cũng như theo dõi được nhiệt độ ,
độ ẩm của môt trường đất
3.Các linh kiện cấu thành:
 Kít Adruino Leonardo
 Module thời gian thực DS1307
 Relay 5v đóng ngắt thiết bị
 Màn hình LCD 20x04 I2C
 Cảm biến nhiệt độ LM35 và cảm biến độ ẩm đất
 Máy bơm chìm mini
 3 viên pin 1.5V
 Các dây kết nối

2
Chương I. TỔNG QUAN VỀ HỆ THỐNG TƯỚI CÂY TỰ ĐỘNG
1.1. Khái niệm về hệ thống tự động
Hệ thống điều khiển tự động là hệ thống bao gồm các phần tử tự động nhằm
điều khiển các quá trình xảy ra trong thiên nhiên, cuộc sống mà không có sự tham
gia trực tiếp của cong người.
Hệ thống điều khiển tự động: là tập hợp các thành phần vật lý có mối liên
quan và tác động qua lại lẫn nhau để chi huy, tự hiệu chỉnh hoặc điều khiển một hệ
thống khác.
Hệ thống điều khiển tự động xuất hiện ngày nay rất phổ biến.
- Hệ thống điều hòa không khí.
- Hệ thống điều chỉnh độ ẩm.
- Hệ thống tự báo cháy v.v..
Trong môi trường sản xuất:
- Các máy tự động.
- Các đường dây sản xuất, lắp ráp.
- Các máy điều khiển theo chương trình, Máy tính , Robot v.v..
1.2 Vai trò của tự đông hóa trong sản xuất
Nền sản xuấ hiện đại hiện nay là thành quả của quá trình cơ giới hóa và điện
khí hóa công cụ lao động và phương tiện lao đông. Mỗi khi có những đột phá mới
trong lĩnh vực vật liệu hay điện tử và IT thì công nghệ tự động hóa lại có cơ hội
phát triển mạnh mẽ, đem lại những giá trị thiết thực cho xã hội. Tự động hóa là yếu
tố then chốt cho sự phát trỉển của nền sản xuất hiện đại.
Trong thực tiễn, khi tự đông hóa được áp dụng trong quá trình sản xuất sẽ
mang lại lợi ích lớn hơn nhiều lần so với việc sử dụng lao động thủ công. Khi quá
trình sản xuất được vận hành tự động thì không chỉ năng suất lao động tăng cao,
chi phí nhân công được cắt giảm mà còn giúp nâng cao trình độ của người lao
động… Từ đó sẽ tăng khả năng cạnh trạnh của doanh nghiệp cũng như cá nhân,
đáp ứng được nhu cầu ngày càng cao hiện nay.
1.3 Ứng dụng của tự động trong hệ thống tưới cây

3
Nền nông nghiệp lạc hậu yêu cầu một số lượng lớn người lao động trong quá
trình sản xuất mà năng suất vẫn không đáp ứng được cả chất lượng cũng như năng
suất, sản lượng. Ứng dụng tự động vào trong quá trình sản xuất sẽ giúp giảm bớt
sức người, nâng cao giá trị sản phẩm,...
Mặc dù hiện nay tự động hóa đã được ứng dụng từ lâu cho viêc tưới tiêu
song nó chỉ phổ biến ở các nước phát triển, còn đối với các nước đang phát triển
hay các nước kém phát triển tuy nông nghiệp chiếm tỉ trọng lớn nhưng việc ứng
dụng tự động hóa trong việc tưới cây còn chưa được phổ biến. Hiên nay để đáp
ứng được nhu cầu từ thực tiễn thì tự động hóa đã và đang được mở rộng dần dần
quy trong đời sống hiện nay.
Ngày nay với những thành tựu to lớn của khoa học công nghệ thì tự động
hóa đã có thể được áp dụng hầu hết trên mọi lĩnh vực. Có thể nói tự động hóa đã
trở thành xu thế tất yếu cho mọi quốc gia hiện nay.

4
CHƯƠNG 2. CÁC PHẦN TỬ CỦA HỆ THỐNG TƯỚI CÂY TỰ
ĐỘNG

Hệ thống được thiết kế gồm 7 khối:


 Khối thu gồm cảm biến nhiệt độ LM 35, cảm biến độ ẩm đất
 Nguồn
 Khối xử lý trung tâm sử dụng Kit Arduino Leonardo
 Khối hiển thị: Màn hình LCD 2004 I2C
 Khối điều khiển thiết bị sử dụng :Relay 5VDC
 Khối thời gian thực (hẹn giờ) :DS1307
 Cơ cấu chấp hành: máy bơm chìm mini
Sơ đồ khối của mạch

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

-Chức năng của từng khối:


 Khối xử lý trung tâm : Kit Adruino Leonardo điều khiển toàn bộ hoạt
động của mạch là nhận dự liệu giải mã tín hiệu nhiệt độ và độ ẩm.
Sau đó hiển thị trên màn LCD và đưa tín hiệu điều khiển bật/tắt thiết
bị.
 Khối hiển thị: Là màn hình LCD 4 dòng 20 kí tự thể hiện nhiệt độ, độ
ẩm của môi trường đất, thời gian thực.
 Khối điều khiển thiết bị : để đóng ngắt mạch của thiết bị và nhận tín
hiệu tù Kit Adruino Leonardo.

5
 Khối thời gian thực: DS1307 là một IC thời gian thực với nguồn
cung cấp nhỏ, dùng để cập nhật thời gian và ngày tháng .
 Nguồn: Cung cấp năng lượng cho hệ thống
 Khối thu: đo tín hiệu độ ẩm , nhiệt độ
 Cơ cấu chấp hành : Bơm nước để tưới cây

2.1. Kit Adrunio Leonardo


2.1.1 Sơ đồ chân của Adruino Leornardo

Hình 2.2 Sơ đồ chân của Adruino Leonardo

2.1.2. Thông số của Adruino Leonardo


Sơ đồ chân của Adruino Leonardo được thể hiện ở hình 2.2 với các đặc điểm cơ
bản như sau:
6
Vi điều khiển ATmega32u4 (họ 8bit)
Điện áp hoạt động 5V – DC
Tần số hoạt động 16 MHz
Dòng tiêu thụ ở các chân I/O 40mA
Điện áp vào khuyên dùng 7-12V – DC
Điện áp vào giới hạn 6-20V – DC
Số chân Digital I/O 14 (7 chân PWM)
12 (các chân PWM có thể dùng như
Số chân Analog chân Analog bình thường - nghĩa là có
thể dùng Analog read) (độ phân giải
10bit
Dòng tối đa trên mỗi chân I/O 40 mA
Dòng ra tối đa (5V) 500 mA
Dòng ra tối đa (3.3V) 50 mA
Bộ nhớ flash 32 KB (ATmega32u4) với 4KB dùng
bởi bootloader
SRAM 2.5 KB (ATmega32u4)
EEPROM 1 KB (ATmega32u4)
Kích thước 68.6mm x 53.3mm

2.2.Cảm biến đo độ ẩm đất


-Hình dáng và thông số cơ bản

Hình 2.3 Cảm biến đo độ ẩm

7
- Cảm biến đo độ ẩm của đất có 4 chân với kết nối như sau
Cảm biến độ ẩm đất Arduino UNO
Vcc 5V
GND GND
D0 2
A0 A0

-Nguyên lý hoạt động


Cảm biến độ ẩm đất, trạng thái đầu ra mức thấp (0V), khi đất thiếu nước đầu ra
sẽ là mức cao (5V), độ nhạy cao chúng ta có thể điều chỉnh được bằng biến
trở. Phần đầu đo được cắm vào đất để phát hiện độ ẩm của đất, khi độ ầm của
đất đạt ngưỡng thiết lập, đầu ra DO sẽ chuyển trạng thái từ mức thấp lên mức cao.

2.3 Cảm biến nhiệt độ LM35

Hình 2.4 cảm biến nhiệt độ LM35

- Các thông số cơ bản:


Điện áp hoạt động: 4~20VDC
Công suất tiêu thụ: khoảng 60uA
Khoảng đo: -55°C đến 150°C
Điện áp tuyến tính theo nhiệt độ: 10mV/°C
Sai số: 0.25°C
Kiểu chân: TO92
8
Kích thước: 4.3 × 4.3mm
-Nguyên lý hoạt động:
Cảm biến LM35 hoạt động bằng cách cho ra một giá trị điện áp nhất định tại
chân VOUT (chân giữa) ứng với mỗi mức nhiệt độ. Như vậy, bằng cách đưa vào
chân bên trái của cảm biến LM35 điện áp 5V, chân phải nối đất, đo hiệu điện thế ở
chân giữa, bạn sẽ có được nhiệt độ (0-100ºC) tương ứng với điện áp đo được.

2.4.Module thời gian thực DS1307


DS1307 là chip thời gian thực hay RTC( Read time clock). Đây là một IC tích
hợp cho thời gian bởi vì tính chính xác về thời gian tuyệt đối cho thời gian:
Thứ ngày, tháng , năm, giờ , phút giây.

Hình 2.5 Module DS1307

Sơ đồ chân DS1307
-Hình ảnh sau đây cho thấy hình dạng và sơ đồ chân của IC RTC DS1307. Để
giảm công suất tiêu thụ, số lượng chân trên IC phải giảm. Do đó, DS1307 RTC sử
dụng Giao tiếp I2C.

Hình 2.6 Sơ đồ chân DS1307

9
Chức năng các chân của module DS1307

Châ
Tên Chức năng
n

1 X1
Đây là các chân kết nối với thạch anh tần số 32.768 KHz để kích
hoạt bộ dao động nội. 
2 X2

Chân này được kết với cực dương pin Lithium 3V để cấp nguồn
3 VBAT
nuôi dự phòng 

4 GND Chân nối đất

Chân dữ liệu nối tiếp (Serial Data). Đây là chân dữ liệu vào/ra của
5 SDA giao thức I2C. Chân này cần đưa lên nguồn 5V thông qua điện trở
10kΩ

Chân đầu vào xung đồng hồ nối tiếp (Serial Clock). Đây là chân
6 SCL ngõ vào xung nhịp của giao thức I2C. Chân này cũng phải được
kéo đến 5V thông qua một điện trở 10kΩ.

Ngõ xuất ra xung vuông, tần số có thể lập trình để thay đổi từ
7 SQW/OUT 1Hz, 4Khz, 8Khz, 32Khz. Nếu không được sử dụng, chân này có
thể được thả nổi.

Chân cấp nguồn chính, khoảng 5VDC. Nếu VCC không có mà


8 VCC VBAT có thì DS1307 vẫn hoạt động bình thường nhưng không ghi
và đọc được dữ liệu.

Ghép nối DS1307 với vi điều khiển


Việc ghép nối nó với điều khiển khá đơn giản , cần xác định chân nào trên vi xử
lý có SCL và SDA để nối với DS1307.

10
2.5.Màn hình LCD20x04 I2C
Màn hình LCD 2004 là màn hình 4 dòng, mỗi dòng hiển thị 20 ký tự. Màn hình
Màn hình LCD 2004 được sử dụng phổ biến trong các ứng dụng: máy photo, máy
fax, máy in laser, các thiết bị công nghiệp, thiết bị mạng như router, thiết bị lưu
trữ...
Với việc kết hợp Màn hình LCD 2004 + Module I2C giúp tiếp kiệm chân trong
giao tiếp LCD2004 với Arduino, Raspberry (chỉ 4 pin). Bên cạnh đó sử dụng màn
hình LCD2004 tích hợp I2C mang lại tiện lợi khi sử dụng

Hình 2.7 Module LCD 20x04 I2C

Thông số kỹ thuật màn hình LCD 2004 :


 Dạng hiển thị: 4 dòng, mỗi dòng 20 ký tự
 Dạng hiển thị: ký tự
 Màu đèn nền: Màu xanh dương
 Góc quan sát rộng với độ tương phản cao
 Bên trong tích hợp chip HD44780 cho điều khiển LCD
 Điện áp hoạt động: 5V DC.
 Kích thước Module: 98mm x 60mm x 12mm.

Sơ đồ nguyên lý
Kết nối chân GND với chân Arduino GND, VCC với chân 5V trên Arduino,
SDA với chân A4, và cuối cùng là SCL với chân A5.

11
Hình 2.8.Sơ đồ nguyên lý

2.6.Relay 5V
Rơ-le là một công tắc (khóa K). Nhưng khác với công tắc ở một chỗ cơ bản, rơ-
le được kích hoạt bằng điện thay vì dùng tay người.

Hình 2.9. Relay 5V kích ở mức thấp

Khối điều khiển thiết bị điện sử dụng Relay để đóng/ ngắt mạch điện khối công
suất này nhận lệnh điều khiển từ vi điều khiển. ( Sử dụng điện áp thấp đống mở
điện áp cao )

12
-Các thông số cơ bản
Thông số Giá trị
Điện áp tải tối đa AC 250V-10A / DC 30V-10A
Điện áp điều khiển 5 VDC
Dòng kích Relay 5mA
Trạng thái kích Mức thấp (0V)
Đường kính Lỗ ốc 3.1 mm
Kích thước 50 * 26 * 18.5 mm

2.7.Máy bơm chìm mini


Máy bơm chìm ngang mini 3V-6V bơm ngang được ứng dụng bơm mini công suất
nhỏ, phù hợp để tưới cây trong nhà, trong bể cá, hòn non bộ, chế bình rót rượu tự
động…

Hinh 2.10 Máy bơm chìm mini

Thông số kỹ thuật
 Điện áp hoạt động: 3VDC – 5VDC.
 Dòng hoạt động: 100-200mA.
 Lưu lượng bơm: ~1 lít/phút.
 Trọng lượng: 28 gram
 Chiều dài dây dẫn: 10 -15 cm.

13
Nguyên lý hoạt động của máy bơm chìm :
Máy bơm chìm đẩy nước lên bề mặt bằng cách biến lực đẩy ly tâm từ các bánh
công tác thành động lực tạo ra năng lượng áp suất. Điều này được thực hiện khi
nước được tràn vào bơm: Đầu tiên nước đi vào thông qua của hút, tràn đến buồng
bơm nơi các cánh quạt đẩy nước thông qua bộ khuếch tán. Từ đó, nước được đẩy
lên bề mặt.

Hình 2.11 Minh họa nguyên lý làm viêc


của máy bơm chìm mini

2.8. Nguồn
- Sử dụng cáp USB và 3 pin 1.5V để cấp nguồn cho kit Adruino và máy bơm chìm
mini

Hinh 2.12 Cáp USB và pin

14
CHƯƠNG III: THIẾT KẾ HỆ THỐNG TƯỚI CÂY
3.1 Sơ đồ nối mạch và cách nối dây
-Sơ đồ tổng thể:

Hình 2.13 Sơ đồ nối mạch

15
-Cảm biến độ ẩm đất và Adruino
Cảm biến độ ẩm Adruino
đất
VCC 5V
GND GND
D0 ~3
A0 A0

Hình 2.14 Cách nối dây của cảm biến


đo độ ẩm đất với vi điều khiển

16
-Cảm biến nhiệt độ LM35 và Adruino
LM35 Adruino
VCC 5V
Analog out A1
GND GND

Hình 2.15 Cách nối dây giữa LM35 và Adruino

17
-DS1307 và Adruino
DS1307 Adruino
5V 5V
GND GND
SDA A4
SCL A5

Hình 2.16 Cách nối dây của module DS1307

18
-LCD 20x04 I2C và Adruino
LCD20x04 I2C Adruino
GND GND
VCC 5v
SDA A4.2
SCL A5.2

Hình 2.17 Cách nối dây giữa màn LCD và Adruino

19
- Relay (5VDC)
Relay (5VDC) Adruino
VCC 5V
GND GND
IN 12

Hình 2.18 Cách nối dây của relay

20
Máy bơm chìm mini
Relay Pin Máy bơm
NO +
NC - -
COM +

Hình 2.19 Cách nối dây của máy bơm

21
3.2 Sơ đồ thuật toán

22
CHƯƠNG IV: LẬP TRÌNH
4.1. Code ardunio
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "RTClib.h"

#define pin_analog A0 //Khai báo cảm biến độ ẩm đất tại chân A0


#define pin_relay 12 //Khai báo relay tắt bật máy bơm tại chân 12

RTC_DS1307 rtc; //Module thời gian thực rtc2307


LiquidCrystal_I2C lcd(0x27,20,4); //Màn hình LCD2004

int sensorPin = A1; //Khai báo cảm biến nhiệt độ tại chân A1
int state1 = 0, state = 0, relay = 0, auto1 = 1; //Biết lưu các lệnh và trường hợp để chạy chương trình
long time_now = 0; //Biến thời gian chạy
int do_am_dat, reading; //Biết độ ẩm đất và biến đọc dữ liệu cảm biến nhiệt độ
float voltage, nhiet_do; //Biến nhiệt độ và biến để tính toán chỉ số nhiệt độ
int y, mt, d, h, m, s; //Biến lưu dữ liệu thời gian thực đọc từ module ds1307
int y1 = 0, mt1 = 0, d1 = 0, h1 = 0, m1 = 0, s1 = 0; //Biến lưu thời gian tưới cây lần gần nhất
double TG1 = 7, TG2 = 17, ND1 = 21, ND2 = 27; //Chỉ số điều kiện tưới cây trong chế độ tự động

void setup() {
Serial.begin(9600); //Khởi động Serial 9600
pinMode (pin_analog, INPUT); //Khai báo cổng ra cảm biến độ ẩm đất
pinMode (pin_relay, OUTPUT); //Khai báo cổng vào điều khiển relay
//lcd.init(); //Khởi động màn LCD
//lcd.backlight(); //Bật đèn màn LCD
if (! rtc.begin()) { //Kiểm tra xem rtc đã bật chưa
//lcd.setCursor(0,0);
//lcd.print("Couldn't find RTC"); //Màn rtc chưa bật thì in thông báo và ngừng chạy
abort();

23
}
}

void loop()
{
delay(100);
getdata(); //Lấy dữ liệu cảm biến và module
//lcdPrint(); //In ra màn hình LCD2004
GetState(); //Nhận các lệnh truyền từ phần mềm
SetCase(); //Chạy các trường hợp đã cài
Change(); //Thay đổi điều kiệu tưới cây trong trường hợp tưới tự động
CheckAuto(); //Kiểm tra chế độ chạy thủ công hay tự động
}

float StartTime() //Hàm tính thời gian chạy


{
time_now = time_now + millis(); //Tính thời gian chạy của Arduino để vẽ đồ thị
}

void getdata() //Hàm đọc dữ liệu từ cảm biến và


{
do_am_dat = analogRead(pin_analog); //Đọc chân A0
reading = analogRead(sensorPin); //Đọc chân A1
DateTime now = rtc.now(); //Đọc thời gian từ module ds1307
y = now.year(); //Đọc năm
mt = now.month(); //Đọc tháng
d = now.day(); //Đọc ngày
h = now.hour(); //Đọc giờ
m = now.minute(); //Đọc phút
s = now.second(); //Đọc giây
voltage = reading * 5.0 / 1024.0; //Tính toán vol

24
nhiet_do = voltage * 100.0; //Tính toán nhiệt độ qua vol
}

void lcdPrint() //Hàm in lên màn hình LCD2004


{
lcd.clear(); //Xóa màn hình
lcd.setCursor(0,0); //In thời gian hiện tại lên màn LCD
if (h<=9) { lcd.print("0"); lcd.print(h, DEC);}
else lcd.print(h, DEC);
lcd.print(':');
if (m<=9) { lcd.print("0"); lcd.print(m, DEC);}
else lcd.print(m, DEC);
lcd.print(':');
if (s<=9) { lcd.print("0"); lcd.print(s, DEC);}
else lcd.print(s, DEC);
lcd.print('-');
if (d<=9) { lcd.print("0"); lcd.print(d, DEC);}
else lcd.print(d, DEC);
lcd.print('/');
if (mt<=9) { lcd.print("0"); lcd.print(mt, DEC);}
else lcd.print(mt, DEC);
lcd.print('/');
lcd.print(y, DEC);
lcd.setCursor(0,1); //In nhiệt độ
lcd.print("Nhiet do: ");
lcd.print(nhiet_do);
lcd.print("C");
lcd.setCursor(0,2); //In độ ẩm đất
lcd.print("Do am dat: ");
lcd.print(do_am_dat);
lcd.setCursor(0,3); //In tình trạng đất
if(do_am_dat > 800) lcd.print("Dat kho");

25
else lcd.print("Dat am");
delay(1000);
}

void Auto() //Hàm đặt chế độ tưới sang tự động


{
if (h >= TG1 && h <= TG2) { //Nếu thời gian trong khoảng thời gian dưới và trên thì xét nhiệt độ, nếu không
thì tắt máy bơm
if (nhiet_do >= ND1 && nhiet_do <= ND2) { //Nếu nhiệt độ trong khoảng nhiệt độ dưới và trên thì xét độ ẩm,
nếu không thì tắt máy bơm
if(do_am_dat > 800) {digitalWrite(pin_relay,LOW); relay = 1;} //Nếu chỉ số độ ẩm trên 800 thì bật máy bơm,
nếu không thì tắt máy bơm
else {digitalWrite(pin_relay,HIGH); relay = 0;}
} else {digitalWrite(pin_relay,HIGH); relay = 0;}
} else {digitalWrite(pin_relay,HIGH); relay = 0;}
}

void GetState() //Hàm nhận lệnh từ phần mềm truyền về các biến để xét chạy
{
if(Serial.available()) //Xét nếu Serial có sẵn
{
char temp = Serial.read(); //temp nhận lệnh từ phần mềm
if(temp == '0') state = 0; //Xét temp và đặt cho biến state
if(temp == '1') state = 1;
if(temp == '2') state = 2;
if(temp == 'a') state1 = 1; //Xét temp và đặt cho biến state1
if(temp == 'b') state1 = 2;
if(temp == 'c') state1 = 3;
if(temp == 'd') state1 = 4;
if(temp == 'e') state1 = 5;
if(temp == 'f') state1 = 6;
if(temp == 'g') state1 = 7;

26
if(temp == 'h') state1 = 8;
if(temp == 'i') state1 = 9;
if(temp == 'j') auto1 = 0; //Xét temp và đặt cho biến auto1
if(temp == 'k') auto1 = 1;
if(temp == 'x') relay = 1; //Xét temp và đặt cho biết relay
if(temp == 'y') relay = 0;
}
}

void SetCase() //Hàm nhận trường hợp để chạy Arduino và truyền dữ liệu qua Serial
{
switch(state) //Xét biến state
{
case 0: //Trường hợp state = 0 dừng chạy
break;
case 1: //Trường hợp state = 1 in các dữ liệu lên Serial cách nhau bới ký tự |
StartTime();
Serial.print(time_now); //In ra thời gian chạy
Serial.print("|");
Serial.print(nhiet_do); //In chỉ số nhiệt độ đã tính
Serial.print("|");
Serial.print(do_am_dat); //In chỉ số độ ẩm đọc được
Serial.print("|");
Serial.print(TG1); //In thời gian giới hạn dưới
Serial.print("|");
Serial.print(TG2); //In thời gian giới hạn trên
Serial.print("|");
Serial.print(ND1); //In nhiệt độ giới hạn dưới
Serial.print("|");
Serial.print(ND2); //In nhiệt độ giới hạn trên
Serial.print("|");
Serial.print(auto1); //In biến xét chạy tự động hay không

27
Serial.print("|");
if (h<=9) { Serial.print("0"); Serial.print(h, DEC);} //In ra dữ liệu thời gian thực đọc từ ds1307
else Serial.print(h, DEC);
Serial.print(':');
if (m<=9) { Serial.print("0"); Serial.print(m, DEC);}
else Serial.print(m, DEC);
Serial.print(':');
if (s<=9) { Serial.print("0"); Serial.print(s, DEC);}
else Serial.print(s, DEC);
Serial.print('-');
if (d<=9) { Serial.print("0"); Serial.print(d, DEC);}
else Serial.print(d, DEC);
Serial.print('/');
if (mt<=9) { Serial.print("0"); Serial.print(mt, DEC);}
else Serial.print(mt, DEC);
Serial.print('/');
Serial.print(y, DEC);
Serial.print("|");

if (relay == 1) //Xét nếu thấy máy bơm thì lưu lại dữ liệu thời gian
{
h1 = h; m1 = m; s1 = s; d1 = d; mt1 = mt; y1 = y; //Lưu lại dữ liệu thời gian
}
if (h<=9) { Serial.print("0"); Serial.print(h1, DEC);} //In ra thời gian tưới cây lần gần nhất đã lưu lại
else Serial.print(h1, DEC);
Serial.print(':');
if (m<=9) { Serial.print("0"); Serial.print(m1, DEC);}
else Serial.print(m1, DEC);
Serial.print(':');
if (s<=9) { Serial.print("0"); Serial.print(s1, DEC);}
else Serial.print(s1, DEC);
Serial.print('-');
if (d<=9) { Serial.print("0"); Serial.print(d1, DEC);}

28
else Serial.print(d1, DEC);
Serial.print('/');
if (mt<=9) { Serial.print("0"); Serial.print(mt1, DEC);}
else Serial.print(mt1, DEC);
Serial.print('/');
Serial.println(y1, DEC);
break;
case 2: //Trường hợp state = 2 đặt lại hai thông số nhiệt độ, độ ẩm đất và dừng chạy
do_am_dat = 0;
nhiet_do = 0;
y1 = 0; mt1 = 0; d1 = 0; h1 = 0; m1 = 0; s1 = 0;
relay = 0;
state = 0;
break;
}
}

void Change() //Hàm xét biết state1 để thay đổi điều kiện thời gian, nhiệt độ trong chế độ tự động
{
if(state1 == 1) { ND1 = ND1 - 1; state1 = 0;} //Nếu state1 = 1 thì giảm nhiệt độ giới hạn dưới 1 độ
else if (state1 == 2) {ND1 = ND1 + 1; state1 = 0;} //Nếu state1 = 2 thì tăng nhiệt độ giới hạn dưới 1 độ
if(state1 == 3) { ND2 = ND2 - 1; state1 = 0;} //Nếu state1 = 3 thì giảm nhiệt độ giới hạn trên 1 độ
else if (state1 == 4) {ND2 = ND2 + 1; state1 = 0;} //Nếu state1 = 4 thì tăng nhiệt độ giới hạn trên 1 độ
if(state1 == 5) { TG1 = TG1 - 1; state1 = 0;} //Nếu state1 = 5 thì giảm nhiệt độ giới hạn dưới 1 giờ
else if (state1 == 6) {TG1 = TG1 + 1; state1 = 0;} //Nếu state1 = 6 thì tăng nhiệt độ giới hạn dưới 1 giờ
if(state1 == 7) { TG2 = TG2 - 1; state1 = 0;} //Nếu state1 = 7 thì giảm nhiệt độ giới hạn trên 1 giờ
else if (state1 == 8) {TG2 = TG2 + 1; state1 = 0;} //Nếu state1 = 8 thì tăng nhiệt độ giới hạn trên 1 giờ
if(state1 == 9) { TG1 = 7; TG2 = 17; ND1 = 21; ND2 = 27; } //Nếu state1 = 9 thì đặt điều kiện thời gian,
nhiệt độ về giá trị ban đầu
}

void CheckAuto() //Kiểm tra xem đang chạy chế độ tự động hay thủ công
29
{
if (auto1 == 1) { //Nếu biến auto1 = 1 thì cho chạy chế độ tự động
Auto(); //Chạy chế độ tưới tự động
} else { //Nếu biến auto1 khác 1 thì chạy chế độ thủ công
if (relay == 1) digitalWrite(pin_relay,LOW); //Nếu biến relay = 1 thì bật máy bơm nước
else digitalWrite(pin_relay,HIGH); //Nếu biết relay khác 1 thì tắt máy bơm nước
}
}

4.2 Code chương trình điều khiển


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
30
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
//Dùng để giao tiếp qua Serial
using System.IO;
using System.IO.Ports;
using System.Xml;

namespace _555
{
public partial class Form1 : Form
{
string SDatas1 = String.Empty; //Chuỗi nhận dữ liệu nhiệt độ từ Serial
string SDatas2 = String.Empty; //Chuỗi nhận dữ liệu độ ẩm từ Serial
string SRealtime = String.Empty; //Chuỗi nhận dữ liệu thời gian thực từ Serial
string SLasttime = String.Empty; //Chuỗi nhận dữ liệu thời gian tưới gần nhất từ Serial
string SStarttime = String.Empty; //Chuỗi nhận dữ liệu thời gian bắt đầu chạy từ Serial
string SAuto = String.Empty; //Chuỗi nhận lệnh chạy tự động hay không
double datas1 = 0; //Biến lưu nhiệt độ
double datas2 = 0; //Biến lưu độ ẩm
double starttime = 0; //Biến lưu thời gian chạy
double auto1 = 0; //Biến lưu chế độ chạy tự động hay thủ công
int status = 0; //Biến dùng để in dữ liệu ra viewList và vẽ đồ thị
string ND1 = String.Empty; //Chuỗi nhận dữ liệu nhiệt độ giới hạn dưới trong chế độ chạy tự động từ
Serial
string ND2 = String.Empty; //Chuỗi nhận dữ liệu nhiệt độ giới hạn trên trong chế độ chạy tự động từ
Serial
string TG1 = String.Empty; //Chuỗi nhận dữ liệu thời gian giới hạn dưới trong chế độ chạy tự động từ
Serial
string TG2 = String.Empty; //Chuỗi nhận dữ liệu thời gian giới hạn trên trong chế độ chạy tự động từ
Serial
double nd1 = 0, nd2 = 0, tg1 = 0, tg2 = 0; //Các biến lưu điều kiện nhiệt độ và thời gian để chạy tự động
String[] ports; //Khai báo chuỗi nhận tên các cổng COM
SerialPort port; //Khai báo cổng
public Form1()

31
{
InitializeComponent();
getAvailableComPorts(); //Lây các cổng đang có sẵn
disableAuto(); //Vô hiệu hóa chế độ tự động
disableDisplay(); //Vô hiệu hóa hiển thị
checkBox1.Enabled = false; //Vô hiệu hóa chế độ thủ công
foreach (string port in ports)
{
comboBox1.Items.Add(port);
Console.WriteLine(port);
if (ports[0] != null)
{
comboBox1.SelectedItem = ports[0];
}
}
}

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)


{
}

void getAvailableComPorts() //Hàm lấy tên các cổng có sẵn


{
ports = SerialPort.GetPortNames(); //Gán chuỗi ports bằng tên các cổng port
}
private void timer1_Tick(object sender, EventArgs e) //Bắt đầu sự kiện các cổng Serial mở ra
{
if (!serialPort1.IsOpen) //Nếu cổng Serial đóng
{
progressBar1.Value = 0; //Cho thanh progressBar bằng không
}
else if (serialPort1.IsOpen) //Nếu cổng Serial mở
{

32
progressBar1.Value = 100; //Cho thanh progressBar bằng 100
Data_Listview(); //Chạy lệnh in dữ liệu ra viewList và vẽ đồ thị
status = 0; //Cho biến Status = 0;
tbND1.Text = ND1; //Hiển thị nhiệt độ giới hạn dưới vào TextBox tbND1
tbND2.Text = ND2; //Hiển thị nhiệt độ giới hạn trên vào TextBox tbND2
tbTG1.Text = TG1; //Hiển thị thời gian giới hạn dưới vào TextBox tbTG1
tbTG2.Text = TG2; //Hiển thị thời gian giới hạn trên vào TextBox tbTG2
textBox1.Text = SRealtime; //Hiển thị thời gian thực vào TextBox1
textBox2.Text = SLasttime; //Hiển thị thời gian tưới cây gần nhất vào TextBox2
if (datas2 > 800) //Nếu chỉ số độ ẩm đất > 800
{
textBox3.Text = "Đất khô!!!"; //Hiển thị đất khô vào TextBox3
textBox3.BackColor = Color.Red; //Đặt màu TextBox3 sang màu đỏ
}
else
{
textBox3.Text = "Đất ẩm"; //Hiển thị đất ẩm vào TextBox3
textBox3.BackColor = Color.Green; //Đặt màu TextBox3 sang màu xanh
}
}
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
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 thời gian thực lưu vào SRealtime
SDatas1 = arrList[1]; // Chuỗi nhiệt độ lưu vào SDatas1
SDatas2 = arrList[2]; // Chuỗi độ ẩm đất lưu vào SDatas2
TG1 = arrList[3]; //Chuỗi thời gian giới hạn dưới vào TG1
TG2 = arrList[4]; //Chuỗi thời gian giới hạn trên vào TG2
ND1 = arrList[5]; //Chuỗi nhiệt độ giới hạn dưới vào ND1
ND2 = arrList[6]; //Chuỗi nhiệt độ giới hạn trên vào ND2
33
SAuto = arrList[7]; //Chuỗi xét chế độ tự động vào SAuto
SRealtime = arrList[8]; //Chuỗi thời gian thực vào SRealtime
SLasttime = arrList[9]; //Chuỗi thời gian tưới cây gần nhất vào SLasttime
double.TryParse(SDatas1, out datas1); // Chuyển đổi nhiệt độ sang kiểu double để vẽ đồ thị
double.TryParse(SDatas2, out datas2); // Chuyển đổi sang độ ẩm đất kiểu double để vẽ đồ thị
double.TryParse(SStarttime, out starttime); // Chuyển đổi thời gian bắt đầu chạy sang kiểu double
để vẽ đồ thị
double.TryParse(SAuto, out auto1); // Chuyển đổi sang kiểu double để xét chạy tự động hay thủ
công
double.TryParse(ND1, out nd1); // Chuyển đổi sang kiểu double để kiểm tra điều kiện tăng giảm
double.TryParse(ND2, out nd2); // Chuyển đổi sang kiểu double để kiểm tra điều kiện tăng giảm
double.TryParse(TG1, out tg1); // Chuyển đổi sang kiểu double để kiểm tra điều kiện tăng giảm
double.TryParse(TG2, out tg2); // Chuyển đổi sang kiểu double để kiểm tra điều kiện tăng giảm
starttime = starttime / 1000.0; //Chuyển thời gian chạy từ mili giây sang giây
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ị
}
catch
{
return;
}
}
private void Data_Listview()
{
if (status == 0)
return;
else
{
ListViewItem item = new ListViewItem(datas1.ToString()); // Gán biến nhiệt độ vào cột đầu tiên
của ListView
item.SubItems.Add(datas2.ToString()); //Gán biến độ ẩm đất vào cột tiếp theo của ListView
listView1.Items.Add(item);
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 đó
this.chart1.Series["Nhiệt độ"].Points.AddXY(starttime, datas1); //Vẽ đồ thị nhiệt độ - thời gian
chạy
34
this.chart1.Series["Độ ẩm đất"].Points.AddXY(starttime, datas2); //Vẽ đồ thị độ ẩm đất - thời gian
chạy
}
}
private void ResetValue()
{
datas1 = 0; //Đặt lại biến nhiệt độ
datas2 = 0; //Đặt lại biến độ ẩm đất
SDatas1 = String.Empty; //Đặt lại chuỗi lưu nhiệt độ
SDatas2 = String.Empty; //Đặt lại chuỗi lưu độ ẩm đất
status = 0; // Chuyển status về 0
}

private void btConnect_Click(object sender, EventArgs e)


{
if (serialPort1.IsOpen) //Nếu cổng Serial mở
{
//serialPort1.Write("y"); //Gửi ký tự "y" tới Serial
serialPort1.Write("2"); //Gửi ký tự "2" tới Serial
serialPort1.Close(); //Đóng cổng Serial
btConnect.Text = "Kết nối"; //Đổi chữ ở nút btConnect sang Kết nối
listView1.Items.Clear(); // Xóa listview
this.chart1.Series["Nhiệt độ"].Points.Clear(); //Xóa đồ thị nhiệt độ - thời gian
this.chart1.Series["Độ ẩm đất"].Points.Clear(); //Xóa đồ thị độ ẩm đất - thời gian
btExit.Enabled = true; //Kích hoạt nút Thoát
disableAuto(); //Vô hiệu hóa tự động
disableDisplay(); //Vô hiện hóa hiển thị
}
else
{
serialPort1.PortName = comboBox1.Text; // Lấy cổng COM
serialPort1.BaudRate = 9600; // Baudrate là 9600, trùng với baudrate của Arduino
try
{
35
serialPort1.Open(); //Mở cổng serial
serialPort1.Write("k"); //Gửi ký tự "k" tới Serial
btConnect.Text = "Ngắt kết nối"; //Đổi chữ ở nút btConnect sang Ngắt kết nối
btExit.Enabled = false; //Vô hiệu hóa nút thoát
enableAuto(); //Kích hoạt tự động
enableDisplay(); //Kích hoạt hiển thị
}
catch
{
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 btRun_Click(object sender, EventArgs e)


{
if (serialPort1.IsOpen)
{
serialPort1.Write("k"); //Gửi ký tự "k" tới Serial
serialPort1.Write("1"); //Gửi ký tự "1" qua Serial
}
}

36
private void btPause_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
serialPort1.Write("0"); //Gửi ký tự "0" qua Serial, Dừng Arduino
}
}

private void btClear_Click(object sender, EventArgs e)


{
if (serialPort1.IsOpen)
{
DialogResult traloi;
traloi = MessageBox.Show("Bạn có chắc muốn xóa?", "Xóa dữ liệu",
MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
if (traloi == DialogResult.OK)
{
if (serialPort1.IsOpen)
{
serialPort1.Write("2"); //Gửi ký tự "2" qua Serial
listView1.Items.Clear(); // Xóa listview
this.chart1.Series["Nhiệt độ"].Points.Clear(); //Xóa đồ thị nhiệt độ - thời gian
this.chart1.Series["Độ ẩm đất"].Points.Clear(); //Xóa đồ thị độ ẩm đất - thời gian
}
}
}
}

private void listView1_SelectedIndexChanged(object sender, EventArgs e)


{

37
private void chart1_Click(object sender, EventArgs e)
{

private void comboBox2_SelectedIndexChanged(object sender, EventArgs e)


{

private void label1_Click(object sender, EventArgs e)


{

private void textBox1_TextChanged(object sender, EventArgs e)


{

private void checkBox1_CheckedChanged(object sender, EventArgs e)


{

private void btSend_Click(object sender, EventArgs e)


{

private void groupBox2_Enter(object sender, EventArgs e)


{

38
}

private void btGTG1_Click(object sender, EventArgs e)


{
if (serialPort1.IsOpen)
{
serialPort1.Write("e"); //Gửi kỹ tự "e" tới Serial
}
}

private void btTTG1_Click(object sender, EventArgs e)


{
if (tg1 == tg2) //Nếu thời gian giới hạn trên bằng nhiệt độ giới hạn dưới thì gửi thông báo lỗi
{
MessageBox.Show("Thời gian ngưỡng dưới không thể cao hơn thời gian ngưỡng trên", "Thông
báo", MessageBoxButtons.OK, MessageBoxIcon.Error);
} else serialPort1.Write("f"); //Nếu không gửi ký tự "f" tới Serial
}

private void btGND1_Click(object sender, EventArgs e)


{
if (serialPort1.IsOpen)
{
serialPort1.Write("a"); //Gửi ký tự "a" tới Serial
}
}

private void btTND1_Click(object sender, EventArgs e)


{
if (nd1 == nd2) //Nếu nhiệt độ giới hạn trên bằng nhiệt độ giới hạn dưới thì gửi thông báo lỗi
{
MessageBox.Show("Nhiệt độ ngưỡng dưới không thể cao hơn nhiệt độ ngưỡng trên", "Thông báo",
MessageBoxButtons.OK, MessageBoxIcon.Error);
} else serialPort1.Write("b"); //Nếu không gửi ký tự "b" tới Serial

39
}

private void btGND2_Click(object sender, EventArgs e)


{
if (nd1 == nd2) //Nếu nhiệt độ giới hạn trên bằng nhiệt độ giới hạn dưới thì gửi thông báo lỗi
{
MessageBox.Show("Nhiệt độ ngưỡng trên không thể thấp hơn nhiệt độ ngưỡng dưới", "Thông
báo", MessageBoxButtons.OK, MessageBoxIcon.Error);
} else serialPort1.Write("c"); //Nếu không gửi ký tự "c" tới Serial
}

private void btTND2_Click(object sender, EventArgs e)


{
if (serialPort1.IsOpen)
{
serialPort1.Write("d"); //Gửi ký tự "d" tới Serial
}
}

private void btGTG2_Click(object sender, EventArgs e)


{
if (tg1 == tg2) //Nếu thời gian giới hạn trên bằng nhiệt độ giới hạn dưới thì gửi thông báo lỗi
{
MessageBox.Show("Thời gian ngưỡng trên không thể thấp hơn thời gian ngưỡng dưới", "Thông
báo", MessageBoxButtons.OK, MessageBoxIcon.Error);
} else serialPort1.Write("g"); //Nếu không gửi ký tự "g" tới Serial
}

private void btTTG2_Click(object sender, EventArgs e)


{
if (serialPort1.IsOpen)
{
serialPort1.Write("h"); //Gửi ký tự "h" tới Serial
}

40
}

private void btReset_Click(object sender, EventArgs e)


{
if (serialPort1.IsOpen)
{
serialPort1.Write("i"); //Gửi ký tự "i" tới Serial
}
}

private void checkBox1_CheckedChanged_1(object sender, EventArgs e)


{
if (checkBox1.Checked) //Nếu checkBox1 đang tích
{
serialPort1.Write("x"); //Gửi ký tự "x" tới Serial
checkBox1.Text = "Máy bơm: Bật"; //Đặt ký tự tại checkBox1 là Máy bơm: Bật
}
else //Nếu không tích thì
{
serialPort1.Write("y"); //Gửi ký tự "y" tới Serial
checkBox1.Text = "Máy bơm: Tắt"; //Đặt ký tự tại checkBox1 là Máy bơm: Tắt
}
}

private void btAuto_Click(object sender, EventArgs e)


{
if (auto1 == 1) //Nếu biến auto1 = 1
{
serialPort1.Write("j"); //Gửi ký tự "j" tới Serial
btAuto.Text = "Thủ công"; //Chữ ở nút btAuto chuyển sang Thủ công
disableAuto(); //Vô hiệu quá tự động
serialPort1.Write("y"); //Gửi ký tự "y" tới Serial
}

41
else //Nếu biến auto1 không bằng 1
{
serialPort1.Write("k"); //Gửi ký tự "k" tới Serial
btAuto.Text = "Tự động"; //Chữ ở nút btAuto chuyển sang Tự động
enableAuto(); //Kích hoạt tự động
}
}
private void disableDisplay() //Vô hiệu hóa hiển thị
{
btClear.Enabled = false;
btAuto.Enabled = false;
btRun.Enabled = false;
btPause.Enabled = false;
listView1.Enabled = false;
chart1.Enabled = false;
textBox1.Enabled = false;
textBox2.Enabled = false;
}

private void textBox1_TextChanged_1(object sender, EventArgs e)


{

private void textBox3_TextChanged(object sender, EventArgs e)


{

private void enableDisplay() //Kích hoạt hiển thị


{
btClear.Enabled = true;
btAuto.Enabled = true;

42
btRun.Enabled = true;
btPause.Enabled = true;
listView1.Enabled = true;
chart1.Enabled = true;
textBox1.Enabled = true;
textBox2.Enabled = true;
}
private void disableAuto() //Vô hiệu hóa tự động
{
tbND1.Enabled = false;
tbND2.Enabled = false;
tbTG1.Enabled = false;
tbTG2.Enabled = false;
btGND1.Enabled = false;
btGND2.Enabled = false;
btGTG1.Enabled = false;
btGTG2.Enabled = false;
btTND1.Enabled = false;
btTND2.Enabled = false;
btTTG1.Enabled = false;
btTTG2.Enabled = false;
btReset.Enabled = false;
checkBox1.Enabled = true;
}
private void enableAuto() //Kích hoạt tự động
{
tbND1.Enabled = true;
tbND2.Enabled = true;
tbTG1.Enabled = true;
tbTG2.Enabled = true;
btGND1.Enabled = true;
btGND2.Enabled = true;
btGTG1.Enabled = true;

43
btGTG2.Enabled = true;
btTND1.Enabled = true;
btTND2.Enabled = true;
btTTG1.Enabled = true;
btTTG2.Enabled = true;
btReset.Enabled = true;
checkBox1.Checked = false;
checkBox1.Text = "Máy bơm";
checkBox1.Enabled = false;
}
}
}

-Giao diện lúc mới bật chương trình, chương trình hiển thị các cổng có sẵn để kết
nối.

44
-Lúc kết nối, chương trình lấy dữ liệu và vẽ biểu đồ nhiệt độ, độ ẩm đất theo thời
gian chạy, hiển thị thời gian thưc cùng với thời gian tưới lần trước.
-Lúc vừa kết nối sẽ chạy theo chế độ tự động.

45
-Thời gian và nhiệt độ giới hạn trong chế độ tưới tự động có thể tùy ý thay đổi để
cho phù hợp hơn với thời tiết hiện tại.

46
-Chương trình đưa ra thông báo lỗi khi thay đổi các thông số thời gian và nhiệt độ
không phù hợp.

47
-Chuyền qua chế độ tưới thủ công, bật tắt máy bơm bằng cách tích vào ô để bật, và
bỏ tích để tắt máy bơm nước.

48
CHƯƠNG V: KẾT LUẬN
5.1 Kết quả đạt được
- Tìm hiểu về các hệ thống tưới cây tự động: phân loại, nguyên lý, v.v…
- Tìm hiểu về kit adruino và các phần tử trong hệ thống ; relay, DS1307, v.v
- Thiết kế chương trình điều khiển hệ thống tưới cây
- Lập trình cho hệ thống tưới cây tự động

5.2 Hạn chế


- Do tài chính có hạn nên hệ thống còn đơn giản và chưa có nhiều chức năng, chế
độ khác nhau.
5.3 Hướng phát triển
- Tích hợp thêm nhiều chức năng : chế độ tưới cho các giống cây khác nhau , tưới
nhỏ giọt, điều khiển từ xa v.v
- Thiết kế thêm vào hệ thống bộ phận thông báo cho người sử dụng biết được tình
trạng của hệ thống.

49
Tài liệu tham khảo

Các website tham khảo


- www.adruino.vn, www.dientuvietnam.net , và các nguồn khác

50

You might also like