Hotline/Zalo: 0919.890.938 (Mr Hơn)
Bài 3. Giao tiếp UART trên ESP32
Giao tiếp UART trên ESP32 là một chuẩn giao tiếp nối tiếp đơn giản và phổ biến, được sử dụng rộng rãi trong các hệ thống nhúng. UART cho phép các thiết bị điện tử khác nhau trao đổi dữ liệu với nhau một cách hiệu quả.
Bài viết này Điện thông minh E-smart sẽ hướng dẫn bạn từng bước cách sử dụng giao tiếp UART trên ESP32, từ việc thiết lập môi trường làm việc cho đến việc xây dựng các ứng dụng thực tế.
Giao tiếp UART là gì?
Giao tiếp UART (Universal Asynchronous Receiver-Transmitter) là một giao thức truyền thông nối tiếp không đồng bộ. Nó được sử dụng để truyền dữ liệu giữa các thiết bị điện tử như vi điều khiển, cảm biến, và module truyền thông.
Cách thức hoạt động:
- UART sử dụng hai dây chính: một dây để truyền dữ liệu (Tx) và một dây để nhận dữ liệu (Rx).
- Dữ liệu được truyền từng bit một, không cần tín hiệu đồng hồ để đồng bộ hóa.
- Mỗi gói dữ liệu bao gồm một bit bắt đầu, các bit dữ liệu, và một hoặc hai bit dừng
Ưu điểm:
- Đơn giản và dễ triển khai.
- Chỉ cần hai dây để truyền và nhận dữ liệu.
Nhược điểm:
- Tốc độ truyền dữ liệu không cao.
- Không phù hợp cho các ứng dụng yêu cầu đồng bộ hóa chính xác
Khi sử dụng giao tiếp UART, bạn cần lưu ý một số điểm sau:
- Tốc độ Baud: Đảm bảo cả hai thiết bị giao tiếp có cùng tốc độ baud (baud rate). Nếu không, dữ liệu sẽ bị lỗi hoặc không thể truyền được.
- Kết nối đúng chân: Chân Tx của thiết bị này phải kết nối với chân Rx của thiết bị kia và ngược lại.
- Điện áp: Đảm bảo các thiết bị có cùng mức điện áp logic. Ví dụ, nếu một thiết bị hoạt động ở 3.3V và thiết bị kia ở 5V, bạn cần sử dụng bộ chuyển đổi mức điện áp.
- Ground chung: Các thiết bị phải có chung một điểm ground để đảm bảo tín hiệu truyền thông ổn định.
- Kiểm tra lỗi: Sử dụng các bit kiểm tra lỗi (parity bit) nếu cần thiết để phát hiện và sửa lỗi trong quá trình truyền dữ liệu.
- Buffer: Kiểm tra và quản lý buffer để tránh tình trạng tràn bộ đệm (buffer overflow), đặc biệt khi truyền dữ liệu lớn.
- Khoảng cách: UART không thích hợp cho truyền thông khoảng cách xa. Nếu cần truyền dữ liệu xa, hãy xem xét các giao thức khác như RS-485.
Giao tiếp UART trên ESP32
- Kết nối truyền nhận dữ liệu với PC
- Truyền nhận dữ liệu với vi điều khiển khác
- Kết nối truyền nhận dữ liệu với module hỗ trợ chuẩn giao tiếp UART
Thiết lập giao tiếp UART trên ESP32
Các bước thiết lập giao tiếp UART trên ESP32 khi dùng Arduino IDE
- Khởi tạo UART:
Serial.begin(baudRate)
: Khởi tạo UART0.Serial2.begin(baudRate)
: Khởi tạo UART2.Serial2.begin(baudRate, config, rxPin, txPin)
: Khởi tạo UART2 với chân RX/TX xác định.
- Gửi dữ liệu:
Serial.print(data)
: Gửi dữ liệu qua UART0.Serial.println(data)
: Gửi dữ liệu kèm theo ký tự xuống dòng qua UART0.
- Nhận dữ liệu:
Serial.available()
: Kiểm tra xem có dữ liệu đến qua UART0 hay không.Serial.read()
: Đọc một byte dữ liệu từ UART0.Serial.readString()
: Đọc một chuỗi dữ liệu từ UART0.
Có hai cách để dùng giao tiếp UART trên ESP32:
Giao tiếp UART cứng
Sử dụng UART cứng qua hai chân Rx0 và Tx0, lưu ý đây cũng là hai dùng để nạp chương trình cho ESP32. Có thể sử dụng hai chân Rx2 và Tx2 để giao tiếp UART.
Ví dụ: khởi tạo truyền và nhận dữ liệu giữa ESP32 với PC
void setup() {
// Khởi động giao tiếp Serial với tốc độ baud 115200
Serial.begin(115200);
// In ra dòng chữ "Hello PC!" để xác nhận kết nối
Serial.println("Hello PC!");
}
void loop() {
// Kiểm tra xem có dữ liệu nào được gửi đến từ Serial không
if(Serial.available() > 0) {
// Đọc toàn bộ chuỗi dữ liệu từ Serial
String data = Serial.readString();
// In ra dữ liệu nhận được từ ESP32
Serial.println("Data from ESP32: " + data);
}
}
Giao tiếp UART mềm
Giao tiếp UART mềm bằng cách sử dụng thư viện SoftwareSerial, khi dùng cách này chúng ta sẽ khai báo hai chân bất kỳ làm chức năng Rx và Tx
Ví dụ: khởi tạo truyền và nhận dữ liệu giữa ESP32 và module SIM với PC
#include <SoftwareSerial.h> // Thư viện để sử dụng Serial mềm
#define rxPin 16 // Định nghĩa chân Rx của ESP32
#define txPin 17 // Định nghĩa chân Tx của ESP32
// Khởi tạo đối tượng Serial mềm với chân Rx và Tx đã định nghĩa
SoftwareSerial mySerial(rxPin, txPin);
void setup() {
// Khởi động giao tiếp Serial với tốc độ baud 115200
Serial.begin(115200);
// Khởi động giao tiếp Serial mềm với tốc độ baud 115200
mySerial.begin(115200);
}
void loop() {
// Kiểm tra xem có dữ liệu nào được gửi đến từ Serial không
while (Serial.available()) {
// Đọc một ký tự từ Serial
char temp = char(Serial.read());
// In ký tự đó ra Serial Monitor
Serial.print(temp);
// Gửi ký tự đó qua Serial mềm
mySerial.write(temp);
}
// Kiểm tra xem có dữ liệu nào được gửi đến từ Serial mềm không
while (mySerial.available()) {
// Đọc và in dữ liệu nhận được từ Serial mềm ra Serial Monitor
Serial.write(mySerial.read());
}
}
Cách truyền nhận dữ liệu qua UART
1. Truyền dữ liệu chuỗi có cấu trúc quy ước
Để truyền nhiều giá trị qua giao tiếp UART, bạn có thể gộp các giá trị vào một chuỗi và sử dụng ký tự phân cách. Khi nhận dữ liệu, bạn tách chuỗi theo ký tự phân cách để lấy các giá trị.
Ví dụ: Truyền giá trị nhiệt độ (32.5) và độ ẩm (73.2) từ ESP32 qua Arduino Uno dưới dạng chuỗi “32.5;73.2”. Arduino Uno sẽ tách chuỗi này theo ký tự “;” để lấy giá trị nhiệt độ và độ ẩm.
Code mẫu trên ESP32:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(16, 17); // RX, TX
void setup() {
Serial.begin(115200);
mySerial.begin(9600);
}
void loop() {
float temperature = 32.5;
float humidity = 73.2;
// Tạo chuỗi dữ liệu với ký tự phân tách
String dataString = String(temperature) + ";" + String(humidity);
// Gửi chuỗi dữ liệu qua UART
mySerial.println(dataString);
delay(1000); // Gửi mỗi giây
}
Code mẫu trên Arduino UNO:
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
void setup() {
Serial.begin(115200);
mySerial.begin(9600);
}
void loop() {
if (mySerial.available()) {
String dataString = mySerial.readString();
// Tách chuỗi dữ liệu theo ký tự phân tách
int separatorIndex = dataString.indexOf(';');
float temperature = dataString.substring(0, separatorIndex).toFloat();
float humidity = dataString.substring(separatorIndex + 1).toFloat();
// Hiển thị giá trị nhiệt độ và độ ẩm lên Serial Monitor
Serial.print("Temperature: ");
Serial.println(temperature);
Serial.print("Humidity: ");
Serial.println(humidity);
}
}
2. Truyền dữ liệu chuỗi định dạng Json
Để truyền nhiều giá trị qua giao tiếp UART, bạn có thể sử dụng chuỗi JSON để gộp các giá trị lại với nhau. JSON giúp dữ liệu có cấu trúc rõ ràng và dễ dàng phân tích khi nhận.
Ví dụ: Bạn muốn truyền giá trị nhiệt độ (32.5) và độ ẩm (73.2) từ ESP32 qua Arduino Uno. Bạn có thể tạo một chuỗi JSON như sau: {"temperature":32.5,"humidity":73.2}
. Khi Arduino Uno nhận được chuỗi này, nó sẽ phân tích chuỗi JSON để lấy giá trị nhiệt độ và độ ẩm.
Code mẫu trên ESP32:
#include <ArduinoJson.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(16, 17); // RX, TX
void setup() {
Serial.begin(115200);
mySerial.begin(9600);
}
void loop() {
float temperature = 32.5;
float humidity = 73.2;
// Tạo chuỗi JSON
StaticJsonDocument<200> doc;
doc["temperature"] = temperature;
doc["humidity"] = humidity;
String jsonString;
serializeJson(doc, jsonString);
// Gửi chuỗi JSON qua UART
mySerial.println(jsonString);
delay(1000); // Gửi mỗi giây
}
Code mẫu trên Arduino UNO:
#include <ArduinoJson.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX
void setup() {
Serial.begin(115200);
mySerial.begin(9600);
}
void loop() {
if (mySerial.available()) {
String jsonString = mySerial.readString();
// Phân tích chuỗi JSON
StaticJsonDocument<200> doc;
DeserializationError error = deserializeJson(doc, jsonString);
if (!error) {
float temperature = doc["temperature"];
float humidity = doc["humidity"];
// Hiển thị giá trị nhiệt độ và độ ẩm lên Serial Monitor
Serial.print("Temperature: ");
Serial.println(temperature);
Serial.print("Humidity: ");
Serial.println(humidity);
}
}
}
Kết luận
Giao tiếp UART trên ESP32 là một công cụ hữu ích và linh hoạt để kết nối ESP32 với các thiết bị khác. Với kiến thức cơ bản về UART, bạn có thể xây dựng nhiều dự án IoT thú vị và ứng dụng thực tế.