Bộ giao tiếp I32C ESP2, giao diện nhiều thiết bị và thay đổi chân

Bộ giao tiếp I32C ESP2, giao diện nhiều thiết bị và thay đổi chân

Giới thiệu giao thức I2C

I2C còn được gọi là mạch tích hợp liên hoặc IIC hoặc I vuông C. Nó là một giao thức truyền thông nối tiếp 2 dây cho các ứng dụng truyền dữ liệu tầm ngắn. Nó là một giao thức truyền thông nối tiếp nửa song công không đồng bộ. Hơn nữa, nó là một giao thức bus đa chủ chỉ yêu cầu hai dây để truyền dữ liệu nối tiếp là SCL và SDA.

  • SDA ( Đường dữ liệu hai chiều)

  • SCL ( Dòng đồng hồ hai chiều)

Đây là một giao thức truyền thông rất phổ biến được sử dụng trong các dự án nhúng để giao diện các cảm biến dựa trên , màn hình chữ số và mô-đun giao tiếp. Các thiết bị muốn giao tiếp với từng kết nối thông qua bus I2C. Bus I2C hỗ trợ nhiều thiết bị nô lệ và nhiều thiết bị chính.

Dữ liệu được truyền từng chút một nối tiếp dọc theo một dây (đường SDA). Giống như SPI, I2C là đồng thời, đầu ra của các bit được đồng bộ hóa với việc kiểm tra các bit bằng tín hiệu đồng hồ được chia sẻ giữa chủ và nô lệ.

Nhiều Cảm biến sử dụng giao thức truyền thông nối tiếp này để truyền dữ liệu của chúng đến các bộ vi điều khiển hoặc thông qua giao thức này, các mạch phụ khác nhau có thể giao tiếp với các mạch chủ. Nó chỉ áp dụng cho việc truyền dữ liệu khoảng cách ngắn.

Chân I2C

Đặc điểm nổi bật của I2C so với SPI là nó chỉ sử dụng hai dây để thực hiện giao tiếp. Một dây là SCL (dòng đồng hồ nối tiếp) đồng bộ hóa việc truyền dữ liệu giữa các thiết bị và dây còn lại là SDA (dữ liệu nối tiếp) mang dữ liệu thực tế cần truyền. Các đường này là các đường thoát nước mở có nghĩa là chúng cần được kết nối để kéo điện trở lên nếu các thiết bị hoạt động ở mức thấp. Mỗi thiết bị phụ được kết nối với xe buýt sẽ có một địa chỉ 8-bit duy nhất.

Lưu ý: Dòng SDA còn được gọi là SDI và dòng SCL còn được gọi là SCK.

Việc giao tiếp giữa các thiết bị cụ thể sử dụng hai dây được thực hiện bởi thực tế là mỗi thiết bị có ID hoặc địa chỉ thiết bị duy nhất của riêng mình và sử dụng địa chỉ này; Master có thể chọn bất kỳ thiết bị cụ thể nào để giao tiếp.

Ví dụ, chúng ta có thể kết nối nhiều nô lệ với một chủ. ESP32 được cấu hình như một thiết bị chính và nhiều thiết bị phụ được kết nối với cùng một bus.

Sơ đồ I2C chủ và nô lệ

Chúng ta cũng có thể kết nối nhiều chủ nhân điều khiển cùng một nô lệ. Ví dụ: hai bo mạch ESP32 được định cấu hình làm thiết bị chính được kết nối với cùng một thiết bị phụ.

Bus I2C

Bus I2C bao gồm nhiều thiết bị như thiết bị phụ và thiết bị chính. Mỗi thiết bị được kết nối với bus I2C có thể ở chế độ chính hoặc ở chế độ phụ. Nhưng chỉ có một thiết bị chính mới có thể bắt đầu quá trình truyền dữ liệu. Thông thường, có một chủ và một thiết bị phụ hoặc nhiều thiết bị phụ được kết nối với cùng một bus I2C thông qua các điện trở kéo lên. Mỗi địa chỉ salve có một địa chỉ duy nhất 7-bit.

Thiết bị phụ

Mỗi thiết bị phụ có một địa chỉ duy nhất được sử dụng để nhận dạng thiết bị trên xe buýt. Nói cách khác, địa chỉ nô lệ giúp thiết bị chính gửi thông tin đến một
thiết bị phụ cụ thể trên bus.

Thiết bị chính

Các thiết bị chính có thể gửi và nhận thông tin. Thiết bị phụ phản ứng với bất cứ điều gì một thiết bị chính gửi. Khi gửi thông tin trên bus, chỉ cần một thiết bị duy nhất có thể gửi thông tin tại một thời điểm.

Tóm lại, chúng ta chỉ cần hai dây để truyền dữ liệu hoặc giao tiếp với các số lượng thiết bị khác nhau. I2C cho phép chúng tôi kết nối với nhiều thiết bị cùng một lúc. Tuy nhiên, bạn không thể sử dụng giao thức này để truyền dữ liệu đường dài.

Chân I32C ESP2

Như đã đề cập trước đó ESP32 có 2 bộ điều khiển I2C có thể được sử dụng để xử lý giao tiếp trên bus I2C. Chúng ta có thể cấu hình chính hoặc phụ. Bây giờ chúng ta hãy xem các chân GPIO mặc định được gán cho bộ điều khiển I2C trong thư viện Arduino IDE cho ESP32.

Chân I2C mặc định trong ESP32 cho SDA là GPIO21 và cho SCL là GPIO22. Nếu chúng ta muốn thay đổi các chân GPIO, chúng ta phải đặt chúng trong mã. Sơ đồ dưới đây cho thấy sơ đồ chân cho ESP32 hiển thị các chân I2C mặc định.

Chân I32C ESP2

Giao diện ESP32 I2C có các tính năng sau:

  • Chế độ tiêu chuẩn (100 Kbit/s)

  • Chế độ nhanh (400 Kbit/s)

  • Lên đến 5 MHz, nhưng bị hạn chế bởi cường độ kéo lên SDA

  • Chế độ định địa chỉ 7-bit/10-bit

  • Chế độ địa chỉ kép

Sử dụng nhiều thiết bị I2C nô lệ với ESP32 (thiết bị I2C có địa chỉ khác nhau)

Trong phần này, trước tiên chúng ta sẽ kết nối ba thiết bị I2C khác nhau với bảng ESP32 bằng các chân I2C mặc định. Sau đó, chúng tôi sẽ lập trình bảng của mình để chạy máy quét I2C.

Các thành phần cần thiết

  1. Bảng phát triển ESP32

  2. Màn hình OLED SSD1306

  3. Cảm biến BME280

  4. Cảm biến MPU6050

  5. Breadboard

  6. Dây kết nối

Trước tiên, hãy để chúng tôi giới thiệu ngắn gọn về ba thiết bị I2C mà chúng tôi sẽ sử dụng trong hướng dẫn này: SSD1306 OLED, BME280 và MPU6050.

Màn hình OLED SSD1306 0,96inch

Mặc dù có một số loại màn hình OLED có sẵn trên thị trường, nhưng loại màn hình mà chúng tôi sẽ sử dụng là màn hình OLED 1306.0 inch SSD96. Thành phần chính của tất cả các loại màn hình OLED khác nhau là bộ điều khiển SSD1306 sử dụng giao thức I2C hoặc SPI để giao tiếp với các bộ vi điều khiển. Màn hình OLED có thể khác nhau về kích thước, màu sắc và hình dạng nhưng chủ yếu được lập trình theo cách tương tự.

Hãy để chúng tôi xem xét màn hình OLED mà chúng tôi sẽ sử dụng trong bài viết này. Nó được gọi là SSD 1306 Màn hình OLED 0.96 inch có 128×64 pixel và chỉ giao tiếp qua giao thức I2C với bo mạch Pi Pico. Nó rẻ và có sẵn trên thị trường.

Sơ đồ sơ đồ chân OLED

BME280 ·

Cảm biến BME280 được sử dụng để đo các chỉ số liên quan đến nhiệt độ môi trường, áp suất khí quyển và độ ẩm tương đối. Nó chủ yếu được sử dụng trong các ứng dụng web và di động, nơi tiêu thụ điện năng thấp là chìa khóa. Cảm biến này sử dụng hoặc để giao tiếp dữ liệu với các bộ điều khiển vi mô. Mặc dù có một số phiên bản BME280 khác nhau có sẵn trên thị trường, nhưng phiên bản chúng tôi sẽ nghiên cứu sử dụng giao thức truyền thông I2C.

Sơ đồ sơ đồ chân BME280

ESP32 giao tiếp với cảm biến BME280 thông qua giao thức I2C để cung cấp các chỉ số về nhiệt độ, áp suất khí quyển và độ ẩm tương đối.

Mô-đun cảm biến MPU6050

Mô-đun cảm biến MPU6050 là mô-đun MEMS (Hệ thống cơ điện tử) có chứa mạch tích hợp MPU6050 IC. Con chip này chứa con quay hồi chuyển ba trục, gia tốc kế ba trục và bộ xử lý điều khiển chuyển động kỹ thuật số trong một gói IC duy nhất. Trên hết, nó cũng chứa một cảm biến nhiệt độ tích hợp.

MPU6050 cung cấp dữ liệu đầu ra trên bus . Do đó, chúng ta có thể sử dụng giao diện bus I2C của MPU6050 để chuyển gia tốc kế 3 trục và các giá trị con quay hồi chuyển 3 trục sang Raspberry Pi Pico. Nói cách khác, chúng ta có thể sử dụng bất kỳ bộ vi điều khiển nào có cổng I2C để đọc dữ liệu đầu ra của cảm biến. Có một địa chỉ chuyên dụng cụ thể được gán cho từng giá trị tham số trong giao diện MPU6050 I2C. Chúng tôi có thể sử dụng các địa chỉ này để nhận các giá trị cụ thể từ cảm biến như gia tốc, con quay hồi chuyển và nhiệt độ.

Một trong những lợi thế của việc sử dụng giao diện I2C của cảm biến này là chúng ta có thể giao tiếp nhiều mô-đun MPU5060 bằng một bộ vi điều khiển duy nhất.

Mô-đun cảm biến MPU6050 Gia tốc kế Cảm biến nhiệt độ con quay hồi chuyển

Giao diện ESP32 với OLED, BME280 và MPU6050

ESP32 với OLED, BME280 và MPU6050

Hãy để chúng tôi xem cách kết nối ESP32 với mô-đun OLED, BME280 và MPU6050 với nhau. Chúng tôi sẽ sử dụng một đường dây I2C chung để kết nối tất cả các thiết bị. ESP32 sẽ hoạt động như một bậc thầy và cảm biến BME280, cảm biến MPU6050 và OLED sẽ hoạt động như nô lệ.

Các kết nối giữa bốn thiết bị mà chúng tôi đang sử dụng có thể được nhìn thấy trong bảng dưới đây.

ESP32 ·

Màn hình OLED SSD1306

BME280 ·

Mpu6050 ·

3.3V

VCC

VCC

VCC

GPIO21 (I2C SDA)

SDA

SDA

SDA

GPIO22 (I2C SCL)

SCL

SCL

SCL

GND ·

GND ·

GND ·

GND ·

Chúng tôi đã sử dụng các kết nối tương tự như được chỉ định trong bảng trên.

ESP32 I2C sử dụng nhiều thiết bị I2C

Máy quét I32C ESP2 Bản phác thảo Arduino

Mỗi thiết bị I2C đều có một địa chỉ được liên kết với nó. ESP32 sử dụng địa chỉ này để giao tiếp với nô lệ thông qua giao thức I2C.

Bây giờ sao chép mã này và tải lên bảng của bạn với tất cả các thiết bị I2C đã được kết nối với nó.

Mã này sẽ quét tìm bất kỳ thiết bị I2C nào được kết nối với ESP32 và sẽ chỉ định số lượng thiết bị có địa chỉ trong thiết bị đầu cuối nối tiếp.

#include <Wire.h>

 

void setup() {

  Wire.begin();

  Serial.begin(115200);

  Serial.println("\nI2C Scanner");

    byte error, address;

  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;

  for(address = 1; address < 127; address++ ) {

    Wire.beginTransmission(address);

    error = Wire.endTransmission();

    if (error == 0) {

      Serial.print("I2C device found at address 0x");

      if (address<16) {

        Serial.print("0");

      }

      Serial.println(address,HEX);

      nDevices++;

    }

    else if (error==4) {

      Serial.print("Unknown error at address 0x");

      if (address<16) {

        Serial.print("0");

      }

      Serial.println(address,HEX);

    }    

  }

  if (nDevices == 0) {

    Serial.println("No I2C devices found\n");

  }

  else {

    Serial.println("done\n");

  }

  delay(5000);  

  Serial.print("i2c devices found:");

  Serial.println(nDevices); 

}

 

void loop() {

      

}

Máy quét I32C ESP2 trong Arduino IDE

Máy quét I2C đã xác định được 3 thiết bị được kết nối với giao diện I2C. Địa chỉ I2C của màn hình OLED là 0x3C, MPU6050 là 0x68, BME280 là 0x76.

Vì tất cả ba thiết bị I2C này đều có các địa chỉ khác nhau nên có thể chia sẻ cùng một bus I2C.

Sử dụng nhiều thiết bị I2C có cùng địa chỉ ESP32

Trong phần trước, chúng tôi có thể kết nối ba thiết bị I2C khác nhau trên cùng một chân I2C của ESP32. Điều này là do ESP32 đã có thể xác định chúng do địa chỉ duy nhất của chúng. Tuy nhiên, điều gì sẽ xảy ra khi chúng ta muốn kết nối nhiều thiết bị với ESP32 để giao tiếp I2C nhưng chúng có cùng địa chỉ? Ví dụ: hai cảm biến BME280 được kết nối với ESP32 hoặc hai OLED được kết nối với ESP32.

TCA9548A 1-to-8 I2C Multiplexer ic

Để sử dụng cùng một thiết bị I2C với bo mạch ESP32, chúng tôi sẽ phải thay đổi địa chỉ I2C của thiết bị hoặc sử dụng bộ ghép kênh I2C. Tuy nhiên, việc thay đổi địa chỉ của một thiết bị không đơn giản và nó chỉ cho phép sử dụng một số thiết bị hạn chế trên cùng một bus I2C. Do đó, chúng ta có thể sử dụng một bộ ghép kênh, ví dụ. TCA9548A sẽ cho phép kết nối tối đa tám thiết bị có cùng địa chỉ với cùng một bus I2C.

Thay đổi chân I32C mặc định ESP2 trong Arduino IDE

Như chúng tôi đã đề cập trước đây, chân I2C mặc định trong ESP32 cho SDA là GPIO21 và cho SCL là GPIO22. Nếu chúng ta muốn thay đổi các chân I2C mặc định, chúng ta phải đặt chúng trong mã. Hầu hết các chân GPIO của ESP32 có thể được đặt làm chân I2C.

Thư viện Wire.h được sử dụng trong Arduino IDE để giao tiếp với các thiết bị I2C. Nó sử dụng phương thức begin() trên phiên bản Wire để khởi tạo giao thức. Nếu chúng tôi không chỉ định bất kỳ tham số nào bên trong chức năng này, thì các chân I2C SDA và SCL mặc định sẽ được sử dụng.

Wire.begin();

Tuy nhiên, nếu chúng tôi muốn thay đổi các chân I2C mặc định thì chúng tôi chỉ định chúng dưới dạng tham số bên trong hàm. Wire.begin() có hai tham số. Đầu tiên là chân I2C SDA và thứ hai là chân I2C SCL mà chúng tôi muốn định cấu hình

Wire.begin(I2C_SDA, I2C_SCL);

Liên lạc qua Thư viện

Đôi khi các thư viện được tham gia để thiết lập liên lạc giữa chủ và nô lệ. Ví dụ: để giao tiếp với cảm biến BME280, chúng tôi yêu cầu thư viện Adafruit BME280. Phương pháp trên sẽ không hoạt động trong trường hợp này vì một thư viện có liên quan để thiết lập giao tiếp giữa cảm biến và bảng ESP32. Do đó, nếu bạn muốn sử dụng các chân I2C khác nhau cho các cảm biến như vậy, thì trước tiên chúng ta nên tham khảo tệp .cpp của thư viện và phân tích cẩn thận các thông số TwoWire. Trong trường hợp, các tệp thư viện chứa wire.begin(), thì trước tiên bạn sẽ phải nhận xét nó để đặt chân I2C của riêng bạn.

Hãy chứng minh điều này bằng cảm biến BME280 với ESP32. Mở Adafruit_BME.cpp và đi đến định nghĩa của phương thức begin(). Tại đây, bạn có thể thấy rằng chúng tôi có một tùy chọn để chuyển TwoWire của riêng mình sang phương pháp này.

ESP32 I2C với BME280 với các chân khác với mặc định

Thay đổi chân I2C với BME280

Trong ví dụ này, chúng tôi sử dụng GPIO4 làm SDA và GPIO5 làm SCL để có được kết quả đọc cảm biến BME280 với ESP32.

ESP32 với BME280 với các chân I2C khác nhau

Bản phác thảo Arduino

Bản phác thảo Arduino dưới đây sử dụng GPIO4 làm SDA và GPIO5 làm SCL để có được số đọc cảm biến BME280.

#include <Wire.h>

#include <Adafruit_Sensor.h>

#include <Adafruit_BME280.h>

 

#define I2C_SDA 4

#define I2C_SCL 5

 

#define SEALEVELPRESSURE_HPA (1013.25)

 

TwoWire I2CBME = TwoWire(0);

Adafruit_BME280 bme;

 

void setup() {

  Serial.begin(115200);

  I2CBME.begin(I2C_SDA, I2C_SCL, 100000ul);

  

  bool status;

  status = bme.begin(0x76, &I2CBME);  

  if (!status) {

    Serial.println("Could not find a valid BME280 sensor, check wiring!");

    while (1);

  }

  delay(1000);

  Serial.println();

}

 

void loop() { 

  Serial.print("Temperature = ");

  Serial.print(bme.readTemperature());

  Serial.println(" *C");

  

  Serial.print("Pressure = ");

  Serial.print(bme.readPressure() / 100.0F);

  Serial.println(" hPa");

 

  Serial.print("Altitude = ");

  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));

  Serial.println(" m");

 

  Serial.print("Humidity = ");

  Serial.print(bme.readHumidity());

  Serial.println(" %");

 

  Serial.println();

  delay(1000);

}

Mã hoạt động như thế nào?

Để sử dụng các chân I2C khác nhau, chúng tôi bắt đầu bằng cách xác định các chân I2C mà chúng tôi muốn đặt cho SDA và SCL trong các biến tương ứng của chúng. Trong ví dụ này, chúng tôi đang sử dụng GPIO4 làm SDA và GPIO5 làm SCL.

#define I2C_SDA 4

#define I2C_SCL 5

Tiếp theo, chúng ta sẽ tạo một phiên bản TwoWire có tên I2CBME cho bus I2C.

TwoWire I2CBME = TwoWire(0);

Bên trong hàm setup(), chúng ta sẽ khởi tạo giao tiếp I2C bằng cách sử dụng phiên bản TwoWire trên phương thức begin(). Nó có ba tham số. Tham số đầu tiên là chân SDA mà chúng ta đã xác định trước đó. Tham số thứ hai là chân SCL mà chúng ta đã xác định trước đó. Tham số thứ ba là tần số xung nhịp.

I2CBME.begin(I2C_SDA, I2C_SCL, 100000ul);

Tiếp theo, chúng ta sẽ khởi tạo đối tượng BME bằng phương thức begin() và chỉ định địa chỉ của cảm biến BME280 là tham số đầu tiên và địa chỉ của phiên bản TwoWire là tham số thứ hai.

status = bme.begin(0x76, &I2CBME);

Để có được số đọc cảm biến BME280, chúng tôi sẽ sử dụng các phương pháp tương ứng trên vật thể bme để có được số đọc nhiệt độ, áp suất và độ ẩm.

Serial.print("Temperature = ");

  Serial.print(bme.readTemperature());

  Serial.println(" *C");

  

  Serial.print("Pressure = ");

  Serial.print(bme.readPressure() / 100.0F);

  Serial.println(" hPa");

 

  Serial.print("Altitude = ");

  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));

  Serial.println(" m");

 

  Serial.print("Humidity = ");

  Serial.print(bme.readHumidity());

  Serial.println(" %");

ESP32 với BME280 với các chân I2C khác nhau màn hình nối tiếp demo

Sử dụng cả hai Giao diện Bus I2C của ESP32

Trong tất cả các ví dụ trước đây, chúng tôi chỉ sử dụng một giao diện I2C của bảng ESP32. Tuy nhiên, ESP32 cung cấp hai giao diện bus I2C, chúng ta hãy xem một số ví dụ về cách sử dụng cả hai. Có hai phương pháp để đạt được điều này.

Arduino Sketch Ví dụ 1

Trong phương pháp này, chúng tôi sẽ kết nối hai cảm biến BME280 với ESP32 trong khi sử dụng hai giao diện I2C của ESP32. Cảm biến BME280 đầu tiên sẽ được kết nối với SDA GPIO4 và SCL GPIO5 và cảm biến BME280 thứ hai sẽ được kết nối với SDA GPIO33 và SCL GPIO32.

ESP32 I2C sử dụng hai kênh I2C với chân mặc định

#include <Wire.h>

#include <Adafruit_Sensor.h>

#include <Adafruit_BME280.h>

 

#define SDA_1 4

#define SCL_1 5

 

#define SDA_2 33

#define SCL_2 32

 

TwoWire I2C_1 = TwoWire(0);

TwoWire I2C_2 = TwoWire(1);

 

Adafruit_BME280 bme1;

Adafruit_BME280 bme2;

 

void setup() {

  Serial.begin(115200);

 

  I2C_1.begin(SDA_1, SCL_1, 100000ul); 

  I2C_2.begin(SDA_2, SCL_2, 100000ul);

 

  bool status1 = bme1.begin(0x76, &I2C_1);  

  if (!status1) {

    Serial.println("Could not find a valid BME280_1 sensor, check wiring!");

    while (1);

  }

  

  bool status2 = bme2.begin(0x76, &I2C_2);  

  if (!status2) {

    Serial.println("Could not find a valid BME280_2 sensor, check wiring!");

    while (1);

  }

  

  Serial.println();

}

 

void loop() { 

  //bme1

  Serial.print("Temperature from BME1= ");

  Serial.print(bme1.readTemperature());

  Serial.println(" *C");

 

  Serial.print("Humidity from BME1 = ");

  Serial.print(bme1.readHumidity());

  Serial.println(" %");

 

  Serial.print("Pressure from BME1 = ");

  Serial.print(bme1.readPressure() / 100.0F);

  Serial.println(" hPa");

 

  Serial.println(" ");

 

  //bme2

  Serial.print("Temperature from BME2 = ");

  Serial.print(bme2.readTemperature());

  Serial.println(" *C");

 

  Serial.print("Humidity from BME2 = ");

  Serial.print(bme2.readHumidity());

  Serial.println(" %");

 

  Serial.print("Pressure from BME2 = ");

  Serial.print(bme2.readPressure() / 100.0F);

  Serial.println(" hPa");

 

  Serial.println(" ");  

  delay(5000);

}

Code hoạt động như thế nào?

Xác định chân I2C SDA và SCL cho cả cảm biến BME280. Trong trường hợp này, chúng tôi đang sử dụng GPIO4 cho SDA và GPIO5 cho SCL cho cảm biến đầu tiên. Tương tự như vậy, chúng tôi đang sử dụng GPIO33 cho SDA và GPIO32 cho SCL cho cảm biến thứ hai.

#define SDA_1 4

#define SCL_1 5

 

#define SDA_2 33

#define SCL_2 32

Tiếp theo, chúng ta sẽ được yêu cầu tạo hai phiên bản TwoWire so với một phiên bản TwoWire duy nhất cho hai giao diện bus I2C.

TwoWire I2C_1 = TwoWire(0);

TwoWire I2C_2 = TwoWire(1)

Tạo hai đối tượng Adafruit_BME280 gọi là 'bme1' cho cảm biến đầu tiên và 'bme2' cho cảm biến thứ hai. Chúng sẽ được sử dụng sau này để truy cập dữ liệu cảm biến.

Adafruit_BME280 bme1;

Adafruit_BME280 bme2;

Tiếp theo, bên trong hàm setup(), chúng ta sẽ khởi tạo giao tiếp I2C cho cả hai giao diện ở các chân và tần số I2C đã xác định.

void setup() {

  I2C_1.begin(SDA_1, SCL_1, frequency1);

  I2C_2.begin(SDA_2, SCL_2, frequency2); 

}

Hơn nữa, chúng tôi cũng sẽ khởi tạo các đối tượng bme1 và bme2 theo địa chỉ thiết bị và bus I2C.

bool status1 = bme1.begin(0x76, &I2C_1);  

bool status2 = bme2.begin(0x76, &I2C_2); 

Để có được dữ liệu cảm biến, chúng tôi sẽ sử dụng các phương pháp liên quan trên các đối tượng bme1 và bme2.

 

  //bme1

  Serial.print("Temperature from BME1= ");

  Serial.print(bme1.readTemperature());

  Serial.println(" *C");

 

  Serial.print("Humidity from BME1 = ");

  Serial.print(bme1.readHumidity());

  Serial.println(" %");

 

  Serial.print("Pressure from BME1 = ");

  Serial.print(bme1.readPressure() / 100.0F);

  Serial.println(" hPa");

 

  //bme2

  Serial.print("Temperature from BME2 = ");

  Serial.print(bme2.readTemperature());

  Serial.println(" *C");

 

  Serial.print("Humidity from BME2 = ");

  Serial.print(bme2.readHumidity());

  Serial.println(" %");

 

  Serial.print("Pressure from BME2 = ");

  Serial.print(bme2.readPressure() / 100.0F);

  Serial.println(" hPa");

Arduino Sketch Ví dụ 2

Trong phương thức thứ hai này, chúng ta sẽ sử dụng các đối tượng Wire() và Wire1() được xác định trước để sử dụng hai bus I2C, trong đó một trong số chúng sẽ sử dụng các chân I2C mặc định và chân còn lại sẽ sử dụng các chân do người dùng xác định. Chúng tôi sẽ kết nối hai cảm biến BME280 với ESP32 trong khi sử dụng hai giao diện I2C của vi điều khiển. Cảm biến BME280 đầu tiên sẽ được kết nối với các chân I2C mặc định của ESP32. Trong khi đó, cảm biến BME280 thứ hai sẽ được kết nối với SDA GPIO33 và SCL GPIO32.

ESP32 I2C sử dụng hai bus I2C với các chân khác nhau

#include <Wire.h>

#include <Adafruit_Sensor.h>

#include <Adafruit_BME280.h>

 

#define SDA_2 33

#define SCL_2 32

 

Adafruit_BME280 bme1;

Adafruit_BME280 bme2;

 

void setup() {

  Serial.begin(115200);

 

  Wire.begin();

  Wire1.begin(SDA_2, SCL_2);

 

  bool status1 = bme1.begin(0x76);  

  if (!status1) {

    Serial.println("Could not find a valid BME280_1 sensor, check wiring!");

    while (1);

  }

  

  bool status2 = bme2.begin(0x76, &Wire1);  

  if (!status2) {

    Serial.println("Could not find a valid BME280_2 sensor, check wiring!");

    while (1);

  }

 

  Serial.println();

}

 

void loop() { 

  //bme1

  Serial.print("Temperature from BME1= ");

  Serial.print(bme1.readTemperature());

  Serial.println(" *C");

 

  Serial.print("Humidity from BME1 = ");

  Serial.print(bme1.readHumidity());

  Serial.println(" %");

  

  Serial.print("Pressure from BME1 = ");

  Serial.print(bme1.readPressure() / 100.0F);

  Serial.println(" hPa");

 

  Serial.println(" ");

  

  //bme2

  Serial.print("Temperature from BME2 = ");

  Serial.print(bme2.readTemperature());

  Serial.println(" *C");

 

  Serial.print("Humidity from BME2 = ");

  Serial.print(bme2.readHumidity());

  Serial.println(" %");

  

  Serial.print("Pressure from BME2 = ");

  Serial.print(bme2.readPressure() / 100.0F);

  Serial.println(" hPa");

 

  Serial.println(" ");

  delay(5000);

}

Xác định chân I2C SDA và SCL cho cảm biến BME280 có chân I2C mà chúng tôi muốn đặt. Trong trường hợp này, chúng tôi đang sử dụng GPIO33 cho SDA và GPIO32 cho SCL cho cảm biến này.

#define SDA_2 33

#define SCL_2 32

Bên trong hàm setup(), chúng ta sẽ khởi tạo giao tiếp I2C trên bus I2C đầu tiên ở chân I2C mặc định và tần số 100000 Hz. Điều này đạt được bởi Wire.begin().

Trong khi đó, Wire1.begin(SDA_2, SCL_2) khởi tạo giao tiếp I2C trên bus I2C thứ hai tại các chân được chỉ định làm tham số bên trong nó. Ở đây chúng tôi đã xác định các chân SDA_2 và SCL_2.

  Wire.begin();

  Wire1.begin(SDA_2, SCL_2);

Ví dụ về giao tiếp nô lệ bậc thầy ESP32 I2C

Trong phần này, chúng ta sẽ thấy một ví dụ để thực hiện giao tiếp I2C giữa hai bảng ESP32. Chúng tôi sẽ định cấu hình một EPS32 làm chủ và một ESP32 khác làm thiết bị phụ.

Chúng tôi sẽ truyền các lệnh từ ESP32 I2C master đến thiết bị phụ để điều khiển đèn LED trên bo mạch của nó. Master sẽ truyền '0' và '1' với độ trễ 1 giây. Thiết bị phụ ESP32 sẽ nhận nó và bật và tắt đèn LED trên thiết bị.

ESP32 Sơ đồ kết nối chính và phụ I2C

Tạo kết nối giữa cả hai bo mạch ESP32 bằng các chân giao tiếp I2C được đưa ra bên dưới trong bảng.

 

ESP32 Chính

ESP32 phụ

SDA

GPIO21 ·

GPIO21 ·

SCL

GPIO22 ·

GPIO22 ·

 

GND ·

GND ·

esp32 i2c giao tiếp nô lệ bậc thầy Arduino ide

Cài đặt ESP32 I2C Slave Library

Dây. thư viện h chỉ cấu hình ESP32 ở chế độ chính. Để sử dụng ESP32 làm thiết bị phụ I2C, chúng ta cần cài đặt thư viện 

Mở Arduino IDE và nhấp vào Sketch > Library > Manage Libraries.

Khi bạn nhấp vào tùy chọn quản lý thư viện, bạn sẽ nhận được cửa sổ này. Trong cửa sổ này, viết 'ESP32I2CSlave' vào thanh tìm kiếm và nhấn enter.

Chọn thư viện được đánh dấu và nhấp vào cài đặt.

Cài đặt thư viện ESP32 I2C Slave Arduino

Mã chính ESP32 I2C

// Wire Master Writer

// by Gutierrez PS <https://github.com/gutierrezps>

// ESP32 I2C slave library: <https://github.com/gutierrezps/ESP32_I2C_Slave>

// based on the example by Nicholas Zambetti <http://www.zambetti.com>

 

// Demonstrates use of the Wire and WirePacker libraries.

// Writes data to an ESP32 I2C/TWI slave device that

// uses ESP32 I2C Slave library. 

// Refer to the "slave_receiver" example for use with this

 

#include <Arduino.h>

#include <Wire.h>

#include <WirePacker.h>

 

#define SDA_PIN 21

#define SCL_PIN 22

#define I2C_SLAVE_ADDR 0x04

 

void setup()

{

    Serial.begin(115200);           // start serial for output

    Wire.begin(SDA_PIN, SCL_PIN);   // join i2c bus

}

 

void loop()

{

    static unsigned long lastWireTransmit = 0;

    static byte x = 0;

 

    // send data to WireSlave device every 1000 ms

    if (millis() - lastWireTransmit > 1000) {

        // first create a WirePacker that will assemble a packet

        WirePacker packer;

 

        // then add data the same way as you would with Wire

        packer.write("x is ");

        packer.write(x);

 

        // after adding all data you want to send, close the packet

        packer.end();

 

        // now transmit the packed data

        Wire.beginTransmission(I2C_SLAVE_ADDR);

        while (packer.available()) {    // write every packet byte

            Wire.write(packer.read());

        }

        Wire.endTransmission();         // stop transmitting

        lastWireTransmit = millis();

        if(x==0)

          x = 1;

        else

        x = 0;

    }

}

Mã I32C ESP2 phụ

// WireSlave Receiver

// by Gutierrez PS <https://github.com/gutierrezps>

// ESP32 I2C slave library: <https://github.com/gutierrezps/ESP32_I2C_Slave>

// based on the example by Nicholas Zambetti <http://www.zambetti.com>

 

// Demonstrates use of the WireSlave library for ESP32.

// Receives data as an I2C/TWI slave device; data must

// be packed using WirePacker.

// Refer to the "master_writer" example for use with this

 

#include <Arduino.h>

#include <Wire.h>

#include <WireSlave.h>

 

#define SDA_PIN 21

#define SCL_PIN 22

#define I2C_SLAVE_ADDR 0x04

 

#define LED 2

 

void receiveEvent(int howMany);

 

void setup()

{

    Serial.begin(115200);

    pinMode(LED, OUTPUT);

    bool success = WireSlave.begin(SDA_PIN, SCL_PIN, I2C_SLAVE_ADDR);

    if (!success) {

        Serial.println("I2C slave init failed");

        while(1) delay(100);

    }

 

    WireSlave.onReceive(receiveEvent);

}

 

void loop()

{

    // the slave response time is directly related to how often

    // this update() method is called, so avoid using long delays

    // inside loop(), and be careful with time-consuming tasks

    WireSlave.update();

 

    // let I2C and other ESP32 peripherals interrupts work

    delay(1);

}

 

// function that executes whenever a complete and valid packet

// is received from master

// this function is registered as an event, see setup()

void receiveEvent(int howMany)

{

    while (1 < WireSlave.available()) // loop through all but the last byte

    {

        char c = WireSlave.read();  // receive byte as a character

        Serial.print(c);            // print the character

    }

 

    int x = WireSlave.read();   // receive byte as an integer

    Serial.println(x);          // print the integer

 

    if(x == 1)

    {

        Serial.println("Setting LED active HIGH ");

        digitalWrite(LED, HIGH);

    }

    else if(x == 0)

    {

        Serial.println("Setting LED active LOW ");

        digitalWrite(LED, LOW);

    }

     Serial.println("");

 

}

Bây giờ hãy tải các bản phác thảo trên lên bảng ESP32 chính và nô lệ.

Sau khi tải bản phác thảo Arduino lên cả hai bảng ESP32, hãy mở màn hình nối tiếp của thiết bị nô lệ, bạn sẽ nhận được các thông báo sau trên màn hình nối tiếp:

Giao tiếp nô lệ chính I2C giữa hai bảng ESP32

Bạn cũng sẽ thấy rằng đèn LED trên bo mạch của nô lệ ESP32 sẽ bật và tắt với độ trễ một giây.

Giao tiếp ESP32 I2C giữa hai bo mạch

>>> 100+ Mã Sản Phẩm Dây Rút: https://mecsu.vn/san-pham/day-rut-nhua.5op

>>> 1000+ Mã Sản Phẩm Đầu Cosse: https://mecsu.vn/san-pham/dau-cosse.Q1j

Bài viết cùng chuyên mục

NHANH

NHANH

Vì Đổi mới liên tục nên Nhanh hơn

ĐÚNG

ĐÚNG

Coi trọng và ưu tiên việc làm Đúng

ĐỦ

ĐỦ

Tìm và mua Đủ Đơn hàng hơn

KỊP THỜI

KỊP THỜI

Hiệu suất tối ưu bởi Kịp Thời hơn