40
Chƣơng 5:
THI CƠNG
5.1 Giới thiệu
Mơ hình bao gồm 2 phần thi công: Phần cứng và phần mềm.
Phần cứng: Bao gồm 1 mạch toàn bộ hệ thống với kích thước 82mm x 52mm. Mạch được in 1 lớp. Thi cơng mơ hình với hộp đựng phù hợp kích thước với board mạch bao gồm hộp đựng mạch và mơ hình lắp thiết bị.
Phần mềm: Lập trình cho ESP8266, giám sát điều khiển đóng ngắt các thiết bị và truyền nhận dữ liệu từ Server. Thiết kế giao diện điều khiển giám sát, xây dựng Web Server, giao diện Website. Sau q trình tính tốn, thiết kế và lựa chọn các linh kiện thích hợp, tiến hành thi công PCB, lắp ráp và kiểm tra mạch.
Sau khi thiết kế hoàn chỉnh sơ đồ nguyên lý cho tồn hệ thống, tiến hành thi cơng mơ hình. Hệ thống được thi công bao gồm hai phần chính là thi cơng phần cứng và thi công phần mềm. Cụ thể như sau:
Về phần cứng: Tiến hành lắp ráp module Node MCU ESP8266 lên mạch PCB, sắp xếp các linh kiện điện tử lên board mạch đã thiết kế.
Về phần mềm: Xây dựng giải thuật và viết chương trình cho hệ thống. Chương trình được lập trình dựa vào nguyên lý hoạt động của hệ thống từ khi cấp nguồn cho đến khi hệ thống ngừng hoạt động, áp dụng được giải thuật điều khiển vào sản phẩm một cách tối ưu nhất.
Tồn bộ q trình thi cơng hệ thống phải đảm bảo tất cả những yêu cầu về thiết kế mà em đã đặt ra ban đầu.
41
5.2 Thi công hệ thống
5.2.1 Thi công board mạch hệ thống
Hình 5.1: Sơ đồ đi dây mạch in lớp dƣới của mạch
42
5.2.2 Danh sách các linh kiện
Dưới đây là linh kiện sử dụng trong đề tài: Module thu phát wifi ESP8266 Node MCU Diode
Relay 5V Opto PC817 Domino
Led, tụ điện, điện trở
5.2.3 Lắp ráp và kiểm tra
Sau khi hoàn thiện mạch PCB như phần trên, ta tiến hành đưa vào vỏ hộp bằng nhựa và lắp đặt vào trên trong tủ kem. Mạch cần được đặt vào nơi kín đáo của tủ nhằm vừa để bắt sóng wifi tốt, vừa để tránh được nhiều khói bụi và độ ẩm.
Hình 5.3: Kiểm tra trƣớc khi lắp mạch tủ kem
43
Tín hiệu hoạt động của tủ sẽ được lấy dựa trên tín hiệu của quạt làm mát, vì trên ngun lí, tủ kem sẽ dừng làm lạnh khi đã đủ độ lạnh, quạt khi này cũng dừng làm mát, và sẽ chỉ làm mát trở lại khi tủ kem bắt đầu làm lạnh. Tín hiệu được cấp vào mạch phát hiện điện áp và sau đó gửi vào ESP8266 để xử lí.
Tín hiệu sau khi vào vi điều khiển sẽ được gửi lên server để tiến hành quản lý, đồng thời cũng gửi lên website thiết bị để theo dõi trên thời gian thực.
5.3 Viết tài liệu hƣớng dẫn sử dụng, thao tác
Để cấp nguồn cho mạch hoạt động cần phải có mạch chuyển đổi nguồn AC từ ổ điện dân dụng sang 5V DC.
44
Kết nối Wifi và đăng nhập website thiết bị
+ Sau khi khởi động tủ, truy cập vào wifi có tên mặc định là “Tukem”, mật khẩu mặc định cho wifi này là “12345678”
+ Sử dụng trình duyệt truy cập vào website thiết bị với địa chỉ IP mặc định là “192.168.1.200”
Hình 5.6: Nhập mật khẩu mặc định
Sau khi truy cập vào website thành cơng, để có thể thao tác chức năng với tủ kem, người dùng cần phải đăng nhập thông qua phương thức nhập mật khẩu. Trong trường hợp chưa được cài đặt mật khẩu từ trước thì mật khẩu mặc định là
“123”.
Tại đây, người dùng cũng có thể thay đổi mật khẩu cho website thiết bị bằng cách nhấn vào nút “Thay đổi mật khẩu”.
Hình 5.7: Giao diện thay đổi mật khẩu
Khi này, giao diện thay đổi mật khẩu sẽ hiện ra, người dùng nhập mật khẩu cũ và mật khẩu mới sau đó nhấn “Lưu”, website sau khi thay đổi mật khẩu sẽ tự
45
quay về màn hình đăng nhập chính (trong trường hợp này sẽ đổi mật khẩu từ “123” sang “long”).
Nhập các thông tin cần thiết. Sau khi đăng nhập vào website thành cơng, người dùng có thể nhập thơng tin tủ kem, theo dõi trạng thái máy và thao tác một số tính năng cơ bản.
46
Giải thích:
[1] Nhập tên wifi tại nơi đặt tủ [2] Nhập password wifi tại nơi đặt tủ [3] Nhập mã số của tủ (serial number)
[4] Nhập địa chỉ IP hoặc tên miền của website quản lý
[5] Nhấn “Nhập” để lưu các thơng tin đã nhập phía trên vào bộ nhớ [6] Nhấn “Khởi động lại” để thiết bị khởi động lại
[7] Nhấn “Khơi phục” để xóa tồn bộ các thông tin wifi đã lưu trong bộ nhớ và thiết bị về trạng thái ban đầu (chỉ sử dụng khi thay đổi wifi mới hoặc khi dời tủ kem đi nơi khác)
[8] Địa chỉ IP hiện tại được chính wifi vừa kết nối cấp xuống (trường hợp trên vẫn chưa hoàn thành kết nối nên địa chỉ IP đang (unset)
[9] Trạng thái máy theo thời gian thực [10] Nút ON/OFF để bật tắt tủ kem
[11] Nhấn thay đổi mật khẩu để thay đổi mật khẩu trực tiếp mà không cần phải quay trở lại màn hình đăng nhập
Kết nối trở lại website với địa chỉ IP đã thay đổi:
Sau khi kết nối với wifi tại nơi đặt tủ thành công, mạng Wifi “Tukem” sẽ tự động dừng phát, website khi này sẽ tự động mất kết nối. Để truy cập trở lại website thiết bị, người dùng sẽ bắt buộc phải kết nối với wifi tại nơi đặt tủ (wifi mà mạch phần cứng đang kết nối).
Sau khi kết nối với mạng wifi tại nơi đặt tủ, địa chỉ IP của website thiết bị sẽ bị thay đổi. Khi này ta truy cập vào website quản lý, vào mục “Detail” của từng tủ kem sẽ có hiển thị địa chỉ IP cấp xuống và mật khẩu đăng nhập website thiết bị.
47
Hình 5.9: Địa chỉ IP đƣợc wifi tại nơi lắp đặt cấp
Sau khi tìm được thơng tin website, người dùng sử dụng trình duyệt truy cập địa chỉ IP và nhập mật khẩu của website.
48
Hình 5.10: Nhập IP trên server để có thể truy cập trở lại website thiết bị
Khi này, người dùng có thể thao tác trở lại bình thường với mạch phần cứng như thay đổi thơng tin, khởi động lại...
49
Hình 5.11: Giao diện chính của website thiết bị
Hình 5.12: Địa chỉ IP kết nối và trạng thái theo thời gian thực
[1] Sau khi kết nối thành công, địa chỉ IP được wifi cấp xuống sẽ hiển thị ở đây. [2] Thời gian thực sẽ được cập nhật lại cho đúng như thời gian trên website quản lý.
50
Chƣơng 6:
ĐÁNH GIÁ KẾT QUẢ, KẾT LUẬN
6.1 Kết quả đạt đƣợc
Sau một thời gian nghiên cứu và hoàn thiện, hệ thống đã thực hiện quản lý và giám sát một chuỗi bao gồm 1000 tủ kem và cho đến hiện tại vẫn đang hoạt động ổn định.
Hệ thống đã truyền nhận thành công và ổn định lên server và website thiết bị mà độ trễ hầu như khơng đáng kể, có thể điều khiển bật tắt mạch trên website thiết bị khá tốt. Đồng thời hệ thống cũng đã thực hiện tạo điểm phát và kết nối với wifi tại nơi đặt tủ rất ổn định mà ít khi bị mất kết nối.
Tất cả cấu thành trong hệ thống đã được thử nghiệm và vận hành tốt, tuy nhiên vẫn còn nhiều nhược điểm do hạn chế về mặt kiến thức. Đề tài nghiên cứu này em sẽ rút kinh nghiệm và hoàn thiện tốt hơn trong tương lai.
6.2 Đánh giá kết quả thực tế
Bảng 6.1: Bảng thực nghiệm kết quả chạy thực tế
Công việc Số lần Số lần thành
công
Thời gian đáp
ứng Đánh giá
Điều khiển và thao tác
trên website thiết bị 50 50 2 - 3 giây Đạt
Hiện thị trạng thái và thời gian thực trên website thiết bị
50 40 1 giây Đạt
Thực hiện tạo điểm
phát và kết nối wifi 50 50 10 – 15 giây Đạt
Gửi dữ liệu và hiển thị
lên server 50 50 15 giây Đạt
51
6.3 Nhận xét
Ưu điểm:
+ Dễ dàng nắm bắt được hiện trạng của hệ thống để đưa ra hướng giải quyết kịp thời.
+ Tiết kiệm thời gian và chi phí nhân cơng. + Đơn giản hóa việc quản lý số lượng lớn tủ kem.
+ Mạch điều khiển nhỏ gọn, hoạt động ổn định, chính xác, dễ dàng lắp đặt vào tủ kem mà khơng gây ảnh hướng đến chức năng chính yếu của tủ.
+ Có server quản lý và lưu trữ dữ liệu.
+ Giao diện điều khiển đơn giản, trực quan và dễ sử dụng. Nhược điểm:
+ Giới hạn về thời gian và kiến thức nên hệ thống chưa tối ưu.
+ Hệ thống cịn phụ thuộc vào tốc độ mạng Internet, đơi khi sẽ xảy ra hiện tượng chậm trễ.
+ Hệ thống hiện tại vẫn đang vận hành trên server thuê bên ngồi, hiện tượng sập server đơi khi xảy ra.
+ Mạch phần cứng thường xuyên có hiện tượng quá nhiệt trong lúc hoạt động.
6.4 Định hƣớng phát triển
+ Sẽ thử nghiệm và thay đổi sang một số loại vi điều khiển thích hợp wifi có tốc độ thu phát tốt hơn trong tương lai.
+ Thêm vào một số cảm biến phục vụ tính năng an tồn như cảm biến nhiệt độ, cảm biến khí gas.
+ Thực hiện thêm vào tính năng bảo mật thơng tin trên đường truyền.
52
TÀI LIỆU THAM KHẢO
I. Tài liệu từ sách
[1]. Ths. Nguyễn Thị Ngọc Anh. Điện tử tương tự 1. Hutech, ấn bản 2015, tr. 1-31 [2]. Ths. Phạm Quốc Phương. Vi điều khiển. Hutech, ấn bản 2015, tr. 31-46, tr.104- 115
II. Tài liệu từ nguồn từ Internet
1/ https://randomnerdtutorials.com/ 2/ https://www.w3schools.com/html/default.asp 3/ https://randomnerdtutorials.com/decoding-and-encoding-json-with-arduino-or- esp8266/ 4/ http://arduino.vn/reference/millis 5/ https://stackoverflow.com/questions/10813718/ajax-onreadystatechange-function 6/ https://arduino.esp8266.vn/wifi/station.html 7/ https://randomnerdtutorials.com/esp32-access-point-ap-web-server/ 8/ https://codelearn.io/sharing/tao-server-cho-trang-web-ca-nhan-voi-arduino 9/ https://www.kasperkamperman.com/blog/arduino/arduino-programming-state- change 10/ http://arduino.vn/bai-viet/1231-ket-noi-voi-esp8266-thuan-voi-board-mo-rong- va- 11/ https://github.com/PaulStoffregen/Time 12/ https://stackoverflow.com/questions/64278397/arduino-esp8266-eeprom- commit-returns-false
53
PHỤ LỤC
Code lập trình Arduino
//================= Khai báo thư viện =============== #include <EEPROM.h> //thư viện bộ nhớ lưu trữ
#include <time.h> //khai báo thư viện thời gian
#include <string.h> // Thư viện hỗ trợ truyền chuỗi dữ liệu #include <ESP8266WiFi.h> //Khai báo thư viện cho ESP
#include <ESP8266WebServer.h> //Khai báo thư viện cho web thiết bị #include <ESP8266HTTPClient.h>
#include <WiFiClient.h> //#include "ArduinoJson.h"
#include <ArduinoJson.h> //Thư viện hỗ trợ gửi dữ liệu lên server ESP8266WebServer webServer(80);//khai báo port web thiết bị ESP8266WebServer webServer2(1605);//khai báo port server ESP8266WebServer webServer3(1605);//khai báo ghi log const int ledPin = 4; //d2
int timezone= 7*60*60; int dst=0;
//class SensorThread: public Thread //{
//public: //int value; //int pin; //void run(){
// Reads the analog pin, and saves it localy //value = map(analogRead(pin), 0,1023,0,255); //runned();
54
//} //};
//=============== Access Point Mode ===================== chế độ điểm phát wifi
char* ssid_ap = "Tukem"; //tên wifi tủ kêm phát ra
char* pass_ap = "12345678"; //mật khẩu wifi tủ kem phát ra //char* pass_login = "123"; //mật khẩu wifi tủ kem phát ra IPAddress ip_ap(192,168,1,200); //IP mặc định của wifi tủ kem IPAddress gateway_ap(192,168,0,1);
IPAddress subnet_ap(255,255,255,0);
//================= Station Mode ==================== String ssid; //Khai báo dữ liệu dạng chuỗi dưới tên biến "ssid" String pass; //Khai báo dữ liệu dạng chuỗi dưới tên biến "pass" String seri; //Khai báo dữ liệu dạng chuỗi dưới tên biến "seri" String addr; //Khai báo dữ liệu dạng chuỗi dưới tên biến "addr" String pass_login1 = "123";
String passwordlogin; String oldpass;
String newpass; String passcomfirm;
// const char* serverName = addr.c_str();
// const char* serverName = "http://14.225.27.59:1605"; //địa chỉ server để cập nhật log
//const char* serverName2 = "http://ctbus.cf:1605/device/update/wifi"; //địa chỉ server để update thông tin wifi
55
//================== phân luồng =========== unsigned long preTimeThread1 = millis();
unsigned long intervalThread1 = 15000; unsigned long preTimeThread4 = millis(); unsigned long intervalThread4 = 1000;
//========================================================== =========================================================== =========================================================== ======== char hex[256]; uint8_t data[256]; int start = 0; int seconds = 0; uint8_t hash[32]; String pin; #define SHA256_BLOCK_SIZE 32 typedef struct { uint8_t data[64]; uint32_t datalen;
unsigned long long bitlen; uint32_t state[8];
} SHA256_CTX;
void sha256_init(SHA256_CTX *ctx);
void sha256_update(SHA256_CTX *ctx, const uint8_t data[], size_t len); void sha256_final(SHA256_CTX *ctx, uint8_t hash[]);
56
#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22)) #define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25)) #define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
static const uint32_t k[64] = { 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f8 2a4,0xab1c5ed5, 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bd c06a7,0xc19bf174, 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a 9dc,0x76f988da, 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca 6351,0x14292967, 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c 2c92e,0x92722c85, 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e 3585,0x106aa070,
57 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9c ca4f,0x682e6ff3, 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3 f7,0xc67178f2 };
void sha256_transform(SHA256_CTX *ctx, const uint8_t data[]) { uint32_t a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
for (i = 0, j = 0; i < 16; ++i, j += 4)
m[i] = ((uint32_t)data[j] << 24) | ((uint32_t)data[j + 1] << 16) | ((uint32_t)data[j + 2] << 8) | ((uint32_t)data[j + 3]);
for ( ; i < 64; ++i)
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
a = ctx->state[0]; b = ctx->state[1]; c = ctx->state[2]; d = ctx->state[3]; e = ctx->state[4]; f = ctx->state[5]; g = ctx->state[6]; h = ctx->state[7]; for (i = 0; i < 64; ++i) {
t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; t2 = EP0(a) + MAJ(a,b,c);
58 h = g; g = f; f = e; e = d + t1; d = c; c = b; b = a; a = t1 + t2; } ctx->state[0] += a; ctx->state[1] += b; ctx->state[2] += c; ctx->state[3] += d; ctx->state[4] += e; ctx->state[5] += f; ctx->state[6] += g; ctx->state[7] += h; } void sha256_init(SHA256_CTX *ctx) { ctx->datalen = 0; ctx->bitlen = 0; ctx->state[0] = 0x6a09e667; ctx->state[1] = 0xbb67ae85; ctx->state[2] = 0x3c6ef372; ctx->state[3] = 0xa54ff53a; ctx->state[4] = 0x510e527f;
59
ctx->state[5] = 0x9b05688c; ctx->state[6] = 0x1f83d9ab; ctx->state[7] = 0x5be0cd19; }
void sha256_update(SHA256_CTX *ctx, const uint8_t data[], size_t len) { uint32_t i;
for (i = 0; i < len; ++i) {
ctx->data[ctx->datalen] = data[i]; ctx->datalen++; if (ctx->datalen == 64) { sha256_transform(ctx, ctx->data); ctx->bitlen += 512; ctx->datalen = 0; } } }
void sha256_final(SHA256_CTX *ctx, uint8_t hash[]) { uint32_t i;
i = ctx->datalen;
// Pad whatever data is left in the buffer. if (ctx->datalen < 56) {
ctx->data[i++] = 0x80; while (i < 56)
60 } else { ctx->data[i++] = 0x80; while (i < 64) ctx->data[i++] = 0x00; sha256_transform(ctx, ctx->data); memset(ctx->data, 0, 56); }
// Append to the padding the total message's length in bits and transform. ctx->bitlen += ctx->datalen * 8; ctx->data[63] = ctx->bitlen; ctx->data[62] = ctx->bitlen >> 8; ctx->data[61] = ctx->bitlen >> 16; ctx->data[60] = ctx->bitlen >> 24; ctx->data[59] = ctx->bitlen >> 32; ctx->data[58] = ctx->bitlen >> 40; ctx->data[57] = ctx->bitlen >> 48; ctx->data[56] = ctx->bitlen >> 56; sha256_transform(ctx, ctx->data);
// Since this implementation uses little endian byte ordering and SHA uses big endian,
// reverse all the bytes when copying the final state to the output hash. for (i = 0; i < 4; ++i) {
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
61
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; }
}
char *btoh(char *dest, uint8_t *src, int len) { char *d = dest;
while( len-- ) sprintf(d, "%02x", (unsigned char)*src++), d += 2; return dest;
}
String SHA256(String data) {
uint8_t data_buffer[data.length()];
for(int i=0; i<data.length(); i++) { data_buffer[i] = (uint8_t)data.charAt(i); } SHA256_CTX ctx; ctx.datalen = 0; ctx.bitlen = 512; sha256_init(&ctx);
sha256_update(&ctx, data_buffer, data.length()); sha256_final(&ctx, hash);
62 return(btoh(hex, hash, 32)); } //========================================================== =========================================================== =========================================================== ========
//================== giao diện web thiết bị ============= const char MainPage[] PROGMEM = R"=====(
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Trang chủ</title> <style> .loader { border: 16px solid #f3f3f3; border-radius: 50%; border-top: 16px solid #3498db; width: 120px; height: 120px;
-webkit-animation: spin 2s linear infinite; /* Safari */ animation: spin 2s linear infinite;
} @-webkit-keyframes spin { 0% { -webkit-transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); } }
63 @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }