Giao tiếp I2C giữa nhiều arduino với nhau

Nhiều bạn thường dùng 2 chân RXD và TXD để giao tiếp, nhưng trong trường hợp chúng ta cần kết nối nhiều arduino với nhau thì việc giao tiếp qua 2 cổng RXD và TXD là không khả thi. Việc sử dụng giao thức I2C cho arduino kết nối với nhau là cực kì đơn giản và chính xác, số lượng arduino có thể kết nối trong cùng 1 mạng, dưới sự điều hành của 1 boad arduino chủ lên tới hơn 100 boad arduino con. 

Thỉnh thoảng mình vẫn hay gặp phải những dự án cần nhiều số lượng chân digital và analog, việc đầu tiên mình nghĩ đến là vác ngay con arudino mega 2560 về. Nhưng thực tế có những dự án 1 con arduino mega 2560 sẽ không đảm nhận được trách nhiệm, 1 phần vì nếu để nó chia áp ra quá nhiều chân sẽ dẫn tới bị loạn chip khi sử dụng hoặc thậm chí có thể sẽ không hoạt động được. và khi đó mình nghĩ tới việc kết nối nhiều con arduino nano vơi nhau.

Tất nhiên chúng ta có thể sử dụng IC khác để giải quyết các vấn đề về số lượng chân như 74hc595. Nhưng mình thích sự nhanh chóng, cắm dây là xong. Nếu các bạn quan tâm thì hãy cùng mình nghiên cứu nội dung này nhé!

Để hiểu rõ hơn về nguyên lý hoạt động của giao tiếp I2C, các bạn xem lại bài viết của mình về i2c nhé 

I. CHUẨN BỊ

laugh

II. SƠ ĐỒ KẾT NỐI

Như bài viết trước mình đã nêu rõ về nguyên lý hoạt động của I2C, việc kết nối giữa arduino với arduino hoàn toàn giống như giữa arduino và các module khác. Ta chỉ cần kết nối chân SDA - SDA; SCL - SCL và đặc biệt quan trọng đó là phải có chung GND. Trong trường hợp cần thiết, cần phải có trở từ 1 - 2k kéo từ các chân SCL và SDA tới +5v để chắc chắn giao tiếp sẽ hoạt động.

Có 1 lưu ý đó là các bạn không được kết nối giữa 2 boad sử dụng mức điện áp khác nhau, ví dụ nếu 1 boad sử dụng nguồn nuôi chip là 5v, kết nối với 1 boad là 3,3v. Boad 5v sẽ không hỏng, nhưng mình không dám chắc boad 3,3v của bạn sẽ còn hoạt động được

Dưới đây là sơ đồ mô phỏng trên proteus mình sẽ

 

việc kết nối với nhiều boad cũng tương tự như trên, chỉ cần nối GND chung, SDA và SCL của các boad theo chung đường với nhau là được

II.CHỦ TRUYỀN LỆNH, TỚ NHẬN LỆNH (master write - Slave read)

Ở phần này mình xin đưa ra ví dụ về việc boad chủ (master) truyền tín hiệu về boad trạm (slave)

Code Chủ

//i2c Master Code(UNO)
#include <Wire.h>
void setup()
{
  Serial.begin(9600);
  Wire.begin(); // Khởi tạo thư viện i2c
}

void loop()
{
  while(Serial.available()) // đợi cho đến khi serial có tín hiệu
  {
    char c = Serial.read(); // gán biến c đọc dữ liệu trong serial
    
    if(c == 'H') / nếu c= "H"
    {
      Wire.beginTransmission(6); // Bắt đầu truyền dữ liệu về địa chỉ số 6
      Wire.write('H'); // Truyền ký tự H
      Wire.endTransmission(); // kết thúc truyền dữ liệu
    }
    else if(c == 'L') // Nếu c = "L"
    {
      Wire.beginTransmission(6); // Bắt đầu truyền dữ liệu về địa chỉ sô 6
      Wire.write('L'); // Truyền ký tự L
      Wire.endTransmission();// Kết thúc truyền dữ liệu
    }
  }
}

Các bạn có thể băn khoăn tại sao lại là  "6"   

 Wire.beginTransmission(6)

Trong bài viết trước mình đã nói  I²C sử dụng 7 bit để định địa chỉ, do đó trên một bus có thể có tới 2^7 địa chỉ tương ứng với 128 thiết bị có thể kết nối, các bạn có thể tùy ý chọn các địa chỉ từ 1-127, ở đây mình chọn là 6, và 6 chính là địa chỉ của Boad trạm (slave).

Boad chủ không cần địa chỉ nhé

Tiếp đến là code cho boad slave

 

//i2c Slave Code(UNO)
#include <Wire.h>
void setup()
{
  Wire.begin(6); // Khởi tạo thư viện i2c địa chỉ 6
  Wire.onReceive(receiveEvent); // khởi tạo chế độ nhận tín hiệu từ boad chủ
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
}

void loop()
{
}

void receiveEvent() // hàm sự kiện nhận tín hiệu từ boad chủ
{
  while(Wire.available()) // chờ cho đến khi có tín hiệu
  {
    char c = Wire.read(); // biến c để lưu dữ liệu nhận được
    
    if(c == 'H') // nếu boad chủ gửi về tín hiệu là H
    {
      digitalWrite(13,HIGH); // chân 13 ở mức High
    }
    else if(c == 'L') // nếu tín hiệu boad chủ gửi về là L
    {
      digitalWrite(13,LOW);// chân 13 ở mức Low
    }
  }
}

Như các bạn thấy việc khởi tạo địa chỉ cho boad slave rất đơn giản, và trong trường hợp các bạn cần nhiều boad slave hơn các bạn chỉ cần khởi tạo các đia chỉ khác nhau

Kết quả sau khi nạp vào 2 boad mình đã mô phỏng được như sau:

Khi gửi L

Khi gửi H

III. KẾT LUẬN

Trên đây là ví dụ đơn giản về việc giao tiếp giữa 2 boad arduino, việc thêm nhiều boad nữa hoàn toàn không có gì khác. 

Chúc các bạn thành công!

lên
24 thành viên đã đánh giá bài viết này hữu ích.
Các dự án được truyền cảm hứng

Select any filter and click on Apply to see results

Các bài viết cùng tác giả

Tự động tắt nguồn cho Arduino bằng MOSFET

Bạn có 1 dự án với yêu cầu điện năng tiêu thụ ở mức tối thiểu. Với nguồn năng lượng chủ yếu là sử dụng pin. Để đáp ứng sử dụng được trong 1 thời gian dài thì yêu cầu tiết kiệm năng lượng là rất quan trọng. Một trong những nhược điểm lớn nhất của các boad Arduino là chúng cần rất nhiều năng lượng, ngay cả khi ở trạng thái nhàn rỗi. Ví dụ như Arduino Uno cần khoảng 40mA khi nhàn rỗi và khoảng 20mA nếu chúng ta đặt các chip Atmega ở trạng thái sleep. Rất tốn phải không? Nó sẽ làm cạn kiệt bất kỳ loại pin nào bất kỳ trong vòng một vài ngày. Vì vậy, Mình sẽ giới thiệu tới các bạn 1 mạch, sẽ làm cho arduino tự tắt nguồn thay vì thực hiện chế độ sleep.  Hãy xem nó hoạt động như thế nào nhé.

lên
15 thành viên đã đánh giá bài viết này hữu ích.

Nghiên cứu về tín hiệu hồng ngoại của Remote điều hòa, ứng dụng trong các dự án nhà thông minh

Tín hiệu hồng ngoại của điều khiển điều hòa là 1 dạng tín hiệu đặc biệt, nó hoàn toàn khác so với tín hiệu hồng ngoại của tivi hay các thiết bị điện gia dụng. Bài viết này mình sẽ giúp các bạn tìm hiểu về tín hiệu hồng ngoại của điều khiển điều hòa, trên cơ sở đó xây dựng dự án Smart Home cho chính mình.

Ví dụ như trước khi về nhà mình sẽ điều khiển điều hòa bật trước với nhiệt độ tùy chọn chẳng hạn.

lên
29 thành viên đã đánh giá bài viết này hữu ích.