Tôi yêu Arduino gửi vào
- 109604 lượt xem
I. Giới thiệu
Có thể nói Serial là một trong những phương thức giao tiếp đơn giản nhất trong môi trường Serial. Vì bạn chỉ cần 2 dây và cách thức truyền dữ liệu của nó lại giống hệt stream trong các ngôn ngữ lập trình. Nhưng thật đáng tiết, con Arduino Uno chỉ có duy nhất một cổng Serial được phần cứng hỗ trợ sẵn (Mega thì 3). Vì vậy, nếu bạn muốn giao tiếp với nhiều module Serial thì đó là một chuyện không thể. Và đó chính là lý do vì sao thư viện Software Serial ra đời. Hôm nay, chúng ta sẽ tìm cách giao tiếp giữa 2 mạch Arduino thông qua Serial và một ví dụ về chuyển tiếp giá trị của một module giao tiếp qua Serial (như module bluetooth) với thư viện này.
II. Giới thiệu về thư viện Software Serial
1. Mục đích ra đời của Software Serial
Giả lập thêm nhiều cổng Serial cho các board Arduino
2. Tải về
Nó đã là một thư viện cứng trong bộ thư viện chuẩn của Arduino, các bạn không cần phải download. Để chắc ăn, các bạn hãy nâng cấp IDE của mình lên bản 1.6.x, có thể tải tại mục Tải về.
3. Phương thức hoạt động
Vì mình không đủ level để hack não được nên bó tay các bạn nhé :D.
4. Hạn chế
Không phải chân nào của Arduino Mega và Arduino Mega 2560 cũng hỗ trợ đổi ngắt, vì vậy chỉ có các chân 10, 11, 12, 13, 50, 51, 52, 53, 62, 64, 65, 66, 67, 68, 69 có thể dùng làm chân RX. Tương tự với mạch Leonardo, cũng chỉ có các chân 8, 9, 10, 11, 14, 15, 16 hỗ trợ để làm chân RX.
Mình thấy cái này cũng không ảnh hưởng gì lắm vì sao? Vì bạn tính thử xem, bạn có bao giờ dùng hết được nó không ? Liệt kê thử nào, GPS, bluetooth, SIM, điều khiển 1 Uno thì cũng chỉ cần đến 4 cổng Arduino. Như vậy là quá nhiều luôn, đúng không nào?
III. Thực nghiệm với 2 Arduino
1. Mục tiêu
Mục tiêu của mình trong phần này đó là hướng dẫn các bạn dùng Arduino giao tiếp với một một Arduino khác thông qua cổng Serial ảo được tạo từ Software Serial.
2. Phần cứng cần chuẩn bị
- 02 x Arduino Uno (hoặc tương tự, Nano, Promini,...)
- 3 cộng breadboard
3. Nạp code cho Arduino "thứ 2"
Vì sao lại là Arduino thứ 2 mà không phài thứ nhất? Bởi vì mình sẽ upload một chương trình giao tiếp serial bình thường vào đây trước. Rồi dùng Arduino "thứ 1" với thư viện Software Serial từ đó giao tiếp với Arduino "thứ 2".
int led = 13; unsigned long time = 0; unsigned long delayTime = 1000; //Thời gian delay (không dùng hàm delay) void setup() { Serial.begin(9600); pinMode(led, OUTPUT); digitalWrite(led, LOW); // Tắt led } void loop() { if (Serial.available()) { time = millis(); //cập nhập lại biến time để cho đèn sáng được trong khoảng delayTime digitalWrite(led, HIGH); // đèn led sáng while (Serial.available()) { //xóa hết bộ đệm Serial.read(); delay(3); } Serial.println("Da nhan duoc"); //trả về lại cho arduino 1 } if (millis() - time > delayTime) digitalWrite(led, LOW); }
Mục đích của đoạn code này rất đơn giản. Khi nào có tín hiệu Serial thì nó sẽ làm đèn 13 nháy sáng lên trong 1 giây và trả về qua Serial (phần cứng) nội dung "Da nhan duoc"! Bạn hãy thử bật Serial Monitor chỉnh baudrate 9600 xem là thấy ngay !
Lưu ý: Nếu bạn đã kết nối Arduino thứ 1 và thứ 2 thì hãy tháo kết nối TX và RX giữa chúng thì mới nạp code được nhé.
4. Mạch kết nối giữa Arduino thứ 1 và Arduino thứ 2
Vì phần này đơn giản quá nên mình sẽ đưa vào bảng tóm tắt cho nhanh .
Arduino thứ 1 | Arduino thứ 2 |
GND | GND |
10 (RX software Serial) | TX |
11 (TX software Serial) | RX |
Lưu ý: Software Serial sẽ giả lập một công Serial, như vậy bạn sẽ có một cổng TX và cổng RX mới!
Vì vậy ở Arduino thứ 1, board dùng thư viện Software Serial sẽ có một cặp TX và RX ảo từ các chân digital.
5. Nạp code cho Arduino thứ 1
Với đoạn chương trình dưới đây, thực ra, nó cũng rất đơn giản. Mình sẽ bật 2 cổng Serial: Serial - hardware ở baudrate 9600, mySerial ở baudrate 9600 luôn, 2 cổng Serial này không nhất thiết phải khác nhau về mức baudrate, sau đó sẽ có 2 nhóm chương trình. Nhóm thứ nhất sẽ nhận dữ liệu từ máy tính và chuyển lại cho Arduino thứ 2, nhóm thứ hai sẽ nhận dữ liệu từ Arduino thứ 2 và xuất ra màn hình Serial monitor (máy tính).
#include <SoftwareSerial.h> SoftwareSerial mySerial(10, 11); // RX, TX void setup() { Serial.begin(9600); Serial.println("Da san sang"); mySerial.begin(9600); } void loop() { // Khi máy tính gửi dữ liệu cho mình if (Serial.available() > 0) { Serial.print("May tinh gui: "); while (Serial.available() > 0) {// in hết nội dung mà máy tính gửi cho mình, đồng thời gửi cho arduino thứ 2 char ch = Serial.read(); //đọc ký tự đầu tiên trogn buffer Serial.write(ch); //xuất ra monitor máy tính mySerial.write(ch); //gửi dữ liệu cho Arduino thứ 2 //delay(3); } Serial.println(); } if (mySerial.available() > 0) { Serial.println("Serial thu 2 gui gia tri: "); //đọc giá trị từ Arduino nếu có delay(20); while (mySerial.available() > 0) { char ch = mySerial.read(); //đọc Serial.write(ch); //xuất ra monitor delay(3); } Serial.println(); } }
Và khi bạn gõ một chuỗi gì đó qua Serial monitor thì nó sẽ chuyển hết chuỗi đó qua Arduino thứ 2, Arduino thứ 2 nhận được biết là có tín hiệu => làm đèn 13 (của arduino thứ 2) sáng trong 1 giây và trả lời nội dung là "Da nhan duoc".
Kết quả qua Serial Monitor máy tính
Mô hình hoạt động của Arduino và thư viện Serial với những module khác nhau (Click vào để xem to hơn)
6. Rút kinh nghiệm
Như vậy, ta đã giả lập được giao tiếp Serial và khi nạp code cho Arduino thứ 1 ta không cần phải tháo TX và RX ra nữa :). Thật tiện lợi phải không nào? Nói thì nói vậy thôi nhưng bạn phải thử thì mới biết cái khó của nó. Nếu bạn có một con mắt tinh tế thì sẽ nhận thấy ở các đoạn code Arduino thứ 1 và thứ 2, mình có để vài làm delay trong vài mili giây? Vì sao mình phải làm vậy nhỉ? Bởi vì, khi nhận dữ liệu Serial qua Software Serial thì lâu lâu nó sẽ bị lỗi mất dữ liệu => làm dữ liệu sai lệch vì tốc độ gửi dữ liệu quá nhanh phần mềm xử lý không kịp. Vì vậy để chắc ăn, bạn hãy dùng thư viện SerialCommand để giao tiếp giữa 2 mạch Arduino nhé.
7. Ví dụ về cách dùng với thư viện Serial Command
Trên cộng đồng của chúng ta đã có bài viết về thư viện Serial Command rồi, nên mình sẽ dùng ví dụ trong bài viết đó luôn. Vì vậy, các bạn nên vào bài viết đó và lắp mạch test trước rồi quay lại đây nhé .
Ở đây CLIENT là Arduino thứ 2, HOST là Client thứ 1. Code của CLIENT khôn thay đổi và chỉ thay đổi code của HOST. Vì sao? Vì CLIENT vẫn dùng serial chuẩn của hắn chứ có cần giao tiếp với máy tính làm gì đâu haha.
Các bạn lưu ý là phải nối RX và TX như mình hướng dẫn ở mục 4 nhé.
Code host sẽ thay đổi như sau.
#include <SoftwareSerial.h> SoftwareSerial mySerial(10, 11); // RX, TX void setup() { mySerial.begin(9600);// Bạn khởi tạo một cổng Serial tại baudrate 9600. Ở Client, bạn cũng phải mở một cổng Serial cùng Baudrate với HOST } int Step = 0; void loop() { if (Step == 0) { mySerial.println("LED_RED 1"); // Đèn đỏ sáng. 1 == HIGH } else if (Step == 1) { mySerial.println("LED_RED 0"); // Đèn đỏ tắt . 0 == LOW } else if (Step == 2) { mySerial.println("LED_BLUE 1");// Đèn xanh sáng } else if (Step == 3) { mySerial.println("LED_BLUE 0");// Đèn xanh tắt } Step = (Step + 1) % 4; //Step sẽ tuần tự tuần hoàn các giá trị trong khoảng từ 0 --> 3 delay(1000);// Dừng một giây giữa các lần gửi }
Các bạn đã thấy sự vi diệu chưa! Phần mở rộng mà tôi muốn các bạn làm đó là hãy điều khiển CLIENT từ máy tính của mình, và tôi se gợi ý ở mục IV!
IV. Biến Arduino trở thành một USB to Serial
1. Mục tiêu
Mục tiêu của mình là không chỉ nói đến Arduino Uno, vì với mạch Arduino Uno bạn chỉ việc tháo con Atmega328p ra và nó đã trở thành một mạch USB to Serial 5V mất rồi! Ở đây, mình hướng đến việc, biến mọi con Arduino bình thường trở thành một mạch USB to Serial.
2. Bài toán đặt ra
Giao tiếp giữa máy tính và một module bluetooth khác sử dụng mạch Arduino bất kỳ.
Mâu thuẫn
Khi sử dụng cổng Serial hardware (chân digital 0 1) thì bạn không thể nào giao tiếp được với máy tính. Như vậy không thể dùng cổng Serial hardware để giao tiếp với module bluetooth từ đó xem giá trị truyền qua Serial được. Nhưng module bluetooth thì chỉ có thể giao tiếp qua giao tiếp Serial. Vậy giờ phải làm sao?
3. Giải pháp
Chúng ta sẽ giả lập một cổng Serial bằng thư viện Software Serial và từ đó biến Arduino trở thành một nơi trung chuyển dư liệu. Nghĩa là khi Arduino nhận gì từ máy tính thì nó đẩy hết qua software Serial và khi software serial nhận được dữ liệu thì lại đẩy hết về máy tính.
4. Ví dụ
Arduino
|
Bluetooth
|
GND
|
GND
|
10 (RX software Serial)
|
TX
|
11 (TX software Serial)
|
RX
|
5V | 5V |
#include <SoftwareSerial.h> SoftwareSerial mySerial(10, 11); // RX, TX void setup() { Serial.begin(115200); //serial hardware kết nối với serial monitor của máy tính mySerial.begin(9600); //software serial kết nối với module sử dụng serial để giao tiếp (ở ví dụ này là bluetooth HC-06) } void loop() { if (mySerial.available()) //khi software serial có dữ liệu Serial.write(mySerial.read()); //viết ra monitor if (Serial.available()) // khi hardware serial có dữ liệu mySerial.write(Serial.read()); //viết lại qua module bluetooth (software serial) }
Rồi, bây giờ bạn hãy thử các câu lệnh AT của module bluetooth đi là sẽ thấy ngay thôi mà, hoặc là dùng điện thoại kết nối với module bluetooth rồi thử gửi lệnh qua là sẽ thấy ngay thôi mà!
5. Nhược điểm
Không như một mạch USB to Serial bình thường, để chuyển đổi giữa mức baudrate nhằm giao tiếp với thiết bị khác ta chỉ việc chỉnh option trong máy tính. Với cách tiếp cận này bạn phải nạp lại code mới cho nó để chỉnh lại baudrate! Nhưng được một cái là, ta không cần phải mua một mạch USB to Serial nếu dự án của ta chỉ là một dự án nhỏ!
V. Kết luận
Như vậy thì các bạn đã biết cách sử dụng thư viện Software Serial phải không nào? Hãy chia sẻ những dự án hay với nó nhé. Và nhớ hãy đọc từ trên xuống dưới đừng nên đọc lướt vì mình có để vài "Lưu ý" trong bài viết đấy!