You are on page 1of 145

2

CHƯƠNG TRÌNH MẪU BỘ ARDUINO UNO R3 PRO KIT

❖ Mục lục tra cứu


➢ Danh sách linh kiện bộ Arduino UNO R3 PRO KIT
➢ Các thao tác cơ bản để bắt đầu học tập và sử…
■ Hướng dẫn tải và cài đặt Arduino
■ Cài đặt driver CH340
■ Kết nối với máy tính
■ Viết và nạp chương trình
■ Hiểu hơn về Arduino UNO
➢ Chương trình mẫu & ý tưởng thực hành
■ Làm việc với nút nhấn
■ Điều khiển đèn LED nhấp nháy
■ Làm việc với Buzzer
■ Làm việc với cảm biến vật cản hồng ngoại
■ Sử dụng cảm biến âm thanh
■ Làm việc với biến trở
■ Làm việc với cảm biến ánh sáng quang trở
■ Làm việc với cảm biến siêu âm
■ Làm việc với cảm biến phát hiện lửa và cảm biến khí…
■ Điều khiển động cơ bằng L298N
■ Làm quen với module relay
■ Làm việc với cảm biến độ ẩm đất
■ Cảm biến nhiệt độ độ ẩm DHT11
■ Sử dụng màn hình LCD bằng giao tiếp I2C
■ Điều khiển động cơ Servo
■ Giao tiếp với module thời gian thực DS1302
■ Sử dụng bàn phím ma trận 4x4
■ Module RFID RC522 tần số 13.56Mhz và thẻ từ
■ Điều khiển LED ma trận MAX7219 8x8
■ Điều khiển LED NeoPixel WS2812B chạy hiệu ứng
■ Sử dụng module DFplayer để điều khiển việc phát âm thanh
➢ Một số gợi ý về ý tưởng thực hiện
➢ Một số lỗi thường gặp và kinh nghiệm xử lý
➢ Một số dự án tham khảo kết hợp nhiều module và kiến…

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 -2
3

❖ Danh sách linh kiện bộ Arduino UNO R3 PRO KIT


➢ Arduino UNO R3 CH340 R3SMD
➢ Module cảm biến nhiệt độ , độ ẩm DHT11 UIJ3
➢ Module cảm biến vật cản hồng ngoại FM52
➢ Module cảm biến cường độ ánh sáng quang trở 2WXL
➢ Module cảm biến phát hiện lửa XH1J
➢ Module cảm biến siêu âm Q9ZV
➢ Module cảm biến âm thanh 0YYH
➢ Module cảm biến độ ẩm đất M9BI
➢ Module cảm biến khí gas MQ-4 MFHY
➢ Module thời gian thực DS1302 X7VB
➢ Module phát âm thanh DFplayer Mini QNZJ
➢ Module RFID RC522 13.56Mhz NOTK
➢ Module relay opto cách ly 5V 1 kênh RN5I
➢ Module điều khiển động cơ L298N SKIQ
➢ Mình hình LCD 1602 kèm I2C 482V
➢ Vòng led NEO Pixel Ring 8 LED FJC2
➢ Động cơ servo SG90 RK7A
➢ Động cơ bơm chìm mini 5VDC SKGO
➢ Module LED ma trận MAX7219 8x8 6RU7
➢ Bàn phím ma trận mềm 4x4 ESCD
➢ IC 74HC595 DIP
➢ Biến trở volume 10kOhm
➢ Còi Buzzer 5V RVVQ
➢ Dây cắm testboard các loại
■ Đực - Đực 20cm 40 sợi
■ Đực - Cái 20cm 40 sợi
■ Cái - Cái 20cm 40 sợi
➢ Testboard 400 lỗ OHDN
➢ Điện trở
■ 220 Ohm
■ 1K Ohm
■ 10K Ohm
➢ LED ruồi 5mm các màu
■ Đỏ
■ Xanh lá
■ Vàng
➢ Nút nhấn
➢ Jack pin 9V to DC 78AD
➢ Pin vuông 9V DZO6
➢ Nguồn Adapter DC 5V 1A PE7M
➢ Jack DC cái đầu ra domino 43A9

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 -3
4

❖ Các thao tác cơ bản để bắt đầu học tập và sử dụng Arduino
➢ Hướng dẫn tải và cài đặt Arduino
■ Bước 1: Truy cập vào địa chỉ trang chủ Arduino:
https://www.arduino.cc/en/software
Các bạn có thể tải Win 7 and newer hoặc ZIP file. Mình tải Win 7 and newer về cài vào
máy luôn.

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 -4
5

■ Bước 2: Sau khi tải về, ta cho chạy file mới tải
● Chọn Next

● Chọn I Agree

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 -5
6
● Chọn nơi lưu trữ sau đó chọn Install để cài đặt

● Nếu hiện hộp thoại như hình bên dưới thì nhấn chọn Install để cài đặt driver

● Tiếp tục nhấn chọn Install để cài đặt driver

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 -6
7

● Sau khi chạy xong hiện Completed nhấn Close để hoàn thành

➢ Cài đặt driver CH340


■ Truy cập đường dẫn https://www.arduined.eu/files/windows10/CH341SER.zip để tải về
driver CH340 cho Arduino UNO SMD
■ Giải nén tệp vừa tải và cài đặt DriverSetup

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 -7
8

Driver install success! cho thấy việc cài đặt hoàn tất

Lưu ý với phiên bản Win 10 trở lên Driver có thể đã được cài đặt tự động khi bạn kết
nối Arduino vào máy tính , vì vậy có thể bỏ qua bước này

➢ Kết nối với máy tính


■ Cắm dây cáp đi kèm vào Arduino UNO sau đó cắm vào cổng USB máy tính
■ Truy cập Device Manager để kiểm tra việc kết nối thiết bị

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 -8
9

■ Kiểm tra nếu thấy USB-SERIAL CH340 (COM …) như hình bên dưới có nghĩa là máy
tính đã kết nối thành công với mạch Arduino UNO và bây giờ chúng ta có thể nạp code

➢ Viết và nạp chương trình


■ Tùy theo phiên bản Arduino mà có giao diện khác nhau, tuy nhiên vẫn cơ bản có các
thành phần và nút lệnh như sau

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 -9
10

■ Nạp chương trình mặc định ( code rỗng ) cho Arduino, đầu tiên vào Tools => Board =>
Arduino AVR Boards ( tùy theo phiên bản ở mục này sẽ khác đôi chút ) => Arduino UNO

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 10
11

■ Chọn cổng COM đúng với board

■ Nhấn nút tick này để biên dịch và kiểm tra lỗi chương trình trước khi nạp

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 11
12

■ Sau khi kiểm tra xong, nếu chương trình không có vấn đề sẽ hiện thông báo Done
Compiling. Nhấn vào nút Upload để nạp chương trình (bạn có bỏ qua bước kiểm tra
phía trên). Màn hình thông báo Done Uploading có nghĩa là chương trình đã được nạp
vào Arduino thành công

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 12
13

➢ Hiểu hơn về Arduino UNO


Arduino UNO là một board phát triển dựa trên vi điều khiển ATmega328P. Nó được sử dụng
rộng rãi trong các dự án điện tử và lập trình nhờ vào tính đơn giản, dễ sử dụng và khả năng
tương thích với nhiều module mở rộng.
Arduino UNO có 14 chân số và 6 chân analog. Dưới đây là một số thông tin cơ bản về các
chân trên Arduino UNO:
■ Chân số (Digital Pins):
● Chân số được đánh số từ 0 đến 13 trên Arduino UNO.
● Các chân này có thể được sử dụng để đọc hoặc ghi tín hiệu số (0 hoặc 1).
● Các chân từ 0 đến 13 cũng có thể được sử dụng để tạo xung (PWM) hoặc đọc tín
hiệu số từ các thiết bị ngoại vi.
■ Chân analog (Analog Pins):
● Arduino UNO có 6 chân analog được đánh số từ A0 đến A5.
● Các chân này được sử dụng để đọc tín hiệu analog từ các cảm biến hoặc linh kiện
khác.
■ Chân Cách sử dụng chân trên Arduino UNO:
● Để đọc hoặc ghi giá trị tín hiệu số vào một chân số, bạn có thể sử dụng các hàm như
digitalRead() và digitalWrite().
● Để đọc giá trị tín hiệu analog từ một chân analog, bạn có thể sử dụng hàm
analogRead().

■ Hình ảnh sơ đồ chân

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 13
14

➢ Tải thư viện cho các dự án


■ Việc dùng arduino chúng ta rất hay dùng đến các thư viện có sẵn được viết bởi đội ngũ
phát triển phần mềm Arduino IDE , ngoài ra cũng thường xuyên phải sử dụng các tệp
thư viện mã nguồn mở được các người dùng Arduino trên toàn cầu phát triển và chia sẻ
để sử dụng các module , các chương trình được tiện lợi hơn
■ Có 2 cách tải và thêm thư viện cho Arduino
● Cách 1: Cài đặt thư viện từ Manager Libraries của Arduino IDE
◆ Mở Arduino IDE trên máy tính của bạn.
◆ Chọn menu "Sketch" và sau đó chọn "Include Library"
◆ Trong menu "Include Library", bạn sẽ thấy danh sách các thư viện có sẵn và
đã được cài đặt trước đó trên máy tính của bạn.
◆ Để tải một thư viện mới, chọn "Manage Libraries" (Quản lý thư viện).
◆ Một cửa sổ "Library Manager" sẽ xuất hiện, cho phép bạn tìm kiếm và cài đặt
các thư viện mới.
◆ Sử dụng ô tìm kiếm để tìm kiếm tên thư viện mà bạn muốn tải về. Sau đó,
chọn thư viện và nhấn nút "Install" (Cài đặt).

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 14
15
◆ Arduino IDE sẽ tải về và cài đặt thư viện tự động. Quá trình này có thể mất
vài giây đến vài phút, tùy thuộc vào kích thước của thư viện và tốc độ kết nối
Internet của bạn.
◆ Sau khi quá trình cài đặt hoàn tất, bạn có thể sử dụng thư viện trong các
chương trình Arduino của mình.

● Cách 2: Cài đặt thư viện từ các tệp nén được chia sẻ bên ngoài

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 15
16
◆ Sau khi tải tệp thư viện định dạng file nén .zip về máy
◆ Chọn menu "Sketch" và sau đó chọn "Include Library"
◆ Chọn Add .ZIP Library…
◆ Chọn đến tệp vừa tải xuống và Open như vậy là đã thêm thành công. Bạn
vào lại phần Include Library và tìm xem thư viện vừa cài đã có hay chưa

➢ Chuyển đổi giao diện sang Dark Theme


■ Hiện Arduino IDE chưa hỗ trợ chính thức tuy nhiên chúng ta nếu thích giao diện tối cho
đỡ mỏi mắt khi làm việc có thể làm theo cách sau
■ Tải theme về theo đường dẫn
● https://github.com/jeffThompson/DarkArduinoTheme
$

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 16
17

● Giải nén thư mục vừa tải


● Tìm đến thư mục bạn đã cài đặt hoặc lưu trữ Arduino IDE.
● Trong trường hợp của tôi, tôi đã cài đặt nó vào ổ đĩa C của máy tính của tôi.
● Thư mục mặc định là "C:\Program Files (x86)\Arduino\lib"

● Bạn sẽ nhìn thấy thư mục Theme , bạn có thể copy và lưu lại thư mục theme gốc
trong trường hợp bạn muốn thay đổi sau này
● Copy thư mục đã giải nén lúc nãy và lưu đè lên thư mục theme gốc
● Như vậy là đã hoàn thành, bạn khởi động lại Arduino IDE và sử dụng

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 17
18

❖ Chương trình mẫu và ý tưởng thực hành


➢ Làm việc với nút nhấn
■ Nhấn nút để bật LED, nhả ra để tắt LED:
● Đây là vấn đề cơ bản nhất với việc tiếp cận Arduino, chúng ta sẽ đọc trạng thái của
nút nhấn để biết khi nào nó được nhấn, từ đó xuất 1 tín hiệu digital để Led sáng lên.
Khi thả tay ra thì led sẽ tắt

/*
Chương trình điều khiển nhấn nút để bật LED

Kết nối chân dương của LED với chân digital 13 trên board Arduino thông
qua resistor 220 ohm.
Kết nối chân âm của LED với GND trên board Arduino.

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 18
19
Kết nối một chân của nút với chân digital 7 trên board Arduino, tại đó
kéo trở 10k lên nguồn 5v của Arduino.
Kết nối chân khác của nút với GND trên board Arduino
*/

const int LED = 13; // chân điều khiển LED


const int button = 7; // chân nút bấm
int buttonState = 0; // lưu trạng thái của nút bấm

void setup() {
pinMode(LED, OUTPUT); // thiết lập chân điều khiển LED là OUTPUT
pinMode(button, INPUT); // thiết lập chân nút bấm là INPUT
}

void loop() {
buttonState = digitalRead(button); // đọc trạng thái của nút bấm

if (buttonState == LOW) { // nếu nút bấm được nhấn


digitalWrite(LED, HIGH); // bật đèn LED
} else { // nếu nút bấm không được nhấn
digitalWrite(LED, LOW); // tắt đèn LED
}
}

■ Sử dụng nút nhấn nhả để bật LED thay vì công tắc như thông thường:
● Để bật tắt 1 bóng đèn chúng ta thường sử dụng 1 công tắc ON/OFF và dễ dàng thực
hiện mà không phải thông qua bất kì mạch điều khiển nào cả, tuy nhiên, với 1 nút
nhấn nhả không giữ trạng thái thì chúng ta vẫn làm được với Arduino. Chương trình
sẽ giúp chúng ta nhấn 1 lần để bật Led, khi Led đang sáng thì nhấn lại 1 lần để tắt.

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 19
20

/*
Chương trình điều khiển nhấn nhả nút để bật/tắt LED

Kết nối chân dương của LED với chân digital 13 trên board Arduino thông
qua resistor 220 ohm.
Kết nối chân âm của LED với GND trên board Arduino.
Kết nối một chân của nút với chân digital 7 trên board Arduino, tại đó
kéo trở 10k lên nguồn 5v của Arduino.
Kết nối chân khác của nút với GND trên board Arduino
*/
const int LED = 13; // chân điều khiển LED
const int button = 7; // chân nút bấm
int buttonState = 0; // lưu trạng thái hiện tại của nút bấm
int lastButtonState = 0; // lưu trạng thái trước đó của nút bấm
int ledstate = 0; // lưu trạng thái của LED
void setup() {
pinMode(LED, OUTPUT); // thiết lập chân điều khiển LED là OUTPUT
pinMode(button, INPUT); // thiết lập chân nút bấm là INPUT
}

void loop() {
buttonState = digitalRead(button); // đọc trạng thái của nút bấm

if (buttonState != lastButtonState) { // nếu nút bấm được nhấn(kích

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 20
21
cạnh xuống)
if (buttonState == LOW) {
ledstate = 1 - ledstate;
digitalWrite(LED, ledstate); // đảo trạng thái đèn LED
}
delay(50); // Đợi 50ms
}
lastButtonState = buttonState; // Lưu trạng thái trước đó của
nút nhấn
}

■ Đọc số lần nhấn nút:


● Đôi khi chúng ta cần điều khiển 1 lệnh nào đó phụ thuộc vào số lần nhấn nút, giống
như việc chúng ta thực hiện thao tác Double-Click trên chuột để mở 1 ứng dụng. Để
thực hiện điều đó cần xác định được 1 chu kỳ thao tác nhấn vào và nhả ra được tính
là 1 lần nhấn, sau đó lưu vào 1 biến đếm.

/*
Chương trình đọc số lần nhấn nút và gửi lên Serial Monitor

Kết nối một chân của nút nhấn với chân digital 2 trên board Arduino, tại
đó kéo trở 10k lên nguồn 5v của Arduino.
Kết nối chân khác của nút với GND trên board Arduino
*/
const int button = 7; // chân nút bấm
int buttonState = 0; // lưu trạng thái hiện tại của nút bấm
int lastButtonState = 0; // lưu trạng thái trước đó của nút bấm
int dem = 0; // biến đếm số lần nhấn nút
void setup() {
Serial.begin(9600); // khởi động Serial Monitor với tốc độ
9600 bps
pinMode(button, INPUT); // thiết lập chân nút bấm là INPUT
} // bạn có thể không đấu trở mà kéo nội trở bằng lệnh INPUT_PULLUP

void loop() {
buttonState = digitalRead(button); // đọc trạng thái của nút bấm
if (buttonState != lastButtonState) { // nếu nút bấm được nhấn(kích
cạnh xuống)
if (buttonState == LOW) {
dem ++; // tăng biến đếm lên 1
Serial.print("So lan nhan nut: ");
Serial.println(dem); // hiển thị số lần đếm lên
Serial Monitor
}
delay(50); // Đợi 50ms
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 21
22
lastButtonState = buttonState; // Cập nhật lại trạng thái
trước đó của nút nhấn
}

➢ Điều khiển đèn LED nhấp nháy


■ Điều khiển 2 đèn LED nhấp nháy
● Để 2 đèn led nhấp nháy luân phiên chúng ta cần sử dụng hàm delay() để duy trì Led
sáng trong 1 khoảng thời gian

/*
Chương trình điều khiển 2 đèn LED nhấp nháy luân phiên
*/
int led1 = 2; // chân kết nối của đèn LED 1
int led2 = 3; // chân kết nối của đèn LED 2

void setup() {
pinMode(led1, OUTPUT); // thiết lập chân kết nối led1 là chân xuất
dữ liệu
pinMode(led2, OUTPUT); // thiết lập chân kết nối led2 là chân xuất
dữ liệu
}

void loop() {
digitalWrite(led1, HIGH); // bật đèn LED 1

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 22
23
digitalWrite(led2, LOW); // tắt đèn LED 2
delay(1000); // chờ 1 giây

digitalWrite(led1, LOW); // tắt đèn LED 1


digitalWrite(led2, HIGH); // bật đèn LED 2
delay(1000); // chờ 1000 mili giây
}

■ Điều khiển nhiều đèn LED bằng IC 74HC595


● Việc điều khiển nhiều Led nếu cứ mỗi Led chúng ta lại sử dụng 1 chân thì như vậy
Arduino không đủ đáp ứng số chân khi chúng ta cần điều khiển rất nhiều Led. Vì vậy
IC 74HC595 sẽ giúp bạn làm việc đó. Các bạn nhớ cài thư viện
ShiftRegister74HC595

/*
Chương trình điều khiển nhiều đèn LED bằng IC 74HC595
Sử dụng thư viện ShiftRegister74HC595 của Timo Denk trên Library

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 23
24
Manager
*/

#include <ShiftRegister74HC595.h> //Cài thư viện ShiftRegister74HC595


của Timo Denk trên Library Manager

// Khai báo các chân kết nối với IC 74HC595


const int SER_Pin = 9;
const int SRCLK_Pin = 10;
const int RCLK_Pin = 8;

// Khai báo đối tượng shift register


ShiftRegister74HC595 sr(SER_Pin, SRCLK_Pin, RCLK_Pin);

void setup() {
// Khởi tạo đối tượng shift register
sr.begin();
}

void loop() {
// Điều khiển từng LED bằng cách xác định giá trị của byte data
// Bật LED ở vị trí nào thì tại vị trí bit đó set bit data = 1
byte data = 0b00000001; // Bật LED thứ nhất
sr.setAll(data);
delay(500);

data = 0b00000010; // Bật LED thứ hai


sr.setAll(data);
delay(500);

data = 0b00000100; // Bật LED thứ ba


sr.setAll(data);
delay(500);

data = 0b00001000; // Bật LED thứ tư


sr.setAll(data);
delay(500);

data = 0b00010000; // Bật LED thứ năm


sr.setAll(data);
delay(500);

data = 0b00100000; // Bật LED thứ sáu


sr.setAll(data);
delay(500);

data = 0b01000000; // Bật LED thứ bảy

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 24
25
sr.setAll(data);
delay(500);

data = 0b10000000; // Bật LED thứ tám


sr.setAll(data);
delay(500);

// Tắt tất cả các LED


sr.resetAll();
delay(500);
}

■ Vậy muốn viết chương trình 2 Led sáng nhưng không “chờ” nhau , không phụ thuộc
nhau chúng ta cần làm gì ? Các bạn nghiên cứu hàm millis() thay cho hàm delay() nhé.

➢ Làm việc với Buzzer


■ Bíp còi khi nhấn nút

/*

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 25
26
Chương trình điều khiển bíp còi khi nhấn nút

Kết nối chân dương của Buzzer với chân digital 3 trên board Arduino
Kết nối chân âm của buzzer với GND trên board Arduino.
Kết nối một chân của nút với chân digital 2 trên board Arduino, tại đó
kéo trở 10k lên nguồn 5v của Arduino.
Kết nối chân khác của nút với GND trên board Arduino
*/
const int buzzer = 11; // chân điều khiển buzzer
const int button = 2; // chân nút bấm
int currentState = 0; // lưu trạng thái hiện tại của nút bấm
int lastButtonState = 0; // lưu trạng thái trước đó của nút bấm
void setup() {
pinMode(buzzer, OUTPUT); // thiết lập chân điều khiển buzzer là OUTPUT
pinMode(button, INPUT); // thiết lập chân nút bấm là INPUT
}

void loop() {
currentState = digitalRead(button); // đọc trạng thái của nút bấm

if (lastButtonState == HIGH && currentState == LOW) { // Nếu nút đã


được nhấn (kích cạnh xuống)
digitalWrite(buzzer, HIGH); // Bật buzzer trong 200ms rồi tắt
delay(200);
digitalWrite(buzzer, LOW);
}

lastButtonState = currentState; // Lưu trạng thái trước đó của nút


nhấn
}

■ Điều chỉnh tần số âm thanh để có tiếng buzzer khác nhau


● Ngoài việc sử dụng HIGH , LOW để bật tắt âm thanh thì ta có thể dùng hàm tone()
để thay đổi cao độ âm thanh. Ví dụ dưới đây tạo âm thanh cảnh báo bạn có thể tham
khảo

/*
Chương trình tạo âm thanh với cao độ khác nhau sử dụng buzzer(cụ
thể là tiếng cảnh báo)

Bởi tai người có thể nghe được ở tần số âm thanh từ 20Hz đến
20kHZ. Vì vậy việc nhân cho 1000 và cộng 2000 để đảm bảo nằm trong phạm
vi 2000 đến 3000.
*/

const int buzzer = 11; // Khởi tạo chân kết nối Buzzer là D11
float sinVal; // Khởi tạo biến giá trị hàm sin

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 26
27
int toneVal; // Khởi tạo giá trị tần số âm thanh
void setup(){
pinMode(buzzer, OUTPUT);
}
void loop(){
for(int x=0; x<180; x++){ // Vòng lặp chạy từ 0
- 180 độ
sinVal = (sin(x*(3.1412/180))); // Chuyển đổi từ độ
sang radian
toneVal = 2000+(int(sinVal*1000)); // Đổi giá trị sinVal
thành tần số âm thanh của còi toneVal.
tone(buzzer, toneVal);
delay(2);
}
}

➢ Làm việc với cảm biến vật cản hồng ngoại


■ Đọc tín hiệu
● Cảm biến hồng ngoại thông thường sẽ trả về giá trị digital 0,1 tương ứng với việc có
hoặc không có vật cản. Tùy từng loại mà nhà sản xuất sẽ làm mức cao hay mức
thấp khi phát hiện vật cản

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 27
28

/*
Chương trình đọc tín hiệu cảm biến vật cản hồng ngoại và gửi lên
Serial Monitor

Kết nối chân OUT của module --> Chân 2 của Arduino
2 chân VCC, GND kết nối tới nguồn 5V trên Arduino
*/

const int IR_PIN = 2; // Chân kết nối với cảm biến vật cản hồng ngoại
int val = 0; // Biến lưu giá trị cảm biến

void setup() {
Serial.begin(9600); // Khởi tạo kết nối Serial
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 28
29

void loop() {
val = digitalRead(IR_PIN); // Đọc giá trị từ cảm biến
Serial.print("Giá trị: "); // In ra màn hình Serial Monitor
Serial.println(val);
delay(50); // Đợi 50 mili giây để giá trị ổn định
}

■ Điều khiển bật Led khi phát hiện vật

/*
Chương trình điều khiển LED đơn sử dụng tín hiệu hồng ngoại

Kết nối chân OUT của module --> Chân 2 của Arduino
2 chân VCC, GND kết nối tới nguồn 5V trên Arduino
*/
const int IR_PIN = 2; // Chân kết nối với cảm biến vật cản hồng
ngoại digital
const int LED_PIN = 13; // Chân kết nối với LED
int sensorValue; // Biến lưu giá trị đọc được từ cảm biến

void setup() {

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 29
30
pinMode(IR_PIN, INPUT); // Khai báo chân kết nối với cảm biến là
INPUT
pinMode(LED_PIN, OUTPUT); // Khai báo chân kết nối với LED là OUTPUT
Serial.begin(9600); // Khởi tạo kết nối Serial
}

void loop() {
sensorValue = digitalRead(IR_PIN); // Đọc giá trị từ cảm biến
if (sensorValue == LOW) { // Nếu có vật cản
digitalWrite(LED_PIN, HIGH); // Bật LED
Serial.println("Phát hiện vật cản!"); // In ra màn hình Serial
Monitor
}
else { // Nếu không có vật cản
digitalWrite(LED_PIN, LOW); // Tắt LED
}
delay(100); // Đợi 0.1 giây
}

■ Báo động khi có vật cản

/*
Chương trình báo động bằng buzzer khi có vật cản

Kết nối chân OUT của module --> Chân 2 của Arduino
2 chân VCC, GND kết nối tới nguồn 5V trên Arduino
*/
const int IR_PIN = 2; // Chân kết nối với cảm biến vật cản hồng
ngoại digital
const int BUTTON_PIN = 3; // Chân kết nối với BUTTON
int sensorValue; // Biến lưu giá trị đọc được từ cảm biến

void setup() {
pinMode(IR_PIN, INPUT); // Khai báo chân kết nối với cảm biến
là INPUT
pinMode(BUTTON_PIN, OUTPUT); // Khai báo chân kết nối với BUTTON là
OUTPUT
Serial.begin(9600); // Khởi tạo kết nối Serial
}

void loop() {
sensorValue = digitalRead(IR_PIN); // Đọc giá trị từ cảm biến
if (sensorValue == LOW) { // Nếu có vật cản
Serial.println("Obstacle detected"); // In ra màn hình Serial
Monitor
digitalWrite(BUTTON_PIN, HIGH); // Bật BUTTON
delay(200); // Trễ 200ms

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 30
31
digitalWrite(BUTTON_PIN, LOW); // Tắt BUTTON
delay(200); // Trễ 200ms
}
else { // Nếu không có vật cản
digitalWrite(BUTTON_PIN, LOW); // Tắt BUTTON
}
delay(100); // Đợi 0.1 giây
}

■ Máy rửa tay tự động sẽ ngắt bơm khi để tay dưới vòi sau 3 giây cho đến khi rút tay ra
và đưa tay vào lại, vậy bạn thử viết chương trình in ra serial xem sao ?

➢ Sử dụng cảm biến âm thanh


■ Đọc dữ liệu cảm biến và gửi thông báo có tiếng ồn lên Serial Monitor
● Nhìn chương trình này quá quen đúng không nào, cảm biến âm thanh này chỉ đơn
giản là xuất tín hiệu digital theo mức biến trở cài đặt để nhận diện tiếng động

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 31
32

/*
Chương trình đọc dữ liệu cảm biến âm thanh gửi thông báo lên Serial
Monitor

*/
int clap = 2; // Khai báo chân kết nối tín hiệu Arduino với module
void setup() {
Serial.begin(9600);
pinMode(clap, INPUT); // Cấu hình chân kết nối của module
}

void loop() {
int soundLevel = digitalRead(clap); // Đọc giá trị âm thanh từ cảm
biến

if (soundLevel == LOW) { // Nếu phát hiện tiếng ồn


Serial.println("Phat hien tieng on!"); // In ra màn hình
}
delay(10); // Chờ 10ms
}

■ Điều khiển LED bằng tiếng vỗ tay


● Vậy để làm 1 dự án bật tắt đèn bằng tiếng vỗ tay quá đơn giản đúng không, bạn thử
tự viết và sau khi hoàn thành có thể so sánh với code dưới đây

/*
CHương trình điều khiển đèn LED bằng 2 tiếng vỗ tay
*/

int sound_sensor = 2; // Chân kết nối cảm biến âm thanh


int LED = 13; // Chân kết nối LED
int clap = 0; // Biến đếm số lần vỗ tay
long detection_range_start = 0; // Thời gian bắt đầu phát hiện âm thanh
long detection_range = 0; // Thời gian kết thúc phát hiện âm thanh
boolean status_lights = false; // Trạng thái đèn hiện tại

void setup() {
pinMode(sound_sensor, INPUT); // Cấu hình chân kết nối của cảm biến âm
thanh
pinMode(LED, OUTPUT); // Cấu hình chân kết nối của LED
}

void loop() {
int status_sensor = digitalRead(sound_sensor); // Đọc trạng thái của
cảm biến âm thanh

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 32
33
if (status_sensor == 0) // Nếu phát hiện âm thanh
{
if (clap == 0) // Nếu đây là lần đầu tiên phát hiện âm thanh
{
detection_range_start = detection_range = millis(); // Ghi nhận
thời gian bắt đầu phát hiện âm thanh và thời gian kết thúc phát hiện âm
thanh
clap++; // Tăng biến
đếm số lần vỗ tay
}
else if (clap > 0 && millis()-detection_range >= 50) // Nếu đã phát
hiện âm thanh trước đó và thời gian giữa hai lần phát hiện âm thanh lớn
hơn 50ms
{
detection_range = millis(); // Cập nhật thời gian kết thúc phát
hiện âm thanh
clap++; // Tăng biến đếm số lần vỗ tay
}
}

if (millis()-detection_range_start >= 400) // Nếu thời gian giữa hai


lần phát hiện âm thanh lớn hơn hoặc bằng 400ms
{
if (clap == 2) // Nếu vỗ tay 2 lần
{
if (!status_lights) // Nếu đèn đang tắt
{
status_lights = true; // Đặt trạng thái đèn là bật
digitalWrite(LED, HIGH); // Bật đèn
}
else if (status_lights) // Nếu đèn đang bật
{
status_lights = false; // Đặt trạng thái đèn là tắt
digitalWrite(LED, LOW); // Tắt đèn
}
}
clap = 0; // Đặt lại biến đếm số lần vỗ tay
}
}

➢ Làm việc với biến trở


■ Đọc giá trị analog từ biến trở
● Khác với giá trị digital chỉ có HIGH = 1 , LOW = 0. Giá trị analog sẽ trả về giá trị trong
khoảng 0-1023

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 33
34

/*
Chương trình đọc giá trị từ biến trở và hiển thị lên Serial Monitor

Kết nối chân thứ 2 của biến trở --> Chân A0 của Arduino
Chân thứ 1 của biến trở --> 5V trên Arduino
Chân thứ 3 của biến trở --> GND trên Arduino
Có thể đảo chân 1,3 lại với nhau --> tín hiệu sẽ đọc ngược lại
*/
const int trimpotPin = A0; // Chân A0 sẽ được sử dụng để đọc giá trị
của biến trở
int trimpotValue = 0; // Biến để lưu giá trị đọc được từ biến
trở

void setup() {
Serial.begin(9600); // Khởi tạo Serial Monitor với baud rate
9600
}

void loop() {
trimpotValue = analogRead(trimpotPin); // Đọc giá trị ADC từ
chân A0
Serial.print("Giá trị đọc được từ biến trở: ");
Serial.println(trimpotValue); // In giá trị đọc được lên
Serial Monitor

delay(100); // Đợi 100ms trước khi


lặp lại quá trình đọc giá trị
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 34
35

■ Điều chỉnh độ sáng của đèn LED thông qua biến trở
● Ở đây chúng ta không nối thẳng biến trở vào LED để điều chỉnh trực tiếp. Chúng ta
sẽ đọc giá trị của biến trở khi tăng giảm , sau đó sẽ quy ra giá trị cho LED từ 0-255

/*
Chương trình điều khiển độ sáng LED bằng biến trở

Kết nối chân thứ 2 của biến trở --> Chân A0 của Arduino
Chân thứ 1 của biến trở --> 5V trên Arduino
Chân thứ 3 của biến trở --> GND trên Arduino
Có thể đảo chân 1,3 lại với nhau --> tín hiệu sẽ đọc ngược lại

Để điều chỉnh độ sáng của LED bằng biến trở arduino, ta cần sử dụng
một chân analog của arduino để đọc giá trị từ biến trở
sau đó dùng giá trị đó để điều chỉnh độ sáng của LED thông qua một
chân PWM, cụ thể là chân Digital 9
*/
const int ledPin = 9; // chân kết nối với LED
const int potPin = A0; // chân kết nối với biến trở

void setup() {
pinMode(ledPin, OUTPUT);
pinMode(potPin, INPUT);
}

void loop() {
int potValue = analogRead(potPin); // đọc giá trị từ
biến trở

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 35
36
int brightness = map(potValue, 0, 1023, 0, 255); // chuyển đổi giá trị
đọc được (0-1023) sang giá trị PWM (0-255)
analogWrite(ledPin, brightness); // điều chỉnh độ sáng của LED
delay(10); // chờ một chút để đọc giá trị mới từ
biến trở
}

➢ Làm việc với cảm biến ánh sáng quang trở


■ Đọc giá trị digital và analog in ra Serial

/*
Chương trình đọc tín hiệu cảm biến ánh sáng quang trở và gửi lên
Serial Monitor

Kết nối chân A0 của module --> Chân A0 của Arduino


Kết nối chân D0 của module --> Chân 2 của Arduino
2 chân VCC, GND kết nối tới nguồn 5V trên Arduino

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 36
37

Bạn có thể tinh chỉnh lại cảm biến bằng cách xoay biến trở trên cảm
biến sao cho phù hợp
*/

const int analogPin = A0; // cổng analog đọc tín hiệu ánh sáng
const int digitalPin = 2; // cổng digital đọc tín hiệu ánh sáng
int analogValue = 0; // giá trị analog của tín hiệu ánh sáng
int digitalValue = 0; // giá trị digital của tín hiệu ánh sáng

void setup() {
Serial.begin(9600); // khởi tạo Serial Monitor với baudrate
9600
pinMode(digitalPin, INPUT); // khai báo cổng digital là input
}

void loop() {
analogValue = analogRead(analogPin); // đọc giá trị analog từ cảm
biến ánh sáng
digitalValue = digitalRead(digitalPin); // đọc giá trị digital từ cảm
biến ánh sáng

// hiển thị giá trị analog và digital lên Serial Monitor


Serial.print("Analog Value: ");
Serial.print(analogValue);
Serial.print(" Digital Value: ");
Serial.println(digitalValue);

delay(1000); // đợi 1 giây trước khi đọc giá trị lại


}

■ Bật LED sáng tự động khi trời tối


● Chương trình này có thể đọc giá trị analog hoặc digital đều được, ở đây mình đọc giá
trị analog, bạn có thể tự viết lại khi sử dụng giá trị digital. Nhớ điều chỉnh biến trở trên
module cảm biến ánh sáng nhé

/*
Chương trình điều khiển LED khi trời tối

Kết nối chân A0 của module --> Chân A0 của Arduino


Kết nối chân D0 của module --> Chân 2 của Arduino
2 chân VCC, GND kết nối tới nguồn 5V trên Arduino

Bạn có thể tinh chỉnh lại cảm biến bằng cách xoay biến trở trên cảm
biến sao cho phù hợp

Lưu ý: giá trị ngưỡng 300 ở dưới có thể được điều chỉnh tùy thuộc

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 37
38
vào môi trường ánh sáng cụ thể của bạn.
*/
const int lightSensorPin = A0; // Chân đọc giá trị từ cảm biến
const int ledPin = 13; // Chân điều khiển LED

void setup() {
pinMode(ledPin, OUTPUT); // Thiết lập chân điều khiển LED là
OUTPUT
}

void loop() {
int lightLevel = analogRead(lightSensorPin); // Đọc giá trị từ cảm
biến

if (lightLevel > 300) { // Nếu giá trị đọc được nhỏ hơn
300(cần điều chỉnh), bật LED
digitalWrite(ledPin, HIGH);
} else { // Ngược lại, tắt LED
digitalWrite(ledPin, LOW);
}

delay(1000); // Đợi 1 giây để cập nhật lại trạng


thái LED
}

➢ Làm việc với cảm biến siêu âm


■ Đo khoảng cách
● Đo khoảng cách có rất nhiều loại cảm biến khác nhau, ở đây chúng ta thử dùng
module cảm biến siêu âm để đo và tính toán khoảng cách

/*
Chương trình đọc khoảng cách từ cảm biến siêu âm hiển thị lên

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 38
39
Serial Monitor
Kết nối:
Chân Trig của module --> chân 2 Arduino
Chân Echo của module --> chân 3 Arduino
2 chân VCC, GND --> 5v, GND trên Arduino
*/
// Khai báo các chân kết nối cảm biến siêu âm
const int trigPin = 2;
const int echoPin = 3;

void setup() {
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}

void loop() {
// Gửi xung trigger
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

// Đọc thời gian từ chân Echo


long duration = pulseIn(echoPin, HIGH);

// Tính toán khoảng cách


float distance = duration * 0.034 / 2; //0.034 là tỉ số giữa vận tốc
âm thanh trong không khí và thời gian tính bằng micro giây, và 2 là vì
khoảng cách cần tính là khoảng cách hai chiều (đi tới và trở lại)

// In kết quả lên Serial Monitor


Serial.print("Khoang cach: ");
Serial.print(distance);
Serial.println(" cm");
delay(500);
}

■ Điều khiển động cơ khi phát hiện trong phạm vi khoảng cách
● Ý tưởng là chúng ta sẽ bật tắt 1 động cơ bơm nước dựa vào khoảng cách từ cảm
biến siêu âm đến mực nước trong bồn chứa

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 39
40

/*
Chương trình điều khiển động cơ khi có vật cản nằm trong phạm vi
ngưỡng cài đặt
Kết nối:
Chân Trig của module --> chân 2 Arduino
Chân Echo của module --> chân 3 Arduino
2 chân VCC, GND --> 5v, GND trên Arduino

Chân động cơ --> chân 4 Arduino. Ở đây ta sử dụng bộ relay để


điều khiển động cơ, bạn xem cơ cấu kết nối, cách điều khiển bạn đọc xem
tại phần Relay
*/
// Khai báo các chân kết nối cảm biến siêu âm
const int trigPin = 2;
const int echoPin = 3;
const int motorPin = 4;

void setup() {
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(motorPin, OUTPUT);
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 40
41
void loop() {
// Gửi xung trigger
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

// Đọc thời gian từ chân Echo


long duration = pulseIn(echoPin, HIGH);

// Tính toán khoảng cách


float distance = duration * 0.034 / 2;
//Giả sử chúng ta có 1 cái bồn chứa nước cao 1.5m , gắn cảm biến siêu
âm trên miệng bồn

if(distance < 10) { // nếu mực nước dâng lên cách cảm
biến 10cm
digitalWrite(motorPin, LOW); // tắt động cơ bơm vì nước gần đầy
}
if(distance > 140) { // mực nước hạ xuống 140cm
digitalWrite(motorPin, HIGH); // bật động cơ bơm vì gần hết nước
}
delay(100); // Đợi 100ms
}

➢ Làm việc với cảm biến phát hiện lửa và cảm biến khí Gas
■ Cảm biến lửa

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 41
42

/*
Chương trình đọc giá trị cảm biến lửa hiển thị lên Serial Monitor
Kết nối:
Arduino --> Cảm biến
5v 5v
GND GND
A0 A0
2 D0
*/
int flameSensor = A0; // Chân analog A0 kết nối với cảm biến phát hiện
lửa
int digitalflame = 2; // Chân digital 2 kết nối với cảm biến phát hiện
lửa
int flameValue = 0; // Khai báo biến lưu trữ giá trị analog cảm biến
phát hiện lửa
int flamedigi = 0; // Khai báo biến lưu trữ giá trị digital cảm biến
phát hiện lửa
void setup() {
Serial.begin(9600); // Khởi tạo giao tiếp Serial với baud rate 9600
pinMode(digitalflame, INPUT);
}

void loop() {
flameValue = analogRead(flameSensor); // Đọc giá trị analog từ cảm
biến phát hiện lửa

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 42
43
flamedigi = digitalRead(digitalflame); // Đọc giá trị digital từ cảm
biến phát hiện lửa
Serial.print("Gia tri cam bien: "); // In ra giá trị cảm biến
Serial.print(flameValue);
Serial.print("Gia tri digital: ");
Serial.println(flamedigi);
delay(1000); // Đợi 1 giây trước khi đọc
lại giá trị
}

■ Cảm biến khí Gas

/*
Chương trình đọc giá trị cảm biến khi Gas hiển thị lên Serial Monitor
Kết nối:
Arduino --> Cảm biến
5v 5v
GND GND

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 43
44
A0 A0
2 D0
*/

int mq4Pin = A0; //Chân kết nối analog A0 của cảm biến MQ4 với
Arduino
int mq4Pindigi = 2; //Chân kết nối digital 2 của cảm biến MQ4 với
Arduino
void setup() {
Serial.begin(9600); //Bắt đầu kết nối với Serial Monitor
pinMode(mq4Pindigi, INPUT);
}

void loop() {
int mq4Value = analogRead(mq4Pin); //Đọc giá trị analog từ cảm
biến MQ4
int mq4digi = digitalRead(mq4Pindigi); //Đọc giá trị digital từ cảm
biến MQ4
Serial.print("Giá trị analog MQ4: ");
Serial.print(mq4Value); //Gửi giá trị analog lên Serial
Monitor
Serial.print(" Giá trị digital MQ4: ");
Serial.println(mq4digi); //Gửi giá trị digital lên Serial
Monitor
delay(1000); //Chờ 1 giây để đọc giá trị mới
}

■ Thử kết hợp 2 cảm biến tạo nên dự án báo rò rỉ khí Gas và báo cháy
● Trong thực tế nếu có rò rỉ khí Gas không nên đóng ngắt tiếp điểm như công tắc, relay
để tránh tạo ra tia lửa gây cháy nổ. Chỉ nên cảnh báo bằng còi chẳng hạn
/*
Chương trình kết hợp cảm biến khí ga MQ4 và cảm biến phát hiện lửa
để cảnh báo sự cố về khí độc và nguy hiểm của lửa.
Khi cảm biến MQ4 phát hiện mức khí ga độc cao hơn ngưỡng cho phép,
buzzer sẽ kêu và đèn LED sẽ chớp đỏ.
Khi cảm biến phát hiện lửa, buzzer cũng sẽ kêu, đèn LED sẽ chớp đỏ
và kích hoạt hệ thống phun nước. Ở đây ta sử dụng relay với động cơ bơm
để thay cho hệ thống phun nước
*/

// Khai báo các chân được sử dụng


const int MQ4_digitalPin = 2; // Cảm biến khí ga MQ4 kết nối với chân
2
const int MQ4_analogPin = A0; // Cảm biến khí ga MQ4 kết nối với chân
A0
const int flame_digitalPin = 3; // Cảm biến phát hiện lửa kết nối với
chân 3

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 44
45
const int flame_analogPin = A1; // Cảm biến phát hiện lửa kết nối với
chân A1
const int buzzerPin = 4; // Buzzer kết nối với chân 4
const int ledPin = 13; // Đèn LED kết nối với chân 5
const int pumpPin = 5;
// Khai báo giá trị ngưỡng cảnh báo khí độc
const int threshold = 600;

void setup() {
// Khai báo chân đầu ra
pinMode(buzzerPin, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(pumpPin, OUTPUT);

// Khai báo chân đầu vào


pinMode(MQ4_digitalPin, INPUT);
pinMode(MQ4_analogPin, INPUT);
pinMode(flame_digitalPin, INPUT);
pinMode(flame_analogPin, INPUT);

// Kích hoạt cổng Serial


Serial.begin(9600);
}

void loop() {
// Đọc giá trị từ cảm biến khí ga MQ4
int MQ4_digitalVal = digitalRead(MQ4_digitalPin);
int MQ4_analogVal = analogRead(MQ4_analogPin);

// Kiểm tra giá trị từ cảm biến khí ga MQ4


if (MQ4_digitalVal == LOW || MQ4_analogVal > threshold) { // hoặc tín
hiệu digital (LOW), hoặc giá trị analog vượt ngưỡng đều bị phát hiện
// Cảnh báo khí Gas
digitalWrite(ledPin, HIGH); // bật LED
tone(buzzerPin, 1, 1000); // lệnh cho buzzer bật lên với tần số 1Hz
, thời gian duy trì 1s
Serial.println("Cảnh báo! Phát hiện nồng độ khí Gas cao!");
} else {
// Không phát hiện khí độc
digitalWrite(ledPin, LOW); // Tắt LED
noTone(buzzerPin); // Lệnh cho buzzer tắt
}

// Đọc giá trị từ cảm biến phát hiện lửa


int flame_digitalVal = digitalRead(flame_digitalPin);

// Kiểm tra giá trị từ cảm biến phát hiện lửa

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 45
46
if (flame_digitalVal == HIGH) {
//Cảnh báo có lửa
digitalWrite(ledPin, HIGH); // bật LED
digitalWrite(pumpPin, HIGH); // bật hệ thống phun nước
tone(buzzerPin, 1, 1000); // lệnh cho buzzer bật lên với tần số 1Hz
, thời gian duy trì 1s
Serial.println("Cảnh báo! Phát hiện có cháy!");
} else {
// Không phát hiện lửa
digitalWrite(ledPin, LOW); // Tắt LED
digitalWrite(pumpPin, LOW); // Tắt hệ thống phun nước
noTone(buzzerPin); // Lệnh cho buzzer tắt
}
}

➢ Điều khiển động cơ bằng L298N


■ Chạy động cơ, đảo chiều quay
● Trong ví dụ này, chúng ta sử dụng các chân kết nối của Arduino để điều khiển động
cơ. Chân enableA và enableB được sử dụng để cấp nguồn cho đầu ra hai động cơ
và được thiết lập ở chế độ OUTPUT. Lưu ý nếu bạn đã cắm jump kết nối tại enableA
và enableB thì không cần viết mã cho chúng. Chân in1 và in2, in3 và in4 được sử
dụng theo cặp để điều khiển chiều quay của 2 bên động cơ và được thiết lập ở chế
độ OUTPUT.

Nguyên lí cơ bản:
in1 và in2: hiệu điện thế tại chân kích = Vin1 - Vin2
in3 và in4: hiệu điện thế tại chân kích = Vin3 - Vin4

Khi Vin1 = HIGH, Vin2 = LOW --> điện thế tại đó > 0 nên động cơ quay chiều
thuận. Khi Vin1 = LOW, Vin2 = HIGH --> điện thế tại đó < 0 nên động cơ quay ngược
chiều. Tương tự với in3 và in4

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 46
47

/*
Chương trình điều khiển động cơ thông qua L298N cơ bản
*/
// Khai báo các chân kết nối với L298N
//int enableA = 9;
//int enableB = 10;

int in1 = 2; // cặp điều khiển ngõ ra OUT2 trên board L298N
int in2 = 3;

int in3 = 4; // cặp điều khiển ngõ ra OUT3 trên board L298N
int in4 = 5;

void setup() {
// Thiết lập chế độ OUTPUT cho các chân kết nối với L298N
//pinMode(enableA, OUTPUT);
//pinMode(enableB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);

// Bật đầu ra cho các chân enableA và enableB nếu không gắn jump

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 47
48
//digitalWrite(enableA, HIGH);
//digitalWrite(enableB, HIGH);
}

void loop() {
// Điều khiển động cơ chạy theo chiều thuận
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);

// Tạm dừng 2 giây


delay(2000);

// Điều khiển động cơ chạy theo chiều nghịch


digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);

// Tạm dừng 2 giây


delay(2000);
}

■ Điều khiển tốc độ động cơ thông qua băm xung PWM


● Ở VD này lưu ý: Chân enableA và enableB được sử dụng để cấp nguồn cho đầu ra
hai động cơ và được thiết lập ở chế độ OUTPUT, Nếu điện thế tại ENA đủ thấp -->
động cơ hoạt động yếu. Nếu điện thế tại ENA cao --> động cơ hoạt động mạnh.
Tương tự với ENB, dựa vào đó ta có thể điều chỉnh tốc độ động cơ bằng cách băm
xung điều khiển điện thế tại ENA và ENB
● Chú ý muốn băm xung cần chọn đúng chân trên Arduino có hỗ trợ băm xung để
tránh sai sót nhé! VD này điều khiển động cơ bên A (ENA), bạn có thể thêm code
làm tương tự như bên B(ENB)

/*
Chương trình điều khiển động cơ thông qua L298N cơ bản

Trong ví dụ này, chúng ta sử dụng các chân kết nối của Arduino để
điều khiển động cơ.
Chân in1 và in2, in3 và in4 được sử dụng theo cặp để điều khiển
chiều quay của 2 bên động cơ và được thiết lập ở chế độ OUTPUT.

Nguyên lý cơ bản:
in1 và in2: hiệu điện thế tại chân kích = Vin1 - Vin2
in3 và in4: hiệu điện thế tại chân kích = Vin3 - Vin4

Khi Vin1 = HIGH, Vin2 = LOW --> điện thế tại đó > 0 nên động cơ

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 48
49
quay chiều thuận
Khi Vin1 = LOW, Vin2 = HIGH --> điện thế tại đó < 0 nên động cơ
quay ngược chiều
Tương tự với in3 và in4
*/

// Khai báo chân điều khiển động cơ L298N


const int ENA = 3;
const int IN1 = 4;
const int IN2 = 5;

// Khai báo biến tốc độ động cơ


int motorSpeed = 0;

void setup() {
// Khởi tạo chân đầu ra
pinMode(ENA, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);

// Khởi tạo mạch PWM


analogWrite(ENA, 0);
}

void loop() {
// Điều khiển tốc độ động cơ tăng dần
for(motorSpeed = 0; motorSpeed <= 255; motorSpeed++) {
analogWrite(ENA, motorSpeed);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
delay(10);
}

// Điều khiển tốc độ động cơ giảm dần


for(motorSpeed = 255; motorSpeed >= 0; motorSpeed--) {
analogWrite(ENA, motorSpeed);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
delay(10);
}
}

■ Điều khiển tốc độ động cơ sử dụng L298N và biến trở

/*
Ở VD này lưu ý: Chân enableA và enableB được sử dụng để cấp nguồn
cho đầu ra hai động cơ và được thiết lập ở chế độ OUTPUT,

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 49
50
Nếu điện thế tại ENA đủ thấp --> động cơ hoạt động
yếu
Nếu điện thế tại ENA cao --> động cơ hoạt động mạnh
Tương tự với ENB, dựa vào đó ta có thể điều chỉnh
tốc độ động cơ bằng cách băm xung điều khiển điện thế tại ENA và ENB
Chú ý muốn băm xung cần chọn đúng chân trên Arduino
có hỗ trợ băm xung để tránh sai sót nhé!
VD này điều khiển động cơ bên A (ENA), bạn có thể thêm code làm
tương tự như bên B(ENB)
*/

// Khai báo chân điều khiển động cơ L298N


const int ENA = 3;
const int IN1 = 4;
const int IN2 = 5;
const int potPin = A0; // chân kết nối với biến trở

// Khai báo biến tốc độ động cơ


int motorSpeed = 0;

void setup() {
// Khởi tạo chân đầu ra
pinMode(ENA, OUTPUT);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
// Khởi tạo chân đầu vào
pinMode(potPin, INPUT);

// Khởi tạo mạch PWM


analogWrite(ENA, 0);
}

void loop() {
int potValue = analogRead(potPin); // đọc giá trị từ
biến trở
int motorSpeed = map(potValue, 0, 1023, 0, 255); // chuyển đổi giá trị
đọc được (0-1023) sang giá trị PWM (0-255)
// Điều khiển tốc độ động cơ theo giá trị motorSpeed đã được chuyển
đổi từ potValue
analogWrite(ENA, motorSpeed);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
delay(10);
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 50
51
➢ Làm quen với module relay
■ Bật tắt máy bơm bằng Relay không sử dụng Code
● Tùy thuộc vào loại relay kích thấp hay kích cao nên cần phải đưa đúng tín hiệu mức
thấp hoặc mức cao

●DC INPUT: tùy từng mạch hỗ trợ nguồn nuôi bao nhiêu volt
●Tín hiệu kích:
◆ Khi ở chế độ kích cao. Nếu tín hiệu kích = HIGH (mức cao) động cơ sẽ hoạt
động, ngược lại nếu tín hiệu kích = LOW (mức thấp), động cơ không hoạt
động
◆ Khi ở chế độ kích thấp. Nếu tín hiệu kích = LOW (mức thấp), động cơ sẽ hoạt
động, ngược lại nếu tín hiệu kích = DC HIGH (mức cao), động cơ không hoạt
động
● Mức LOW tương ứng với việc kích 1 dây dẫn từ GND vào chân IN
● Mức HIGH khoảng 3v đến dưới điện áp nguồn nuôi, có nghĩa là sẽ nối 1 dây dẫn từ
DC+ vào chân IN ( Ví dụ nguồn nuôi tối đa của mạch là 12v thì Mức HIGH có thể
kích trong khoảng 3 – 12V đều được )
■ Bật tắt relay bằng Code
● Nối 1 dây cắm từ chân 12 của arduino vào chân tín hiệu IN của module relay ( ở đây
sử dụng module relay 5V ) và tiến hành code sau

/*
Chương trình bật tắt relay cơ bản
Sơ đồ đấu nối nằm ở phần trước (phần "Bật tắt máy bơm bằng Relay
không sử dụng Code")
Tín hiệu kích sẽ kết nối với chân Digital 12 như đã khai báo bên
dưới
*/
const int relayPin = 12; //khai báo chân digital sử dụng để kích hoạt
relay

void setup() {
pinMode(relayPin, OUTPUT); //khai báo chân digital là output
}

void loop() {
digitalWrite(relayPin, HIGH); //bật relay, nếu kích thấp để trạng thái
LOW
delay(1000); //đợi 1 giây
digitalWrite(relayPin, LOW); //tắt relay, nếu kích thấp để trạng thái

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 51
52
HIGH
delay(1000); //đợi 1 giây
}

➢ Làm việc với cảm biến độ ẩm đất


■ Đọc giá trị

/*
Chương trình đọc dữ liệu cảm biến độ ẩm đất và gửi lên Serial
Monitor
Kết nối:
Arduino --> Sensor
2 D0
A0 A0
GND GND
5V VCC
Bạn có thể tinh chỉnh lại độ nhạy của cảm biến bằng cách điều chỉnh
biến trở trên cảm biến sao cho phù hợp
*/
const int analogPin = A0; // Chân analog kết nối với cảm biến độ ẩm đất
const int digitalPin = 2; // Chân digital kết nối với cảm biến độ ẩm đất

void setup() {
Serial.begin(9600); // Khởi tạo kết nối Serial với baud rate là 9600
}

void loop() {
int analogValue = analogRead(analogPin); // Đọc giá trị analog từ cảm
biến độ ẩm đất

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 52
53
int digitalValue = digitalRead(digitalPin); // Đọc giá trị digital từ
cảm biến độ ẩm đất

Serial.print("Analog value: "); // In ra thông tin giá trị analog


Serial.println(analogValue);

Serial.print("Digital value: "); // In ra thông tin giá trị digital


Serial.println(digitalValue);

delay(1000); // Delay 1 giây để giảm tải cho Arduino


}

■ Thử làm mô hình tưới cây, bật tắt bơm chìm dựa vào thông số độ ẩm đất
● Để bật bắt 1 thiết bị chúng ta không được đấu trực tiếp thiết bị đó vào arduino mà
phải xem thiết bị đó dùng điện áp bao nhiêu, dòng tiêu thụ ra sao. Ở đây để bật tắt
bơm chìm tưới nước chúng ta nối bơm qua relay, sau đó điều khiển relay. Kết hợp
với giá trị độ ẩm đất phù hợp chúng ta sẽ có 1 mô hình bơm tưới cây thông minh

/*
Chương trình điều khiển tưới nước tự động dựa trên cảm biến độ ẩm
đất
Để sử dụng cảm biến độ ẩm đất để điều khiển tưới nước tự động, ta
cần kết hợp cảm biến độ ẩm đất với một mạch điều khiển động cơ bơm nước.
Cụ thể, nếu độ ẩm đất thấp hơn một ngưỡng nào đó, ta sẽ kích hoạt
mạch điều khiển động cơ bơm nước để tưới nước cho cây trồng.
*/
const int sensorPin = A0; // Chân analog kết nối với cảm biến độ ẩm đất
const int pumpPin = 9; // Chân kết nối với mạch điều khiển động cơ
bơm nước

int sensorValue = 0; // Giá trị đọc được từ cảm biến độ ẩm đất


int threshold = 500; // Ngưỡng giá trị độ ẩm đất cần tưới nước

void setup() {
pinMode(pumpPin, OUTPUT); // Chọn chân kết nối với mạch điều khiển
động cơ bơm nước là OUTPUT
Serial.begin(9600); // Khởi động giao tiếp serial để đọc giá trị
độ ẩm đất
}

void loop() {
// Đọc giá trị độ ẩm đất từ cảm biến
sensorValue = analogRead(sensorPin);

// Gửi giá trị độ ẩm đất lên Serial Monitor


Serial.print("Sensor value: ");

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 53
54
Serial.println(sensorValue);

// Nếu giá trị độ ẩm đất nhỏ hơn ngưỡng định trước thì bật động cơ bơm
nước
if (sensorValue < threshold) {
digitalWrite(pumpPin, HIGH);
} else {
digitalWrite(pumpPin, LOW);
}

delay(1000); // Đợi 1 giây để đọc giá trị độ ẩm đất mới


}

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


■ Đọc giá trị của cảm biến và in ra Serial

/*
Chương trình đọc dữ liệu cảm biến DHT11 và gửi lên Serial Monitor

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 54
55

Trước tiên ta cài 2 thư viện ở link sau


<https://github.com/adafruit/DHT-sensor-library> và
<https://github.com/adafruit/Adafruit_Sensor> bắt buộc cài cả 2 nhé!
Để cài thư viện dạng tệp .zip, .rar bên ngoài ta thực hiện Sketch ->
Include Library -> Add .ZIP Library -> Chọn file dạng .zip, .rar bạn đã
tải về
*/
#include <DHT.h>

#define DHTPIN 2 // Chân kết nối cảm biến DHT11


#define DHTTYPE DHT11 // Loại cảm biến DHT11

DHT dht(DHTPIN, DHTTYPE); // Khởi tạo đối tượng cảm biến DHT11

void setup() {
Serial.begin(9600); // Khởi động Serial Monitor
dht.begin(); // Khởi động cảm biến DHT11
}

void loop() {
delay(2000); // Chờ 2 giây để cảm biến đo độ ẩm và nhiệt
độ
float h = dht.readHumidity(); // Đọc giá trị độ ẩm
float t = dht.readTemperature(); // Đọc giá trị nhiệt độ

// Kiểm tra xem cảm biến có đọc được giá trị không
if (isnan(h) || isnan(t)) {
Serial.println("Khong doc duoc gia tri tu DHT11");
return;
}

// In giá trị đọc được lên Serial Monitor


Serial.print("Do am: ");
Serial.print(h);
Serial.print("%\t");
Serial.print("Nhiet do: ");
Serial.print(t);
Serial.println(" *C");
}

■ Điều hòa nhiệt độ trong phòng sử dụng cảm biến DHT11


● Ý tưởng là chúng ta sẽ khống chế nhiệt độ ở khoảng mong muốn. Ví dụ chúng ta
muốn nhiệt độ phòng luôn nằm trong khoảng 20-22 độ thì khi nhiệt độ cao hơn 22 độ
chúng ta sẽ bật máy lạnh. Khi nhiệt độ thấp hơn 20 độ chúng ta sẽ tắt máy lạnh và
bật máy sưởi lên

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 55
56
/*
Điều hòa nhiệt độ trong phòng sử dụng cảm biến DHT11

Trước tiên ta cài 2 thư viện ở link sau


<https://github.com/adafruit/DHT-sensor-library> và
<https://github.com/adafruit/Adafruit_Sensor> bắt buộc cài cả 2 nhé!
Để cài thư viện dạng tệp .zip, .rar bên ngoài ta thực hiện Sketch ->
Include Library -> Add .ZIP Library -> Chọn file dạng .zip, .rar bạn đã
tải về
*/
#include <DHT.h> // Khai báo thư viện DHT
//Khai báo các chân thiết bị làm nóng, làm lạnh trong phòng
#define COLD_PIN 9
#define HOT_PIN 10
#define DHTPIN 2 // Chân kết nối cảm biến DHT11
#define DHTTYPE DHT11 // Loại cảm biến DHT11

DHT dht(DHTPIN, DHTTYPE); // Khởi tạo đối tượng cảm biến DHT11
void setup() {
// Khởi tạo cổng Serial để gửi dữ liệu đến máy tính
Serial.begin(9600);
dht.begin(); // Khởi động cảm biến DHT11
delay(100);
// Cài đặt chân COLD_PIN, HOT_PIN là OUTPUT
pinMode(COLD_PIN, OUTPUT);
pinMode(HOT_PIN, OUTPUT);

void loop() {
delay(2000); // Chờ 2 giây để cảm biến đo độ ẩm và nhiệt
độ

float h = dht.readHumidity(); // Đọc giá trị độ ẩm


float t = dht.readTemperature(); // Đọc giá trị nhiệt độ

// In giá trị đọc được lên Serial Monitor


Serial.print("Do am: ");
Serial.print(h);
Serial.print("%\t");
Serial.print("Nhiet do: ");
Serial.print(t);
Serial.println(" *C");

// Kiểm tra nhiệt độ, nếu nhiệt độ vượt quá ngưỡng 22 độ, bật chế độ

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 56
57
làm mát
if (t >= 22) {
digitalWrite(COLD_PIN, HIGH); // bật máy lạnh
digitalWrite(HOT_PIN, LOW); // tắt máy sưởi
}
// Kiểm tra nhiệt độ, nếu nhiệt độ bé hơn ngưỡng 20 độ, bật chế độ
sưởi ấm
if (t <= 20) {
digitalWrite(COLD_PIN, LOW); // tắt máy lạnh
digitalWrite(HOT_PIN, HIGH); // bật máy sưởi
}
}

➢ Sử dụng màn hình LCD bằng giao tiếp I2C


■ Hiển thị text “Hello World” đơn giản lên màn hình

/*
Chương trình hiển thị Hello World lên LCD
Kết nối:
Arduino LCD 1602 I2C
5V VCC
GND GND
A4 SDA
A5 SCL

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 57
58
Trước tiên ta cài thư viện LiquidCrystal_I2C tại link
<https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library>
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Đặt địa chỉ LCD thành 0x27 để hiển thị 16 ký tự và 2 dòng, nếu không
hiển thị có thể thử với địa chỉ 0x3F
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
// Khởi động LCD
lcd.begin();

// Bật đèn màn hình và gửi chuỗi lên LCD


lcd.backlight();
lcd.print("Hello, world!");
}

void loop()
{
//Có thể thêm chương trình chính tại đây
}

■ Hiển thị giá trị đọc được từ cảm biến


● Với các đoạn code đã thực hiện các phần trên chúng ta thường kiểm tra bằng cách
in giá trị ra Serial màn hình máy tính. Bây giờ khi đã biết cách làm việc với LCD ta sẽ
cho hiển thị các giá trị từ cảm biến , thông số , … ra màn hình để tiện theo dõi
/*
Chương trình hiển thị Hello World lên LCD
Kết nối:
Arduino LCD 1602 I2C
5V VCC
GND GND
A4 SDA
A5 SCL
Trước tiên ta cài thư viện LiquidCrystal_I2C tại link
<https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library>
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>

#define DHTPIN 2 // Chân kết nối cảm biến DHT11


#define DHTTYPE DHT11 // Loại cảm biến DHT11

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 58
59
DHT dht(DHTPIN, DHTTYPE); // Khởi tạo đối tượng cảm biến DHT11

// Đặt địa chỉ LCD thành 0x27 để hiển thị 16 ký tự và 2 dòng, nếu không
hiển thị có thể thử với địa chỉ 0x3F
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
// Khởi động LCD
lcd.begin();
dht.begin(); // Khởi động cảm biến DHT11

// Bật đèn màn hình và gửi chuỗi lên LCD


lcd.backlight();
lcd.print("Hello, world!");
delay(1000); // Đợi 1s rồi xóa màn hình
lcd.clear();
}

void loop()
{
float h = dht.readHumidity(); // Đọc giá trị độ ẩm
float t = dht.readTemperature(); // Đọc giá trị nhiệt độ

// In giá trị đọc được lên LCD


lcd.clear(); // Xóa màn hình LCD
lcd.setCursor(0,0); // Di chuyển con trỏ đến vị trí
(0,0)
lcd.print("Humidity: "); // In chuỗi ký tự
lcd.setCursor(12,0); // Di chuyển con trỏ đến vị trí
(12,0)
lcd.print(h); // In giá trị độ ẩm

lcd.setCursor(0,1); // Di chuyển con trỏ đến vị trí


(0,1)
lcd.print("Temp: "); // In chuỗi ký tự
lcd.setCursor(12,1); // Di chuyển con trỏ đến vị trí
(12,1)
lcd.print(t); // In giá trị nhiệt độ

delay(1000); // Chờ 1 giây

➢ Điều khiển động cơ Servo


■ Điều khiển động cơ Servo quét 180 độ

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 59
60
● Để điều khiển servo 1 cách đơn giản hơn chúng ta sử dụng thư viện có sẵn Servo.h

/*
Chương trình điều khiển Servo xoay 180 độ
Kết nối chân tín hiệu(chân vàng) của Servo tới chân 9 của Arduino
Chân nguồn VCC(chân đỏ) kết nối tới 5V trên Arduino
Chân GND (chân nâu) kết nối tới GND của Arduino
*/
#include <Servo.h>

Servo myservo; // Tạo đối tượng Servo để điều khiển servo

int pos = 0; // Biến lưu trữ vị trí của servo

void setup() {
myservo.attach(9); // kết nối servo đến chân số 9 của arduino
}

void loop() {
for (pos = 0; pos <= 180; pos += 1) { // Di chuyển từ vị trí 0 độ đến
180 độ
myservo.write(pos); // Điều khiển servo đến vị trí
được lưu trong biến 'pos'
delay(15); // Chờ 15 ms để servo di chuyển
đến vị trí mới
}
for (pos = 180; pos >= 0; pos -= 1) { // Di chuyển từ vị trí 180 độ đến
0 độ
myservo.write(pos); // Điều khiển servo đến vị trí
được lưu trong biến 'pos'
delay(15); // Chờ 15 ms để servo di chuyển
đến vị trí mới

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 60
61
}
}

■ Điều khiển góc của động cơ Servo chạy theo biến trở

/*
Chương trình điều khiển Servo sử dụng biến trở
Kết nối chân tín hiệu(chân vàng) của Servo tới chân 9 của Arduino
Chân nguồn VCC(chân đỏ) kết nối tới 5V trên Arduino
Chân GND (chân nâu) kết nối tới GND của Arduino

Kết nối chân thứ 2 của biến trở --> Chân A0 của Arduino
Chân thứ 1 của biến trở --> 5V trên Arduino
Chân thứ 3 của biến trở --> GND trên Arduino
Có thể đảo chân 1,3 lại với nhau --> tín hiệu sẽ đọc ngược lại
*/
#include <Servo.h>

Servo myservo; // tạo đối tượng servo để điều khiển một servo

int potpin = A0; // chân analog được sử dụng để kết nối với biến trở
int val; // biến để đọc giá trị từ chân analog

void setup() {
myservo.attach(9); // kết nối servo đến chân số 9 của arduino
}

void loop() {
val = analogRead(potpin); // đọc giá trị từ biến trở (giá trị
từ 0 đến 1023)
val = map(val, 0, 1023, 0, 180); // chuyển đổi giá trị đọc được từ 0
đến 1023 thành giá trị góc quay từ 0 đến 180 độ

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 61
62
myservo.write(val); // điều khiển servo di chuyển đến vị
trí tương ứng với giá trị góc quay
delay(15); // đợi cho servo đến vị trí mới
}

➢ Giao tiếp với module thời gian thực DS1302


■ Đọc và hiển thị thời gian lên Serial
● Sử dụng thư viện ArduinoRTClibrary và kết nối theo sơ đồ. Lưu ý trong code nó sẽ
dòng lệnh myRTC.setDS1302Time() , dòng lệnh này chỉ thực hiện 1 lần đầu tiên để
lưu giá trị thời gian vào module . Thời gian này sẽ được duy trì bằng pin trên mạch,
và tiếp tục chạy theo thời gian thực , vì vậy ngay cả khi ta rút nguồn 5V của module
thì khi kết nối lại mạch vẫn trả về đúng thời gian.

/*
Chương trình đọc giá trị thời gian từ DS1302 gửi lên Serial Monitor
DS1302: CLK pin -> Arduino chân 2

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 62
63
DAT pin -> Arduino chân 3
RST pin -> Arduino chân 4
Nguồn cấp có thể sử dụng từ 3.3v - 5v
Trước tiên cần tải thư viện ArduinoRTClibrary tại link
<https://github.com/chrisfryer78/ArduinoRTClibrary>
*/
#include <virtuabotixRTC.h>
// Tạo đối tượng đồng hồ thời gian thực
virtuabotixRTC myRTC(2, 3, 4); //Khai báo chân kết nối theo định dạng
(CLK, DAT, RST)

void setup() {
Serial.begin(9600);
// Thiết lập ngày và giờ hiện tại theo định dạng sau:
// giây, phút, giờ, ngày trong tuần, ngày trong tháng, tháng, năm
myRTC.setDS1302Time(00, 57, 04, 6, 28, 4, 2023); //có thể bỏ dòng
này nếu đã cài giờ xong
}
void loop() {
// Cho phép cập nhật thời gian
myRTC.updateTime();
// Bắt đầu in các phần tử như giây, phút, giờ, ngày trong tuần, ngày
trong tháng, tháng, năm
Serial.print("Thời gian hiện tại: ");
Serial.print(myRTC.dayofmonth); // Gửi ngày lên Serial Monitor
Serial.print("/");
Serial.print(myRTC.month); // Gửi tháng lên Serial
Monitor
Serial.print("/");
Serial.print(myRTC.year); // Gửi năm lên Serial Monitor
Serial.print(" ");
Serial.print(myRTC.hours); // Gửi giờ lên Serial Monitor
Serial.print(":");
Serial.print(myRTC.minutes); // Gửi phút lên Serial Monitor
Serial.print(":");
Serial.println(myRTC.seconds); // Gửi giây lên Serial Monitor
// Đợi để chương trình không in ra liên tục
delay(500);
}

■ Đọc và hiển thị thời gian lên màn hình LCD

/*
Chương trình hiển thị thời gian từ DS1302 lên LCD
Kết nối:

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 63
64
Arduino LCD 1602 I2C
5V VCC
GND GND
A4 SDA
A5 SCL

DS1302: CLK pin -> Arduino chân 2


DAT pin -> Arduino chân 3
RST pin -> Arduino chân 4
Nguồn cấp có thể sử dụng từ 3.3v - 5v
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <virtuabotixRTC.h>
// Tạo đối tượng đồng hồ thời gian thực
virtuabotixRTC myRTC(2, 3, 4); //Khai báo chân kết nối theo định dạng
(CLK, DAT, RST)

// Đặt địa chỉ LCD thành 0x27 để hiển thị 16 ký tự và 2 dòng, nếu không
hiển thị có thể thử với địa chỉ 0x3F
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
// Thiết lập ngày và giờ hiện tại theo định dạng sau:
// giây, phút, giờ, ngày trong tuần, ngày trong tháng, tháng, năm
//myRTC.setDS1302Time(00, 57, 04, 6, 28, 4, 2023); //có thể bỏ
dòng này nếu đã cài giờ xong

lcd.begin(); // Khởi động LCD

// Bật đèn màn hình và gửi chuỗi lên LCD


lcd.backlight();
}

void loop()
{
// Cho phép cập nhật thời gian
myRTC.updateTime();

// In giá trị đọc được lên LCD


lcd.clear(); // Xóa màn hình LCD
lcd.setCursor(0,0); // Di chuyển con trỏ đến vị trí
(0,0)
lcd.print(myRTC.dayofmonth); // In ngày
lcd.setCursor(2,0); // Di chuyển con trỏ đến vị trí
(2,0)

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 64
65
lcd.print("/");
lcd.setCursor(3,0); // Di chuyển con trỏ đến vị trí
(3,0)
lcd.print(myRTC.month); // In tháng
lcd.setCursor(5,0); // Di chuyển con trỏ đến vị trí
(5,0)
lcd.print("/");
lcd.setCursor(6,0); // Di chuyển con trỏ đến vị trí
(6,0)
lcd.print(myRTC.year); // In năm

lcd.setCursor(0,1); // Di chuyển con trỏ đến vị trí


(0,1)
lcd.print(myRTC.hours); // In giờ
lcd.setCursor(2,1); // Di chuyển con trỏ đến vị trí
(2,1)
lcd.print(":");
lcd.setCursor(3,1); // Di chuyển con trỏ đến vị trí
(3,1)
lcd.print(myRTC.minutes); // In phút
lcd.setCursor(5,1); // Di chuyển con trỏ đến vị trí
(5,1)
lcd.print(":");
lcd.setCursor(6,1); // Di chuyển con trỏ đến vị trí
(6,1)
lcd.print(myRTC.seconds); // In giây

delay(1000); // Chờ 1 giây

■ Khi có được các mốc thời gian, bạn hãy thử viết 1 chương trình hẹn giờ hoặc đếm
ngược xem sao ?

➢ Sử dụng bàn phím ma trận 4x4


■ Sơ đồ kết nối dây
● Sơ đồ mạch điện của bàn phím và sơ đồ nối dây với Arduino để test code

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 65
66

Arduino 5 6 7 8 9 10 11 12

Keypad 8 7 6 5 4 3 2 1

■ Đọc và hiển thị kí tự bàn phím ma trận lên Serial Monitor


● Để sử dụng bàn phím này ta cần sử dụng thư viện Keypad.h để thuận tiện hơn. Và
việc quan trọng là định nghĩa các key tương ứng với các kí tự xuất ra.

/*
Chương trình đọc dữ liệu KEYPAD 4x4 và gửi dữ liệu lên Serial
Monitor
Ta cần cài thư viện Keypad tại link sau
<https://github.com/Chris--A/Keypad>
*/
#include <Keypad.h>

const byte rows = 4; //số hàng


const byte columns = 4; //số cột

//Định nghĩa các giá trị trả về


char keys[rows][columns] =
{
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'},
};

// Khởi tạo các chân kết nối với Arduino

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 66
67
byte rowPins[rows] = {5, 6, 7, 8};
byte columnPins[columns] = {9, 10, 11, 12};

Keypad keypad = Keypad(makeKeymap(keys), rowPins, columnPins, rows,


columns); // Khởi tạo kết nối các chân trên KEYPAD
void setup() {
Serial.begin(9600); // Khởi tạo Serial với baudrate 9600

}
void loop() {
char temp = keypad.getKey(); // Đọc giá trị từ keypad

if (temp){ // Nếu có giá trị đọc về từ keypad


Serial.println(temp); // In ra màn hình
}
delay(100);
}

■ Đọc và hiển thị 1 dãy kí tự lên Serial Monitor khi nhấn phím

/*
Chương trình đọc và hiển thị 1 dãy kí tự lên Serial Monitor khi nhấn
phím #
Ta cần cài thư viện Keypad tại link sau
<https://github.com/Chris--A/Keypad>
*/
#include <Keypad.h>

const byte rows = 4; //số hàng


const byte columns = 4; //số cột

//Định nghĩa các giá trị trả về


char keys[rows][columns] =
{
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'},
};

// Khởi tạo các chân kết nối với Arduino


byte rowPins[rows] = {5, 6, 7, 8};
byte columnPins[columns] = {9, 10, 11, 12};

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 67
68
String str = ""; // Khởi tạo chuỗi str rỗng
Keypad keypad = Keypad(makeKeymap(keys), rowPins, columnPins, rows,
columns); // Khởi tạo kết nối các chân trên KEYPAD
void setup() {
Serial.begin(9600); // Khởi tạo Serial với baudrate 9600

}
void loop() {
char temp = keypad.getKey(); // Đọc giá trị từ keypad

if (temp){ // Nếu có giá trị đọc về từ keypad


if (temp == '#') { // Nếu nhấn kí tự #
Serial.println("");
Serial.print("Kí tự đã viết: ");
Serial.println(str); // In ra màn hình kí tự đã nhấn
str = ""; // Xóa str cho lần viết tiếp theo
}
else { // Nếu không phải kí tự #
Serial.print(temp); // In ra màn hình để biết mình đã nhấn
str = str + temp; // Thêm kí tự vào chuỗi Str
}
}

delay(100);
}

➢ Module RFID RC522 tần số 13.56Mhz và thẻ từ


■ Đọc thẻ RFID và hiển thị dãy mã thẻ lên Serial Monitor
● Để giao tiếp được với module đọc thẻ các bạn sử dụng thư viện được chia sẻ
MFRC522

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 68
69

/*
Chương trình đọc thẻ RFID và gửi ID đọc được lên Serial Monitor
Ta cần cài thư viện MFRC522 trên Manage Libraries hoặc cài tại
link <https://github.com/miguelbalboa/rfid>
Sơ đồ kết nối:
Arduino --> RFID

3.3V VCC
GND GND
13 SCK
12 MISO
11 MOSI
10 SDA
9 RST
*/

#include <SPI.h>
#include <MFRC522.h>

// Khai báo chân kết nối


#define RST_PIN 9
#define SS_PIN 10

MFRC522 mfrc522(SS_PIN, RST_PIN); // khởi tạo đối tượng MFRC522 để

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 69
70
đọc thẻ RFID trên các chân đã định nghĩa.
String UID =""; // Khởi tạo chuỗi UID rỗng
void setup() {
Serial.begin(9600); // Khởi tạo kết nối Serial với baudrate 9600
SPI.begin(); // Khởi tạo kết nối SPI
mfrc522.PCD_Init(); // Khởi tạo đọc thẻ RFID
}

void loop()
{
if(mfrc522.PICC_IsNewCardPresent())
// Nếu có thẻ RFID mới được đưa vào
{
if(mfrc522.PICC_ReadCardSerial())
// Nếu thẻ RFID đang được đọc
{
Serial.print("The UID: ");
for (byte i = 0; i < mfrc522.uid.size; i++)
// Vòng lặp để in ra mã thẻ
{
//Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
//Serial.print(mfrc522.uid.uidByte[i], HEX);
UID = UID + String(mfrc522.uid.uidByte[i], HEX);
// Cộng thêm mỗi Byte dữ liệu đọc được trong 1 vòng lặp và chuyển sang
hệ HEX
}
Serial.println(UID);
// In ra màn hình chuỗi mã thẻ UID đọc được
UID = "";
// Xóa chuỗi cho lần đọc tiếp theo
mfrc522.PICC_HaltA();
// Dừng đọc thẻ RFID
}
}
}

■ Quét thẻ RFID điều khiển đóng mở cửa


● Khi đã giao tiếp được với module đọc thẻ, chúng ta thử làm tiếp 1 ứng dụng nhỏ là
đóng mở cửa khi quẹt thẻ từ bằng việc so sánh dãy số thẻ

/*
Chương trình quét thẻ RFID đóng mở cửa
Ta sử dụng relay thay cho hệ thống đóng mở cửa.
Trước tiên cần cài thư viện MFRC522 trên Manage Libraries hoặc cài
tại link <https://github.com/miguelbalboa/rfid>
Sơ đồ kết nối:

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 70
71
Arduino --> RFID

3.3V VCC
GND GND
13 SCK
12 MISO
11 MOSI
10 SDA
9 RST
*/

#include <SPI.h>
#include <MFRC522.h>

// Khai báo chân kết nối


#define RST_PIN 9
#define SS_PIN 10

const int relay = 7; // Khai báo chân Relay


String str = "c3ed9c95";

MFRC522 mfrc522(SS_PIN, RST_PIN); // khởi tạo đối tượng MFRC522 để


đọc thẻ RFID trên các chân đã định nghĩa.
String UID =""; // Khởi tạo chuỗi UID rỗng
void setup() {
pinMode(relay, OUTPUT); // Cấu hình cho chân relay là đầu ra
Serial.begin(9600); // Khởi tạo kết nối Serial với baudrate 9600
SPI.begin(); // Khởi tạo kết nối SPI
mfrc522.PCD_Init(); // Khởi tạo đọc thẻ RFID
}

void loop()
{
if(mfrc522.PICC_IsNewCardPresent())
// Nếu có thẻ RFID mới được đưa vào
{
if(mfrc522.PICC_ReadCardSerial())
// Nếu thẻ RFID đang được đọc
{
Serial.print("The UID: ");
for (byte i = 0; i < mfrc522.uid.size; i++)
// Vòng lặp để in ra mã thẻ
{
//Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
//Serial.print(mfrc522.uid.uidByte[i], HEX);
UID = UID + String(mfrc522.uid.uidByte[i], HEX);

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 71
72
// Cộng thêm mỗi Byte dữ liệu đọc được trong 1 vòng lặp và chuyển sang
hệ HEX
}
Serial.print(UID);
// In ra màn hình chuỗi mã thẻ UID đọc được
if (UID == str) {
// Nếu đúng mã đã cài đặt thì cho phép mở cửa và in ra màn hình
digitalWrite(relay,HIGH);
Serial.println(" Chap nhan, cho phep mo cua!");
}
else {
// Nếu sai mã thì từ chối của cửa
digitalWrite(relay,LOW);
Serial.println(" Sai ma!");
}
UID = "";
// Xóa chuỗi cho lần đọc tiếp theo
mfrc522.PICC_HaltA();
// Dừng đọc thẻ RFID
}
}
}

➢ Điều khiển LED ma trận MAX7219 8x8


■ Hiển thị chữ “A” lên LED ma trận
● Sử dụng thư viện LedControl.h

/*
CHương trình điều khiển LED ma trận hiển thị chữ A
Trước tiên ta cần cài thư viện tại link
<https://github.com/wayoda/LedControl>
*/
#include "LedControl.h" // Nạp thư viện LedControl.h
LedControl lc=LedControl(12,11,10,1); // Khởi tạo đối tượng LedControl
và gắn chân tương ứng
// Chân 12 nối với chân DataIn
// Chân 11 nối với chân CLK
// Chân 10 nối với chân LOAD
// Sử dụng 1 IC MAX7219

byte A[8] = {B00011000, B00100100, B01000010, B01000010, B01111110,


B01000010, B01000010, B01000010};
// Khai báo một mảng 8 phần tử là 8 byte để lưu trữ thông tin về chữ A
trong định dạng nhị phân

void setup() {

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 72
73
lc.shutdown(0,false); // Kích hoạt MAX7219
lc.setIntensity(0,8); // Đặt độ sáng tối đa là 8 cho MAX7219
lc.clearDisplay(0); // Xóa bất kỳ ký tự nào còn hiển thị trên
MAX7219
}

void loop() {
for (int i=0; i<8; i++) { // Vòng lặp 8 lần để hiển thị từng byte của
mảng A
lc.setRow(0,i,A[i]); // Hiển thị byte thứ i của mảng A tại hàng
thứ i trên MAX7219
delay(100); // Đợi 100ms
}
}

■ Tạo hiệu ứng chạy từ phải qua trái cho chữ ARDUINO

/*
CHương trình điều khiển LED ma trận hiển thị từng chữ và hiển thị chữ
với hiệu ứng chạy phải qua trái
Trước tiên ta cần cài thư viện tại link
<https://github.com/wayoda/LedControl>
*/
#include "LedControl.h"// thêm thư viện
LedControl matrix = LedControl(12, 11, 10, 1);
// Chân 12 nối với chân DataIn
// Chân 11 nối với chân CLK
// Chân 10 nối với chân LOAD
// Sử dụng 1 IC MAX7219
void setup() {
matrix.shutdown(0, false); // Bật hiển thị
matrix.setIntensity(0, 15); // Đặt độ sáng lớn nhất
matrix.clearDisplay(0); // Tắt tất cả led
}
// Thiết lập mã cho các ký tự
byte A[56] = { // Bảng mã chữ ARDUINO
0x00,0x7E,0xFF,0x81,0x81,0xFF,0x7E,0x00, // O
0x00,0xFF,0x03,0x0C,0x30,0xC0,0xFF,0x00, // N
0x00,0x81,0x81,0xFF,0xFF,0x81,0x81,0x00, // I
0x00,0xFE,0xFF,0x01,0x01,0xFF,0xFE,0x00, // U
0x00,0x3C,0x7E,0x81,0x81,0xFF,0xFF,0x00, // D
0x00,0x61,0x92,0x94,0x98,0xFF,0xFF,0x00, // R
0x00,0x3F,0x7F,0xA4,0xA4,0x7F,0x3F,0x00 // A
};
// Chương trình con chạy chuỗi ký tự
void scroll() {
matrix.clearDisplay(0);

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 73
74
int pos = 8;
for (int j = -56; j < pos; j++) { // Vòng lặp thay đổi vị trí
for (int i = 0; i < 56; i++) { // Vòng lặp để hiển thị ký tự
matrix.setRow(0, i + j, A[i]);
}
delay(100);
}
}

// Chương trình con hiển thị từng ký tự


void show() {
matrix.clearDisplay(0);
for (int i = 0; i < 8; i++) matrix.setRow(0, i, A[i]); //Hiển thị
từng hàng để được ký tự A, tương tự với các kí tự khác
delay(200);
for (int i = 0; i < 8; i++) matrix.setRow(0, i, A[i + 8]);
delay(200);
for (int i = 0; i < 8; i++) matrix.setRow(0, i, A[i + 16]);
delay(200);
for (int i = 0; i < 8; i++) matrix.setRow(0, i, A[i + 24]);
delay(200);
for (int i = 0; i < 8; i++) matrix.setRow(0, i, A[i + 32]);
delay(200);
for (int i = 0; i < 8; i++) matrix.setRow(0, i, A[i + 40]);
delay(200);
for (int i = 0; i < 8; i++) matrix.setRow(0, i, A[i + 48]);
delay(200);
}
void loop() {
scroll(); // Gọi chương trình con chạy chuỗi ký tự
show(); // Gọi chương trình con hiển thị từng ký tự
}

➢ Điều khiển LED NeoPixel WS2812B chạy hiệu ứng


■ Hiển thị màu và vị trí LED trên module
● Cần sử dụng thư viện Adafruit_NeoPixel.h, các dòng code mình đã giải thích rất kĩ,
bạn xem code phía dưới để hiểu hơn nhé

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 74
75

/*
Chương trình hiển thị màu và vị trí LED trên mạch hiển thị NeoPixel 8
LED
Trước tiên ta cần cài thư viện tại
<https://github.com/adafruit/Adafruit_NeoPixel>

*/
#include <Adafruit_NeoPixel.h>

#define PIN 6 // Chân điều khiển led NeoPixel


#define NUMPIXELS 8 // Số lượng led NeoPixel

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB +

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 75
76
NEO_KHZ800); // Khởi tạo đối tượng NeoPixel với số lượng và chân điều
khiển

void setup() {
pixels.begin(); // Khởi tạo thư viện NeoPixel
}

void loop() {
// Hiển thị màu sắc của LED tại vị trí thứ tự cho trước
showPixelColor(0, 0, 255, 0); // LED thứ tự 0 sẽ được hiển thị
màu xanh lá cây
showPixelColor(3, 255, 255, 255); // LED thứ tự 3 sẽ được hiển thị
màu trắng
}

void showPixelColor(int pixel, int r, int g, int b) { // Chương trình


con điều khiển
pixels.setPixelColor(pixel, pixels.Color(r, g, b)); // Đặt màu cho
LED tại vị trí thứ tự
pixels.show(); // Hiển thị màu
sắc lên LED
}

■ Chạy hiệu ứng LOADING với NeoPixel 8 LED Ring


● Sau khi đã thử nghiệm SET màu cho 1 Led ở 1 vị trí mong muốn như code trên, giờ
hãy thử SET cho từng Led và áp dụng các vòng lặp tạo hiệu ứng thay đổi về cả vị trí
và màu sắc nhé

/*
Chương trình chạy hiệu ứng LOADING trên mạch hiển thị NeoPixel 8 LED
Trước tiên ta cần cài thư viện tại
<https://github.com/adafruit/Adafruit_NeoPixel>

*/
#include <Adafruit_NeoPixel.h>

#define PIN 6 // Chân điều khiển led NeoPixel


#define NUMPIXELS 8 // Số lượng led NeoPixel

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB +


NEO_KHZ800); // Khởi tạo đối tượng NeoPixel với số lượng và chân điều
khiển

void setup() {
pixels.begin(); // Khởi tạo thư viện
NeoPixel
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 76
77

void loop() { // chạy hiệu ứng led đuổi


for(int i = 0; i < NUMPIXELS; i++) {
pixels.setPixelColor(i, 255, 255, 255); // Đặt màu cho LED thứ i là
màu trắng
pixels.show(); // Cập nhật hiển thị
delay(50); // Đợi 50ms
}

for(int i = 0; i < NUMPIXELS; i++) {


pixels.setPixelColor(i, 0, 0, 0); // Đặt màu cho LED thứ i là
màu đen(tắt LED)
pixels.show(); // Cập nhật hiển thị
delay(50); // Đợi 50ms
}
}

➢ Sử dụng module DFplayer để điều khiển việc phát âm thanh


■ Tài liệu chi tiết xem tại trang chủ nhà sản xuất
● https://wiki.dfrobot.com/DFPlayer_Mini_SKU_DFR0299

■ Giao tiếp không sử dụng code


● Kiểu điều khiển qua 2 tín hiệu IO, kết nối sử dụng tai nghe

● Kiểu điều khiển qua 2 tín hiệu IO, kết nối sử dụng loa dưới 3W

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 77
78

● Kiểu điều khiển qua 2 chân ADKEY

■ Giao tiếp không sử dụng code


● Sơ đồ kết nối

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 78
79

● Chương trình
/*
Chương trình điều khiển phát nhạc sử dụng module DFplayer MINI
*/
#include "SoftwareSerial.h" // Thư viện để sử dụng phần mềm
Serial
SoftwareSerial mySerial(10, 11); // Khai báo đối tượng phần mềm
Serial với chân TX ở 10, RX ở 11

# define Start_Byte 0x7E // Khai báo giá trị cho byte bắt
đầu (7E)
# define Version_Byte 0xFF // Khai báo giá trị cho byte phiên
bản (FF)
# define Command_Length 0x06 // Khai báo giá trị cho độ dài lệnh
(06)

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 79
80
# define End_Byte 0xEF // Khai báo giá trị cho byte kết
thúc (EF)
# define Acknowledge 0x00 // Khai báo giá trị phản hồi (00) -
phản hồi với lệnh 0x41 [0x01: có thông tin, 0x00: không có thông tin]

# define ACTIVATED LOW // Khai báo trạng thái đúng hoặc


sai của nút nhấn

int buttonNext = 2; // Chân nút Next


int buttonPause = 3; // Chân nút Pause
int buttonPrevious = 4; // Chân nút Previous
boolean isPlaying = false; // Trạng thái phát nhạc, false nếu
đang tạm dừng

void setup () {

pinMode(buttonPause, INPUT); // Khai báo chân Pause là đầu vào


digitalWrite(buttonPause,HIGH); // Kích hoạt điện trở kéo lên
pinMode(buttonNext, INPUT); // Khai báo chân Next là đầu vào
digitalWrite(buttonNext,HIGH); // Kích hoạt điện trở kéo lên
pinMode(buttonPrevious, INPUT); // Khai báo chân Previous là đầu
vào
digitalWrite(buttonPrevious,HIGH); // Kích hoạt điện trở kéo lên
mySerial.begin (9600); // Khởi tạo giao tiếp phần mềm
Serial với tốc độ truyền 9600

delay(1000); // Đợi 1 giây để phát nhạc đầu


tiên
playFirst(); // Phát nhạc đầu tiên
isPlaying = true; // Đặt trạng thái phát nhạc là
đang phát
}

void loop () {

if (digitalRead(buttonPause) == ACTIVATED){ // Kiểm tra xem nút


pause đã được nhấn chưa
if(isPlaying){ // Nếu đang phát
nhạc thì tạm dừng phát
pause();
isPlaying = false;
}
else{ // Nếu không đang
phát nhạc thì bắt đầu phát
isPlaying = true;
play();

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 80
81
}
}

if (digitalRead(buttonNext) == ACTIVATED) // Kiểm tra xem nút


next đã được nhấn chưa
{
if(isPlaying) // Nếu đang phát
nhạc thì phát bài hát tiếp theo
{
playNext();
}
}

if (digitalRead(buttonPrevious) == ACTIVATED) // Kiểm tra xem nút


previous đã được nhấn chưa
{
if(isPlaying) // Nếu đang phát
nhạc thì quay trở lại bài hát trước đó
{
playPrevious();
}
}
}

void playFirst() // Hàm phát bài hát


đầu tiên
{
execute_CMD(0x3F, 0, 0);
delay(500);
setVolume(20);
delay(500);
execute_CMD(0x11,0,1);
delay(500);
}

void pause() // Hàm tạm dừng phát


nhạc
{
execute_CMD(0x0E,0,0);
delay(500);
}

void play() // Hàm bắt đầu phát


nhạc
{
execute_CMD(0x0D,0,1);

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 81
82
delay(500);
}

void playNext() // Hàm phát bài hát


tiếp theo
{
execute_CMD(0x01,0,1);
delay(500);
}

void playPrevious() // Hàm phát bài hát


trước đó
{
execute_CMD(0x02,0,1);
delay(500);
}

void setVolume(int volume) // Hàm đặt âm lượng


phát nhạc
{
execute_CMD(0x06, 0, volume); // Cài âm lượng
(0x00~0x30)
delay(2000);
}

void execute_CMD(byte CMD, byte Par1, byte Par2)


{
word checksum = -(Version_Byte + Command_Length + CMD + Acknowledge +
Par1 + Par2); // tính toán giá trị checksum (2 byte)

byte Command_line[10] = { Start_Byte, Version_Byte, Command_Length,


CMD, Acknowledge, // tạo một mảng byte chứa dữ liệu của lệnh cần
gửi đi với các giá trị được lưu tại các biến tương ứng.
Par1, Par2, highByte(checksum), lowByte(checksum), End_Byte};

for (byte k=0; k<10; k++)


// gửi lệnh tới module qua cổng serial.
{
mySerial.write( Command_line[k]);
}
}

Ngoài ra các bạn có thể sử dụng thư viện DFRobotDFPlayerMini.h , thư viện này sẽ giúp
bạn những dòng lệnh tối ưu và nhanh hơn

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 82
83

❖ Một số gợi ý về ý tưởng thực hiện:


➢ Kết hợp nhiều LED ma trận để mở rộng hiển thị hơn…
➢ Sử dụng KEYPAD kết hợp với RFID để tăng bảo mật hơn..có thể thêm LCD để hiển thị
➢ Sử dụng 2 cảm biến vật cản hồng ngoại để:
■ Đo tốc độ của 1 vật thể: Nguyên lí là bắt đầu đếm thời gian từ lúc cảm biến 1 phát hiện
vật thể cho đến khi cảm biến 2 phát hiện, sau đó sử dụng công thức tính Quãng đường/
thời gian ta được vận tốc, với quãng đường là khoảng cách giữa 2 cảm biến (chỉ gần
đúng khi quỹ đạo vật thể đi từ cảm biến 1 tới cảm biến 2 là đường thẳng)
■ Đếm số xe vào, số xe ra: Nguyên lý đếm là khi xe tới, cảm biến 1 phát hiện rồi tới cảm
biến 2 phát hiện(tức xe vào). Nếu cảm biến 2 phát hiện trước rồi đến cảm biến 1(tức xe
ra)
➢ Mở rộng chức năng với module DS1302, hẹn giờ bật tắt thiết bị, thiết kế đồng hồ hiển thị
với LCD hoặc LED ma trận…
➢ Tùy vào từng loại bàn phím, có thể sử dụng bàn phím với thiết kế là các số và phép toán
để làm 1 chiếc máy tính cầm tay
➢ Sử dụng cảm biến ánh sáng để điều khiển sao cho tấm pin năng lượng mặt trời nhận
được nhiều ánh sáng nhất
➢ Sử dụng cảm biến siêu âm SRF04 kết hợp với L298N để tạo 1 chiếc xe tránh vật cản
➢ Sử dụng cảm biến siêu âm SRF04 tạo thiết bị radar dò xét xung quanh
➢ Kết hợp các cảm biến như: cảm biến nhiệt độ độ ẩm DHT11, cảm biến Gas MQ4, cảm biến
độ ẩm đất,… để tạo nên mô hình Smart Home
➢ Sử dụng kết hợp vòng tròn LED WS2812B và module DFPlayer và hàm random() tạo trò
chơi lô tô 8 số với âm thanh sống động, LED nhấp nháy khi ra kết quả. Các bạn nhớ loại
trừ các con số đã ra trước đó nhé

❖ Một số lỗi thường gặp và kinh nghiệm xử lý:


➢ Lỗi thiếu thư viện
■ Tình trạng này dễ và thường xuyên gặp khi các bạn tải code ở trên các nền tảng khác
về , hoặc đơn giản là các bạn copy các dòng code mà trong code đó bao gồm các khai
báo sử dụng thư viện
■ Hoặc khi các bạn code nhưng do máy của các bạn chưa có thư viện đã khai báo trong
code

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 83
84
■ Có 2 cách khắc phục :
● Cách 1 : Các bạn vào Sketch → Include Library → Managers Library

Tại đây các bạn gõ tìm tên thư viện cần cài đặt sau đó bấm Install để cài ( giao diện
trong hình ảnh sẽ khác một chút với các phiên bản Arduino IDE khác nhau )

● Cách 2 : Các bạn sẽ tìm thư viện trên mạng

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 84
85

Sau khi tải về, các bạn tiến hành thêm như sau :
◆ Các bạn vào Sketch → Include Library → Add ZIP Library
◆ Các bạn tìm đến thư mục chứa file thư viện vừa tải về ở trên rồi thêm vào là
được

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 85
86

➢ Lỗi trùng lặp thư viện


■ Lỗi này xuất hiện khi bạn cài thư viện ở nhiều thư mục khác nhau, thường gặp do tải
thư viện file rar trên mạng về và đồng thời tải thêm ở phần Manage Libraries… trong
phần mềm gây xung đột.
■ Trong phần thông báo sẽ xuất hiện kiểu : used …. not used ….
Bạn hãy gỡ bớt 1 cái và thống nhất 1 thư viện chung để dễ quản lý hơn

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 86
87
➢ Lỗi Could not open COM , không nhận Port

■ Một số nguyên nhân có thể là chọn sai cổng COM => vào Device Manager => Port =>
kiểm tra rút ra cắm lại thử xem có thay đổi gì không, nếu hiện cổng thay đổi thì nhìn và
chọn lại cho đúng
■ Nguyên nhân do sợi cáp kết nối bị lỗi , hoặc sợi cáp bạn dùng chỉ có chức năng cấp
nguồn chứ không có dây giao tiếp với máy tính => Đổi cáp khác và thử lại
■ Do cổng USB máy tính bị lỗi => Đổi cổng hoặc đổi máy tính và thử lại

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 87
88

■ Khi gặp lỗi này các bạn cần phải kiểm tra lại sợi cáp có bị hỏng hay không, các bạn có
thể dùng sợi cáp khác để kiểm tra.
■ Nếu sợi cáp không vấn đề thì chúng ta kiểm tra đến phần driver, các bạn vào Device
Manager → Com Port : xem có cổng nào chưa có driver không ( đa số sẽ có dấu chấm
than kế bên cổng, như hình dưới.
■ Để khắc phục lỗi này , chúng ta chỉ cần tải driver từ trên mạng về và cài vào máy là đã
xử lý được
■ Trường hợp này không chỉ áp dụng riêng cho arduino, mà còn có thể áp dụng cho nhiều
mạch USB giao tiếp khác như CP2102, CP2104, USB to TTL, …v…v các bạn cũng có
thể làm cách này để kiểm tra

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 88
89
➢ Lỗi chưa khai báo biến

■ Khi bạn gặp lỗi này tức là có một biến trong chương trình chưa được khai báo, cụ thể ở
ví dụ trên là biến flowRate
■ Cách khắc phục : các bạn chỉ cần khai báo thêm biến vào chương trình là được

➢ Lỗi đường dẫn thư viện có tên tiếng Việt hoặc kí tự đặc biệt
■ Khi chương trình báo thiếu thư viện, chúng ta thường hay tải thư viện ở Github rồi add
vào. Thông thường khi chúng ta add lần đầu là được, nhưng sẽ có trường hợp dù đã
add vào rồi nhưng vẫn báo không có thư viện.

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 89
90

■ Trường hợp này các bạn kiểm tra lại phần đường link dẫn vào thư mục chứa thư viện
■ Vào File → Preferences

■ Trên đây chính là đường link dẫn vào thư mục chứa thư viện của chương trình, lúc này,
các bạn chú ý đến đường link, trong đường link có chứa thư mục tên có dấu tiếng Việt,
dấu này máy không thể hiểu được nên không thể dẫn vào, do đó các bạn thêm vào rồi
nhưng máy vẫn báo lỗi
■ Các giải quyết : các bạn hãy tạo một thư mục chứa thư viện tên không có dấu tiếng Việt
rồi chọn lại đường link đó là được. Ví dụ như này

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 90
91

➢ Lỗi mất bootloader


■ Khi bạn nạp code vào arduino, dù đã chọn đúng board, port nhưng chương trình vẫn
không nạp được và bị treo , đèn TX và RX trên board cũng không chớp tắt thì khả năng
chip đã bị mất bootloader - là một ứng dụng có mục tiêu chính là nâng cấp hoặc sửa đổi
phần mềm hệ thống mà không cần sự can thiệp của các công cụ nâng cấp chương
trình cơ sở chuyên dụng.
■ Bootloader có thể có nhiều chức năng, nhưng nó chủ yếu được sử dụng để quản lý ứng
dụng. Nó cũng có thể sử dụng các giao thức khác nhau như UART, CAN, I2C, I2S,
Ethernet hoặc USB để thiết lập giao tiếp và bắt đầu nâng cấp firmware.
■ Một ví dụ điển hình là bootloader trong bo Arduino, được cấu hình để flash phần mềm
ứng dụng trong bộ nhớ flash của chip ATMega.

■ Cách khắc phục:


● Bạn phải có sẵn 1 Arduino có bootloader, sau đó cắm dây kết nối giữa board Arduino
mất bootloader và Arduino còn bootloader như hình bên dưới

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 91
92

● Tiến hành nạp bootloader


◆ Mở Arduino IDE
◆ Mở chương trình mẫu Arduino ISP

◆ Nạp chương trình mẫu Arduino ISP lên mạch Arduino đang có bootloader\
➢ Vào menu Tools -> Boards để chọn mạch Arduino đang có bootloader
➢ Vào menu Tools -> Serial Port để chọn cổng Serial đang sử dụng
➢ Vào menu Tools -> Programmer chọn AVR ISP

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 92
93
➢ Bấm nạp chương trình
◆ Nạp bootloader
➢ Vào menu Tool -> Boards để chọn mạch Arduino cần được nạp
bootloader
➢ Vào menu Tool -> Programmer chọn Arduino as ISP
➢ Vào menu Tools chọn Burn Bootloader
➢ Đợi một lát là xong
◆ Sau khi nạp bootloader xong, bạn sẽ thấy đèn LED 13 trên cả 2 mạch Arduino
nhấp nháy báo hiệu bootloader đã được nạp thành công.

➢ Lỗi không đồng bộ

■ Lỗi này xuất hiện khi các bạn dùng các module, mạch điện có chức năng giao tiếp
UART như HC-05 , HC-06, …v…v

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 93
94
■ Các bạn nối trực tiếp chân TX và RX vào chân RX và TX của arduino, khi nạp code, sẽ
xảy ra xung đột và khiến cho chương trình bị treo và sinh ra lỗi này
■ Có 2 cách khác phục :
● Cách 1 : nếu các bạn dùng UART cứng ( tức là 2 chân TX và RX arduino có sẵn ) thì
các bạn cần tháo 2 chân TX và RX ra trong quá trình nạp code, khi nạp xong rồi
chúng ta cắm lại và dùng bình thường.
● Cách 2 : là các bạn dùng UART mềm - chính là dùng thư viện SoftwareSerial để cấu
hình 2 chân bất kỳ của arduino để làm 2 chân TX và RX, với việc này thì các bạn có
thể cắm và nạp code cùng lúc không sợ bị xung đột

➢ Lỗi không nạp được trên Arduino Nano

■ Lỗi này ít khi gặp , nhưng trên win 10 khi chúng ta dùng arduino nano dù cho đã chọn
đúng port, đúng board nhưng không thể nạp được.
■ Cách khắc phục : Các bạn vào Tools → Processor → chọn ATmega328P ( Old
Bootloader)

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 94
95

❖ Một số dự án tham khảo kết hợp nhiều module và kiến thức khác nhau ( cập nhật
thường xuyên khi có dự án mới )
➢ Trò chơi bắt gậy
■ Mô tả:
● Thông thường mình thấy đa phần sẽ làm từ 8-10 cây gậy rơi ngẫu nhiên, thời gian rơi
của mỗi cây tầm 3-4 giây.
● Phần vòng cung các bạn có thể làm bằng gỗ, ống nước cứng , đặt gia công bằng sắt
● Phần cây cột đứng chịu lực phải đủ vì vậy nếu làm bằng ống nước như mình sẽ bị
cong, không thể đứng vững.
● Các cây gậy ( 8 -10 cây tùy ý ) làm bằng ống nước theo mình là ổn nhất vì các bạn có
thể điều chỉnh trọng lượng bằng cách thêm cát , nước vào bên trong, việc này sẽ làm
thay đổi tốc độ rơi của gậy.

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 95
96

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 96
97

int relay1 = 2;
int relay2 = 3;
int relay3 = 4;
int relay4 = 5;
int relay5 = 6;
int relay6 = 7;
int relay7 = 8;
int relay8 = 9; //khai báo 8 relay tương ứng chân 2-9 trên arduino

int randNumber;
int randTime; //biến thời gian sau khoảng x giây sẽ rơi

int myNum[9]; //mảng 9 số để chứa các số ngẫu nhiên randNumber


int i;
int j;
int so;

int button = 10; //nút start chân số 10


bool chay; //khai báo biến chạy đúng - sai để xác nhận trạng thái hoạt
động

void setup() {
Serial.begin(9600);
randomSeed(analogRead(A0)); //đây là thủ thuật tạo số ngẫu nhiên không
trùng lặp giữa các vòng, tham khảo thêm tài liệu
chay = false; //ban đầu set chay = false tương ứng không hoạt động
i = 1;
pinMode(button, INPUT_PULLUP);

pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
pinMode(relay3, OUTPUT);
pinMode(relay4, OUTPUT);
pinMode(relay5, OUTPUT);
pinMode(relay6, OUTPUT);
pinMode(relay7, OUTPUT);
pinMode(relay8, OUTPUT);

digitalWrite(relay1, LOW);
digitalWrite(relay2, LOW);
digitalWrite(relay3, LOW);
digitalWrite(relay4, LOW);
digitalWrite(relay5, LOW);
digitalWrite(relay6, LOW);

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 97
98
digitalWrite(relay7, LOW);
digitalWrite(relay8, LOW); //ban đầu cho tất cả các relay không kích
}

void loop() {
if (digitalRead(button) == 0) { //nếu nút nhấn được kích hoạt
chay = true; //thì chay=true => hoạt động
}
if (chay == true) {
if (i <= 8) { //chạy i=1 đến 8
randTime = random(2800, 4600)/100*100; //thời gian ngẫu nhiên từ
2.8 giây đến 4.6 giây, chia 100 * 100 để làm gì các bạn tìm hiểu thử xem
delay(randTime); //tạm ngừng
Serial.println(randTime);
demlai:
randNumber = random(1, 9); //gán biến randNumber ngẫu nhiên 1 tới
8
myNum[i] = randNumber; //số thứ i trong mảng = randNumber , các
bạn có thể thay 2 lệnh trên bằng myNum[i]=random(1,9) và xem lại kết quả
có giống hay không

for (j = 1; j < i; j++) { //cho chạy biến j để kiểm tra lại các số
ngẫu nhiên có bị trùng hay không
if (myNum[i] != myNum[j]) {

} else { //nếu trùng xảy ra thì thực hiện lại thao tác gán
randNumber
goto demlai; //các bạn tìm hiểu thêm về cấu trúc lệnh goto để
hiểu chỗ này nhé, lệnh sẽ quay lại dòng lệnh trên mà không chạy tiếp các
lệnh dưới
}
}

Serial.print("so thu ");


Serial.print(i);
Serial.print(" :");
Serial.println(myNum[i]);

so = myNum[i] + 1;
digitalWrite(so, HIGH); //nếu thỏa các điều kiện trên thì kích
relay thứ myNum[i]+1 , tại vì relay 1 thì chân 2 , relay chân 3 nên phải
cộng thêm 1
i++ ; //tăng i lên 1 để tiếp tục so sánh

Serial.println(digitalRead(relay1));
Serial.println(digitalRead(relay2));

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 98
99
Serial.println(digitalRead(relay3));
Serial.println(digitalRead(relay4));
Serial.println(digitalRead(relay5));
Serial.println(digitalRead(relay6));
Serial.println(digitalRead(relay7));
Serial.println(digitalRead(relay8));

} else {

digitalWrite(relay1, LOW);
digitalWrite(relay2, LOW);
digitalWrite(relay3, LOW);
digitalWrite(relay4, LOW);
digitalWrite(relay5, LOW);
digitalWrite(relay6, LOW);
digitalWrite(relay7, LOW);
digitalWrite(relay8, LOW);

i = 1;
chay = false;
}
}
delay(1000);
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 99
100
➢ Mô hình cửa tự động
■ Cửa tự động đóng mở khi có người dựa vào cảm biến chuyển động
■ Cửa tự động mở ra khi bị kẹt dựa vào cảm biến dòng

const int cambien = 8; // khai báo chân cảm biến


const int ctClose = 12; // khai báo chân công tắc hành trình báo hiệu đã
đóng cửa
const int ctOpen = 13; // khai báo chân công tắc hành trình báo hiệu đã
mở cửa

int M1_Left = 9; //Direccion


int M1_Right = 10; //Direccion
unsigned long timer = 0;
int trangthai;
float dongdienTB = 0;
void setup() {
Serial.begin(9600);

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 100
101
pinMode(cambien, INPUT_PULLUP);
pinMode(ctOpen, INPUT_PULLUP);
pinMode(ctClose, INPUT_PULLUP);
pinMode(M1_Left, OUTPUT);
pinMode(M1_Right , OUTPUT);
}

void loop() {
if (digitalRead(cambien) == 1) { //Phát hiện có người di chuyển gần
Serial.println(digitalRead(cambien));
openDoor(); //Gọi hàm mở cửa
delay(3200);
}
else //ngược lại nếu không phát hiện người di chuyển
{
Serial.println(digitalRead(cambien));

if ( (unsigned long) (millis() - timer) > 10 )


{
dongdienTB = 0;
for (int i = 0; i < 1000; i++) {
dongdienTB = dongdienTB + (.0264 * analogRead(A0) - 13.51) /
1000; // trung bình 1000 lần để đạt độ chính xác cao hơn
}
delay(1);
timer = millis();
Serial.println(abs(dongdienTB));
}

if (abs(dongdienTB) > 0.4) { // căn chỉnh dòng điện lớn hơn mức trung
bình của động cơ
openDoor(); // Nếu có vật cản , dòng điện sẽ tăng hơn mức trung
bình => mở cửa ra tránh vật cản
delay(1000);
}
else {
closeDoor(); //Gọi hàm đóng cửa
}
}
//Xác định trạng thái cửa -------------------------
if (digitalRead(ctClose) == 0) //công tắc hành trình đang được kích
{
trangthai = 0;
}
if (digitalRead(ctOpen) == 0) //công tắc hành trình đang được kích
{
trangthai = 1;

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 101
102
}
if (digitalRead(ctClose) == 1 && digitalRead(ctOpen) == 1) //cả công
tắc hành trình đang được kích, cửa đang chạy
{
trangthai = 2;
}
delay(10);
}

void openDoor() {
if (trangthai != 1) { //nếu cửa chưa mở hoàn toàn ( trạng khái khác 1
, 1 là báo hiệu đã mở )
Serial.println("Cua dang mo");
digitalWrite(M1_Left, HIGH); //Động cơ quay trái
digitalWrite(M1_Right, LOW);
}
else { //ngược lại là đã chạm công tắc hành trình báo hiệu đã mở
Serial.println("Cua da mo");
stopDoor();
}
}
void closeDoor() {
if (trangthai != 0) { //nếu cửa chưa đóng hoàn toàn
Serial.println("Cua dang dong");
digitalWrite(M1_Left, LOW);
digitalWrite(M1_Right, HIGH); //Động cơ quay phải
}
else { //ngược lại là đã chạm công tắc hành trình báo hiệu đã đóng
Serial.println("Cua da dong");
stopDoor();
}
}

void stopDoor() {
//dừng động cơ
digitalWrite(M1_Left, LOW);
digitalWrite(M1_Right, LOW);
}

➢ Mô hình tưới cây tự động


■ Đọc giá trị cảm biến độ ẩm đất hiển thị lên LCD
■ So sánh giá trị độ ẩm với độ ẩm cần thiết để tưới cây, nếu độ ẩm thấp hơn 30%H thì sẽ
kích relay bật cho bơm chạy, đến khi độ ẩm đạt 50%H thì sẽ ngắt module relay tắt bơm
và quá trình lập lại như trên
■ Có thể theo dõi độ ẩm thông qua LCD

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 102
103

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); //0X3F thay đổi tùy theo địa chỉ
I2C, có thể là 0x3F hoặc 0x27
int cb = A0; // khai báo chân để đọc giá trị cảm biến độ ẩm đất
int bom = 3;// khai báo chân điều khiển relay
int giatri,doam; // khai báo các biến lưu giá trị
void setup()
{
Serial.begin(9600);
lcd.begin();
pinMode(bom,OUTPUT); // cấu hình chân điều khiển relay là OUTPUT
}
void loop()
{
giatri = analogRead(cb); // dùng hàm analogRead để đọc giá trị cảm biến
doam = map(giatri,0,1023,100,0); // qui đổi giá trị analog từ 0-1023

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 103
104
thành giá trị độ ẩm 0-100 phần trăm
lcd.setCursor(0, 0); // set tọa độ chữ
lcd.print("Do Am:");
lcd.setCursor(6, 0);
lcd.print(doam); // in ra thông số độ ẩm từ biến doam đã khai báo
lcd.print(" "); // in ra khoảng cách (khoảng trắng)
delay(200);
lcd.setCursor(9, 0);
lcd.print("%H");
lcd.setCursor(0, 1);
lcd.print("Duoi:30");
lcd.setCursor(9, 1);
lcd.print("Tren:50");
if (doam <= 30) {digitalWrite(bom,HIGH);} // so sánh giá trị của độ
ẩm, nếu dưới 30% thì bật bơm
if (doam >= 50) {digitalWrite(bom,LOW);} // so sánh giá trị của độ
ẩm, nếu trên 50% thì tắt bơm
}

➢ Mô hình mở cửa bằng cách nhập mật khẩu


■ Mô hình thể hiện cách mở / khóa cửa bằng mật khẩu sử dụng bàn phím ma trận mềm
4x44
■ Nếu nhập mật khẩu đúng thì sẽ thực hiện việc mở hoặc đóng cửa bằng Servo SG90

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 104
105

#include <Keypad.h> // thêm thư viện của bàn phím


#include <Servo.h> // thêm thư viện của servo
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // Khai báo thư viện LCD sử dụng I2C
LiquidCrystal_I2C lcd(0x27, 16, 2); // 0x27 địa chỉ LCD, 16 cột và 2 hàng
Servo myservo; //Tạo biến myServo của loại Servo

const byte ROWS = 4;


const byte COLS = 4;
char password[5]; // mảng lưu mật khẩu khi nhập
char PassOP[]="1234"; // Mật khẩu mở cửa
char PassCL[]="0000"; // Mật khẩu đóng cửa
int i = 0;
int on=0;
int servo = 10;
int Led = 13;

char MatrixKey[ROWS][COLS] =
{
{'1','2','3','A'},
{'4','5','6','B'},

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 105
106
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {9,8,7,6}; // R1,R2,R3,R4
byte colPins[COLS] = {5,4,3,2}; // C1,C2,C3,C4

Keypad customKeypad = Keypad( makeKeymap(MatrixKey), rowPins, colPins,


ROWS, COLS);

//======================================================================

void setup()
{
Serial.begin(9600);
pinMode(Led,OUTPUT);
lcd.begin(); // Khởi tạo màn hình Màn hình
lcd.backlight(); // Bật đèn màn hình Màn hình
myservo.attach(servo);
myservo.write (0);
lcd.print(" Nhap mat khau!");

}
//======================================================================

void loop()
{
char EnterKey = customKeypad.getKey(); // đọc giá trị khi nhấn bàn phím

if (EnterKey)
{
password[i]=EnterKey; // Nhập lần lượt các ký tự vào biến chuỗi ký
tự Password
i++;
on++;
if (i == 0) {
password[0] = EnterKey;//lưu số được nhập vào vị trí đầu tiên của
mảng
lcd.setCursor(6, 1);
lcd.print(password[0]);
delay(500); // Ký tự hiển thị trên màn hình LCD trong 0.5s
lcd.setCursor(6, 1);
lcd.print("*"); // Ký tự được thay bởi dấu *
}
if (i == 1) {
password[1] = EnterKey; //lưu số được nhập vào vị trí thứ 2 của
mảng
lcd.setCursor(7, 1);

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 106
107
lcd.print(password[1]); //in ra số đó trên màn hình
delay(500);
lcd.setCursor(7, 1);
lcd.print("*"); //đổi hiển thị số đó thành ký tự *
}
if (i == 2) {
password[2] = EnterKey;//lưu số được nhập vào vị trí thứ 3 của
mảng
lcd.setCursor(8, 1);
lcd.print(password[2]);
delay(500);
lcd.setCursor(8, 1);
lcd.print("*");
}
if (i == 3) {
password[3] = EnterKey;//lưu số được nhập vào vị trí thứ 4 của
mảng
lcd.setCursor(9, 1);
lcd.print(password[3]);
delay(500);
lcd.setCursor(9, 1);
lcd.print("*");
}
}
if(on==4)
{
if(!strcmp(password,PassOP)) // hàm so sánh mảng đã được
nhập với mảng mật khẩu mở cửa, nếu đúng thì thực hiện mở cửa
{
lcd.clear();
lcd.print(" Dung mat khau!");
myservo.write(180); // Mở cửa!
digitalWrite(Led,LOW);
delay(1000);
lcd.clear();
lcd.print(" Cua da mo!");
i=0;
Serial.println(" Dung mat khau mo cua!");

if(!strcmp(password,PassCL)) //hàm so sánh mảng đã được


nhập với mảng mật khẩu đóng cửa, nếu đúng thì thực hiện đóng cửa
{
lcd.clear();
myservo.write(0); // Đóng cửa
lcd.print(" Cua da dong!");

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 107
108
digitalWrite(Led,LOW);
delay(2000);
lcd.clear();
lcd.print(" Nhap mat khau!");
i=0;
}

if(strcmp(password,PassOP)) // hàm so sánh mảng đã


được nhập với mảng mật khẩu mở cửa
{
if(strcmp(password,PassCL)) //hàm so sánh mảng đã
được nhập với mảng mật khẩu đóng cửa cửa
{

lcd.clear();
lcd.print(" Mat khau sai!"); // nếu cả 2 đều cho kết
quả không trùng thì báo mật khẩu sai, yêu cầu nhập lại
delay(1000);
lcd.clear();
lcd.print(" Xin thu lai!");
delay(1000);
lcd.clear();
lcd.print(" Nhap mat khau!");
i = 0;
Serial.println(" Mat khau sai!");
digitalWrite(Led,HIGH);

}
}
on=0;
}
}

➢ Trò chơi Simon (luyện trí nhớ)


■ Trò chơi gồm 4 nút nhấn và 4 màu khác nhau, nên chọn nút loại tích hợp đèn led 3V
■ Khi bắt đầu trò chơi sẽ cho số màu ngẫu nhiên, nhiệm vụ của bạn là sẽ phải nhớ và
bấm nút đúng với chương trình đã cho, nếu bấm đúng bạn sẽ qua vòng mới ( số màu
sẽ tăng dần) nếu bạn bấm sai thì kết thúc trò chơi và chạy lại từ đầu.
■ Phần hiển thị có thể dùng LCD hoặc OLED

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 108
109

#include <Wire.h>
#include <Adafruit_GFX.h> //Thư viện text
#include <Adafruit_SH1106.h>//Thư viện màn hình oled
#define SCREEN_WIDTH 128

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 109
110
#define SCREEN_HEIGHT 64
#define OLED_RESET 4
Adafruit_SH1106 display(OLED_RESET);
#define max_level 15 //Cài đặt số màn chơi, ở đây 15 level

byte i;
byte x;
byte level;
byte button[4] = { 2, 3, 4, 5 } ; // Red, Green, Blue, Yellow
byte led[4] = { 9, 10, 11, 12 } ; // Red, Green, Blue, Yellow
byte pattern[max_level] ;

void setup()
{
Serial.begin(9600);
display.begin(SH1106_SWITCHCAPVCC, 0x3C);
pinMode( button[0], INPUT_PULLUP); // INPUT_PULLUP >> kéo nội trở,
khai báo thế này khi nhấn nút sẽ trả về mức 0
pinMode( button[1], INPUT_PULLUP);
pinMode( button[2], INPUT_PULLUP);
pinMode( button[3], INPUT_PULLUP);
pinMode( led[0], OUTPUT);
pinMode( led[1], OUTPUT);
pinMode( led[2], OUTPUT);
pinMode( led[3], OUTPUT);
sta(); //gọi function reset game bên dưới
}

void loop()
{

create_pattern();
for ( level = 1 ; level <= max_level ; level ++ )
{
display.clearDisplay();
display.setCursor(35,2);
display.setTextSize(2);
display.setTextColor(WHITE);
display.println("ROUND");
display.setCursor(45,30);
display.setTextSize(4);
display.setTextColor(WHITE);
display.println(level);
display.display();
Serial.println(level);

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 110
111
show_pattern( level);
if (valid (level))
{
Serial.println("Good");
delay(500);
}
else
{
display.clearDisplay();
display.setCursor(15,25);
display.setTextSize(2);
display.setTextColor(WHITE);
display.println("YOU LOSE!");
display.display();
Serial.println("You lose");
lose();
break ;
}
Serial.println();
}
if (level > max_level)
{
display.clearDisplay();
display.setCursor(15,25);
display.setTextSize(2);
display.setTextColor(WHITE);
display.println("YOU WIN!");
display.display();
win();
//break ;
}

byte get_key () // function kiểm tra khi nút nhấn được tác động
{
byte i = 0 ;

do
{
for (i = 0; i < 4 ; i++)
{
if ( digitalRead(button[i]) == 0)
{
Serial.print("Button :");
Serial.println(i);
digitalWrite(led[i], 1);

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 111
112
tone(8, (400+i*400), 200);

while (digitalRead(button[i])==0);
delay(200);
digitalWrite(led[i], 0);
noTone(8);
return (i);
}
}
} while ( digitalRead(button[0]) && digitalRead(button[1]) &&
digitalRead(button[2]) && digitalRead(button[3]));
get_key ();
}

void create_pattern () //function tạo ngẫu nhiên


{
byte i ;
for ( i = 0 ; i < max_level ; i++ )
{
pattern[i] = random(0, 4);
}
}

void show_pattern(byte level) //This function show the pattern


{
byte i ;
for ( i = 0 ; i < level ; i++ )
{
x = pattern[i] ;
Serial.print(x);
Serial.print(" ");
digitalWrite(led[x], 1);
tone(8, (400+x*400), 200);
delay(200);
digitalWrite(led[x], 0);
noTone(8);
delay(200*pow(1.1,-level)); // This function in time delay makes the
delay shorter each level
}
Serial.println();
}

byte valid (byte level) // This function check if your input is same as
the pattern
{
byte i ;
for ( i = 0 ; i < level ; i++ )

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 112
113
{
if (get_key() != pattern[i] )
return (0);
}
return (1);
}

void lose() // This function reset the game


{
int i ;

for ( i = 0 ; i < 4 ; i++ )


{
digitalWrite(led[i], 1);
tone(8, (400+i*400), 200);
delay(200);
digitalWrite(led[i], 0);
noTone(8);
}
delay(200);
for ( i = 3 ; 0 <= i ; i-- )
{
Serial.println(i);
digitalWrite(led[i], 1);
tone(8, (400+i*400), 200);
delay(200);
digitalWrite(led[i], 0);
noTone(8);
}
delay(2000);
}
void win() // This function reset the game
{
int i ;

for ( i = 0 ; i < 4 ; i++ )


{
digitalWrite(led[i], 1);
tone(8, (400+i*400), 200);
delay(200);
digitalWrite(led[i], 0);
noTone(8);
}
delay(200);
for ( i = 3 ; 0 <= i ; i-- )
{
Serial.println(i);

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 113
114
digitalWrite(led[i], 1);
tone(8, (400+i*400), 200);
delay(200);
digitalWrite(led[i], 0);
noTone(8);
}
delay(2000);
}
void sta() // This function reset the game
{
int i ;

for ( i = 0 ; i < 4 ; i++ )


{
digitalWrite(led[i], 1);
tone(8, (400+i*400), 200);
delay(200);
digitalWrite(led[i], 0);
noTone(8);
}
delay(200);
for ( i = 3 ; 0 <= i ; i-- )
{
Serial.println(i);
digitalWrite(led[i], 1);
tone(8, (400+i*400), 200);
delay(200);
digitalWrite(led[i], 0);
noTone(8);
}
delay(2000);
}

➢ Mô hình mở khóa cửa bằng thẻ từ RFID


■ Mô hình mô tả hoạt động mở cửa giống như các bạn thường thấy ở chung cư, khách
sạn. Khi quét đúng mã thẻ thì cửa sẽ mở, quét lại một lần nữa thì cửa sẽ đóng
■ Mô hình này dùng arduino giao tiếp với module đọc thẻ từ RFID RC522, hiển thị trạng
thái ra LCD. Dùng servo để mô tả khóa cửa , khóa chốt. Mô hình có dùng còi báo
Buzzer để báo trạng thái

Module RC522 UNO R3

SDA(SS) 10

SCK 13

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 114
115
MOSI 11

MISO 12

GND GND

RST 9

3.3V 3.3V

#include <Servo.h> // thư viện servo


#include <LiquidCrystal_I2C.h> // thư viện màn hình LCD I2C
#include <SPI.h>
#include <MFRC522.h> // thư viện của module RFID RC522

#define SS_PIN 10 // khai báo các chân module RC522

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 115
116
#define RST_PIN 9
#define buzzer 2 // khai báo chân còi
#define servoPin 3 // khai báo chân điều khiển servo

String UID = "43 8B 65 A6"; // mã thẻ dùng để quét


byte lock = 0;

Servo servo;
LiquidCrystal_I2C lcd(0x27, 16, 2);
MFRC522 rfid(SS_PIN, RST_PIN);
void setup() {
Serial.begin(9600);
servo.write(70);
lcd.begin(); // khởi tạo LCD
lcd.backlight();
servo.attach(servoPin);
SPI.begin();
rfid.PCD_Init();
pinMode(buzzer, OUTPUT);
}

void loop() {
lcd.setCursor(4, 0);
lcd.print("Welcome!");
lcd.setCursor(1, 1);
lcd.print("Put your card");

if ( ! rfid.PICC_IsNewCardPresent())
return;
if ( ! rfid.PICC_ReadCardSerial())
return;

lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Scanning");
Serial.print("NUID tag is :");
String ID = "";
for (byte i = 0; i < rfid.uid.size; i++) {
lcd.print(".");
ID.concat(String(rfid.uid.uidByte[i] < 0x10 ? " 0" : " "));
ID.concat(String(rfid.uid.uidByte[i], HEX));
delay(300);
}
ID.toUpperCase();

if (ID.substring(1) == UID && lock == 0 ) { // so sánh mã thẻ đọc được


với mã thẻ đã lưu ở trên, nếu đúng thì thực hiện khóa cửa

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 116
117
digitalWrite(buzzer, HIGH);
delay(300);
digitalWrite(buzzer, LOW);
servo.write(50);
delay(100);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Locked");
delay(1500);
lcd.clear();
lock = 1;
} else if (ID.substring(1) == UID && lock == 1 ) { // so sánh mã thẻ
đọc được với mã thẻ đã lưu ở trên, nếu đúng thì thực hiện mở cửa
digitalWrite(buzzer, HIGH);
delay(300);
digitalWrite(buzzer, LOW);
servo.write(110);
delay(100);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Unlocked");
delay(1500);
lcd.clear();
lock = 0;
} else { // ngược lại nếu sai thì in ra màn hình là thẻ sai
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Wrong card!");
digitalWrite(buzzer, HIGH);
delay(200);
digitalWrite(buzzer, LOW);
delay(200);
digitalWrite(buzzer, HIGH);
delay(200);
digitalWrite(buzzer, LOW);
delay(200);
digitalWrite(buzzer, HIGH);
delay(200);
digitalWrite(buzzer, LOW);
delay(200);
delay(1500);
lcd.clear();
}
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 117
118
➢ Mô hình thùng rác phát âm thanh
■ Ý tưởng là chúng ta sẽ biến chiếc thùng rác nhàm chán thành 1 “con robot” tự động mở
nắp thùng rác và có tương tác âm thanh để thêm phần sinh động
■ Khi bạn đưa tay qua cảm biến, cơ cấu mở thùng rác hoạt động. Ở đây chúng ta dùng
servo sẽ đẩy nắp thùng rác mở lên và sau đồng thời phát đoạn âm thanh “xin hãy cho
tôi rác” , khi bạn bỏ rác xong, thùng rác sẽ tự động đóng lại và nói “cảm ơn” . Việc phát
âm thanh này cần dùng đến module DFPlayer có trong bộ kit, bạn cần thêm 1 loa 2W
hoặc 3W nữa nhé

■ Bạn có thể tạo đoạn âm thanh bằng cách


● Truy cập trang web https://vbee.vn/
● Sau đó tạo và đăng nhập tài khoản theo hướng dẫn
● Chọn dịch vụ sử dụng là STUDIO

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 118
119

● Chọn giọng đọc


● Gõ văn bản muốn chuyển thành giọng nói
● Bấm chuyển văn bản
● Tải về định dạng *.mp3 và sử dụng

#include <Servo.h>
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
static const uint8_t PIN_MP3_TX = 11; // Connects to module's RX
static const uint8_t PIN_MP3_RX = 10; // Connects to module's TX

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 119
120
SoftwareSerial softwareSerial(PIN_MP3_RX, PIN_MP3_TX);
DFRobotDFPlayerMini player;
Servo myservo;
int cb = 4;

void setup()
{
Serial.begin(9600); // giao tiếp Serial với baudrate 9600
softwareSerial.begin(9600);
myservo.attach(5);
pinMode(cb,INPUT);
myservo.write(0);
if (player.begin(softwareSerial)) {
// Set volume to maximum (0 to 30).
player.volume(30);

} else {
Serial.println("Connecting to DFPlayer Mini failed!");
}
delay(1000);
}

void loop()
{
int gt = digitalRead(cb);
if (gt == 0)
{
myservo.write(180);
delay(500);
player.play(1);
delay(5000);
myservo.write(0);
delay(500);
player.play(2);

}
}

➢ Làm một chiếc máy tính bỏ túi với Arduino


■ Ở đây chúng ta sử dụng Arduino Uno R3 kết hợp với bàn phím ma trận mềm Keypad
4x4 để nhập liệu tính toán
■ Sau khi tính toán sẽ in kết quả ra màn hình LCD 1602 I2C

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 120
121

■ Với bàn phím này chúng ta không có các dấu Cộng Trừ Nhân Chia Bằng vì vậy sẽ quy
ước như sau
● * là xóa
● # là dấu bằng
● A là cộng
● B là trừ
● C là nhân
● D là chia

#include <Keypad.h> // thêm thư viện của bàn phím


#include <Wire.h>
#include <LiquidCrystal_I2C.h> // Khai báo thư viện LCD sử dụng I2C
LiquidCrystal_I2C lcd(0x27, 16, 2); // 0x27 địa chỉ LCD, 16 cột và 2 hàng

const byte ROWS = 4;


const byte COLS = 4;

// Define the Keymap


char keys[ROWS][COLS] =
{

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 121
122
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};

byte rowPins[ROWS] = {9,8,7,6}; // R1,R2,R3,R4


byte colPins[COLS] = {5,4,3,2}; // C1,C2,C3,C4

Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


// tạo bàn phím
long Num1,Num2,Number; // các biến lưu trữ dữ liệu
char key,action;
boolean result = false;

void setup() {
lcd.begin();
lcd.print("MAY TINH"); //Display a intro message
lcd.setCursor(0, 1); // set the cursor to column 0, line 1
lcd.print("ARDUINO"); //Display a intro message

delay(2000); //Wait for display to show info


lcd.clear(); //Then clean it
}

void loop() {

key = kpd.getKey(); //storing pressed key value in a char

if (key!=NO_KEY)
DetectButtons();

if (result==true)
CalculateResult();

DisplayResult();
}

void DetectButtons()
{
lcd.clear(); //Then clean it
if (key=='*') //If cancel Button is pressed
{Serial.println ("Button Cancel"); Number=Num1=Num2=0;
result=false;}

if (key == '1') //If Button 1 is pressed


{Serial.println ("Button 1");

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 122
123
if (Number==0)
Number=1;
else
Number = (Number*10) + 1; //Pressed twice
}

if (key == '4') //If Button 4 is pressed


{Serial.println ("Button 4");
if (Number==0)
Number=4;
else
Number = (Number*10) + 4; //Pressed twice
}

if (key == '7') //If Button 7 is pressed


{Serial.println ("Button 7");
if (Number==0)
Number=7;
else
Number = (Number*10) + 7; //Pressed twice
}

if (key == '0')
{Serial.println ("Button 0"); //Button 0 is Pressed
if (Number==0)
Number=0;
else
Number = (Number*10) + 0; //Pressed twice
}

if (key == '2') //Button 2 is Pressed


{Serial.println ("Button 2");
if (Number==0)
Number=2;
else
Number = (Number*10) + 2; //Pressed twice
}

if (key == '5')
{Serial.println ("Button 5");
if (Number==0)
Number=5;
else
Number = (Number*10) + 5; //Pressed twice
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 123
124
if (key == '8')
{Serial.println ("Button 8");
if (Number==0)
Number=8;
else
Number = (Number*10) + 8; //Pressed twice
}

if (key == '#')
{Serial.println ("Button Equal");
Num2=Number;
result = true;
}

if (key == '3')
{Serial.println ("Button 3");
if (Number==0)
Number=3;
else
Number = (Number*10) + 3; //Pressed twice
}

if (key == '6')
{Serial.println ("Button 6");
if (Number==0)
Number=6;
else
Number = (Number*10) + 6; //Pressed twice
}

if (key == '9')
{Serial.println ("Button 9");
if (Number==0)
Number=9;
else
Number = (Number*10) + 9; //Pressed twice
}

if (key == 'A' || key == 'B' || key == 'C' || key == 'D')


//Detecting Buttons on Column 4
{
Num1 = Number;
Number =0;
if (key == 'A')
{Serial.println ("Addition"); action = '+';}
if (key == 'B')

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 124
125
{Serial.println ("Subtraction"); action = '-'; }
if (key == 'C')
{Serial.println ("Multiplication"); action = '*';}
if (key == 'D')
{Serial.println ("Devesion"); action = '/';}

delay(100);
}

}
void CalculateResult()
{
if (action=='+')
Number = Num1+Num2;

if (action=='-')
Number = Num1-Num2;

if (action=='*')
Number = Num1*Num2;

if (action=='/')
Number = Num1/Num2;
}

void DisplayResult()
{
lcd.setCursor(0, 0); // set the cursor to column 0, line 1
lcd.print(Num1); lcd.print(action); lcd.print(Num2);

if (result==true)
{lcd.print(" ="); lcd.print(Number);} //Display the result

lcd.setCursor(0, 1); // set the cursor to column 0, line 1


lcd.print(Number); //Display the result
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 125
126
➢ Đo mực nước trong bồn chứa bằng cảm biến siêu âm

#include <LiquidCrystal_I2C.h> // thư viện màn hình LCD I2C


LiquidCrystal_I2C lcd(0x27, 16, 2);

const int trig = 3; // chân trig của HC-SR04


const int echo = 4; // chân echo của HC-SR04
int relay = 5;
void setup()
{
Serial.begin(9600);
lcd.begin(); // khởi tạo LCD // giao tiếp Serial với baudrate
9600
pinMode(trig,OUTPUT); // chân trig sẽ phát tín hiệu
pinMode(echo,INPUT);
pinMode(relay,OUTPUT); // chân echo sẽ nhận tín hiệu
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 126
127
void loop()
{
unsigned long duration; // biến đo thời gian
int distance; // biến lưu khoảng cách
digitalWrite(trig,0); // tắt chân trig
delayMicroseconds(2);
digitalWrite(trig,1); // phát xung từ chân trig
delayMicroseconds(5); // xung có độ dài 5 microSeconds
digitalWrite(trig,0); // tắt chân trig
duration = pulseIn(echo,HIGH);
distance = int(duration/2/29.412);
Serial.print(distance);
Serial.println("cm");
delay(200);
lcd.setCursor(0, 0);
lcd.print("Muc nuoc:");
if (distance == 5)
{
lcd.setCursor(9, 0);
lcd.print("100%");
lcd.setCursor(0, 1);
lcd.print("da day");
lcd.print(" ");
digitalWrite(relay,LOW);
}
if(distance == 10)
{
lcd.setCursor(9, 0);
lcd.print("66%");
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
}
if(distance == 15)
{
lcd.setCursor(9, 0);
lcd.print("33%");
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
}
if(distance == 20)
{
lcd.setCursor(9, 0);
lcd.print("10%");
lcd.print(" ");
lcd.setCursor(0, 1);

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 127
128
lcd.print("dang bom");
digitalWrite(relay,HIGH);
}

➢ Làm bộ khống chế nhiệt độ máy ấp trứng

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "OneButton.h"
#include "DHT.h"
#define DHTPIN 2
#define DHTTYPE DHT11 // DHT 11

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 128
129
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 16, 2);
int coi = 3;
int relay = 4;
void setup()
{

dht.begin();
lcd.begin();
pinMode(coi,OUTPUT);
pinMode(relay,OUTPUT);
lcd.backlight();
digitalWrite(coi,LOW);
}

void loop()
{

float h = dht.readHumidity();
float t = dht.readTemperature();
float f = dht.readTemperature(true);
if (isnan(h) || isnan(t) || isnan(f)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
float hif = dht.computeHeatIndex(f, h);
float hic = dht.computeHeatIndex(t, h, false);
Serial.print(" %t");
lcd.setCursor(0,0);
lcd.print("ND:");
lcd.setCursor(3,0);
lcd.print(t);
lcd.print(" ");
lcd.setCursor(9,0);
lcd.print("*C");
lcd.setCursor(0,1);
lcd.print("Tren:31");
lcd.setCursor(8,1);
lcd.print("Duoi:30");
if (t<30)
{
digitalWrite(relay,HIGH);
}
if (t>31)
{
digitalWrite(relay,LOW);
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 129
130
if (t>32)
{
digitalWrite(coi,HIGH);
}
if (t<32)
{
digitalWrite(coi,LOW);
}
}

➢ Mô hình mở khóa cửa bằng mật khẩu


[Phần 1] Những dự án có thể làm được với Arduino UNO Pro Kit phần 1

#include <Keypad.h> // thêm thư viện của bàn phím


#include <Servo.h> // thêm thư viện của servo
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // Khai báo thư viện LCD sử dụng I2C
LiquidCrystal_I2C lcd(0x27, 16, 2); // 0x27 địa chỉ LCD, 16 cột và 2 hàng
Servo myservo; //Tạo biến myServo của loại Servo

const byte ROWS = 4;


const byte COLS = 4;
char password[5]; // mảng lưu mật khẩu khi nhập

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 130
131
char PassOP[]="1234"; // Mật khẩu mở cửa
char PassCL[]="0000"; // Mật khẩu đóng cửa
int i = 0;
int on=0;
int servo = 10;
int CL = 11;
int OP = 12;
int ERR = 13;

char MatrixKey[ROWS][COLS] =
{
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {9,8,7,6}; // R1,R2,R3,R4
byte colPins[COLS] = {5,4,3,2}; // C1,C2,C3,C4

Keypad customKeypad = Keypad( makeKeymap(MatrixKey), rowPins, colPins,


ROWS, COLS);

//======================================================================
===========================================

void setup()
{
Serial.begin(9600);
pinMode(OP,OUTPUT);
pinMode(CL,OUTPUT);
pinMode(ERR,OUTPUT);
lcd.begin(); // Khởi tạo màn hình Màn hình
lcd.backlight(); // Bật đèn màn hình Màn hình
myservo.attach(servo);
myservo.write (0);
lcd.print(" Nhap mat khau!");
digitalWrite(CL,HIGH);

}
//======================================================================
===========================================

void loop()
{
char EnterKey = customKeypad.getKey(); // đọc giá trị khi nhấn bàn phím

if (EnterKey)

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 131
132
{
password[i]=EnterKey; // Nhập lần lượt các ký tự vào biến chuỗi ký
tự Password
i++;
on++;
if (i == 0) {
password[0] = EnterKey;//lưu số được nhập vào vị trí đầu tiên của
mảng
lcd.setCursor(6, 1);
lcd.print(password[0]);
delay(500); // Ký tự hiển thị trên màn hình LCD trong 0.5s
lcd.setCursor(6, 1);
lcd.print("*"); // Ký tự được thay bởi dấu *
}
if (i == 1) {
password[1] = EnterKey; //lưu số được nhập vào vị trí thứ 2 của
mảng
lcd.setCursor(7, 1);
lcd.print(password[1]);
delay(500);
lcd.setCursor(7, 1);
lcd.print("*");
}
if (i == 2) {
password[2] = EnterKey;//lưu số được nhập vào vị trí thứ 3 của
mảng
lcd.setCursor(8, 1);
lcd.print(password[2]);
delay(500);
lcd.setCursor(8, 1);
lcd.print("*");
}
if (i == 3) {
password[3] = EnterKey;//lưu số được nhập vào vị trí thứ 4 của
mảng
lcd.setCursor(9, 1);
lcd.print(password[3]);
delay(500);
lcd.setCursor(9, 1);
lcd.print("*");
}
}
if(on==4)
{
if(!strcmp(password,PassOP)) // hàm so sánh mảng đã được
nhập với mảng mật khẩu mở cửa, nếu đúng thì thực hiện mở cửa
{

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 132
133
lcd.clear();
lcd.print(" Dung mat khau!");
myservo.write(180); // Mở cửa!
digitalWrite(CL,LOW);
digitalWrite(OP,HIGH);
delay(1000);
lcd.clear();
lcd.print(" Cua da mo!");
i=0;
Serial.println(" Dung mat khau mo cua!");

if(!strcmp(password,PassCL)) //hàm so sánh mảng đã được


nhập với mảng mật khẩu đóng cửa, nếu đúng thì thực hiện đóng cửa
{
lcd.clear();
myservo.write(0); // Đóng cửa
lcd.print(" Cua da dong!");
digitalWrite(OP,LOW);
digitalWrite(CL,HIGH);
delay(2000);
lcd.clear();
lcd.print(" Nhap mat khau!");
i=0;
}

if(strcmp(password,PassOP)) // hàm so sánh mảng đã


được nhập với mảng mật khẩu mở cửa
{
if(strcmp(password,PassCL)) //hàm so sánh mảng đã
được nhập với mảng mật khẩu đóng cửa cửa
{
digitalWrite(OP,LOW);
digitalWrite(CL,LOW);
digitalWrite(ERR,HIGH);
lcd.clear();
lcd.print(" Mat khau sai!"); // nếu cả 2 đều cho kết
quả không trùng thì báo mật khẩu sai, yêu cầu nhập lại
delay(1000);
lcd.clear();
lcd.print(" Xin thu lai!");
delay(1000);
lcd.clear();
lcd.print(" Nhap mat khau!");
i = 0;
Serial.println(" Mat khau sai!");

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 133
134
digitalWrite(CL,HIGH);
digitalWrite(ERR,LOW);
}
}
on=0;
}
}

➢ Mô hình thùng rác thông minh phát âm thanh


[Phần 4] Những dự án có thể làm được với Arduino UNO Pro Kit phần 4 - chế thùng …

#include <Servo.h>
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 134
135
static const uint8_t PIN_MP3_TX = 11; // Connects to module's RX
static const uint8_t PIN_MP3_RX = 10; // Connects to module's TX
SoftwareSerial softwareSerial(PIN_MP3_RX, PIN_MP3_TX);
DFRobotDFPlayerMini player;
Servo myservo;
int cb = 4;

void setup()
{
Serial.begin(9600); // giao tiếp Serial với baudrate 9600
softwareSerial.begin(9600);
myservo.attach(5);
pinMode(cb,INPUT);
myservo.write(0);
if (player.begin(softwareSerial)) {
// Set volume to maximum (0 to 30).
player.volume(30);

} else {
Serial.println("Connecting to DFPlayer Mini failed!");
}
delay(1000);
}

void loop()
{
int gt = digitalRead(cb);
if (gt == 0)
{
myservo.write(180);
delay(500);
player.play(1);
delay(3000);
myservo.write(0);
delay(500);
player.play(2);

}
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 135
136
➢ Làm máy rót rượu tự động

int cb = 2;
int coi = 3;
int btr = A0;
int relay = 4;
int gt, gt1,time;
void setup()
{
Serial.begin(9600);
pinMode(cb,INPUT);
pinMode(btr,INPUT);
pinMode(coi,OUTPUT);
pinMode(relay,OUTPUT);
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 136
137
void loop()
{
gt = digitalRead(cb);
gt1 = analogRead(btr);
time = map(gt1,0,1023,1000,10000);
Serial.println(time);
if(gt == LOW)
{
digitalWrite(relay,HIGH);
coi1();
delay(time);
digitalWrite(relay,LOW);
coi2();
}

}
void coi1()
{
digitalWrite(coi,HIGH);
delay(100);
digitalWrite(coi,LOW);
}
void coi2()
{
digitalWrite(coi,HIGH);
delay(500);
digitalWrite(coi,LOW);
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 137
138
➢ Làm trò chơi nhanh tay nhanh mắt với Led ws2812

// We need these libraries installed from library manager


#include <Adafruit_NeoPixel.h>
#include "OneButton.h"

// What GPIO is the strip connected to


#define PIXELPIN 4

// How many NeoPixels in the strip


#define NUMPIXELS 32

// What GPIO is the button connected to?


#define BUTTON_TAP 3

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 138
139
// Initialise the button, with a default low
OneButton buttonTAP(BUTTON_TAP, false);

// Initialise the pixel strip


Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIXELPIN,
NEO_GRB + NEO_KHZ800);

// A bunch of variables
int playerIndex = -1;
int playerIndexTrail = -1;
int playerDirection = 1;
float nextMove = 0;
float currentPlayerSpeed = 150;
unsigned long countdown = 0;
int enemyIndex = -1;
int coinIndex = -1;
int score = 0;
int bestScore = 0;
int lastScore = 0;
bool gameOver = false;

void setup()
{
// make the button pin an input
pinMode( BUTTON_TAP, INPUT );

// Attatch click functions to the button


buttonTAP.attachClick(singleClick);
buttonTAP.attachLongPressStart(longClick);

// Initialise the strip and set it's brightness to 20%


pixels.begin();
pixels.setBrightness(20);

// set a 2 second countdown before the player appears and starts


moving
countdown = millis() + 2000;
}

void loop()
{
// Every cycle we need to tick the button state
buttonTAP.tick();

// If the game is in game over state, exit loop early


if ( gameOver )
return;

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 139
140

// Set the pixel display state of the level


// This sets the enemy position and the coin position
SetLevel();

// wait for a second for the player to get ready


if ( countdown > millis() )
{
pixels.show();
return;
}

// All the player display, movement and game logic is in here


DisplayPlayer();

// This sends the updated pixel color to the hardware.


pixels.show();
}

// Clear the level, setting all pixels to black


void ClearLevel()
{
for(int i=0;i<NUMPIXELS;i++)
pixels.setPixelColor(i, pixels.Color(0,0,0)); // Moderately bright
green color.

pixels.show();
}

// Show the best score in yellow and if the last score was less than the
best, show that on top in red
void BestScore()
{
// Best score in yellow
for(int i=0;i<NUMPIXELS;i++)
{
if ( i < bestScore )
pixels.setPixelColor(i, pixels.Color(255,155,0)); // Moderately
bright green color.
else
pixels.setPixelColor(i, pixels.Color(0,0,0));
}

// last score is less than best is in red


if ( lastScore < bestScore )
{
for(int i=0;i<lastScore;i++)

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 140
141
pixels.setPixelColor(i, pixels.Color(255,0,0)); // Moderately
bright green color.
}
pixels.show();
}

// Game over animation


void GameOver()
{
// First pass we animate the strip going red from the enemy position
int a = enemyIndex;
int b = enemyIndex;

for(int i=0;i<NUMPIXELS/2;i++)
{
pixels.setPixelColor(a, pixels.Color(255,0,0)); // Moderately
bright green color.
pixels.setPixelColor(b, pixels.Color(255,0,0)); // Moderately
bright green color.

a = ( a + 1) % NUMPIXELS;
b--;
if ( b == -1 )
b = NUMPIXELS;

pixels.show();
delay(20);
}

delay(100);

// Second pass we animate the strip going back from the enemy position
a = enemyIndex;
b = enemyIndex;

for(int i=0;i<NUMPIXELS/2;i++)
{
pixels.setPixelColor(a, pixels.Color(0,0,0)); // Black
pixels.setPixelColor(b, pixels.Color(0,0,0)); // Black

a = ( a + 1) % NUMPIXELS;
b--;
if ( b == -1 )
b = NUMPIXELS;

pixels.show();
delay(20);

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 141
142
}

// Now we show the best score


delay(100);
BestScore();
}

// Setup the level including the position of the enemy and the coin
void SetLevel()
{
// If the enemy position is -1 (has been reset)
// Find a new position for the enemy
if ( enemyIndex < 0 )
{
// I fthe player not playing, always start the enemy at the half
strip position
if ( playerIndex < 0 )
{
enemyIndex = NUMPIXELS / 2;
}
// The player is in the game, so make sure not to place the enemy on
or too close to the player
else
{
enemyIndex = random(0, NUMPIXELS);

while ( abs(enemyIndex - playerIndex ) < ( NUMPIXELS / 4 ) )


enemyIndex = random(0, NUMPIXELS);
}
}
// If the coin position is -1 (has been reset)
// Find a new position for the coin
if ( coinIndex < 0 )
{
coinIndex = random(0, NUMPIXELS);

// pick a coin position somewhere between the player and enemy


while ( abs(coinIndex - playerIndex ) < 7 || ( abs(coinIndex -
enemyIndex ) < 7 ) )
coinIndex = random(0, NUMPIXELS);
}

pixels.setPixelColor(enemyIndex, pixels.Color(255,0,0));
pixels.setPixelColor(coinIndex, pixels.Color(255,255,0));
}

// This is where all the magic happens

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 142
143
// Player movement happens here as well as game logic for collecting
coins or hitting the enemy
void DisplayPlayer()
{

if ( nextMove < millis() )


{
nextMove = millis() + currentPlayerSpeed;

// The player has a visual trail, so these next 2 if statements


shows or clears the trail
if ( playerIndexTrail >= 0 )
pixels.setPixelColor(playerIndexTrail, pixels.Color(0, 0, 0));

if ( playerIndex >= 0)
{
pixels.setPixelColor(playerIndex, pixels.Color(0, 100, 0));
playerIndexTrail = playerIndex;
}

// Move the player in their current direction


playerIndex += playerDirection;

// Wrap the player at the strip edges


if ( playerIndex < 0 )
playerIndex = NUMPIXELS - 1;
else if ( playerIndex == NUMPIXELS )
playerIndex = 0;

pixels.setPixelColor(playerIndex, pixels.Color(0, 255, 0));

// Did the player hit the coin?


// If so, increase the score, reset coin and enemy positions and
clear the level
// Next loop the SetLevel() will reset the enemy and coin
// Player speed is also increased for every coin hit
if ( playerIndex == coinIndex )
{
enemyIndex = -1;
coinIndex = -1;
score++;
currentPlayerSpeed = constrain( currentPlayerSpeed - 10, 50, 150
);
ClearLevel();
pixels.setPixelColor(playerIndex, pixels.Color(0, 255, 0));
}
// Did the player hit the enemy?

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 143
144
// Set the last/best score and call game over
else if ( playerIndex == enemyIndex )
{
lastScore = score;
if ( score >= bestScore )
bestScore = score;

GameOver();

gameOver = true;
enemyIndex = -1;
coinIndex = -1;
playerIndex = -1;
}
}
}

// nhấn 1 lần để chuyển hướng


void singleClick()
{
if ( countdown > millis() )
return;

playerDirection = -playerDirection;
}

// nhấn giữ để reset


void longClick()
{
gameOver = !gameOver;
if ( gameOver )
{
enemyIndex = -1;
coinIndex = -1;
playerIndex = -1;
currentPlayerSpeed = 150;
ClearLevel();
}
else
{
ClearLevel();
score = 0;
currentPlayerSpeed = 150;
countdown = millis() + 2000;
}
}

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 144
145
➢ Làm đồng hồ hồ đếm ngược , tập trung công việc với màn hình LCD
➢ Đang cập nhật

CẦN HỖ TRỢ KỸ THUẬT , GIẢI ĐÁP THẮC MẮC LIÊN HỆ ZALO : 0339449749 - 145

You might also like