Vậy nên, sử dụng một hệ thống chấm công bằng việc cung cấp cho mỗi nhân viênmột thẻ nhân viên cá nhân để dùng để điểm danh công làm việc một cách tự độngthông qua hệ thống.. Thông tin từ
Tổng quan
Giới thiệu đề tài
Hiện nay, với sự phát triển của công nghệ thông tin và thị trường yêu cầu một lượng lớn lao động Nhưng để kiểm soát lượng lao động với con số lớn như vậy là chuyện không dễ dàng chỉ với cách quản trị truyền thống
Vậy nên, sử dụng một hệ thống chấm công bằng việc cung cấp cho mỗi nhân viên một thẻ nhân viên cá nhân để dùng để điểm danh công làm việc một cách tự động thông qua hệ thống Nhờ vậy mà ta có thể tiết kiệm được thời gian cho việc kiểm soát nhân viên và rà soát lượng thời gian làm việc của họ
Thông tin từ việc chấm công sẽ được lưu trữ vào một bảng tính trực tuyến trên Google Sheet Việc lưu trữ thông tin này được thực hiện sau khi nhân viên sử dụng thẻ RFID của mình để điểm danh qua thiết bị sử dụng ESP32.
Mục tiêu của đề tài
Đề tài: ”Hệ thống chấm công thẻ RFID sử dụng lưu log trên Google Sheet” sau khi hoàn thành sẽ đạt được lần lượt các mục như sau:
●Nhân viên đưa thử RFID đến đầu đọc RFID được kết nối với ESP32
●ESP32 đọc thông tin từ thẻ RFID gồm số nhận dạng của người dùng
●ESP32 sử dụng kết nối Wifi để truy cập và gửi thông tin chấm công tới Google Sheet
●Google Sheet Nhận thông tin chấm công và lưu trữ nó vào một hàng mới trong bảng tính
●Dữ liệu chấm công có thể xem và phân tích từ Google Sheet, cho phép quản lý theo dõi và tính toán thời gian làm việc của nhân viên
Hệ thống mang lại nhiều lợi ích bao gồm tính tự động, chính xác và tiết kiệm thời giam cho quá trình chấm công Và nó cũng cho phép quản lý dễ dàng truy cập vào dữ liệu bất kỳ nơi nào có truy cập Internet.
Phạm vi ứng dụng
Đây là một hệ thống có thể áp dụng cho các trường học, doanh nghiệp, tổ chức, cơ quan để có thể quản lý thời gian làm việc của sinh viên, nhân viên,cán bộ Điều này giúp tự động hoá quy trình chấm công và cải thiện tính chính xác việc ghi nhận thời gian làm việc.
Phân chia nhiệm vụ
Mã sinh viên Họ và tên Nhiệm vụ
201413969 Lê Quang Huy Liên kết các unit test
Hoàn thiện phần mềm và phần cứng
201403981 Trần Thái Hưng Tìm hiểu và hoàn thiện báo cáo
Thực hiện unit test: module RFID
201405882 Nguyễn Văn Tâm Tìm hiểu và hoàn thiện slide
Thực hiện unit test: LCD, còi báo
201413901 Nguyễn Anh Duy Tìm hiểu và viết API để có thể kết nối ESP32 với Google Sheet
Chuẩn bị
Phần mềm thực hiện
Arduino IDE (Integrated Development Environment) - là một phần mềm mã nguồn mở được sử dụng để lập trình và nạp code cho các bo mạch Arduino Nó cung cấp một môi trường phát triển đơn giản và dễ sử dụng cho việc viết và tải lên code vào bo mạch Arduino.
Hình 1 : Biểu tượng của Arduino IDE
Dưới đây là một số điểm nổi bật về Arduino IDE:
●Giao diện đồ họa thân thiện: Arduino IDE có giao diện đồ họa đơn giản và thân thiện, giúp người dùng dễ dàng thao tác và lập trình cho bo mạch Arduino.
●Editor code: Arduino IDE đi kèm với một trình soạn thảo code tích hợp, cho phép người dùng viết mã Arduino dễ dàng Nó hỗ trợ các tính năng như kiểm tra cú pháp, tô màu cú pháp, và gợi ý từ khóa.
●Thư viện và ví dụ: Arduino IDE cung cấp một bộ thư viện phong phú cho các chức năng và module phổ biến, như điều khiển động cơ, giao tiếp không dây, đọc cảm biến, và nhiều hơn nữa Ngoài ra, nó cũng cung cấp các ví dụ code để người dùng có thể học và áp dụng vào dự án của mình.
●Nạp code dễ dàng: Arduino IDE cho phép người dùng nạp code từ máy tính vào bo mạch Arduino thông qua cổng kết nối USB Người dùng có thể chọn bo mạch Arduino mục tiêu và cổng COM tương ứng để nạp code.
● Hỗ trợ đa nền tảng: Arduino IDE có sẵn cho nhiều hệ điều hành như Windows, macOS và Linux, giúp người dùng có thể sử dụng trên nhiều nền tảng khác nhau.
Google Sheets còn được gọi là Google trang tính là sản phẩm nổi bật trong bộ sưu tập ứng dụng của Google Drive, dựa trên trình duyệt để tạo và chỉnh sửa bảng tính miễn phí tương tự như Microsoft Excel.
Hình 2 : Biểu tượng Google Sheets
Google Sheets giúp trải nghiệm trang tính với rất nhiều tính năng như sau:
●Tạo và chỉnh sửa bảng tính: Google Sheets cho phép bạn tạo, chỉnh sửa và định dạng bảng tính trực tuyến
●Cộng tác đồng thời: Google Sheets cho phép nhiều người cùng làm việc trên cùng một bảng tính cùng một lúc
Công thức và hàm tính toán: Google Sheets cung cấp nhiều công thức và hàm
●Đồ thị và biểu đồ: Google Sheets cho phép bạn tạo đồ thị và biểu đồ từ dữ liệu trong bảng tính
●Tính năng tự động và thông minh: Google Sheets có nhiều tính năng tự động và thông minh giúp tiết kiệm thời gian và tăng hiệu suất
●Kết nối và tích hợp dữ liệu: Google Sheets cho phép bạn kết nối và tích hợp dữ liệu từ các nguồn khác nhau.
● Thống kê và phân tích dữ liệu: Google Sheets cung cấp các công cụ thống kê và phân tích dữ liệu để bạn hiểu và khám phá thông tin từ dữ liệu.
Linh kiện
ESP32 là một dòng vi điều khiển giá rẻ, tiết kiệm năng lượng, và hỗ trợ kết nối Wi-Fi và Bluetooth cùng một lúc
Nó sử dụng công nghệ vi xử lý Tensilica Xtensa LX6 với lựa chọn lõi đơn hoặc lõi kép ESP32 tích hợp các thành phần quan trọng như anten, bộ khuếch đại công suất, bộ khuếch đại thu nhiễu thấp, và module quản lý năng lượng Được phát triển bởi Espressif Systems, ESP32 là một bước tiến từ dòng vi điều khiển trước đó là ESP8266 ESP32 được sản xuất với công nghệ tiến tiến 40 nm và cung cấp khả năng linh hoạt cho các ứng dụng IoT và kết nối không dây.
Hình 3 :Các chân của ESP 32 Đặc điểm:
●Bộ xử lý: oCPU: Bộ vi xử lý Xtensa lõi kép (hoặc lõi đơn) 32-bit LX6, hoạt động ở tần số 240 MHz (160 MHz cho ESP32-S0WD và ESP32-U4WDH) và hoạt động ở tối đa 600 MIPS (200 MIPS với ESP32-S0WD/ESP32-U4WDH) oBộ đồng xử lý (co-processor) công suất cực thấp (Ultra low power, viết tắt: ULP) hỗ trợ việc đọc ADC và các ngoại vi khi bộ xử lý chính (main processor) vào chế độ deep sleep
●Hệ thống xung nhịp: CPU Clock, RTC Clock và Audio PLL Clock.
●Bộ nhớ nội: o448 KB bộ nhớ ROM cho việc booting và các tính năng lõi.
●Kết nối không dây: oWi-Fi: 802.11 b/g/n. oBluetooth: v4.2 BR/EDR và BLE (chia sẻ sóng vô tuyến với Wi-Fi)
●34 GPIO pad vật lý với các ngoại vi: oADC SAR 12 bit, 18 kênh. oDAC 2 × 8-bit. o10 cảm biến cảm ứng (touch sensor) (GPIO cảm ứng điện dung). o3 SPI (SPI, HSPI và VSPI) hoạt động ở cả 2 chế độ master/slave Module ESP32 hỗ trợ 4 ngoại vi SPI với SPI0 và SPI1 kết nối đến bộ nhớ flash của ESP32 còn SPI2 và SPI3 tương ứng với HSPI và VSPI Các GPIO đều có [10] thể được dùng để triển khai HSPI và VSPI o2 I²S o2 I²C, hoạt động được ở cả chế độ master và slave, với chế độ Standard mode (100 Kbit/s) và Fast mode (400 Kbit/s) Hỗ trợ 2 chế độ định địa chỉ là 7-bit và 10-bit Các GPIO đều có thể được dùng để triển khai I²C o3 UART (UART0, UART1, UART2) với tốc độ lên đến 5 Mbps oSD/SDIO/CE-ATA/MMC/eMMC host controller oSDIO/SPI slave controller oEthernet MAC interface cho DMA và IEEE 1588 Precision Time Protocol (tạm dịch: Giao thức thời gian chính xác IEEE 1588) oCAN bus 2.0 oBộ điều khiển hồng ngoại từ xa (TX/RX, lên đến 8 kênh) oPWM cho điều khiển động cơ oLED PWM (lên đến 16 kênh) oCảm biến hiệu ứng Hall oBộ tiền khuếch đại analog công suất cực thấp (Ultra low power analog pre- amplifier)
●Bảo mật: oHỗ trợ tất cả các tính năng bảo mật chuẩn IEEE 802.11, bao gồm WFA, WPA/WPA2 và WAPI. oSecure boot (tạm dịch: khởi động an toàn) oMã hóa flash o1024-bit OTP, lên đến 768-bit cho khách hàng oTăng tốc mã hóa phần cứng: AES, SHA-2, RSA, elliptic curve cryptography (ECC, tạm dịch: mật mã đường cong ellip), random number generator (viết tắt: RNG, tạm dịch: trình tạo số ngẫu nhiên)
●Quản lý năng lượng: oHỗ trợ 5 chế độ hoạt động với mức tiêu thụ năng lượng khác nhau: Active, Modem-sleep, Light-sleep, Deep-sleep và Hibernation oBộ ổn áp nội với điện áp rơi thấp (internal low-dropout regulator) oIndividual power domain (tạm dịch: Miền nguồn riêng) cho RTC oTrở lại hoạt động từ ngắt GPIO, timer, đo ADC, ngắt với cảm ứng điện dung
Là một module đọc thẻ RFID (Radio Frequency Identification) sử dụng chip MFRC522 Nó là một công nghệ được sử dụng rộng rãi trong các ứng dụng nhận dạng và theo dõi vật phẩm trong thực tế.
●Tần số hoạt động: 13.56Mhz
●Khoảng cách hoạt động: 0~60mm mifare1 card( )
●Tốc độ truyền dữ liệu: tối đa 10Mbit/s
●Các loại card RFID hỗ trợ: mifare1 S50, mifare1 S70, mifare UltraLight, mifare Pro, mifare Desfire
● Kích thước: 40mm × 60mm Đặc điểm:
●Hoạt động tần số radio: RFID RC522 hoạt động trong dải tần số 13.56 MHz, một dải tần số được sử dụng phổ biến cho các ứng dụng RFID.
●Hỗ trợ thẻ RFID: Module này có khả năng đọc và ghi các thẻ RFID chuẩn 13.56 MHz, chẳng hạn như thẻ MIFARE Classic 1K, MIFARE Classic 4K, MIFARE Ultralight, và các thẻ tương thích.
●Giao tiếp SPI: RFID RC522 sử dụng giao tiếp SPI (Serial Peripheral Interface) để kết nối với vi điều khiển hoặc mạch điều khiển khác Giao tiếp SPI cho phép truyền và nhận dữ liệu nhanh chóng và đơn giản.
●Đọc và ghi dữ liệu: Module này cho phép bạn đọc dữ liệu từ các thẻ RFID và ghi dữ liệu lên thẻ RFID Có thể sử dụng nó để nhận dạng và theo dõi các vật phẩm được gắn thẻ RFID.
●Khoảng cách đọc: Khoảng cách đọc của RFID RC522 tùy thuộc vào anten và thẻ RFID, nhưng thông thường khoảng cách đọc từ 2cm đến 10cm.
●Hỗ trợ nhiều ngôn ngữ lập trình: RFID RC522 có thư viện và hỗ trợ cho nhiều ngôn ngữ lập trình như Arduino, Raspberry Pi, và các nền tảng phát triển khác
2.2.3 LCD 1602 tích hợp Module chuyển đổi I2C LCD
Là một mô-đun hiển thị LCD 16x2 (16 cột x 2 hàng) có tích hợp một module chuyển đổi giao diện I2C Module chuyển đổi I2C giúp đơn giản hóa quá trình kết nối và điều khiển LCD thông qua giao diện I2C, giảm số lượng dây kết nối cần thiết.
Hình 5 : LCD tích hợp module chuyển đổi I2C LCD 9050 R7 Đặc điểm:
●Kích thước và độ phân giải: Mô-đun LCD 1602 có kích thước 84x44mm và có khả năng hiển thị 16 cột x 2 hàng ký tự, tức là có thể hiển thị tối đa 32 ký tự cùng một lúc.
●Giao diện I2C: Module chuyển đổi I2C "LCD 8050 R7" tích hợp trên mô-đun LCD 1602 cho phép giao tiếp thông qua giao diện I2C Thông qua đó, mô- đun LCD có thể được kết nối và điều khiển bằng các thiết bị khác sử dụng chỉ hai dây: dây dữ liệu (SDA) và dây đồng hồ (SCL).
●Điều khiển dễ dàng: Với module chuyển đổi I2C, việc điều khiển mô-đun LCD 1602 trở nên dễ dàng hơn Thay vì phải sử dụng nhiều chân GPIO để điều khiển LCD theo giao thức song song, ta chỉ cần kết nối một cặp dây I2C và sử dụng lệnh giao tiếp I2C để điều khiển hiển thị trên màn Hình LCD.
● Đa ngôn ngữ: Mô-đun LCD 1602 với module chuyển đổi I2C
"LCD 8050 R7" hỗ trợ nhiều ngôn ngữ và ký tự đặc biệt, cho phép hiển thị các ký tự tiếng Anh, ký tự Unicode, ký tự tùy chỉnh và nhiều ngôn ngữ khác trên màn Hình LCD.
Thí nghiệm và kết quả
Kiểm tra thành phần hệ thống
3.1.1 Kết nối ESP32 với Module RFID RC522 a Sơ đồ
Hình 6 : Sơ đồ két nối ESP32 với Module RFID RC522 b.Lưu đồ thuật toán
Hình 7: Lưu dồ thuật toán của kết nối ESP32 với Module RFID RC522 c Chương trình
#define RST_PIN 13 // Configurable, see typical pin layout above
#define SS_PIN 15 // Configurable, see typical pin layout above MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance void setup() {
Serial.begin(115200); // Initialize serial communications with the PC while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
SPI.begin(); // Init SPI bus mfrc522.PCD_Init(); // Init MFRC522 delay(4); // Optional delay Some board do need more time after init to be ready, see Readme mfrc522.PCD_DumpVersionToSerial(); // Show details of PCD - MFRC522 Card Reader details
Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks ")); } void loop() {
// Reset the loop if no new card present on the sensor/reader This saves the entire process when idle. if ( ! mfrc522.PICC_IsNewCardPresent()) { return;
//Select one of the cards if ( ! mfrc522.PICC_ReadCardSerial()) { return;
// Dump debug info about the card; PICC_HaltA() is automatically called mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
Video 1 : Unit test kết nối ESP32 với Module RFID RC522
3.1.2 Kết nối ESP32 với LCD a Sơ đồ
Hình 8 : Sơ đồ kết nối ESP32 với LCD b Lưu đồ thuật toán
Hình 9 : Lưu dồ thuật toán của kết nối ESP32 với LCD c Chương trình
#include int lcdColumns = 16; int lcdRows = 2;
// set LCD address, number of columns and rows
// if you don't know your display address, run an I2C scanner sketch
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows); void setup(){
// turn on LCD backlight lcd.backlight();
// set cursor to first column, first row lcd.setCursor(0, 0);
// print message lcd.print("Hello, World!"); delay(1000);
// clears the display to print new message lcd.clear();
// set cursor to first column, second row lcd.setCursor(0,1); lcd.print("Hello, World!"); delay(1000); lcd.clear();
Video 2: Unit test kết nối ESP32 với LCD
3.1.3 Đẩy thông tin lên Google Sheet
Các bước dể thêm 1 Script vào Google Sheet:
B1: Mở cửa sổ trang tính
Hình 10 : Tiện ích Apps Scropt trên Google Sheets
B3: Trong Script Editor, điền mã lệnh
Hình 11 : Giao diện Apps Scripts trên Google Sheets
B4: Lưu dự án và chạy chương trình
Code Script: (Source code: btl-rfid-ggsheet/Source/ggsheet.gs at master ã Lqhuy125/btl-rfid-ggsheet (github.com) ) var timeZone="Asia/Ho_Chi_Minh"; var dateTimeFormat="dd/MM/yyyy HH:mm:ss"; var logSpreadSheetId=""; var attendanceLogSheetName="attendance log"; var defaultTerminalName="headquarter"; var mainTabName="Staff Infor"; function onOpen() { var ui = SpreadsheetApp.getUi(); ui.createMenu('Anyboards Menu')
addItem('Thêm các UID mới', 'addNewUIDsFromAttendanceLogUiHandler') addItem('Thêm 1 UID được lựa chọn', 'addOneSelectedUID')
{ var tabName=SpreadsheetApp.getActiveSheet().getName(); if(tabName!=attendanceLogSheetName)
SpreadsheetApp.getUi().alert('Bạn cần lựa chọn trang tính '+ attendanceLogSheetName+' để có thể sử dụng chức năng này'); var row=SpreadsheetApp.getActiveSheet().getActiveCell().getRow(); var col=SpreadsheetApp.getActiveSheet().getActiveCell().getColumn(); addNewUIDsFromAttendanceLog(row);
{ var response = ui.alert('Tất cả các UID mới từ '+attendanceLogSheetName+' sẽ được thêm vào '+mainTabName+'', 'Bạn có muốn tiếp tục không?', ui.ButtonSet.YES_NO); if (response == ui.Button.YES) addNewUIDsFromAttendanceLog();
{ var mainTab=getMainSheet(); var data=mainTab.getRange(2,1,mainTab.getLastRow(),1).getValues(); var registeredUIDs=[]; data.forEach(x=>registeredUIDs.push(x[0])); registeredUIDs=[ new Set(registeredUIDs)]; var attendanceSheet=getAttendanceLogSheet(); var data; if(row) data=attendanceSheet.getRange(row,1,row,2).getValues(); else data=attendanceSheet.getRange(2,1,attendanceSheet.getLastRow(),2).getValues()
; var arr=[]; for(var i=0; i=0; i )
{ var row=[]; row[0]=arr[i].uid; row[1]='Person '+(startRow-2+arr.length-i); row[2]=-1; row[3]="Ban chua duoc dky"; row[4]=0; row[5]=arr[i].date; data.push(row);
} if(data.length>0) mainTab.getRange(startRow, 1,data.length,data[0].length).setValues(data);} if(!getAttendanceLogSheet())
{ var mainSheet=SpreadsheetApp.getActiveSheet().setName(mainTabName); var rowData = ['UID','Name','Access','Role','Visits Count', 'Last Visit']; mainSheet.getRange(1, 1,1,rowData.length).setValues([rowData]); mainSheet.setColumnWidths(1, rowData.length+1,150); rowData=['Date Time','UID','Name','Access','Terminal']; var attendanceSheet=SpreadsheetApp.getActiveSpreadsheet().insertSheet(attendance LogSheetName); attendanceSheet.getRange(1, 1,1,rowData.length).setValues([rowData]); attendanceSheet.setColumnWidths(1, rowData.length+1,150);
} else{ var ui = SpreadsheetApp.getUi(); ui.alert('Bảng tính đã được khởi tạo thành công!');
} function doGet(e) { var access="-1"; var text='Pls contact Admin'; var name='Ban can dang ky'; var dateTime=Utilities.formatDate(new Date(), timeZone, dateTimeFormat);
Logger.log(JSON.stringify(e)); var result = 'Ok'; if (e.parameter == 'undefined') result = 'No Parameters'; else
{ var uid = ''; var terminal = defaultTerminalName; for (var param in e.parameter) { var value = stripQuotes(e.parameter[param]); switch (param) { case 'uid': uid = value; break; case 'terminal': terminal = value; break; default: result = "unsupported parameter";
} var mainSheet=getMainSheet(); var data = mainSheet.getDataRange().getValues(); if (data.length == 0) return; for (var i = 0; i < data.length; i++)
{ if (data[i][0] == uid) accessa[i][2]; texta[i][3]; var numOfVisits=mainSheet.getRange(i+1,5).getValue(); mainSheet.getRange(i+1,5).setValue(numOfVisits+1); mainSheet.getRange(i+1,6).setValue(dateTime+' '+terminal); break;
} var attendanceSheet=getAttendanceLogSheet(); data=[dateTime,uid,name,access,terminal]; attendanceSheet.getRange(attendanceSheet.getLastRow()
} resultcess+":"+name+":"+text; return ContentService.createTextOutput(result);
SpreadsheetApp.getActiveSpreadsheet().getSheetByName(attendanceLogSheetN ame);
SpreadsheetApp.getActiveSpreadsheet().getSheetByName(mainTabName);} function stripQuotes(value) { return value.replace(/^["']|['"]$/g, "");
Sản phẩm hoàn thiện
Hình 12 : Sơ đồ kết nối hoàn thiện b Lưu đồ thuật toán
Hình 13 : Lưu đồ thuật toán tổng quát c Chương trình
#define TERMINAL_NAME "basement" const char *mainLinkForSpr "https://script.google.com/macros/s/AKfycbwkqrVOX2MyoKiUAKy5wjE Sza5ixywgK0voh087XRIRoTpp4fYpYSPAr7q5_fIQQxKq/exec"; // test const char *ssid = "jqk"; const char *password = "abcd1234@&";
MFRC522 mfrc522(SS_PIN, RST_PIN);
MFRC522::StatusCode status; uint64_t clearDisplayTimer=0;
// WiFiClientSecure client; const char *root_ca " -BEGIN CERTIFICATE -\n" \
"MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BA QwFADBHMQsw\n" \
"CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlc nZpY2VzIExMQzEU\n" \
"MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDA wWhcNMzYwNjIyMDAw\n" \
"MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ 2xlIFRydXN0IFNlcnZp\n" \
"Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCS qGSIb3DQEBAQUA\n" \
"A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0 yBoJx9vaMf/vo\n" \
"27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLG cY9vXmX7w\n" \
"Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g 4M/SCYe7zUjw\n" \
"TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2we aSUKK0Pfybl\n" \
"qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPw LxAwAtcvfaH\n" \
"szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncK KiPo4Zor8\n" \
"Y/ kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUs pzBmk\n" \
"MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/
1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYW k70p\n" \
"aDPvOmbsB4om3xPXV2V4J95eSRQAogB/ mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN\n" \
"VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/ oFB2ACYPTrIrnqYNxgFlQID\n" \
"AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4E\n" \
"FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQAD ggIBAJ+qQibb\n" \
"C5u+/ x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg 6LEe\n" \
"QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+ GlQebtuy\n" \
"h6f88/ qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/ H9oPM4\n" \
"7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/
"ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko 8cdLiA6Ef\n" \
"MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/ bal8xa5meLMFrUKTX5hgUvYU/\n" \
Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbd T\n" \
"6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/ tSQdirpLsQBqvFAnZ\n" \
"2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/
// - void dualPrint(const FlashStringHelper* text); void beep(int count); void openDoor(); void clearDisplayIn(); void handleDataFromGoogle(String data); void setup(){ pinMode(DOOR_PIN, OUTPUT); pinMode(LOCK_PIN, OUTPUT); lcd.init();
// Print a message to the LCD. lcd.backlight(); lcd.setCursor(0, 0); lcd.print("Connecting wifi"); lcd.setCursor(0, 1);
Serial.begin(115200); // Initialize serial communications with the PC while (!Serial);
SPI.begin(); // Init SPI bus mfrc522.PCD_Init(); // Init MFRC522
WiFi.begin(ssid, password); byte printedDots = 0; while (WiFi.status() != WL_CONNECTED)
{ delay(500); if(printedDots > 15){ for (byte i = 1; i 1)
{ lcd.clear(); lcd.setCursor(0,1); lcd.print("Xin moi quet the");
} beep(1); lcd.backlight(); getGoogleData(); mfrc522.PICC_HaltA(); mfrc522.PCD_StopCrypto1(); beep(1);
} void dualPrint(const FlashStringHelper* text)
{ ledcSetup(BUZZ_CHANNEL, 5000, 10); ledcAttachPin(BUZZ_PIN, BUZZ_CHANNEL); for (size_t j = 0; j < count; j++)
} ledcDetachPin(BUZZ_PIN); pinMode(BUZZ_PIN,INPUT);
{ digitalWrite(DOOR_PIN,HIGH); delay(2000); digitalWrite(DOOR_PIN,LOW);
{ digitalWrite(LOCK_PIN,HIGH); delay(2000); digitalWrite(LOCK_PIN,LOW); d Kết quả
Video 3 : Unit test sảm phẩm hoàn thiện