Hướng dẫn chi tiết cách tạo server và điều khiển Arduino cho dự án IoT

Internet of Things - Iot đang dần phổ biến, nhưng số lượng bài viết hoàn thiện khá ít. Mình từng gặp vấn đề này, bỏ nhiều thời gian nghiên cứu và đã thành công.

Câu hỏi đầu tiên của các bạn khi muốn làm IoT là bắt đầu từ đâu? Khó phải không. Bài viết này mình sẽ đi từ bước đầu tiên (tạo server) tới bước cuối cùng (điều khiển arduino) nhé. Ưu điểm của tạo webserver là bạn có thể điều khiển arduino từ bất cứ đâu có internet, 3G (so với cách tạo local server của ESP8266)

Bố cục bài viết bao gồm: Tạo server -> Viết code php đơn giản để nhận lệnh -> ứng dụng android gửi lệnh lên server -> Lập trình arduino với command line đọc lệnh từ server và đổi trạng thái led.

1. Tạo server

Đây là bước quan trọng nhất. Mình tốn khá nhiều thời gian để tìm server nào miễn phí và hỗ trợ php. Rất may đã tìm được.

Đầu tiên bạn vào trang này nhé https://www.000webhost.com/

Nhấn vào Free Signup. Nhập thông tin Tên, Email, Mật Khẩu, nhớ chọn phần Free Subdomain, nhập tên trang web mình mong muốn. Ví dụ như hình mình chọn luutruthongtin, thì sau này webserver của mình sẽ có dạng luutruthongtin.net16.net (ngày xưa mình tạo nó cho chọn số thoải mái ko phải 16)

Sau khi xác nhận email, chờ khoảng 30 phút trạng thái tài khoản sẽ được chuyển thành active. Bắt đầu code thôi heart

Nhấn vào Go to CPanel, tìm File Manager 2. Trong cửa sổ hiện lên, mở folder public_html. Đây là nơi ta lập trình php.

Ra ngoài desktop, tạo 1 file text bất kỳ, dán đoạn code này vào

<?php
  $var2 = $_GET['State'];   //Tên biến State
  $fileContent = $var2;
  file_put_contents("data.html", $fileContent); //Lưu giá trị của biến State vào file data.html
?>

Lưu lại với tên bất kỳ bạn muốn. Trong trường hợp của mình là ReceiveData.php

Quay lại server, bên góc trái trên cùng nhấn Upload file, chọn file của mình rồi OK. Đến đây xong bước 1 rồi đó.

Nếu bạn nào thấy khó có thể bỏ qua bước này, mình đã tạo sẵn server, bạn chỉ cần gửi lệnh lên http://luutruthongtin.net46.net/ReceiveData.php , rồi dán địa chỉ http://luutruthongtin.net46.net/report.php để xem kết quả. Biến là State

2. Gửi lệnh điều khiển Arduino lên server

Có 2 cách để gửi dữ liệu.

  • Cách 1: Viết thêm 1 file php khác tạo textbox, nhập lệnh rồi nhấn gửi (mình đề cập sau vì hơi phức tạp với những bạn chưa quen php)
  • Cách 2: Đơn giản hơn. Bạn tải ứng dụng Android mình làm sẵn trên Play Store

https://play.google.com/store/apps/details?id=com.pub.home.data2server&hl=vi

Cách sử dụng

Hỗ trợ điều khiển 9 thiết bị. Nhấn vào menu bên phải như trên hình để vào thiết lập

Các bạn nhập như trong hình (Chức năng Various Settings)

  • Web address: Địa chỉ webserver mới tạo (lưu ý không có http://)
  • Ping web address: Chức năng phụ, nhập địa chỉ webserver của bạn để chương trình kiểm tra xem còn kết nối không.
  • Check connection time interval: Thời gian lặp lại kiểm tra (Dành cho ping địa chỉ)

Save Settings để lưu lại.

Chức năng Button settings

Dùng để đặt tên thiết bị, lệnh gửi đi khi nhấn ON và OFF. Các bạn lưu ý biến State tương ứng với file php mình viết ở trên.

Save Settings để lưu lại.

Thoát ra màn hình chính, nhấn vào icon mình vừa đổi tên để gửi lệnh. Màu icon sẽ đổi theo lệnh vừa gửi ON/OFF

Đối với các bạn muốn test thử trước khi làm, chỉ cần tải ứng dụng của mình về, thiết lập y như trên hình, nhấn Light, sau đó mở Chrome/Firefox/IE lên nhập địa chỉ http://luutruthongtin.net46.net/report.php sẽ thấy thay đổi tương ứng (Sau khi nhấn thì refresh lại trang web sẽ nhìn thấy)

3. Code Arduino

Đoạn code dưới đây mình đã test nhiều lần, có thể tự reset chip ESP8266 khi bị lỗi. Sơ đồ chân cẳng như sau (Arduino Pro Mini)

Arduino ESP8266
2 RX
3 TX
7 CN_PD
3v3 VCC
GND GND

Các bạn thay đổi tên wifi, mật khẩu, tên webserver, tên html theo ý mình nhé. Đoạn code lấy đèn LED 13 của Arduino Pro Mini để hiển thị trạng thái ON/OFF luôn cho tiện laugh

#include <SoftwareSerial.h>
SoftwareSerial esp(2, 3); // RX | TX

#define BUFFER_SIZE 512
#define GET_SIZE 64
#define CH_PH 7

char OKrn[] = "OK\r\n"; 
char buffer[BUFFER_SIZE];
char get_s[GET_SIZE];
boolean start = false;  //Signal Start
boolean run = false;   //Run loop check internet
boolean conn = false; //Allow connection
String response;    
 
byte wait(int timeout, char* term=OKrn) {
  unsigned long t=millis();
  bool found=false;
  int i=0;
  int len=strlen(term);
  // wait for at most timeout milliseconds
  // or if OK\r\n is found
  while(millis()<t+timeout) {
    if(esp.available()) {
      buffer[i++]=esp.read();
      if(i>=len) {
        if(strncmp(buffer+i-len, term, len)==0) {
          found=true;
          break;
        }
      }
    }
  }
  
  buffer[i]=0;
  response.concat(buffer);
  Serial.print(buffer);
  return found;
}

void setup() 
{
    pinMode(CH_PH, OUTPUT);
    pinMode(13, OUTPUT);
    Serial.begin(9600);     while (!Serial)   { ; }
 
    esp.begin(9600); 
    Serial.println("Ready");
    Serial.println("");
    start = true;
}
 
void loop() 
{
  if(start){
    start = false;
    run = true;
    reset();   delay(1000);
    esp.println("AT+CWMODE=3");    wait(1000);   CheckESPResponse();
    esp.println("AT+CWJAP=\"password\",\"ten_wifi\"");    wait(5000); CheckESPResponse();
    
  }
  if(run){  getData();  delay(5000);}
}

void reset(){
  digitalWrite(CH_PH, LOW); 
  digitalWrite(13, HIGH);
  Serial.print("Reset Module.");  delay(500);
  Serial.print(".");              delay(500);
  digitalWrite(CH_PH, HIGH);         delay(1000);
  digitalWrite(13, LOW);
  wait(2000);     delay(2000);
  Serial.println(". Ready"); 
}

void CheckESPResponse(){
  if(response.indexOf("200 OK") >= 0) {conn = true;  Serial.println("connect ok");}
  else if (response.indexOf("SEND OK") >= 0){response = "";  Serial.println("send OK");}
  else if(response.indexOf("ERROR") >= 0){esp.print("AT+CIPCLOSE=0"); wait(1000); conn = false;   response = ""; run = false;  start = true;}
  else if(response.indexOf("OK") >= 0){response = ""; Serial.println("ok");}
}

void getData(){
    esp.println("AT+CIPMUX=1");    wait(3000);  CheckESPResponse();
    String data = "GET /data.html HTTP/1.1\r\nHost: www.luutruthongtin.net46.net\r\n\r\n";
    esp.println("AT+CIPSTART=0,\"TCP\",\"www.luutruthongtin.net46.net\",80\"");    wait(4000); CheckESPResponse(); 
    esp.print("AT+CIPSEND=0,");  
    esp.println(data.length());  wait(2000);  
    esp.print(data); 
    wait(5000);
    CheckESPResponse();
    wait(1000);
    wait(1000);   
    wait(1000);
    wait(1000);
    wait(1000);
    CheckESPResponse();
    delay(1500);
    if(conn){ //Lấy chuỗi
      int index = response.indexOf('<');
      String command = response.substring(index-1, index);
      Serial.println(command);
      if(command == "1")   digitalWrite(13, HIGH);
      else if(command = "0")  digitalWrite(13, LOW);
      esp.print("AT+CIPCLOSE=0"); wait(1000);wait(1000);
      response = "";
    }
}
/*
void SerialEvent(){
  while(Serial.available()){
    char inChar = Serial.read(); 
    if(inChar=='s'){  start = true;  Serial.println("Start!");}
    if(inChar=='t'){  start = false; Serial.println("Stop!"); run = false;}
  }
}*/

Cảm ơn các bạn đã quan tâm

Có gì thắc mắc xin gửi tin nhắn đến kysiphieulang hoặc comment bên dưới!

lên
28 thành viên đã đánh giá bài viết này hữu ích.
Từ khóa: 
Chuyên mục: 
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ả

[Phần 2] Lập trình trực tiếp trên ESP8266 Bật/Tắt LED

Bài trước mình có giới thiệu cách đọc dữ liệu từ server để điều khiển. Đó là dùng AT command của ESP. Ưu điểm của nó là dễ lập trình, nhưng thời gian phản hồi rất chậm, thường xuyên bị lỗi.

Theo yêu cầu của 1 số bạn muốn tạo giao diện web điều khiển bật tắt led, hôm nay mình làm tiếp Phần 2 - hướng dẫn lập trình trực tiếp trên ESP8266 để tăng tính ổn định, kết hợp tạo giao diện web mức độ cơ bản.

lên
18 thành viên đã đánh giá bài viết này hữu ích.
Từ khóa: