Giao tiếp giữa hai Arduino

Trong hướng dẫn này, chúng ta sẽ học:

giao tiếp giữa hai Arduino

Hướng dẫn cung cấp mã Arduino cho hai trường hợp:

Phần cứng cần chuẩn bị

2×Arduino UNO R4 WiFi
2×USB Cable Type-C

Alternatively if using Ethernet:

2×Arduino Uno R3
2×USB 2.0 cable type A/B
2×Arduino Ethernet Shield
2×Ethernet Cable
1×(Khuyến nghị) Screw Terminal Block Shield for Arduino UNO R4
1×(Khuyến nghị) Breadboard Shield for Arduino UNO R4
1×(Khuyến nghị) Enclosure for Arduino UNO R4
1×(Khuyến nghị) Power Splitter for Arduino UNO R4
1×(Khuyến nghị) Prototyping Base Plate & Breadboard Kit for Arduino UNO

Or you can buy the following kits:

1×DIYables STEM V3 Starter Kit (Arduino included)
1×DIYables Sensor Kit (30 sensors/displays)
1×DIYables Sensor Kit (18 sensors/displays)

Giao tiếp giữa hai Arduino - Tổng quan

Chúng ta hãy xem xét một trường hợp cụ thể: Arduino số 1 giao tiếp với Arduino số 2. Có nhiều phương pháp để cho phép giao tiếp giữa hai Arduino. Chúng ta có thể chọn một trong số chúng tùy thuộc vào phạm vi giao tiếp. Bảng dưới đây cho thấy một số phương pháp và phạm vi giao tiếp của chúng.

Methods Range
I2C very short
SPI very short
UART (TTL) very short
UART (RS-232/485/422) short
Bluetooth short
LoRa long
Ethernet/WiFi unlimited(*)

※ Lưu ý:

(*):

  • Nếu hai Arduino được kết nối với Internet, phạm vi giao tiếp là vô hạn
  • Nếu hai Arduino không được kết nối với Internet, nhưng chúng được kết nối trong cùng một mạng LAN, chúng vẫn có thể giao tiếp với nhau. Phạm vi giao tiếp bị giới hạn trong mạng LAN.

Trong số các phương pháp trên, bài hướng dẫn này sử dụng Ethernet/WiFi để cho phép giao tiếp giữa hai Arduino vì nó cho phép hai Arduino giao tiếp ở khoảng cách không giới hạn.

Giao tiếp giữa hai Arduino qua Ethernet/WiFi

Hai Arduino có thể giao tiếp với nhau qua Ethernet hoặc WiFi nếu:

  • Hai Arduino trong cùng một mạng LAN, không cần kết nối Internet
  • Hai Arduino ở các mạng LAN khác nhau, cần kết nối Internet

Dù hai thiết bị Arduino có kết nối với nhau trong một mạng LAN cục bộ hay qua Internet, có hai loại giao tiếp:

Trong trường hợp giao tiếp trực tiếp, hầu hết các trường hợp, một Arduino đóng vai trò là máy khách TCP, còn Arduino kia đóng vai trò là máy chủ TCP.

Trong trường hợp giao tiếp qua một máy chủ tập trung, ở hầu hết các trường hợp, cả hai Arduino đóng vai trò là máy khách TCP.

Tùy thuộc vào ứng dụng, chúng ta cần chọn một giao thức ứng dụng để giao tiếp giữa hai bo mạch Arduino. Dưới đây là một số giao thức ứng dụng mà chúng ta có thể sử dụng:

  • Giao thức tự định nghĩa trên TCP thô (trực tiếp)
  • Modbus TCP (trực tiếp)
  • HTTP (trực tiếp)
  • Telnet (trực tiếp)
  • SSH (trực tiếp)
  • MQTT (thông qua một máy chủ tập trung)

※ Lưu ý:

Không quan trọng nếu:

  • Cả hai Arduino đều dùng Ethernet
  • Cả hai Arduino đều dùng WiFi
  • Một Arduino dùng Ethernet, Arduino còn lại dùng WiFi

Giao thức UDP nằm ngoài phạm vi của bài hướng dẫn này.

Ứng dụng ví dụ

Hãy hiện thực hóa ứng dụng sau: Một nút nhấn hoặc công tắc được kết nối với Arduino số 1 sẽ điều khiển một LED được kết nối với Arduino số 2 qua Ethernet/WiFi.

giao tiếp giữa hai Arduino.

Hướng dẫn này sử dụng hai Shield Ethernet của Arduino. Bạn có thể sử dụng một Arduino - WiFi hoặc Arduino - Mạng Ethernet khác. Nếu bạn sử dụng một shield khác, chỉ cần chỉnh sửa mã một chút.

Như đã đề cập ở trên, có một số giao thức ứng dụng mà chúng ta có thể sử dụng. Trong ví dụ này, để đơn giản, chúng ta sẽ tự định nghĩa một giao thức (một giao thức do chính chúng ta định nghĩa).

Giao thức tự định nghĩa

Hãy định nghĩa một giao thức đơn giản:

  • Một kết nối TCP được tạo giữa Arduino #1 và Arduino #2
  • Arduino #1:
    • Đóng vai trò là máy chủ TCP, tích cực gửi yêu cầu kết nối TCP tới Arduino #2
    • Khi công tắc được bật, Arduino #1 gửi một byte (lệnh) có giá trị là 1 tới Arduino #2.
    • Khi công tắc được tắt, Arduino #1 gửi một byte (lệnh) có giá trị là 0 tới Arduino #2.
  • Arduino #2:
    • Đóng vai trò là máy chủ TCP, lắng nghe yêu cầu kết nối TCP từ Arduino #1
    • Nếu byte nhận được bằng 1, Bật đèn LED
    • Nếu byte nhận được bằng 0, Tắt LED

    Sơ đồ đấu dây

    hai nút bật/tắt LED cho Arduino

    ※ Lưu ý:

    Bạn cần thêm một điện trở cho LED nếu LED không có điện trở tích hợp sẵn. Bạn có thể tìm hiểu thêm trong các bài hướng dẫn Arduino - LED - Nhấp nháyArduino - Nút nhấn.

Giao tiếp giữa hai Arduino thông qua WiFi

Mã Arduino cho Arduino Uno R4 WiFi #1

/* * Mã Arduino này được phát triển bởi newbiely.vn * Mã Arduino này được cung cấp để sử dụng công khai, không có ràng buộc. * Để xem hướng dẫn chi tiết và sơ đồ kết nối, vui lòng truy cập: * https://newbiely.vn/tutorials/arduino/communication-between-two-arduino */ // ARDUINO #1: TCP CLIENT + A BUTTON/SWITCH #include <ezButton.h> #include <WiFiS3.h> const char ssid[] = "YOUR_WIFI_SSID"; // change your network SSID (name) const char pass[] = "YOUR_WIFI_PASSWORD"; // change your network password (use for WPA, or use as key for WEP) const int BUTTON_PIN = 7; const int serverPort = 4080; ezButton button(BUTTON_PIN); // create ezButton that attach to pin 7; IPAddress serverAddress(192, 168, 0, 180); WiFiClient TCPclient; int status = WL_IDLE_STATUS; void setup() { Serial.begin(9600); button.setDebounceTime(50); // set debounce time to 50 milliseconds Serial.println("ARDUINO #1: TCP CLIENT + A BUTTON/SWITCH"); // check for the WiFi module: if (WiFi.status() == WL_NO_MODULE) { Serial.println("Communication with WiFi module failed!"); // don't continue while (true) ; } String fv = WiFi.firmwareVersion(); if (fv < WIFI_FIRMWARE_LATEST_VERSION) { Serial.println("Please upgrade the firmware"); } // attempt to connect to WiFi network: while (status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network. Change this line if using open or WEP network: status = WiFi.begin(ssid, pass); // wait 10 seconds for connection: delay(10000); } // print your board's IP address: Serial.print("IP Address: "); Serial.println(WiFi.localIP()); // connect to TCP server (Arduino #2) if (TCPclient.connect(serverAddress, serverPort)) Serial.println("Connected to TCP server"); else Serial.println("Failed to connect to TCP server"); } void loop() { button.loop(); // MUST call the loop() function first if (!TCPclient.connected()) { Serial.println("Connection is disconnected"); TCPclient.stop(); // reconnect to TCP server (Arduino #2) if (TCPclient.connect(serverAddress, serverPort)) Serial.println("Reconnected to TCP server"); else Serial.println("Failed to reconnect to TCP server"); } if (button.isPressed()) { TCPclient.write('1'); TCPclient.flush(); Serial.println("- The button is pressed, sent command: 1"); } if (button.isReleased()) { TCPclient.write('0'); TCPclient.flush(); Serial.println("- The button is released, sent command: 0"); } }

Mã Arduino cho Arduino Uno R4 WiFi #2

/* * Mã Arduino này được phát triển bởi newbiely.vn * Mã Arduino này được cung cấp để sử dụng công khai, không có ràng buộc. * Để xem hướng dẫn chi tiết và sơ đồ kết nối, vui lòng truy cập: * https://newbiely.vn/tutorials/arduino/communication-between-two-arduino */ // ARDUINO #2: TCP SERVER + AN LED #include <WiFiS3.h> const char ssid[] = "YOUR_WIFI_SSID"; // change your network SSID (name) const char pass[] = "YOUR_WIFI_PASSWORD"; // change your network password (use for WPA, or use as key for WEP) const int LED_PIN = 7; const int serverPort = 4080; WiFiServer TCPserver(serverPort); int status = WL_IDLE_STATUS; void setup() { Serial.begin(9600); pinMode(LED_PIN, OUTPUT); Serial.println("ARDUINO #2: TCP SERVER + AN LED"); // check for the WiFi module: if (WiFi.status() == WL_NO_MODULE) { Serial.println("Communication with WiFi module failed!"); // don't continue while (true) ; } String fv = WiFi.firmwareVersion(); if (fv < WIFI_FIRMWARE_LATEST_VERSION) { Serial.println("Please upgrade the firmware"); } // attempt to connect to WiFi network: while (status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network. Change this line if using open or WEP network: status = WiFi.begin(ssid, pass); // wait 10 seconds for connection: delay(10000); } // Print your local IP address: Serial.print("TCP Server IP address: "); Serial.println(WiFi.localIP()); Serial.println("-> Please update the serverAddress in Arduino #1 code"); // Listening for a TCP client (from Arduino #1) TCPserver.begin(); } void loop() { // Wait for a TCP client from Arduino #1: WiFiClient client = TCPserver.available(); if (client) { // Read the command from the TCP client: char command = client.read(); if (command == '1') { Serial.print("- Received command: "); Serial.println(command); digitalWrite(LED_PIN, HIGH); // Turn LED on } else if (command == '0') { Serial.print("- Received command: "); Serial.println(command); digitalWrite(LED_PIN, LOW); // Turn LED off } } }

Giao tiếp giữa hai Arduino qua Ethernet

Mã Arduino cho Arduino Ethernet #1

/* * Mã Arduino này được phát triển bởi newbiely.vn * Mã Arduino này được cung cấp để sử dụng công khai, không có ràng buộc. * Để xem hướng dẫn chi tiết và sơ đồ kết nối, vui lòng truy cập: * https://newbiely.vn/tutorials/arduino/communication-between-two-arduino */ // ARDUINO #1: TCP CLIENT + A BUTTON/SWITCH #include <ezButton.h> #include <SPI.h> #include <Ethernet.h> const int BUTTON_PIN = 7; const int serverPort = 4080; ezButton button(BUTTON_PIN); // create ezButton that attach to pin 7; byte mac[] = {0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x03}; IPAddress serverAddress(192, 168, 0, 180); EthernetClient TCPclient; void setup() { Serial.begin(9600); button.setDebounceTime(50); // set debounce time to 50 milliseconds Serial.println("ARDUINO #1: TCP CLIENT + A BUTTON/SWITCH"); // Initialize Ethernet Shield: if (Ethernet.begin(mac) == 0) Serial.println("Failed to configure Ethernet using DHCP"); // connect to TCP server (Arduino #2) if (TCPclient.connect(serverAddress, serverPort)) Serial.println("Connected to TCP server"); else Serial.println("Failed to connect to TCP server"); } void loop() { button.loop(); // MUST call the loop() function first if (!TCPclient.connected()) { Serial.println("Connection is disconnected"); TCPclient.stop(); // reconnect to TCP server (Arduino #2) if (TCPclient.connect(serverAddress, serverPort)) Serial.println("Reconnected to TCP server"); else Serial.println("Failed to reconnect to TCP server"); } if (button.isPressed()) { TCPclient.write('1'); TCPclient.flush(); Serial.println("- The button is pressed, sent command: 1"); } if (button.isReleased()) { TCPclient.write('0'); TCPclient.flush(); Serial.println("- The button is released, sent command: 0"); } }

Mã Arduino cho Arduino Ethernet #2

/* * Mã Arduino này được phát triển bởi newbiely.vn * Mã Arduino này được cung cấp để sử dụng công khai, không có ràng buộc. * Để xem hướng dẫn chi tiết và sơ đồ kết nối, vui lòng truy cập: * https://newbiely.vn/tutorials/arduino/communication-between-two-arduino */ // ARDUINO #2: TCP SERVER + AN LED #include <SPI.h> #include <Ethernet.h> const int LED_PIN = 7; const int serverPort = 4080; byte mac[] = {0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02}; EthernetServer TCPserver(serverPort); void setup() { Serial.begin(9600); pinMode(LED_PIN, OUTPUT); Serial.println("ARDUINO #2: TCP SERVER + AN LED"); // Initialize Ethernet Shield: if (Ethernet.begin(mac) == 0) Serial.println("Failed to configure Ethernet using DHCP"); // Print your local IP address: Serial.print("TCP Server IP address: "); Serial.println(Ethernet.localIP()); Serial.println("-> Please update the serverAddress in Arduino #1 code"); // Listening for a TCP client (from Arduino #1) TCPserver.begin(); } void loop() { // Wait for a TCP client from Arduino #1: EthernetClient client = TCPserver.available(); if (client) { // Read the command from the TCP client: char command = client.read(); if (command == '1') { Serial.print("- Received command: "); Serial.println(command); digitalWrite(LED_PIN, HIGH); // Turn LED on } else if (command == '0') { Serial.print("- Received command: "); Serial.println(command); digitalWrite(LED_PIN, LOW); // Turn LED off } Ethernet.maintain(); } }

Hướng dẫn từng bước

  • Nếu dùng Ethernet Shield, xếp chồng các Ethernet Shield lên Arduino #1 và Arduino #2
  • Kết nối một nút nhấn/công tắc với Arduino #1
  • Kết nối một LED với Arduino #2
  • Mở Arduino IDE (gọi là Arduino IDE #1)
  • Cài đặt thư viện ezButton trên Arduino IDE
  • Kết nối Arduino #1 với máy tính qua cáp USB và chọn cổng COM của Arduino #1 trên Arduino IDE #1
  • Mở một cửa sổ Arduino IDE khác (gọi là Arduino IDE #2) bằng nhấp vào biểu tượng Arduino IDE trên máy tính của bạn (quan trọng!())
  • Kết nối Arduino #2 với máy tính qua cáp USB và chọn cổng COM của Arduino #2 trên Arduino IDE #2
  • Sao chép mã Arduino #1, dán vào Arduino IDE #1 và lưu lại (đặt tên Arduino1)
  • Sao chép mã Arduino #2, dán vào Arduino IDE #2 và lưu lại (đặt tên Arduino2)
  • Tải mã Arduino #2 lên Arduino #2 trước
  • Mở Serial Monitor trên Arduino IDE #2, lấy địa chỉ IP của máy chủ TCP
COM6
Send
ARDUINO #2: TCP SERVER + AN LED TCP Server IP address: 192.168.0.2 -> Please update the serverAddress in Arduino #1 code
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  
  • Cập nhật địa chỉ IP máy chủ TCP trong mã Arduino #1
  • Tải mã Arduino #1 lên Arduino #1
  • Mở Serial Monitor trong Arduino IDE #1
  • Nhấn và giữ nút trên Arduino #1 → xem trạng thái LED ở Arduino #2 (BẬT)
  • Nhả nút trên Arduino #1 → xem trạng thái LED ở Arduino #2 (TẮT)
  • Nhấn, giữ và thả nút vài lần.
  • Xem đầu ra trên cả hai Serial Monitor
  • Serial Monitor của Arduino #1
COM6
Send
ARDUINO #1: TCP CLIENT + A BUTTON/SWITCH Connected to TCP server - The button is pressed, sent command: 1 - The button is released, sent command: 0 - The button is pressed, sent command: 1 - The button is released, sent command: 0 - The button is pressed, sent command: 1 - The button is released, sent command: 0
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  
  • Trình giám sát nối tiếp của Arduino #2
COM6
Send
ARDUINO #2: TCP SERVER + AN LED TCP Server IP address: 192.168.0.2 -> Please update the serverAddress in Arduino #1 code - Received command: 1 - Received command: 0 - Received command: 1 - Received command: 0 - Received command: 1 - Received command: 0
Autoscroll Show timestamp
Clear output
9600 baud  
Newline  

※ Lưu ý:

  • (): Nếu bạn mở cửa sổ Arduino IDE #2 bằng cách vào "File" → "New" hoặc "Open" từ cửa sổ Arduino IDE #2, bạn sẽ không thể mở hai trình theo dõi Serial cho hai Arduino trên cùng một máy tính cùng một lúc.
  • Có một phương án thay thế cho giao thức tự định nghĩa này. Đó là Modbus TCP. Giao thức Modbus được chuẩn hóa, nó có nhiều ưu điểm so với giao thức tự định nghĩa. Xem thêm trong hướng dẫn Arduino - Modbus.

Video Tutorial

Việc sản xuất video tốn rất nhiều thời gian. Nếu video hướng dẫn hữu ích cho việc học của bạn, hãy đăng ký kênh YouTube để ủng hộ. Nếu nhu cầu đủ cao, chúng tôi sẽ cố gắng làm thêm nhiều video.

Cách kết nối hai Arduino qua Internet

Có hai loại địa chỉ IP: địa chỉ IP riêng tư và địa chỉ IP công khai. Địa chỉ IP bạn đang sử dụng trong mạng gia đình thường là một địa chỉ IP riêng tư.

Bạn có thể dễ dàng nhận diện địa chỉ IP riêng. Địa chỉ IP riêng có ba mẫu: 10.x.x.x, 172.16.x.x, 192.168.x.x

Việc sử dụng địa chỉ IP riêng trong trường hợp sau đây không quan trọng:

  • Nếu hai Arduino nằm trong cùng một mạng LAN, bất kể chúng giao tiếp trực tiếp hay thông qua một máy chủ tập trung, bất kể mạng LAN của bạn có kết nối với Internet hay không.
  • Nếu hai Arduino ở hai mạng LAN khác nhau và giao tiếp với nhau thông qua một máy chủ tập trung

Trong trường hợp hai Arduino ở các mạng LAN khác nhau và giao tiếp với nhau trực tiếp. Máy khách TCP Arduino có thể sử dụng địa chỉ IP riêng. Tuy nhiên, máy chủ TCP Arduino phải sử dụng một trong hai cái sau:

  • Một địa chỉ IP công khai
  • Một địa chỉ IP riêng với chuyển tiếp cổng trên Router/AP

Quá trình thực hiện 'Port Forwarding' khác nhau tùy từng router/AP. Điều này nằm ngoài phạm vi của bài hướng dẫn này.