Hướng dẫn giao tiếp serial adruino uno r3 năm 2024
Truyền thông nối tiếp là một khái niệm quan trọng giúp chúng ta có thể dễ dàng nắm bắt những nội dung về một số chuẩn giao tiếp thông dụng của Arduino như I2C, SPI, 1-Wire, Serial… sẽ được giới thiệu ở các phần tiếp theo. Trong thực tế, khi xây dựng một ứng dụng sử dụng Arduino, giả sử chúng ta cần trao đổi thông tin giữa 2 thiết bị (giữa máy tính với board Arduino hoặc giữa các board Arduino với nhau hay có thể là giữa Arduino với các module…), thông tin trao đổi gồm có 8 bit, vậy đâu là giải pháp cho vấn đề này? Có lẽ cách dễ dàng tiếp cận nhất đó là sử dụng 8 dây data, ứng với mỗi dây data, mỗi bit sẽ được truyền từ bộ phát đến bộ thu, đây được gọi là phương pháp truyền song song (Parallel Communication), phương pháp này có ưu điểm tốc độ truyền tải nhanh, dễ dàng cài đặt, tuy nhiên nhược điểm lớn nhất là số lượng đường truyền cần phải lớn, thật khó chấp nhận đối với các dòng vi điều khiển có số lượng chân I/O là hạn chế. Do đó truyền thông nối tiếp (Serrial Communication) được ra đời để giải quyết vấn đề này. Cụ thể, để thực hiện việc truyền tải dữ liệu, ta chỉ cần sử dụng 1 (hoặc một số) đường truyền, và dữ liệu cần trao đổi sẽ được truyền lần lượt từng bit theo đường truyền này. Do đó, trong các ứng dụng thực tế, ta thường lựa chọn phương pháp truyền thông nối tiếp thay vì truyền song song dù cho tốc độ truyền thấp hơn, nhưng làm tiết kiệm số lượng đường truyền và chân điều khiển của các loại vi điều khiển được sử dụng. Hình 1. Giao tiếp nối tiếp và giao tiếp song song (Nguồn Wikipedia) Ngoài ra, với phương pháp truyền thông nối tiếp, để đảm bảo tính chính xác của thông tin truyền nhận giữa bộ truyền và bộ nhận cần có những tiêu chuẩn cụ thể. Một số giao thức như I2C, SPI,… sử dụng một đường truyền phát xung (CLOCK) có chức năng đồng bộ quá trình trao đổi thông tin. Ví dụ, thiết bị thứ nhất muốn truyền một bit data, thiết bị này sử dụng thêm một dây tín hiệu chuyển từ mức thấp lên mức cao để thông báo cho thiết bị thu biết đang có dữ liệu gửi đến. Đây là một cách giúp giảm thiểu rủi ro sai lệch thông tin trong quá trình giao tiếp, được gọi là phương pháp truyền thông đồng bộ (Synchronous). Khác với truyền thông đồng bộ, truyền thông không đồng bộ (Asynchronous) có những cách chuẩn hóa riêng giữa các thiết bị giao tiếp với nhau và sẽ không cần dùng đến dây tín hiệu phát xung. Ứng với cách này, giả sử ta quy định cho bộ truyền và bộ nhận rằng cứ mỗi 1 micro giây thì bộ truyền sẽ gửi 1 bit dữ liệu, do đó cứ mỗi 1 micro giây bộ nhận sẽ chỉ cần kiểm tra và tiếp nhận thông tin, sau đó tổng hợp để thu được dữ liệu có nghĩa. Giao tiếp SerialTrong phần này chúng ta sẽ cùng tìm hiểu về chuẩn giao tiếp Serial (Serial protocol) một chuẩn giao tiếp đại diện điển hình nhất của phương pháp truyền thông nối tiếp không đồng bộ (Asynchronous Serial). Nội dung phần này sẽ lần lượt trình bày các khái niệm cơ bản xoay quanh giao tiếp Serial cũng như những ví dụ thực tế từ chuẩn giao tiếp này. Những khái niệm cơ bảnChuẩn giao tiếp Serial là gì?Serial là chuẩn giao tiếp truyền thông nối tiếp không đồng bộ (được trình bày trong phần trước), sử dụng UART (Universal Asynchronous Receiver-Transmitter, một bộ phận phần cứng được tích hợp bên trong chip ATmega328 của board Arduino Uno) kết hợp với mức logic TTL (mức điện áp cao tương ứng với 5V hoặc 3.3V và mức điện áp thấp tương ứng với 0V). Trong thực tế, chúng ta vẫn có thể kết hợp UART và các mức logic khác để tạo ra một số chuẩn truyền khác chẳng hạn RS232, nhưng trong khuôn khổ quyển sách này chúng ta chỉ khảo sát mức logic TTL là chính. UART là tên gọi để chỉ một bộ phận phần cứng dùng để chuyển đổi thông tin từ thanh ghi chứa nội dung cần trao đổi ra bên ngoài (thông thường có 8 bits) thành 2 dây tín hiệu Serial, phục vụ cho chuẩn giao tiếp Serial chứ không phải là tên gọi của một chuẩn giao tiếp. Hình 2. RS232 và TTL Như đã giới thiệu từ phần trước, khi sử dụng chuẩn giao tiếp Serial, để trao đổi thông tin một cách hiệu quả, đòi hỏi các thiết bị giao tiếp với nhau cần phải thống nhất với nhau một số quy cách riêng như tốc độ baud (baudrate), khung truyền (frame), start bit, stop bits,… và sau đây chúng ta sẽ lần lượt tìm hiểu: BaudrateNhư trong ví dụ về việc truyền 1 bit data sau mỗi 1 micro giây, ta nhận thấy rằng để việc giao tiếp diễn ra thành công, giữa 2 thiết bị cần có những thống nhất rõ ràng về khoảng thời gian truyền cho mỗi bit dữ liệu, hay nói cách khác tốc độ truyền cần phải được thống nhất với nhau. Tốc độ này được gọi là tốc độ baud (baudrate), được định nghĩa là số bit truyền trong mỗi giây. Ví dụ, nếu tốc độ baud được sử dụng là 9600, có nghĩa thời gian truyền cho 1 bit là 1/9600 = 104.167 micro giây. Khung truyền (frame)Bên cạnh tốc độ baud, khung truyền đối với chuẩn giao tiếp Serial cũng hết sức quan trọng để đảm bảo việc truyền nhận được diễn ra chính xác. Khung truyền quy định về số lượng bit truyền trong mỗi lần truyền, bao gồm start bit, các bit data, stop bits, ngoài ra còn có thể có parity bit (kiểm tra lỗi dữ liệu trong quá trình truyền nhận). Hình 3. Ví dụ về một khung truyền Hình ảnh trên là một ví dụ về khung truyền, bao gồm 1 bit start, 8 bits data và cuối cùng là 1 bit stop. Start bitĐây là bit đầu tiên được truyền vào khung truyền, có chức năng thông báo cho thiết bị nhận biết đang có một chuỗi dữ liệu sắp truyền đến. Đối với các dòng AVR nói chung và UnoX nói riêng, ở trạng thái chưa có dữ liệu (Idle) đường truyền luôn kéo lên mức cao. Khi có dữ liệu mới, đường truyền được kéo xuống mức thấp, do đó start bit sẽ được quy định là mức 0. Dữ liệu (data)Dữ liệu cần truyền thông thường gồm 8 bits, tuy nhiên chúng ta hoàn toàn có thể tùy chỉnh số lượng bit data cho một gói tin, có thể là 5, 6, 7, 9… Trong quá trình truyền, bit có trọng số thấp nhất (LSB) sẽ được truyền trước, và cuối cùng sẽ là bit có trọng số cao nhất (MSB). Stop bitsStop bits là một hoặc nhiều bit có chức năng thông báo cho thiết bị nhận biết rằng một gói dữ liệu đã được gởi xong. Đây là bit quan trọng, cần phải có trong một khung truyền. Giá trị của các stop bit luôn bằng mức Idle (mức nghỉ) và ngược với giá trị của start bit. Đối với các dòng vi điều khiển AVR các bit kết thúc này luôn là mức cao. Sử dụng chuẩn giao tiếp Serial với boad Arduino UnoGiao tiếp Serial giữa 2 thiết bị với nhau thông thường sẽ có 2 dây tín hiệu, đó là TX (Transmitter) có chức năng truyền tải dữ liệu và RX (Receiver) có chức năng thu nhận dữ liệu. 2 dây tín hiệu này được kết nối chéo nhau giữa 2 thiết bị. Cụ thể, TX của thiết bị 1 kết nối với RX của thiết bị 2 và RX của thiết bị 1 kết nối với TX của thiết bị 2. Điều đặc biệt của Serial đó là quá trình truyền và quá trình nhận dữ liệu được diễn ra hoàn toàn độc lập với nhau. Hình 4. Giao tiếp 2 thiết bị sử dụng Serial UART Hiện nay, các board Arduino đều được hỗ trợ sẵn 1 hoặc nhiều cổng giao tiếp Serial. Đối với board Arduino Uno, cổng Serial được ra chân tại vị trí chân số 1 và chân số 0 trên board), đây được gọi là Hardware Serial, tức là giao tiếp Serial dựa trên phần cứng (có sử dụng UART). Ngoài ra, đối với các vi điều khiển không hỗ trợ UART hoặc trong trường hợp muốn mở rộng nhiều cổng Serial để giao tiếp với nhiều thiết bị có hỗ trợ giao tiêp Serial, chúng ta hoàn toàn có thể giả lập giao tiếp Serial bằng thư viện cho Arduino có tên là SoftwareSerial, chúng ta sẽ tìm hiểu thư viện thú vị này ở phần sau. Hình 5. Vị trí chân giao tiếp UART trên board Arduino Uno Ứng dụngGiao tiếp Serial của board Arduino Uno với máy tính cá nhânKhi kết nối board Arduino Uno với máy tính bằng cable USB, thông qua chip USB-to-Serial CH430E trên board, cổng USB của máy tính sẽ được chuyển đổi thành tín hiệu Serial để kết nối với chân TX, RX của board, lúc này, ta có thể dễ dàng trao đổi dữ liệu giữa board và máy tính. Và đây cũng là cách để nạp chương trình từ máy tính xuống cho board Arduino Uno. Sau đây, ta sẽ xét một số ví dụ đơn giản khi giao tiếp giữa Arduino Uno và máy tính. 1. Lắng nghe dữ liệu từ board Arduino Uno 1.1. Giới thiệu: Việc máy tính lắng nghe dữ liệu từ board Arduino Uno thông thường được sử dụng khi debug chương trình, qua đó chúng ta có thể quan sát và kiểm tra kết quả trả về từ board trong khi hoạt động thông qua cửa sổ Serial Monitor. Một số hàm cần lưu ý khi sử dụng chức năng này:
Trong đó:
1.2. Ví dụ: Đọc giá trị từ biến trở, xuất kết quả ra Serial Monitor. Chuẩn bị:
Kết nối: Hình 6. Kết nối Arduino với biến trở Source code:
Xem kết quả: Chọn Hình 7. Chọn baudrate trên Serial Monitor để xem kết quả 2. Gửi dữ liệu từ máy tính đến board Arduino Uno qua Serial Monitor 2.1. Giới thiệu Ta thường sử dụng Serial Monitor của Arduino IDE để gửi lệnh đến board Arduino Uno. Một số hàm cần chú ý:
2.2. Ví dụ Gửi lệnh điều khiển LED từ máy tính xuống board Arduino Uno bằng Serial. Chuẩn bị:
Kết nối: Hình 8. Kết nối LED với board Arduino Uno Source Code:
Giải thích code Chương trình trên sử dụng hàm Serial.available() để kiểm tra lệnh được gửi đến board. Bất cứ khi nào giá trị Serial.available() khác 0, ta sẽ dùng biến c kiểu char đọc từng kí tự được gửi đến, nếu c không phải là kí tự kết thúc dòng
0 thì điều khiển LED tắt (digitalWrite(LED,LOW)). Tất nhiên, nếu người dùng gửi lệnh khác “on” và “off” thì board Arduino Uno sẽ không làm gì cả. Khi người dùng hoàn thành việc nhập lệnh và click send hoặc nhấn phím Enter đồng nghĩa với chuỗi lệnh mà người dùng gửi đến có kết thúc là kí tự xuống dòng ‘\n’ chương trình trên sử dụng đặc điểm này để nhận biết khi nào là kết thúc 1 chuỗi rồi tiến hành kiểm tra chuỗi đó có nội dung là gì. Để thực hiện việc này ta cần tùy chỉnh chế độ nhập từ Serial Monitor là Newline, ngoài ra cần phải chỉnh tốc độ baud là 9600 như ví dụ trước. Hình 9. Tùy chỉnh chế độ nhập của Serial Monitor Kết quả: Hình 10. Nhập “on” hoặc “off” trên Serial Monitor 3. Giao tiếp Serial giữa 2 board Arduino qua Serial Ví dụ tiếp theo chúng ta sẽ thực hiện việc trao đổi thông tin giữa 2 board Arduino Uno, board thứ nhất làm master và board còn lại là slave. Board master sẽ gửi lệnh điều khiển đèn LED xuống board Slave. Board Slave khi nhận được lệnh thì sẽ điều khiển đèn LED có sẵn trên board của chính nó. 3.1. Chuẩn bị
3.2. Kết nối chân Số thứ tự Arduino Uno (Slave) Arduino khác(Master) 1 TXD RXD 2 RXD TXD 3 GND GND Hình 11. Hình ảnh kết nối 2 board Arduino Uno Lưu ý: Để hoạt động được, 2 board này cần được cấp nguồn, nguồn này có thể chung hoặc riêng nhưng GND của cả hai board cần được kết nối với nhau. 3.3. Source Code và giải thích Master code:
Slave code:
3.4. Kết quả Nếu thành công, ta sẽ thấy đèn LED trên board Arduino Uno chớp tắt theo chu kì 2 giây 3.5. Mở rộng từ ví dụ Qua ví dụ này, ta đã biết cách giao tiếp giữa 2 board Arduino bằng Serial, điều này phục vụ cho các dự án lớn khi 1 board Arduino là chưa đủ để quản lí hết tất cả các thiết bị, việc thêm 1 hay nhiều board Arduino để chia sẻ tác vụ là hết sức cần thiết. Có nhiều cách để trao đổi thông tin giữa các Arduino, nhưng dùng Serial là giải pháp giúp tiết kiệm số lượng đường truyền với thời gian truyền đáp ứng tốt. 4. Giao tiếp Serial giữa board Arduino Uno và module Sim800 Ví dụ tiếp theo, chúng ta sẽ sử dụng Arduino cùng với thư viện SoftwareSerial để điều khiển module Sim800L nhắn tin đến điện thoại di động. 4.1. Module Sim800 Module Sim800L là một giải pháp hiệu quả cho các ứng dụng về GSM và GPRS (nhắn tin, gọi điện hoặc sử dụng dịch vụ mạng 2G). Nếu bạn đang tìm kiếm một loại module giúp bạn trong các dự án như phát hiện có đối tượng lạ xâm nhập thì cần gọi điện hoặc nhắn tin đến người chủ, điều khiển hệ thống tưới bằng tin nhắn điện thoại, thu thập dữ liệu gửi lên Server bằng dịch vụ GPRS,… thì Sim800L là giải pháp bạn cần cân nhắc đầu tiên. Sim800L được hỗ trợ giao tiếp Serial TTL do đó rất dễ sử dụng để giao tiếp với các vi điều khiển thông qua tập lệnh AT. Hình 12. Module Sim800L GSM GPRS Các thông số kỹ thuật của module Sim800L:
4.2. Tập lệnh AT: Một số module như Sim, GPS, ESP8266, bluetooth… được hỗ trợ giao tiếp Serial TTL đi kèm với đó là tập lệnh AT (AT commands), bằng những tập lệnh này thế giới bên ngoài có thể truy cập vào module, đưa ra những câu lệnh về thiết lập, điều khiển hoặc lấy thông tin,… Tương tự ví dụ thứ 2 ta sử dụng dụng máy tính để ra lệnh cho Arduino điều khiển đèn LED thông qua chuẩn giao tiếp Serial, tập lệnh AT cũng có chức năng giống vậy tuy nhiên cấu trúc các lệnh AT được chuẩn hóa theo cách riêng. Ví dụ một số lệnh AT cơ bản đối với module Sim800L:
4.3. Thư viện SoftwareSerial Như đã giới thiệu, đối với một số vi điều khiển không được hỗ trợ Serial hoặc số cổng Serial được hỗ trợ là hạn chế như board Arduino Uno thì việc mở rộng giao tiếp với nhiều thiết bị bằng Serial thật sự khó khăn, khi đó việc sử dụng thư viện giúp giả lập giao tiếp bằng Serial là hết sức cần thiết, và
1 là thư viện tốt nhất hỗ trợ việc này. Theo đó, ta chỉ cần kết nối bằng 2 chân GPIO bất kì của Arduino rồi khai báo sử dụng 2 này để giao tiếp Serial là ta có thể sử dụng Serial như cách truyền thống. Khai báo sử dụng Serial ảo: SoftwareSerial mySerial(RX,TX), trong đó TX, RX là các pin sử dụng cho giao tiếp Serial. Kết thúc việc khai báo này, ta có thể sử dụng đối tượng mySerial trong lập trình để đọc, ghi dữ liệu bằng Serial (Giống như biến Serial trong các ví dụ trước). 4.4. Kết nối chân Trong ví dụ lần này, ta sẽ sử dụng chân 9 và 10 của board Arduino Uno làm TX và RX để giao tiếp bằng Serial với module Sim800L. Vì module Sim800L chỉ có thể hoạt động ở mức điện áp từ 3.7V đến 4.2V do đó để cung cấp đúng mức điện áp cho module ta sử dụng pin 3.7V LiPo. Hình 13. Pin 3.3V LiPo Bảng 1. Bảng đấu nối Số thứ tự Arduino Uno Module Sim800L 1 GND GND 2 9 RX 3 10 TX Hình 14. Hình ảnh kết nối board Arduino Uno với Sim800L Sau khi hoàn tất kết nối, ta cần lắp thẻ microSim vào khay sim của module. 4.5. Source Code và giải thích
Ta cần khai báo chính xác số điện thoại để Sim800 gửi đúng. 4.6. Kết quả Kết quả ta sẽ nhận được tin nhắn có nội dung “Hello, this is Arduino Uno” sau vài giây từ khi board Arduino Uno khởi động. 4.7. Mở rộng Qua ví dụ trên, chúng ta đã biết cách sử dụng thư viện SoftwareSerial để điều khiển module Sim800L gửi tin nhắn đến điện thoại di động, ngoài ra vẫn còn rất nhiều ứng dụng thú vị khác được sử dụng với Sim800L chẳng hạn như thực hiện cuộc gọi hay sử dụng dịch vụ GPRS,… Tuy nhiên đối với các ứng dụng phức tạp, để tiện cho sử dụng ta hay dùng thư viện đã module hóa các tác vụ thành các hàm phục vụ cho nhắn tin, gọi điện hay cập nhật dữ liệu qua GPRS,… nhưng nguyên lí chung vẫn là sử dụng tập lệnh AT để điều khiển Sim800L. Nếu nắm được bản chất này chúng ta hoàn toàn có thể sử dụng các module khác tương tự như GPS, ESP8266, bluetooth,… Chỉ cần tra cứu tập lệnh riêng của từng module là ta có thể áp dụng ngay chúng vào dự án. Đối với thư viện SoftwareSerial, đây là một công cụ hữu ích giúp chúng ta có thể mở rộng để kết nối nhiều module hỗ trợ Serial với Arduino. Bạn đọc hoàn toàn có thể sử dụng thư viện này để giao tiếp 2 board Arduino như trong ví dụ thứ 3 mà không cần phải sử dụng Serial Hardware. Tổng kếtQua chương này, chúng ta đã cùng tìm hiểu về giao thức Serial cũng như những ứng dụng cơ bản xoay quanh chuẩn giao thức này, đó là tiền đề giúp chúng ta có thể xây dựng hệ thống, trong đó có nhiều thiết bị giao tiếp với nhau bằng Serial. |