RS485 là gì?
Giao thức RS485 là một tiêu chuẩn cho giao tiếp nối tiếp trên khoảng cách xa. Giao thức này sử dụng tín hiệu vi sai để truyền dữ liệu và hỗ trợ nhiều thiết bị trên một bus duy nhất. Giao thức RS485 được sử dụng rộng rãi trong tự động hóa công nghiệp, tự động hóa tòa nhà và các ứng dụng khác khi nhiều thiết bị cần giao tiếp với nhau.
Truyền thông giữa nhiều ESP32
Để giao tiếp nhiều thiết bị ESP32 bằng giao thức RS485, bạn cần chọn một bộ thu phát RS485. Bộ thu phát RS485 là một thành phần quan trọng chuyển đổi tín hiệu UART sang giao thức RS485. Bạn có thể chọn từ nhiều loại bộ thu phát RS485 có sẵn trên thị trường, chẳng hạn như MAX485, SN75176, v.v. Trong hướng dẫn này, chúng ta sẽ sử dụng bộ chuyển đổi MAX485 TTL sang RS485. Bạn cần kết nối bộ thu phát RS485 với các chân GPIO của ESP32.
MAX485 được sử dụng để giao tiếp giữa master và slave. Tính năng chính của module này là nó có thể giao tiếp trong phạm vi khoảng 1 Kilômét.
Giao tiếp giữa các ESp32 thông qua RS485
Trong dự án ví dụ này, chúng ta sẽ sử dụng ba ESP32. Một cho master và hai cho Slave. Hai nút được kết nối với master, một cho slave một và một cho slave hai. Hai đèn LED được kết nối với slave một và slave hai tương ứng. Khi nhấn nút một, đèn LED 1 sẽ sáng và khi nhấn nút hai, đèn LED 2 sẽ sáng và mỗi slave gửi phản hồi đến master.
Sơ đồ mạch
Kết nối chân
Kết nối giữa ESP32 và MAX485:
ESP32 Pin |
MAX485 Pin |
GPIO 16 (Rx) |
R0 |
GPIO 17 (Tx) |
DI |
GPIO 2 |
DE, RE |
VCC / Vin |
VCC / 5V |
GND |
GND |
Kết nối giữa Master ESP32 và Button:
ESP32 (Master) Pin |
Button |
GPIO 12 |
Button 1 (Control slave 1 LED) |
GPIO 13 |
Button 2 (Control slave 2 LED) |
GND |
Another pin of the Button |
Kết nối giữa Slave ESP32 và LED:
ESP32 (Slave) Pin |
LED |
GPIO 4 (Slave_01) |
Slave 1 LED Anode |
GPIO 4 (Slave_02) |
Slave 2 LED Anode |
GND |
Cathode of both LED |
Code cho Master ESP
ESP32 có đến 3 cổng UART là UART0, UART1 and UART2.
UART |
RX Pin
|
TX Pin
|
UART 0 |
GPIO 3 |
GPIO 1 |
UART 1 |
GPIO 9 |
GPIO 10 |
UART 2 |
GPIO 16 |
GPIO 17 |
Trong bài, chúng ta sẽ dùng UART 2 in our project. Sử dụng thư viện HardwareSerial.h.
#include <Arduino.h> #include <string.h> #include <HardwareSerial.h> HardwareSerial SerialPort(2);
Dòng này để xác định hai số của slave. Các số slave này được gửi đến đường dữ liệu nối tiếp khi số slave khớp với một slave cụ thể thì slave này sẽ phản hồi.
int slave_1_id = 1; int slave_2_id = 2;
Định nghĩa hai nút nhấn. Nút số 1 cho slave 01 và nút số 2 cho slave 02. khi một trong các nút được nhấn, một số slave sẽ được gửi đến đường dữ liệu. Ví dụ, nếu nút 1 được nhấn thì slave_1_id = 1 sẽ được gửi đến cổng nối tiếp và slave 01 sẽ phản hồi. Ngoài ra, định nghĩa một chân Enable để chọn chế độ gửi và nhận dữ liệu.
const int BUTTON_PIN_01 = 12; const int BUTTON_PIN_02 = 13; const int Enable = 2;
Trong chức năng thiết lập, chọn tốc độ bund 115200 theo Serial.begin(115200) cho UART 0 giao tiếp giữa Máy tính và ESP32 chủ. Cùng một bund được chọn theo SerialPort.begin(115200, SERIAL_8N1, 16, 17) cho UART 2 được sử dụng để giao tiếp giữa ESP32 này với ESP32 khác. Đặt chân cho phép làm đầu ra và làm cho nó Thấp. Có hai chế độ của MAX485, một là chế độ truyền và một là chế độ nhận. Để giữ MAX485 ở chế độ truyền, chân DE và RE của MAX485 phải ở chế độ Cao và đối với chế độ nhận, chân DE và RE phải ở chế độ Thấp. Ban đầu, chúng tôi giữ nó ở chế độ nhận. Ngoài ra, kích hoạt kéo lên đầu vào cho nút 1 và nút 2.
void setup() { Serial.begin(115200); SerialPort.begin(115200, SERIAL_8N1, 16, 17); //SerialPort.setTimeout(250); pinMode(Enable, OUTPUT); digitalWrite(Enable, LOW); pinMode(BUTTON_PIN_01, INPUT_PULLUP); pinMode(BUTTON_PIN_02, INPUT_PULLUP); }
Trong hàm vòng lặp khi nút 01 được nhấn, chân enable sẽ lên mức cao để giữ MAX485 ở chế độ truyền vì mục tiêu của chúng ta là truyền một số dữ liệu đến slave. Theo hàm SerialPort.flush(), chúng ta gửi hai hoặc nhiều dữ liệu theo kiểu tuần tự và dữ liệu được nhận theo mẫu cũ nhất trước. Đầu tiên, một số slave được gửi và sau đó là dữ liệu, trong trường hợp này, chúng ta gửi một chuỗi “ON”. Chân enable sẽ xuống mức thấp để giữ Max485 ở chế độ nhận để nhận phản hồi từ slave 01.
void loop() { /* Master Program */ if(digitalRead(BUTTON_PIN_01) == 0){ delay(500); digitalWrite(Enable, HIGH); SerialPort.print(slave_1_id); SerialPort.print("ON"); SerialPort.flush(); digitalWrite(Enable, LOW); //digitalWrite(BUTTON_PIN_01, HIGH); }
Khi chúng ta nhấn nút 02, điều tương tự sẽ xảy ra. Lúc này Slave 2 sẽ phản hồi.
if(digitalRead(BUTTON_PIN_02) == 0){ delay(500); digitalWrite(Enable, HIGH); SerialPort.print(slave_2_id); SerialPort.print("ON"); SerialPort.flush(); digitalWrite(Enable, LOW); }
Cuối cùng, khi slave gửi tin nhắn phản hồi, chúng ta sẽ thấy tin nhắn phản hồi từ slave01 hoặc slave02. SerialPort.available() có nghĩa là UART2 tìm dữ liệu và nếu dữ liệu khả dụng thì in tin nhắn phản hồi trên màn hình nối tiếp của Arduino IDE.
if(SerialPort.available()){ Serial.println(SerialPort.readString()); }
Code đầy đủ cho master ESP32
#include <Arduino.h> #include <string.h> #include <HardwareSerial.h> HardwareSerial SerialPort(2); int slave_1_id = 1; int slave_2_id = 2; const int BUTTON_PIN_01 = 12; const int BUTTON_PIN_02 = 13; const int Enable = 2; void setup() { Serial.begin(115200); SerialPort.begin(115200, SERIAL_8N1, 16, 17); //SerialPort.setTimeout(250); pinMode(Enable, OUTPUT); digitalWrite(Enable, LOW); pinMode(BUTTON_PIN_01, INPUT_PULLUP); pinMode(BUTTON_PIN_02, INPUT_PULLUP); } void loop() { /* Master Program */ if(digitalRead(BUTTON_PIN_01) == 0){ delay(500); digitalWrite(Enable, HIGH); SerialPort.print(slave_1_id); SerialPort.print("ON"); SerialPort.flush(); digitalWrite(Enable, LOW); //digitalWrite(BUTTON_PIN_01, HIGH); } if(digitalRead(BUTTON_PIN_02) == 0){ delay(500); digitalWrite(Enable, HIGH); SerialPort.print(slave_2_id); SerialPort.print("ON"); SerialPort.flush(); digitalWrite(Enable, LOW); } if(SerialPort.available()){ Serial.println(SerialPort.readString()); } delay(100); }
Code cho Slave 01
Tương tự như code cho Master, ta có
#include <HardwareSerial.h> HardwareSerial SerialPort(2); const int Enable = 2;
lấy một số nguyên lưu trữ số slave. Xác định chân LED cho LED 01.
const int SlaveNumber = 1; int Slave; const int LED = 4; //In setup function makes LED and Enable pin low and set as output. void setup() { pinMode(Enable, OUTPUT); pinMode(LED, OUTPUT); digitalWrite(Enable, LOW); digitalWrite(LED, LOW); }
Trong hàm vòng lặp khi serial tìm thấy dữ liệu bằng hàm SerialPort.available() kiểm tra số slave. Nếu số slave khớp với số slave đến từ master bằng hàm SerialPort.parseInt(), thì nó sẽ so sánh chuỗi đến bằng SerialPort.readString(). Nếu hàm chuỗi đến khớp với chuỗi điều kiện, thì đèn LED sẽ sáng. Và một thông báo phản hồi được gửi đến master bằng SerialPort.println. Cuối cùng, thông báo “Slave 1 is triggered” sẽ hiển thị trên màn hình serial của Arduino IDE.
void loop() { digitalWrite(Enable, LOW); if(SerialPort.available()) { Slave = SerialPort.parseInt(); Serial.println(Slave); if(Slave == SlaveNumber) { String command = SerialPort.readString(); Serial.println(command); if(command == "ON") { digitalWrite(LED, HIGH); delay(2000); digitalWrite(LED, LOW); } digitalWrite(Enable, HIGH); SerialPort.println("Slave 1 is triggered"); } // Serial.println("loop"); } }
Code đầy đủ cho slave 01
#include <HardwareSerial.h> HardwareSerial SerialPort(2); const int Enable = 2; const int SlaveNumber = 1; int Slave; const int LED = 4; void setup() { Serial.begin(115200); SerialPort.begin(115200, SERIAL_8N1, 16, 17); SerialPort.setTimeout(250); pinMode(Enable, OUTPUT); pinMode(LED, OUTPUT); digitalWrite(Enable, LOW); digitalWrite(LED, LOW); } void loop() { digitalWrite(Enable, LOW); if(SerialPort.available()) { Slave = SerialPort.parseInt(); Serial.println(Slave); if(Slave == SlaveNumber) { String command = SerialPort.readString(); Serial.println(command); if(command == "ON") { digitalWrite(LED, HIGH); delay(2000); digitalWrite(LED, LOW); } digitalWrite(Enable, HIGH); SerialPort.println("Slave 1 is triggered"); } //Serial.println("loop");/ } }
Code cho Slave 02
Tương tự code slave 01. Số của slave 2 được khai báo const int SlaveNumber = 2.
Code đầy đủ slave 02
#include <HardwareSerial.h> HardwareSerial SerialPort(2); const int Enable = 2; const int SlaveNumber = 2; int Slave; const int LED = 4; void setup() { Serial.begin(115200); SerialPort.begin(115200, SERIAL_8N1, 16, 17); SerialPort.setTimeout(250); pinMode(Enable, OUTPUT); pinMode(LED, OUTPUT); digitalWrite(Enable, LOW); digitalWrite(LED, LOW); } void loop() { digitalWrite(Enable, LOW); if(SerialPort.available()) { Slave = SerialPort.parseInt(); Serial.println(Slave); if(Slave == SlaveNumber) { String command = SerialPort.readString(); Serial.println(command); if(command == "ON") { digitalWrite(LED, HIGH); delay(2000); digitalWrite(LED, LOW); } digitalWrite(Enable, HIGH); SerialPort.println("Slave 2 is triggered"); } //Serial.println("loop");/ } }