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ả

LCD Graphic 128x64 dòng KS0108 VÀ ST7920 - Viết, vẽ và làm mọi thứ với LCD

Graphic LCD (gọi tắt là GLCD) loại chấm không màu là các loại màn hình tinh thể lỏng nhỏ dùng để hiển thị chữ, số hoặc hình ảnh. Khác với Text LCD, GLCD không được chia thành các ô để hiển thị các mã ASCII vì GLCD không có bộ nhớ CGRAM (Character Generation RAM). GLCD 128x64 có 128 cột và 64 hàng tương ứng có 128x64=8192 chấm (dot). Mỗi chấm tương ứng với 1 bit dữ liệu, và như thế cần 8192 bits hay 1024 bytes RAM để chứa dữ liệu hiển thị đầy mỗi 128x64 GLCD. Tùy theo loại chip điều khiển, nguyên lý hoạt động của GLCD có thể khác nhau, trong bài này tôi giới thiệu loại GLCD được điều khiển bởi chip KS0108 của Samsung, có thể nói GLCD với KS0108 là phổ biến nhất trong các loại GLCD loại này (chấm, không màu). Hình 1 là hình ảnh thật của 1 GLCD 128x64 điều khiển bởi KS0108.

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

Sạc cho nguồn và cấp nguồn cho Arduino - Giải quyết vấn đề năng lượng bằng một bài viết bỏ túi

Đối với các dự án không tiêu thụ nhiều năng lượng, các bạn có thể sử dụng pin AAA hoặc pin 9v. Nhưng với những dự án tiêu thụ nhiều năng lượng bao gồm cả động cơ, màn hình LCD hay âm thanh thì pin 18650 là lựa chọn tối ưu, vừa bền, vừa gọn nhẹ.

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