Bài 7. Kết nối ESP8266 và Arduino qua giao tiếp UART

Kết nối ESP8266 Arduino qua giao tiếp UART để truyền dữ liệu chúng ta có nhiều cách khác nhau. Tuy nhiên để đơn giản Điện thông minh E-smart sẽ hướng dẫn các bạn 2 cách để giúp ta truyền dữ liệu qua giao tiếp uart một cách thuận tiện và nhanh chóng.

Sơ đồ kết nối ESP8266 và Arduino UNO giao tiếp UART

Trong phần này, chúng ta sẽ lấy ví dụ về cách truyền và nhận dữ liệu nhiệt độ và độ ẩm từ kít NodeMCU ESP8266 đến Arduino UNO qua giao tiếp UART.

Để làm được bài giao tiếp uart này bạn cần trang bị các phần cứng sau:

  • NodeMCU ESP8266
  • Arduino UNO
  • Cảm biến DHT11

Sơ đồ kết nối ESP8266 Arduino Uno truyền dữ liệu DHT11 qua giao tiếp uart

Giao tiếp uart trên esp8266 và arduino uno

1. Truyền dữ liệu chuỗi có cấu trúc quy ước qua giao tiếp UART

Đối với cách truyền này chúng ta sẽ truyền được giá trị của nhiều biến khác nhau trong 1 chuỗi dữ liệu truyền đi qua giao tiếp uart. Chúng ta sẽ quy ước thứ tự cho các giá trị cần truyền trong chuỗi và thêm ký tự phân cách vào giữa các giá trị đó. Khi nhận dữ liệu ta cần sử dụng hàm tách chuỗi dữ liệu theo ký tự phân cách để lấy các giá trị ở vị trí tương ứng.

Ví dụ: bạn muốn truyền giá trị nhiệt độ (32.5) và độ ẩm (73.2) từ ESP8266 qua Arduino Uno dùng giao tiếp uart thì ta quy ước truyền với dạng chuỗi là “32.5;73.2” hai giá trị này phân cách bởi ký tự “;” lúc này bên Arduino Uno nhận được chuỗi và sẽ dùng hàm tách chuỗi dựa vào ký tự “;” để lấy được giá trị nhiệt độ và độ ẩm bên ESP8266 truyền qua.

Hàm tách chuỗi dữ liệu theo ký tự phân cách

String getValue(String data, char separator, int index){
  int found = 0;
  int strIndex[] = { 0, -1 };
  int maxIndex = data.length() - 1;

  for (int i = 0; i <= maxIndex && found <= index; i++) {
      if (data.charAt(i) == separator || i == maxIndex) {
          found++;
          strIndex[0] = strIndex[1] + 1;
          strIndex[1] = (i == maxIndex) ? i+1 : i;
      }
  }
  return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

Truyền Data từ ESP8266 qua Arduino UNO qua giao tiếp UART

Code mẫu nạp cho Nodemcu ESP8266

#include <DHTesp.h> // Thư viện cho cảm biến DHT11
#include <SoftwareSerial.h> // Thư viện cho EspSoftwareSerial

#define DHTPIN D0 // Chân kết nối với cảm biến
#define RX_PIN 4 // Chân RX của EspSoftwareSerial
#define TX_PIN 5 // Chân TX của EspSoftwareSerial

DHTesp dht; // Tạo một đối tượng DHT
SoftwareSerial mySerial(RX_PIN, TX_PIN); // Tạo một đối tượng EspSoftwareSerial

void setup() {
  Serial.begin(9600); // Khởi tạo cổng nối tiếp cứng với tốc độ baud là 9600
  mySerial.begin(9600); // Khởi tạo cổng nối tiếp mềm với tốc độ baud là 9600
  dht.setup(DHTPIN, DHTesp::DHT11); // Khởi tạo cảm biến
}

void loop() {
  delay(2000); // Đợi 2 giây

  TempAndHumidity th = dht.getTempAndHumidity(); // Đọc độ ẩm và nhiệt độ

  if (dht.getStatus() != DHTesp::ERROR_NONE) { // Kiểm tra xem có lỗi không
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  //Thiết lập Data gửi đi dạng: "35.6;71.2" 2 giá trị phân cách bởi ';'
  String Data = String(th.temperature,1) + ";" + String(th.humidity,1);
  mySerial.println(Data); //Gửi giá trị nhiệt độ và độ ẩm qua Software serial
  Serial.println(Data); //In ra Serial Monitor chuỗi gửi đi
}

Trong code chương trình này chúng ta sẽ sử dụng giao tiếp uart Software Serial trên ESP8266 để truyền chuỗi Data nhiệt độ và độ ẩm đến Arduino UNO sử dụng hai chân D1 D2.

Code mẫu nạp Arduino UNO

#include <SoftwareSerial.h> // Thư viện cho cổng nối tiếp mềm

#define RX_PIN 10 // Chân RX của cổng nối tiếp mềm
#define TX_PIN 11 // Chân TX của cổng nối tiếp mềm

SoftwareSerial mySerial(RX_PIN, TX_PIN); // Tạo một đối tượng cổng nối tiếp mềm

// Hàm tách chuỗi dữ liệu theo ký tự phân cách và trả về phần tử thứ index
String getValue(String data, char separator, int index){
  int found = 0;
  int strIndex[] = { 0, -1 };
  int maxIndex = data.length() - 1;

  for (int i = 0; i <= maxIndex && found <= index; i++) {
      if (data.charAt(i) == separator || i == maxIndex) {
          found++;
          strIndex[0] = strIndex[1] + 1;
          strIndex[1] = (i == maxIndex) ? i+1 : i;
      }
  }
  return found > index ? data.substring(strIndex[0], strIndex[1]) : "";
}

void setup() {
  Serial.begin(9600); // Khởi tạo cổng nối tiếp cứng với tốc độ baud là 9600
  mySerial.begin(9600); // Khởi tạo cổng nối tiếp mềm với tốc độ baud là 9600
}

void loop() {
  if (mySerial.available()) { // Nếu có dữ liệu từ cổng nối tiếp mềm
    String data = mySerial.readString(); // Đọc chuỗi dữ liệu
    Serial.println(data); // In ra chuỗi dữ liệu
    String value1 = getValue(data, ';', 0); // Tách phần tử thứ 0 theo ký tự phân cách ';'
    String value2 = getValue(data, ';', 1); // Tách phần tử thứ 1 theo ký tự phân cách ';'
    Serial.println("Temperature:"+value1); // In ra phần tử thứ 0
    Serial.println("Humidity:"+value2); // In ra phần tử thứ 1
  }
}

Khi Arduino UNO nhận được chuỗi Data từ ESP8266 truyền đến qua giao tiếp uart ở hai chân 1011 thì nó sẽ dùng hàm tách dữ liệu dựa vào ký tự phân cách “;”. Giá trị tại vị trí index0 chính là giá trị nhiệt độ, giá trị tại vị trí index1 là giá trị độ ẩm.

2. Truyền dữ liệu chuỗi định dạng Json qua giao tiếp UART

JSON là gì?

JSON là viết tắt của JavaScript Object Notation, là một định dạng dữ liệu dựa trên văn bản, thường được sử dụng để trao đổi dữ liệu giữa các ứng dụng web và máy chủ. JSON có cấu trúc dạng chuỗi, bao gồm các cặp tên/giá trị (name/value) hoặc các mảng (array) của các giá trị. JSON có thể biểu diễn các kiểu dữ liệu cơ bản như số, chuỗi, boolean, null, cũng như các kiểu dữ liệu phức tạp như đối tượng (object) và mảng (array).

Để sử dụng cấu trúc dữ liệu dạng chuỗi JSON trên Arduino IDE, bạn cần tuân theo các quy tắc sau:

  • Một chuỗi JSON phải được bao quanh bởi dấu ngoặc kép (” “).
  • Một cặp tên giá trị phải được ngăn cách bởi dấu hai chấm (:).
  • Các cặp tên giá trị phải được ngăn cách bởi dấu phẩy (,).
  • Một đối tượng JSON phải được bao quanh bởi dấu ngoặc nhọn ({ }).
  • Một mảng JSON phải được bao quanh bởi dấu ngoặc vuông ([ ]).

Ví dụ: Đây là một chuỗi JSON biểu diễn một đối tượng có hai thuộc tính: temperature humidity.

{
  "temperature": 25.6,
  "humidity": 45.3
}

Sử dụng chuỗi JSON trên Arduino IDE

Để sử dụng chuỗi JSON trong Arduino IDE, bạn cần sử dụng thư viện ArduinoJson để phân tích (parse) hoặc tạo ra (generate) chuỗi JSON. Bạn có thể tải thư viện này từ Trình quản lý thư viện của Arduino IDE hoặc từ trang web chính thức của thư viện: https://arduinojson.org/. Thư viện này cung cấp các hàm và lớp để làm việc với các đối tượng và mảng JSON.

Giáo tiếp esp8266 với arduino qua uart

Code mẫu cho NodeMCU ESP8266

Trong code này chúng ta sử dụng chân D0 đọc dữ liệu từ DHT11 và gửi data từ ESP8266 qua Arduino UNO dùng giao tiếp uart SoftwareSerial

// Khai báo các thư viện cần thiết
#include <ArduinoJson.h>
#include <DHTesp.h>
#include <SoftwareSerial.h>

// Định nghĩa kiểu cảm biến DHT là DHT11 và số chân GPIO kết nối với cảm biến là 16
#define DHTTYPE DHTesp::DHT11
#define DHTPIN 16

// Tạo một đối tượng DHT để làm việc với cảm biến
DHTesp dht;

// Tạo một đối tượng JsonDocument có dung lượng 100 byte
StaticJsonDocument<100> doc;

#define RX_PIN 4 // Chân RX của EspSoftwareSerial
#define TX_PIN 5 // Chân TX của EspSoftwareSerial
// Tạo một đối tượng SoftwareSerial
SoftwareSerial mySerial(RX_PIN , TX_PIN ); // RX, TX

void setup() {
  // Khởi tạo giao tiếp nối tiếp với tốc độ baud là 9600
  Serial.begin(9600);
  // Khởi tạo cảm biến DHT
  dht.setup(DHTPIN, DHTTYPE);
  // Khởi tạo cổng nối tiếp ảo
  mySerial.begin(9600);
}

void loop() {
  // Đọc giá trị nhiệt độ và độ ẩm từ cảm biến
  float temperature = dht.getTemperature();
  float humidity = dht.getHumidity();

  // Kiểm tra xem các giá trị có hợp lệ hay không
  if (isnan(temperature) || isnan(humidity)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Gán giá trị nhiệt độ và độ ẩm vào đối tượng JsonDocument
  doc["temperature"] = temperature;
  doc["humidity"] = humidity;

  // Chuyển đổi đối tượng JsonDocument thành chuỗi JSON và gửi nó qua cổng nối tiếp ảo
  serializeJson(doc, mySerial);
  mySerial.println();

  // Chuyển đổi đối tượng JsonDocument thành chuỗi JSON và gửi nó qua cổng nối tiếp thật
  serializeJson(doc, Serial);
  Serial.println();

  // Đợi một giây
  delay(1000);
}

Code mẫu cho Arduino UNO

Chúng ta sử dụng giao tiếp uart SoftwareSerial trên Arduino UNO để nhận dữ liệu từ ESP8266

// Khai báo thư viện cần thiết
#include <ArduinoJson.h>

// Khai báo thư viện SoftwareSerial
#include <SoftwareSerial.h>

#define RX_PIN 10 // Chân RX của cổng nối tiếp mềm
#define TX_PIN 11 // Chân TX của cổng nối tiếp mềm

SoftwareSerial mySerial(RX_PIN, TX_PIN); // Tạo một đối tượng cổng nối tiếp mềm

// Tạo một đối tượng JsonDocument có dung lượng 100 byte
StaticJsonDocument<100> doc;

void setup() {
  // Khởi tạo giao tiếp nối tiếp với tốc độ baud là 9600
  Serial.begin(9600);
  // Khởi tạo cổng nối tiếp ảo
  mySerial.begin(9600);
}

void loop() {
  // Kiểm tra xem có dữ liệu nào sẵn sàng trên cổng nối tiếp ảo hay không
  if (mySerial.available()) {
    // Đọc một dòng từ cổng nối tiếp ảo
    String line = mySerial.readStringUntil('\n');

    // Chuyển đổi chuỗi JSON thành đối tượng JsonDocument
    DeserializationError error = deserializeJson(doc, line);

    // Kiểm tra xem có lỗi nào trong quá trình chuyển đổi hay không
    if (error) {
      Serial.print("deserializeJson() failed: ");
      Serial.println(error.c_str());
      return;
    }

    // Lấy giá trị nhiệt độ và độ ẩm từ đối tượng JsonDocument
    float temperature = doc["temperature"];
    float humidity = doc["humidity"];

    // In các giá trị ra màn hình nối tiếp
    Serial.print("Temperature: ");
    Serial.print(temperature);
    Serial.println(" C");
    Serial.print("Humidity: ");
    Serial.print(humidity);
    Serial.println(" %");
  }
}

Đây là cách sử dụng cấu trúc dữ liệu dạng chuỗi JSON trên Arduino IDE để truyền và nhận nhiều dữ liệu khác nhau qua giao tiếp UART giữa ESP8266 Arduino UNO. Bạn có thể tham khảo thêm các ví dụ và tài liệu của thư viện ArduinoJson tại https://arduinojson.org/.

Kết luận

Như vậy qua bài viết này chúng ta có thể vận dụng 2 cách này để có thể truyền nhận nhiều dữ liệu khác nhau giữa ESP8266 Arduino UNO qua giao tiếp UART. Nếu dữ liệu truyền có ít giá trị và không đòi hỏi độ chính xác cao thì ta dùng cách 1, ngược lại nếu dữ liệu có nhiều giá trị và cần độ chính xác thì ta dùng cách 2.

5/5 - (10 bình chọn)

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Chiêu sinh khóa Lập trình ESP32 căn bản, lớp (20h-21h30) 3-5-7 ngày 19/11/2024. Học phí 1tr/khóa (20 buổi). Đăng ký qua zalo: 0919.890.938

X
Contact Me on Zalo