Cách tự "hack" điều khiển thiết bị điện trong nhà chỉ với 30 phút

Mô tả dự án: 

Một thiết bị điện thông minh hiện đại là phải "có thể lập trình được" để có thể làm theo ý mình. Với cuộc cách mạng công nghiệp 4.0, những sản phẩm IoT hiện này đã rất phổ biến. Những ý tưởng tưởng chừng như "điên rồ" trước đây thì nay đã trở thành hiện thực. Hãy cùng tôi "hack" vào cái công tắc điện trong nhà và dùng những tấm thẻ RFID để bật tắt điện trong nhà nhé.

Chúng ta sẽ làm gì hôm nay

Với một mạch iNut - Nút nhấn (1 thiết bị) mình mua từ MySmarthome với chức năng bật tắt và hẹn giờ qua Internet và Wifi nội bộ. Ngoài ra, đây cũng là một thiết bị trong hệ thống iNut Platform. Vì vậy, thiết bị này hỗ trợ REST API và có thể lập trình điều khiển được. Thế là bắt tay ngay vào việc suy nghĩ cho ngày "mùng name" Tết Mậu Tuất 2018 của mình. Và, kịch bản sẽ là:

  • Đưa một thẻ RFID nào đó để bật đèn
  • Một thẻ nữa là để tắt đèn.
  • Với sự góp ý của bạn Nguyễn Bảo Sang, mình thêm một thẻ RFID nữa để đổi trạng thái (Toggle) luôn cái thiết bị đó.

Thế là với 3 thẻ RFID mình sẽ thử điều khiển cái bóng điện của mình.

Các bạn có thể sáng tạo để có thể mở cửa cuốn, mở cửa nhà từ xa nữa nha,... bạn có thể làm tất cả mọi thứ với iNut Platform.

Bạn cần chuẩn bị những gì để bắt đầu

Bạn cần bao lâu để làm bài hướng dẫn này

  • Thời gian lắp mạch iNut vào mạch điện và cài đặt qua App iNut: 10 - 20 phút.
  • Thời gian lắp mạch RFID: 5 - 10 phút.
  • Thời gian lấy địa chỉ RFID từ thẻ RFID: 5 - 10 phút.
  • Sửa chữa code, nạp code vào NodeMCU để điều khiển thử nghiệm: 10 phút.

Vậy, bạn chỉ cần 30 phút là có thể hoàn thành bài hướng dẫn này rồi. Hãy lựa chọn thời điểm thích hợp trong tuần sau Tết để chiến đấu nghen ^_^.

Mắc và cài đặt thiết bị iNut vào mạch điện

Bước 1: Nối điện iNút

Bước 2: Cài đặt mạng (Password: inut12345)

 

Bước 3: Điều khiển thiết bị

Một chạm điều khiển thiết bị

 

Mắc mạch RFID và lấy thông tin 03 thẻ thiết bị

Các bạn hãy mắc mạch như sau vào module RFID và NodeMCU nhé. Bỏ cái đèn LED đi, trong bài này, chúng ta không dùng đến đèn LED này. Các bạn tải về các thư viện còn thiếu (thư viện RFID, thư viện ArduinoJson và thư viện Socket.IO-client) ở đây nhé.

Các bạn nạp code đoạn code sau vào NodeMCU nha: 

 

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

#define RST_PIN         D1          // Chân RST
#define SS_PIN          D2          // Chân SS hoặc một số mạch là SDA

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance

void setup() {
 // delay(5000);
  Serial.begin(9600);   // Khởi tạo serial với baudrate 9600
  
  Serial.println("setup()");
  
  SPI.begin();      //
  Serial.println("Khoi tao SPI");
  mfrc522.PCD_Init();   // Init MFRC522
  Serial.println("Khoi dong module RFID");
  mfrc522.PCD_DumpVersionToSerial();  // In ra thông tin của module (version)
  Serial.println("Luot the RFID de co thong tin");
}

void loop() {
  
  
  // Chờ xem phải thẻ RFID mới ko?
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }

  // Chọn một thẻ
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return;
  }

  unsigned long uidDec = 0;

  // Hien thi so UID cua the
  Serial.print("Card UID: ");
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    unsigned long uidDecTemp = mfrc522.uid.uidByte[i];
    uidDec = uidDec*256+uidDecTemp;
  } 

  Serial.println(uidDec);

  Serial.print("Size: ");
  Serial.println(mfrc522.uid.size);
}

Ví dụ, khi ta để một thẻ RFID lên phía rên module RFID nó hiện ra đoạn mã 3236458659. Số này, chính là mã của thẻ RFID, tùy vào chương trình của bạn mà nó sẽ ra một số khác nhé.

Bạn lặp lại quy trình với 02 thẻ còn lại. Mình có 03 danh sách thẻ RFID như sau:

unsigned long turnOnCardId = 3878428834UL;
unsigned long turnOffCardId = 3071341165UL;
unsigned long toggleCardId = 3236458659UL;

Tại sao lại có chữ UL ở dưới. Vì để đánh dấu đây là hằng số nguyên dương mang kiểu unsigned long.

Nào ta cùng "hack"

Các bạn thay thế giá trị vào các biến:

  • ssid: tên mạng wifi nhà bạn
  • password: mật khẩu nhà bạn
  • turnOnCardId:
  • turnOffCardId
  • toggleCardId
  • nodeJson1mã uuid, node_id, token của thiết bị, bạn có thể xem video hướng dẫn lấy mã này ở ngay video dưới.

//Thư viện để dùng module RFID
#include <SPI.h>
#include <MFRC522.h>

//Thư viện để giải mã chuỗi JSON cho dễ code
#include <ArduinoJson.h>

//Thư viện để dùng kết nối vào Wifi và socket
#include <ESP8266WiFi.h>
#include <SocketIOClient.h>

//Thư viện để tạo http request nhằm điều khiển thiết bị
#include <ESP8266HTTPClient.h>

#define RST_PIN         D1          // Chân RST
#define SS_PIN          D2          // Chân SS hoặc một số mạch là SDA

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance

SocketIOClient client;
const char* ssid = "linksys";          //Tên mạng Wifi mà Socket server của bạn đang kết nối
const char* password = "khanhdeptrai";  //Pass mạng wifi ahihi, anh em rãnh thì share pass cho mình với.
 
char host[] = "socket.mysmarthome.vn";  //Địa chỉ IP dịch vụ, hãy thay đổi nó theo địa chỉ IP Socket server của bạn.
int port = 80;                  //Cổng dịch vụ socket server do chúng ta tạo!

//từ khóa extern: dùng để #include các biến toàn cục ở một số thư viện khác. Trong thư viện SocketIOClient có hai biến toàn cục
// mà chúng ta cần quan tâm đó là
// RID: Tên hàm (tên sự kiện
// Rfull: Danh sách biến (được đóng gói lại là chuối JSON)
extern String RID;
extern String Rfull;

unsigned long turnOnCardId = 3878428834UL;
unsigned long turnOffCardId = 3071341165UL;
unsigned long toggleCardId = 3236458659UL;

//token, uuid, node_id
String nodeJson1 = "{\"node_id\":\"r1O92dtSz\",\"uuid\":\"52JRJHs3jcdqH6pC8R3f130ETnJ3\",\"token\":\"b1baa1421c29e7b6451074024fb3bfaa830715216097\"}";


//hàm đăng ký một node vào socket client
void registerNode(String json) {
  // debug
  StaticJsonBuffer<300> jsonBuffer;
  JsonObject &node = jsonBuffer.parseObject(json.c_str());
  String uuid = node.get<const char *>("uuid");
  String node_id = node.get<const char *>("node_id");
  String token = node.get<const char *>("token");
  Serial.println("Dang ky node: ");
  Serial.print("uuid: ");
  Serial.println(uuid);
  Serial.print("node_id: ");
  Serial.println(node_id);
  Serial.print("token: ");
  Serial.println(token);

  //bước đăngký
  client.send("register_node", json);
}




void setup() {
 // delay(5000);
  Serial.begin(9600);   // Khởi tạo serial với baudrate 9600
  
  Serial.println("setup()");
  
  
  Serial.print("Ket noi vao Wifi: ");
  Serial.println(ssid);
  Serial.print("Mat khau: ");
  Serial.println(password);
  WiFi.begin(ssid, password);
  
  //Chờ đến khi đã được kết nối
  while (WiFi.status() != WL_CONNECTED) { //Thoát ra khỏi vòng 
      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)) {
      Serial.println(F("Ket noi den socket server that bai!"));
      return;
  }

  //Khi đã kết nối thành công
  if (client.connected()) {
      //Thì gửi sự kiện ("connection") đến Socket server ahihi.
      Serial.println("Ket noi thanh cong");
      registerNode(nodeJson1);
  }

  SPI.begin();      //
  Serial.println("Khoi tao SPI");
  mfrc522.PCD_Init();   // Init MFRC522
  Serial.println("Khoi dong module RFID");
  mfrc522.PCD_DumpVersionToSerial();  // In ra thông tin của module (version)
  Serial.println("Luot the RFID de co thong tin");
}

void loop() {
  
  static unsigned long prevUidDec = 0;
  // Chờ xem phải thẻ RFID mới ko?
  if (mfrc522.PICC_IsNewCardPresent()) {
    
    // Chọn một thẻ
    if (mfrc522.PICC_ReadCardSerial()) {
      unsigned long uidDec = 0;
      

      // Hien thi so UID cua the
      
      for (byte i = 0; i < mfrc522.uid.size; i++) {
        unsigned long uidDecTemp = mfrc522.uid.uidByte[i];
        uidDec = uidDec*256+uidDecTemp;
      } 
      if (prevUidDec != uidDec) {
        Serial.print("Card UID: ");
        Serial.println(uidDec);
      
        Serial.print("Size: ");
        Serial.println(mfrc522.uid.size);


        prevUidDec = uidDec;
        if (uidDec == turnOnCardId) {
          sendPostRequestJSONtoINutDevice(nodeJson1, 0, "ON");
        } else if (uidDec == turnOffCardId) {
          sendPostRequestJSONtoINutDevice(nodeJson1, 0, "OFF");
        } else if (uidDec == toggleCardId) {
          sendPostRequestJSONtoINutDevice(nodeJson1, 0, "TOGGLE");
        }
      }
    }
  }

  static unsigned long timer = 0;
  //Sau 3 giây kể từ lần cuối nhận được thẻ thì cho phép dùng lại)
  if (prevUidDec > 0 && millis() - timer > 3000UL) { 
    prevUidDec = 0;
    timer = millis();
  } else if (prevUidDec == 0) {
    timer = millis();
  }

  

  

  //Khi bắt được bất kỳ sự kiện nào thì chúng ta có hai tham số:
  //  +RID: Tên sự kiện
  //  +RFull: Danh sách tham số được nén thành chuỗi JSON!
  if (client.monitor()) {
      Serial.println(RID);
      Serial.println(Rfull);
      if (RID == "please_login") {
        //yêu cầu đăng nhập nên ta sẽ gửi thông tin token, uuid,..., nói chung sau khi đã có lệnh please_login thì ta gửi đăng ký thêm lúc nào cũng được
        registerNode(nodeJson1);
      }
  }

  //Kết nối lại!
  if (!client.connected()) {
    Serial.println("Ket noi lai");
    client.reconnect(host, port);
  }
}

//hàm sinh ra lệnh tắt bật đèn
String getAPIUrl(String json) {
  
  StaticJsonBuffer<300> jsonBuffer;
  JsonObject &node = jsonBuffer.parseObject(json.c_str());
  String uuid = node.get<const char *>("uuid");
  String node_id = node.get<const char *>("node_id");
  String token = node.get<const char *>("token");
  
  String res = "http://connect.mysmarthome.vn/api/1.0/request/";
  res += uuid;
  res += "/";
  res += node_id;
  res += "/";
  res += token;
  return res;
}

//hàm gửi lệnh cho API req_device_toggle
void sendPostRequestJSONtoINutDevice(String json, int id, String command) {
  StaticJsonBuffer<300> JSONbuffer;
  JsonObject& root = JSONbuffer.createObject(); 

  root["id"] = id;
  root["command"] = command.c_str();
  
  char JSONmessageBuffer[300];
  root.prettyPrintTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));
  Serial.println(JSONmessageBuffer);

  HTTPClient http;    //Declare object of class HTTPClient

  http.begin(getAPIUrl(json) + "/req_device_toggle");      //Specify request destination
  http.addHeader("Content-Type", "application/json");  //Specify content-type header

  int httpCode = http.POST(JSONmessageBuffer);   //Send the request
  String payload = http.getString();                                        //Get the response payload

  Serial.println(httpCode);   //Print HTTP return code
  Serial.println(payload);    //Print request response payload

  http.end();  //Close connection
}

Ý tưởng của chương trình trên:

  • Chương trình sẽ kết nối vào Wifi sau đó cài đặt các đoạn code cần thiết để dùng được module RFID-RC522.
  • Sau đó, kết nối vào Socket API của iNut Platform với mục đích là khi có data mới (ví dụ người dùng nhấp trong app hay nhấn ngoài thiết bị iNut thì mình biết được).
  • Sau đó cài đặt chương trình nếu nhận đúng thẻ RFID đã cài đặt thì dùng REST API để điều khiển thiết bi.

Code hết sức là đơn giản luôn. Chúc các bạn thành công!

lên
5 thành viên đã đánh giá bài viết này hữu ích.
Các dự án được truyền cảm hứng

Select any filter and click on Apply to see results

Các bài viết cùng tác giả

Arduino Nano - Nhỏ, tiện lợi, mang trên mình tinh hoa của Arduino Uno

Điều đầu tiên tớ muốn chia sẻ với các bạn khi tiếp xúc với Arduino Nano, đó là sự tiện dụng, đơn giản, có thể lập trình trực tiếp bằng máy tính (như Arduino Uno R3) và đặc biệt hơn cả đó là kích thước của nó. Kích thước của Arduino Nano cực kì nhỏ chỉ tương đương đồng 2 nghìn gấp lại 2 lần thôi, rất thích hợp cho các newbie, vì giá rẻ hơn Arduino Uno nhưng dùng được tất cả các thư việt của mạch này. Hôm nay, tớ viết bài này nhằm mục đích giới thiệu về mạch Arduino Nano và các thông số kĩ thuật, cùng với đó là những gợi ý ứng dụng khi bắt đầu với mạch này.

lên
18 thành viên đã đánh giá bài viết này hữu ích.

Vấn đề của số chấm động và số nguyên trong ngôn ngữ lập trình C++ trên board mạch Arduino

Có bao giờ bạn tự hỏi: "Dự án của mình làm tốt thế này, chạy ngon lành rành rành thế này, chắc không có bugs đâu?". Thực sự, nếu dự án của bạn không có phần xử lý số thực chấm động trong đó thì mình nghĩ phần code của bạn sẽ hoạt động ngon lành theo thời gian. Nhưng mà có số thực thì từ từ, chúng ta cần xét lại code. Trước đây, có một số bạn nhắn tin riêng hỏi mình về code với điểm chung là "code mình chạy ngon lành lúc đầu, sau đó bị lỗi, không rõ nguyên nhân". Loại trừ các phần code logic sai ra, thì hầu hết đều là do lỗi khi xử lý số chấm động mà không quan tâm đến nền tảng lập trình bên dưới! Mà cũng đúng, chúng ta rất dễ bị đánh lừa bởi chính đoạn code chúng ta viết. Vì nó có báo lỗi biên dịch đâu mà, kaka. Qua bài viết này, mình muốn phân tích và cùng các bạn rút kinh nghiệm về số chấm động float, cách hạn chế lỗi sai với số chấm động.

lên
22 thành viên đã đánh giá bài viết này hữu ích.