Báo cáo bài tập lớn môn học Thiết kế hệ nhúng của Viện điện tử viễn thông, trường Đại học Bách Khoa Hà Nội. Đề tài: Thiết kế ứng ứng điều khiển thiết bị điện trong nhà và đọc các dữ liệu cảm biến thông qua môi trường Internet. Các thành phần phần cứng được sử dụng trong đề tài bao gồm: Bo mạch Arduino, ESP8266, Module replay, cảm biến nhiệt độ và độ ẩm DHT11. Thành phần phần mềm bao gồm Server, ứng dụng Android, ứng dụng Web.
TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI VIỆN ĐIỆN TỬ - TRUYỀN THÔNG BÁO CÁO BTL THIẾT KẾ HỆ NHÚNG ĐỀ TÀI: THIẾT KẾ ỨNG DỤNG ĐIỀU KHIỂN THIẾT BỊ VÀ ĐỌC CẢM BIẾN QUA INTERNET Hà Nội, 05/2017 MỤC LỤC MỤC LỤC GIỚI THIỆU VỀ IOT GIỚI THIỆU ỨNG DỤNG MÔI TRƯỜNG THỰC HIỆN 3.1 WebSocket 3.2 NodeJS 3.3 Socket.IO 3.4 Arduino 3.5 ESP8266 THIẾT KẾ SƠ ĐỒ KHỐI 11 TRIỂN KHAI ĐỀ TÀI 12 5.1 Phía Server 12 5.2 Phía Client 17 5.2.1 WebApp 17 5.2.2 AndroidApp 21 5.2.3 ESP8266 32 5.2.4 Arduino 34 TÀI LIỆU THAM KHẢO 39 GIỚI THIỆU VỀ IOT Internet of Thing (IoT) khái niệm đặt Kevin Ashton, kỹ sư người anh đầu lĩnh vực radio-frequency identification (RFID), người đặt móng hệ thống mà cảm biến điện tử khắp nơi kết nốt với giới thông qua Internet Ba thành phần chủ chốt IoT “things”, “Internet” “sự kết nối” chúng Khi mà vạn vật có chung mạng kết nối việc liên lạc làm việc trở nên dễ dàng Con người thực hóa mục đích tương lai Chúng ta hồn tồn kiểm sốt thứ Giả sử hệ thống tưới nước tự động cối gia đình bạn tích hợp cơng nghệ IOT Giúp bạn điều khiển qui trình chăm sóc cây, tưới nước cây, chí bắt sâu bọ,…khi bạn có chuyến cơng tác xa vài ngày hay vài tháng mà thực chức Điều trở nên đơn giải giả sử mà hệ thống tưới tự động điện thoại laptop, PC, bạn kết nối mạng lưới Internet qua trao đổi thông tin thực thi câu lệnh mà bạn mong muốn “Sự kết nối” mà đề cập thành phần quan trọng mạng lưới IoT cảm biến (sensors) Các thiết bị cần kết nối phải tích hợp chip cảm biến để chuyển đổi, phát hiện tượng môi trường tự nhiên biến thành liệu mơi trường Internet để xử lý liệu tiến hành thực thi điều hướng mạng Internet theo cách mà người dùng mong muốn Lấy ví dụ hệ thống tưới nước tự động hệ thống sinh thái phải gắn cảm biến dùng để nhận biết yếu tố như: nhiệt độ, lượng nước, độ ẩm, thời tiết,… Sau chuyển thành liệu liệu sử dụng thiết lập thiết lập chế độ theo mục đích sử dụng Và qui trình kết nối hoạt động môi trường Internet để thông báo tạo giao diện đến người dùng Ứng dụng IoT: Thực khái niệm Internet Of Things đưa vào năm 1999 Khi mà công nghệ Internet bước phát triển Và ngày nay, Internet Of Things khơng vấn đề viễn vông, cụ thể nhiều phát mình, ứng dụng trình làng Khái niệm thiết bị thông minh, tủ lạnh thông minh, tivi thông minh, … sử dụng rỗng rãi thể giới cơng nghệ ngày Các bạn điều khiển tivi điều hướng bàn tay, giọng nói,…bằng công nghệ smart tivi hãng Samsung, máy lạnh tự động điều chỉnh nhiệt độ theo thời tiết,…Hay xe ô tô tích hợp chức chống sốc tự dộng, tự động báo cho người sử dụng lốp xe bị xẹp hay gặp trúng vật cản phía trước khoảng mét chẳng hạn Thậm chí ngơi nhà – nơi sống có định nghĩa nhà thông minh với nhiều ứng dụng công nghệ đại Rất nhiều ứng dụng Internet Of Things công ty công nghệ khai thác vấn đề GIỚI THIỆU ỨNG DỤNG Ứng dụng điều khiển thiết bị đọc cảm biến thông qua mạng internet ứng dụng giúp người dùng điều khiển bật tắt thiết bị điện nhà, đọc giá trị cảm biến nhiệt độ, độ ẩm máy tính điện thoại nơi có kết nối internet Hình 1: Giao diện web ứng dụng Hình 2: Giao diện điện thoại MÔI TRƯỜNG THỰC HIỆN 3.1 WebSocket WebSoket công nghệ hỗ trợ giao tiếp hai chiều client server cách sử dụng TCP socket để tạo kết nối hiệu tốn Mặc dù thiết kế để chuyên sử dụng cho ứng dụng web, lập trình viên đưa chúng vào loại ứng dụng WebSockets xuất HTML5, kỹ thuật Reverse Ajax WebSockets cho phép kênh giao tiếp song song hai chiều hỗ trợ nhiều trình duyệt (Firefox, Google Chrome Safari) Kết nối mở thông qua HTTP request (yêu cầu HTTP), gọi liên kết WebSockets với header đặc biệt Kết nối trì để bạn viết nhận liệu JavaScript bạn sử dụng TCP socket đơn Dữ liệu truyền tải thông qua giao thức HTTP (thường dùng với kĩ thuật Ajax) chứa nhiều liệu không cần thiết phần header Một header request/response HTTP có kích thước khoảng 871 byte, với WebSocket, kích thước byte (sau kết nối) Vậy giả sử bạn làm ứng dụng game tới 10,000 người chơi đăng nhập lúc, giây họ gửi/nhận liệu từ server Hãy so sánh lượng liệu header mà giao thức HTTP WebSocket giây: - HTTP: 871 x 10,000 = 8,710,000 bytes = 69,680,000 bits per second (66Mbps) - WebSocket: x 10,000 = 20,000 bytes = 160,000 bits per second (0.153 Kbps) ❖ Ưu điểm WebSockets cung cấp khả giao tiếp hai chiều mạnh mẽ, có độ trễ thấp dễ xử lý lỗi Khơng cần phải có nhiều kết nối phương pháp Comet long-polling khơng có nhược điểm Comet streaming API dễ sử dụng trực tiếp mà không cần tầng bổ sung nào, so với Comet, thường đòi hỏi thư viện tốt để xử lý kết nối lại, thời gian chờ timeout, Ajax request (yêu cầu Ajax), tin báo nhận dạng truyền tải tùy chọn khác (Ajax long-polling jsonp polling) ❖ Nhược điểm - Nó đặc tả HTML5, nên chưa tất trình duyệt hỗ trợ - Khơng có phạm vi u cầu Do WebSocket TCP socket HTTP request, nên khơng dễ sử dụng dịch vụ có phạm vi-yêu cầu, SessionInViewFilter Hibernate Hibernate framework kinh điển cung cấp lọc xung quanh HTTP request Khi bắt đầu request, thiết lập contest (chứa transaction liên kết JDBC) ràng buộc với luồng request Khi request kết thúc, lọc hủy bỏ contest 3.2 NodeJS Node.js hệ thống thiết kế để viết ứng dụng internet có khả mở rộng, đặc biệt máy chủ web Chương trình viết JavaScript, sử dụng kỹ thật điều khiển theo kiện, nhập/xuất khơng đồng để tối thiểu tổng chi phí tối đại khả mở rộng Node.js bao gồm có V8 JavaScript engine Google, libUV, vài thư viện khác Node.js tạo Ryan Dahl từ năm 2009, phát triển bảo trợ Joyent Mục tiêu ban đầu Dahl làm cho trang web có khả push số ứng dụng web Gmail Sau thử với vài ngôn ngữ Dahl chọn Javascript API Nhập/Xuất khơng đầy đủ Điều cho phép anh định nghĩa quy ước Nhập/Xuất điểu khiển theo kiện, non-blocking Vài môi trường tương tự viết ngôn ngữ khác bao gồm Twisted cho Python, Perl Object Environment cho Perl, libevent cho C EventMachine cho Ruby Khác với hầu hết chương trình Javascript, Nodejs khơng chạy trình duyệt mà chạy Server Node.js sử dụng nhiều chi tiết kỹ thuật CommonJs Nó cung cấp môi trường REPL cho kiểm thử tương tác Node.js ngôn ngữ mới, xây dựng túy javascript Đây điểm lợi Node.js để lập trình web-socket: Thứ nhất: javascript ngơn ngữ lập trình hướng kiện, mà lập trình thời gian thực, cách tiếp cận lập trình kiện cách tiếp cận khôn ngoan Thứ hai: Node.js chạy non-blocking việc hệ thống tạm ngừng để xử lý xong request giúp cho server trả lời client gần tức Thứ ba: lập trình socket u cầu bạn phải xây dựng mơ hình lắng nghe – trả lời từ bên Nói khác đi, vai trò client server phải tương đương nhau, mà client chạy javascript, nên server chạy javascript nữa, việc lập trình dễ dàng thân thiện 3.3 Socket.IO Socket.IO thư viện javascript có mục đích tạo ứng dụng realtime trình duyệt thiết bị di động Việc sử dụng thư viện đơn giản giống server lẫn client Server: tạo đối tượng socket phương thức listen(port) Phương thức chờ đợi yêu cầu kết nối từ client - Client: Kết nối đến server phương thức connect(url,{port: server_port}) - Socket.IO cung cấp event connect, message disconnect Chúng kích hoạt client/server: • connect: tạo kết nối • message: nhận thơng điệp • disconnect: ngắt kết nối Ví dụ: Khai báo cho socket nhận kiện “message” socket.on("message", function(msg){ // console.log("Received: "+ msg); }); Socket.IO gửi nhận event tự tạo với phương thức emit() Hai phía gửi nhận phải biết tên event để thực giao tiếp: Ví dụ: // client gửi dòng message "welcome" lên event "hello" socket.emit("hello", {msg: "welcome"}); // Server nhận kiện event đưa lên socket.on("hello", function (data) { console.log(data);}); 3.4 Arduino Arduino board mạch vi xử lý, nhằm xây dựng ứng dụng tương tác với với môi trường thuận lợi Phần cứng bao gồm board mạch nguồn mở thiết kế tảng vi xử lý AVR Atmel 8bit, ARM Atmel 32bit Những Model trang bị gồm cổng giao tiếp USB, chân đầu vào analog, 14 chân I/O kỹ thuật số tương thích với nhiều board mở rộng khác Nhắc tới dòng mạch Arduino dùng để lập trình, mà người ta thường nói tới dòng Arduino UNO Hiện dòng mạch phát triển tới hệ thứ (R3) Hình 3: Arduino UNO R3 Các cổng vào/ra UNO R3: Arduino UNO có 14 chân digital dùng để đọc xuất tín hiệu Chúng có mức điện áp 0V 5V với dòng vào/ra tối đa chân 40mA Ở chân có điện trở pull-up từ cài đặt vi điều khiển ATmega328 (mặc định điện trở khơng kết nối) • chân Serial: (RX) (TX): dùng để gửi (transmit – TX) nhận (receive – RX) liệu TTL Serial Arduino Uno giao tiếp với thiết bị khác thơng qua chân • Chân PWM (~): 3, 5, 6, 9, 10, 11: cho phép bạn xuất xung PWM với độ phân giải 8bit (giá trị từ → 28-1 tương ứng với 0V → 5V) hàm analogWrite() • Chân giao tiếp SPI: 10 (SS), 11 (MOSI), 12 (MISO), 13 (SCK) Ngồi chức thơng thường, chân dùng để truyền phát liệu giao thức SPI với thiết bị khác • LED 13: Arduino UNO có đèn led màu cam (kí hiệu chữ L) Khi bấm nút Reset, bạn thấy đèn nhấp nháy để báo hiệu Nó nối với chân số 13 Khi chân người dùng sử dụng, LED sáng Arduino UNO có chân analog (A0 → A5) cung cấp độ phân giải tín hiệu 10bit (0 → 210-1) để đọc giá trị điện áp khoảng 0V → 5V 3.5 ESP8266 ESP8266 mạch vi điều khiển giúp điều khiển thiết bị điện tử Điều đặc biệt nó, kết hợp module Wifi tích hợp sẵn bên vi điều khiển Hiện nay, ESP8266 giới nghiên cứu tự động hóa Việt Nam ưa chuộng giá thành rẻ (chỉ Arduino Nano), lại tích hợp sẵn Wifi, nhớ flash 8Mb ESP8266 có nhiều phiên đóng gói theo nhiều cách khác nhau, nhiên lại giống chức khả lập trình Trên thị trường phổ biến ESP8266v1, ESP8266v7 ESP8266v12 Các mạch đóng gói theo nhiều cách khác tên gọi hình ảnh đây: Hình 4: Các phiên ESP8266 status_sw1 = data.getString("decive_1_Status"); status_sw2 = data.getString("decive_2_Status"); status_sw3 = data.getString("decive_3_Status"); status_sw4 = data.getString("decive_4_Status"); } catch (JSONException e) { return; } if (status_sw1 == "1") sw1.setChecked(true); else sw1.setChecked(false); if (status_sw2 == "1") sw2.setChecked(true); else sw2.setChecked(false); if (status_sw3 == "1") sw3.setChecked(true); else sw3.setChecked(false); if (status_sw4 == "1") sw4.setChecked(true); else sw4.setChecked(false); } }); }//end call() }; //end Listener public void btb_UpdateProcess(View v) { mSocket.emit("UPDATE"); Toast.makeText(this, "Dữ liệu cập nhật", Toast.LENGTH_LONG).sh ow(); } //Hàm tạo menu option @Override public boolean onCreateOptionsMenu(Menu menu) { 25 MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.options, menu); return true; } //Xử lý kiện click vao menu @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.voice: promptSpeechInput(); //Toast.makeText(this, "Tính phát triển", Toast.LENG TH_SHORT).show(); return (true); } return super.onOptionsItemSelected(item); } /** * Showing google speech input dialog */ private void promptSpeechInput() { Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault()); intent.putExtra(RecognizerIntent.EXTRA_PROMPT, getString(R.string.speech_prompt)); try { startActivityForResult(intent, REQ_CODE_SPEECH_INPUT); } catch (ActivityNotFoundException a) { Toast.makeText(getApplicationContext(), getString(R.string.speech_not_supported), Toast.LENGTH_SHORT).show(); } } /** * Receiving speech input 26 */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent da ta) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQ_CODE_SPEECH_INPUT: { if (resultCode == RESULT_OK && null != data) { ArrayList result = data getStringArrayListExtra(RecognizerIntent.EXTRA_RE SULTS); test.setText(result.get(0)); } break; } } } MainActivity.xml: 27 31 5.2.3 ESP8266 ESP82266 dùng Arduino IDE để lập trình, ngôn ngữ sử dụng C++: #include #include #include #include SerialCommand sCmd; l Command //Khai báo biến sử dụng thư viện Seria SocketIOClient client; //Khia báo biến client //WiFiClient client; const char* ssid = "Tientran"; kết nối //Tên mạng Wifi mà Socket server const char* password = "tonytran"; kết nối //Pass mạng Wifi mà Socket server //char host[] = "192.168.1.3"; u đưa Internet thay tên miền //Địa IP Socket server, nế //char host[] = "t-home.herokuapp.com"; char host[] = "bk-home.mybluemix.net"; int port = 80; //Cổng dịch vụ tạo Socket server char namespace_esp8266[] = "esp8266"; //Namespace esp8266 /* * Từ khóa extern: dùng để #include biến tồn cục số thư viện khác * Trong thư viện SocketIOClient có hai biến tồn cục mà cần quan tâm là: * RID: Tên hàm (tên kiện) * Rfull: Danh sách biến (được đóng gói lại chuối JSON) */ 32 extern String RID; extern String Rfull; void setup() { Serial.begin(57600); p với Arduino //Bật baudrate mức 57600 để giao tiế delay(10); /* * Bỏ qua việc Debug dùng Serial cho kết nối với Arduino * Serial.print("Ket noi vao mang "); * Serial.println(ssid); */ WiFi.begin(ssid, password); //Kết nối vào mạng Wifi while (WiFi.status() != WL_CONNECTED){ delay(500); //Serial.print('.'); } /* Serial.println(); Serial.println(F("Da ket noi WiFi")); Serial.println(F("Di chi IP cua ESP8266 (Socket Client ESP8266): ")); Serial.println(WiFi.localIP()); */ if (!client.connect(host, port, namespace_esp8266)){ ại kết nối lại //Khi kết nối thất b return; } sCmd.addDefaultHandler(defaultCommand); qua, chuyển xuống hàm defaultCommand //Bắt tất lệnh } void loop() { /* Khi bắt kiện có hai tham số: RID: Tên kiện RFull: Danh sách tham số nén thành chuỗi JSON! */ if(client.monitor()){ 33 //Chuyển kiện xuống cho Arduino thông qua Serial Serial.print(RID); Serial.print('\r'); Serial.print(Rfull); Serial.print('\r'); } //Kết nối lại! if(!client.connected()){ client.reconnect(host, port, namespace_esp8266); } sCmd.readSerial(); } void defaultCommand(String command){ Server //Hàm defaultCommand chuyển liệu lên char *json = sCmd.next(); json //Bắt tất lệnh chuỗi cho vào client.send(command, (String)json); //Gửi chuỗi json cho Socket Server } 5.2.4 Arduino Code cho Arduino viết Arduino IDE, ngôn ngữ dùng C++: #include #include #include /* * Khia báo cho cảm biến DHT11 */ const int DHTPIN = 2; Arduino //Đọc liệu từ DHT11 chân mạch const int DHTTYPE = DHT11; 11 DHT22 //Khai báo loại cảm biến, có loại DHT DHT dht(DHTPIN, DHTTYPE); //Khai báo biến dht dọc nhiệt độ độ ẩm const int TEMP_CONST = 32; const int HUMI_CONST = 80; SerialCommand sCmd; mmand //Khai báo biến sử dụng thư viện Serial Co /* 34 * Khai báo thiết bị điều khiển */ const int decive_1 = 3; //Thiết bị nối vào digital (Điều hòa) const int decive_2 = 4; //Thiết bị nối vào digital const int decive_3 = 5; //Thiết bị nối vào digital const int decive_4 = 6; ) //Thiết bị nối vào digital (Máy hút ẩm void setup(){ Serial.begin(57600); tiếp với esp8266 dht.begin(); //Khởi tạo Serial baudrate 57600 để giao //Khởi tạo cảm biến DHT11 /* * Set chân điều khiển cảm biến thiết bị */ pinMode(decive_1, OUTPUT); //Set decive_1 OUTPUT pinMode(decive_2, OUTPUT); //Set decive_2 OUTPUT pinMode(decive_3, OUTPUT); //Set decive_2 OUTPUT pinMode(decive_4, OUTPUT); //Set decive_2 OUTPUT pinMode(DHTPIN, INPUT); //Set DHTPIN INPUT /* * Bắt lệnh esp8266 truyền tới */ sCmd.addCommand("CONTROL", Control); ực thi hàm Control() //Khi có lệnh CONTROL th sCmd.addCommand("UPDATE", Update_Sensor); c thi hàm Update_Sensor() //Khi có lệnh UPDATE thự } const unsigned long CHU_KY = 60000UL; lặp lại //Cứ sau 2000ms = 2s chu kỳ unsigned long chuky = 0; void loop() { if(millis() - chuky > CHU_KY){ ến DHT11 //Tạo chu kì 30s đọc cảm bi chuky = millis(); Update_Sensor(); Update_decive(); } 35 sCmd.readSerial(); } /* * Hàm Update_Sensor() thực đọc cảm biến truyền cho esp8266 */ void Control(){ char *json = sCmd.next(); ược từ lệnh CONTROL cho vào chuỗi json //Đọc tham số nhận đ StaticJsonBuffer jsonBuffer; chứa tối đa 200 ký tự //Tạo Buffer json có khả JsonObject& root = jsonBuffer.parseObject(json); mang kiểu json //Khai báo biến root int decive_1_Status = root["Status"][0]; ng Status Server //Phần tử thứ mả int decive_2_Status = root["Status"][1]; ng Status Server //Phần tử thứ mả int decive_3_Status = root["Status"][2]; ng Status Server //Phần tử thứ mả int decive_4_Status = root["Status"][3]; ng Status Server //Phần tử thứ mả digitalWrite(decive_1, decive_1_Status); digitalWrite(decive_2, decive_2_Status); digitalWrite(decive_3, decive_3_Status); digitalWrite(decive_4, decive_4_Status); Update_decive(); } void Update_Sensor(){ float h = dht.readHumidity(); //Đọc độ ẩm float t = dht.readTemperature(); //Đọc nhiệt độ //Nếu nhiệt độ độ aame ngưỡng bật thiết bị if(t > TEMP_CONST){ digitalWrite(decive_1, 1); } if(h > HUMI_CONST){ digitalWrite(decive_4, 1); } StaticJsonBuffer jsonBuffer2; //Bộ đệm chứa thông tin cảm biến 36 JsonObject& root2 = jsonBuffer2.createObject(); json root2["Humidity"] = h; root2["Temperature"] = t; //Tạo biến root2 mang kiểu //Đưa thông tin độ ẩm vào chuỗi json root2 //Đưa thông tin nhiệt độ vào chuỗi json root2 /* * Gửi chuỗi json root2 chứa thông tin * nhiệt độ độ ẩm cho esp8266 gửi lên * Server */ Serial.print("SENSOR"); //Gửi tên lệnh Serial.print('\r'); //Gửi \r root2.printTo(Serial); //Gửi chuỗi JSON Serial.print('\r'); //Gửi \r } void Update_decive(){ /* * Lưu trạng thái thiết bị * vào biến root1 kiểu json */ int dev_1 = digitalRead(decive_1); int dev_2 = digitalRead(decive_2); int dev_3 = digitalRead(decive_3); int dev_4 = digitalRead(decive_4); StaticJsonBuffer jsonBuffer1;//Bộ đệm jsonBuffer1 chứa tối đa 200 kýtự JsonObject& root1 = jsonBuffer1.createObject(); //Khai báo biến root1 root1["decive_1_Status"] = dev_1;//Đưa giá trị mảng Status vào chỗi json root1["decive_2_Status"] = dev_2;//root1 với tham số trạng thái root1["decive_3_Status"] = dev_3;//thiết bị tương ứng root1["decive_4_Status"] = dev_4; /* * Tạo mảng chuỗi root1 chứa * giá trị trạng thái thiết bị * gửi cho esp8266 truyền lên Server */ JsonArray& data = root1.createNestedArray("data"); g JSON chứa trạng thái Led data.add(dev_1); //Tạo mảng data tron //Add trạng thái decive vào data 37 data.add(dev_2); data.add(dev_3); data.add(dev_4); //Add trạng thái decive vào data //Add trạng thái decive vào data //Add trạng thái decive vào data /* * Gửi chuỗi json root1 chứa trạng thái * thiết bị mảng data cho esp8266 */ Serial.print("DECIVE"); //Gửi tên lệnh Serial.print('\r'); //Gửi \r root1.printTo(Serial); //Gửi chuỗi JSON Serial.print('\r'); //Gửi \r } 38 TÀI LIỆU THAM KHẢO [1] http://blog.rikkeisoft.com/seminar-gioi-thieu-ve-websocket-va-node-js, truy cập lần cuối ngày 26/5/2017 [2] https://socket.io/#how-to-use, truy cập lần cuối ngày 26/5/2017 [3] http://arduino.vn, truy cập lần cuối ngày 26/5/2017 39 ... công nghệ khai thác vấn đề GIỚI THIỆU ỨNG DỤNG Ứng dụng điều khiển thiết bị đọc cảm biến thông qua mạng internet ứng dụng giúp người dùng điều khiển bật tắt thiết bị điện nhà, đọc giá trị cảm biến. .. class="list-group-item list-group-item-home"> T-Home hệ thống nhà thông h đơn giản với chức cho phép người dùng điều khiển bật tắt thiết bị điện nhà, hiển thị nhiệt độ độ ẩm thông qua mạng internet, ... (0 → 21 0-1 ) để đọc giá trị điện áp khoảng 0V → 5V 3.5 ESP8266 ESP8266 mạch vi điều khiển giúp điều khiển thiết bị điện tử Điều đặc biệt nó, kết hợp module Wifi tích hợp sẵn bên vi điều khiển Hiện