Как подключить несколько устройств I2C?

Я пытаюсь подключить I2C OLED SSD1306 и I2C INA219 к ESP32, но безуспешно.

Первая попытка:

#include <WiFi.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_INA219.h>
Adafruit_INA219 ina219;

#define SDA1 21  //OLED SSD1306
#define SCL1 22  //OLED SSD1306
#define SDA2 5  //INA219
#define SCL2 4  //INA219

float shuntvoltage = 0;
float busvoltage = 0;
float current_mA = 0;
float current_A = 0;
float loadvoltage = 0;
float power_W = 0;


#define SCREEN_WIDTH 128 
#define SCREEN_HEIGHT 64 
#define OLED_RESET   0
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const char* ssid     = "SSID";
const char* password = "PASSWORD";

IPAddress local_IP(192, 168, 0, 241);
IPAddress gateway(192, 168, 0, 230);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);   
IPAddress secondaryDNS(8, 8, 4, 4); 

void setup()
{
  Serial.begin(115200);

  Wire.begin(SDA1, SCL1); 

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Не продолжать, цикл бесконечен
  }

   display.fillScreen(BLACK);
   display.setTextColor(WHITE);
   display.setTextWrap(false);  

   startWiFi(); 

  Wire.begin(SDA2, SCL2); 
  ina219.begin();


  display.ssd1306_command(SSD1306_DISPLAYOFF);
  delay(5000);
  display.ssd1306_command(SSD1306_DISPLAYON);
  display.println("Awake!");
  display.display();

}


void loop()
{
      shuntvoltage = ina219.getShuntVoltage_mV();
      busvoltage = ina219.getBusVoltage_V();
      current_mA = ina219.getCurrent_mA();
      loadvoltage = busvoltage + (shuntvoltage / 1000);
      current_A = current_mA / 1000;
      power_W = current_A * loadvoltage; 

      Serial.println("");
      Serial.print("Bus Voltage:   "); Serial.print(busvoltage); Serial.println(" V");
      Serial.print("Shunt Voltage: "); Serial.print(shuntvoltage); Serial.println(" mV");
      Serial.print("Load Voltage:  "); Serial.print(loadvoltage); Serial.println(" V");
      Serial.print("Current:       "); Serial.print(current_mA); Serial.println(" mA");
      Serial.print("Power:       "); Serial.print(power_W); Serial.println(" w");
      Serial.println("");

  delay(1000);

  display.stopscroll();
  display.fillScreen(BLACK);
  display.invertDisplay(0);

  testscrolltext("TESTING");    // Рисуем прокручиваемый текст


}

const char* wl_status_to_string(wl_status_t status) {
  switch (status) {
    case WL_NO_SHIELD: return "WL_NO_SHIELD";
    case WL_IDLE_STATUS: return "WL_IDLE_STATUS";
    case WL_NO_SSID_AVAIL: return "WL_NO_SSID_AVAIL";
    case WL_SCAN_COMPLETED: return "WL_SCAN_COMPLETED";
    case WL_CONNECTED: return "WL_CONNECTED";
    case WL_CONNECT_FAILED: return "WL_CONNECT_FAILED";
    case WL_CONNECTION_LOST: return "WL_CONNECTION_LOST";
    case WL_DISCONNECTED: return "WL_DISCONNECTED";
  }
}


void printWifiStatus() {
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  Serial.print("Gateway: ");
  Serial.println(WiFi.gatewayIP());
  Serial.print("Subnet: ");
  Serial.println(WiFi.subnetMask());
  Serial.print("Primary DNS: ");
  Serial.println(primaryDNS);

  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");

  Serial.printf("BSSID: %s\n", WiFi.BSSIDstr().c_str());
  Serial.println("Connected to wifi");
}


void startWiFi() { // Запускаем точку доступа Wi-Fi и пытаемся подключиться к некоторым заданным точкам доступа. Затем дождитесь подключения AP или STA.

typedef enum {
    WL_NO_SHIELD        = 255,   // для совместимости с библиотекой WiFi Shield
    WL_IDLE_STATUS      = 0,
    WL_NO_SSID_AVAIL    = 1,
    WL_SCAN_COMPLETED   = 2,
    WL_CONNECTED        = 3,
    WL_CONNECT_FAILED   = 4,
    WL_CONNECTION_LOST  = 5,
    WL_DISCONNECTED     = 6
} wl_status_t;

  WiFi.begin(ssid, password);
  Serial.print("MAC Address: ");
  Serial.println(WiFi.macAddress());    
  WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
  WiFi.mode(WIFI_STA); 
  Serial.println("Connecting Wifi...");
  delay(5000);

  // Ожидаем соединения
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println("NOT Connected to wifi");
    Serial.print("Status: ");
    Serial.println(wl_status_to_string(WiFi.status()));
    WiFi.begin(ssid, password);     
  WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
    WiFi.mode(WIFI_STA); 
    delay(5000);
    ESP.restart();
  }

  //Если соединение успешно, отобразить IP-адрес на последовательном мониторе
  Serial.println("Connected to wifi");
  printWifiStatus();

}

void testscrolltext(char * text) {
  display.clearDisplay();

  display.setTextSize(2); // Рисуем текст в масштабе 2X
  display.setTextColor(WHITE);
  display.setCursor(10, 0);
  display.println(F(text));
  display.display();      // Показ исходного текста
  delay(100);

  // Прокрутка в разных направлениях с паузой между ними:
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
}

OLED не работает. А вот INA219 работает отлично.

Вторая попытка:

#include <WiFi.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_INA219.h>
Adafruit_INA219 ina219;

#define SDA1 21  //OLED SSD1306
#define SCL1 22  //OLED SSD1306
#define SDA2 5  //INA219
#define SCL2 4  //INA219

TwoWire I2Cone = TwoWire(0);
TwoWire I2Ctwo = TwoWire(1);

float shuntvoltage = 0;
float busvoltage = 0;
float current_mA = 0;
float current_A = 0;
float loadvoltage = 0;
float power_W = 0;


#define SCREEN_WIDTH 128 
#define SCREEN_HEIGHT 64 
#define OLED_RESET   0
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const char* ssid     = "SSID";
const char* password = "PASSWORD";

IPAddress local_IP(192, 168, 0, 241);
IPAddress gateway(192, 168, 0, 230);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);   
IPAddress secondaryDNS(8, 8, 4, 4); 

void setup()
{
  Serial.begin(115200);

  I2Cone.begin(SDA1,SCL1,400000); 
  I2Ctwo.begin(SDA2,SCL2,400000); 

  I2Cone.beginTransmission(0x3C);
  I2Ctwo.beginTransmission(0x40);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Не продолжать, цикл бесконечен
  }

   display.fillScreen(BLACK);
   display.setTextColor(WHITE);
   display.setTextWrap(false);  

  startWiFi(); 
  ina219.begin();


  display.ssd1306_command(SSD1306_DISPLAYOFF);
  delay(5000);
  display.ssd1306_command(SSD1306_DISPLAYON);
  display.println("Awake!");
  display.display();

}


void loop()
{

      shuntvoltage = ina219.getShuntVoltage_mV();
      busvoltage = ina219.getBusVoltage_V();
      current_mA = ina219.getCurrent_mA();
      loadvoltage = busvoltage + (shuntvoltage / 1000);
      current_A = current_mA / 1000;
      power_W = current_A * loadvoltage; 

      Serial.println("");
      Serial.print("Bus Voltage:   "); Serial.print(busvoltage); Serial.println(" V");
      Serial.print("Shunt Voltage: "); Serial.print(shuntvoltage); Serial.println(" mV");
      Serial.print("Load Voltage:  "); Serial.print(loadvoltage); Serial.println(" V");
      Serial.print("Current:       "); Serial.print(current_mA); Serial.println(" mA");
      Serial.print("Power:       "); Serial.print(power_W); Serial.println(" w");
      Serial.println("");

  delay(1000);

  display.stopscroll();
  display.fillScreen(BLACK);
  display.invertDisplay(0);

  testscrolltext("TESTING");    // Рисуем прокручиваемый текст


}

OLED работает отлично. Но INA219 не работает.

Как заставить OLED SSD1306 и INA219 работать одновременно?

Пожалуйста, помогите...

, 👍0

Обсуждение

почему ваш код содержит функции Wi-Fi? .... сократите свой код до минимума..... отобразите фиксированный текст на OLED и прочитайте одно значение из INA219, @jsotola

почему вы используете два экземпляра TwoWire? I2C — это шина. подключите оба устройства к одной и той же паре контактов, @Juraj


3 ответа


Лучший ответ:

0

Я использовал oled-дисплей 128*64 с ina219. Оба они работали нормально. Проверьте приведенный ниже код. Надеюсь, это поможет.

#include <Adafruit_INA219.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>

#define I2C_OLED_ADDRESS    0x3C
#define I2C_INA219_ADDRESS  0x40

#define OLED_RESET  4

 Adafruit_SSD1306 oled(OLED_RESET);
 Adafruit_INA219 ina219;

 void initialize_device () {

  oled.begin (SSD1306_SWITCHCAPVCC, I2C_OLED_ADDRESS);
  oled.setTextColor (WHITE);
  oled.clearDisplay ();

  ina219.begin ();
}

 void refresh_oled (float current_ma, float load_voltage) {
  oled.clearDisplay ();

  oled.setTextSize (2);
  oled.setCursor (0, 0);
  oled.print ("V:"); oled.print (load_voltage); oled.print ('V'); 
  oled.setCursor(0, 20);
  oled.print ("I:"); oled.print (current_ma); oled.print ("mA");

  oled.display();
}

 void setup () {
  initialize_device ();
}

 void loop () {

  float current_ma = ina219.getCurrent_mA ();
  float load_voltage = ina219.getBusVoltage_V () + (ina219.getShuntVoltage_mV() / 1000);

  refresh_oled (current_ma, load_voltage);

  delay(100);
}
,

Обратите внимание, что оба модуля были подключены к одним и тем же линиям шины I2C., @thilinaur

Большое спасибо за заметку, Тилинаур. Благодаря вашей заметке я понял свою ошибку. I2C не требует отдельных контактов SDA SCL. Пока каждое устройство имеет отдельные адреса, можно использовать одни и те же контакты SDA SCL., @wieb


0

Я думаю, что проблема связана с инициализацией INA219.

В соответствии с функцией begin класса Adafruit_INA219.< /п>

Использовать:

ina219.begin(&I2CTwo);

вместо

ina219.begin();

,

Согласно конструктору класса Adafruit_INA219, адрес INA219 по умолчанию равен 0x40. Пока адрес INA219 равен «0x40», нет необходимости в «ina219.begin(&I2CTwo)». ina219.begin() автоматически найдет 0x40., @wieb

@wieb, проблема НЕ в адресе, а в экземпляре класса i2c, который нужно использовать. Я имел в виду функцию начала, а не конструктор., @leoc7


0

Вот код для подключения I2C OLED SSD1306 и I2C INA219 к ESP32, которые будут работать одновременно

#include <WiFi.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_INA219.h>
Adafruit_INA219 ina219;

#define SDA 21  //OLED SSD1306 & контакт INA219
#define SCL 22  //OLED SSD1306 & контакт INA219

float shuntvoltage = 0;
float busvoltage = 0;
float current_mA = 0;
float current_A = 0;
float loadvoltage = 0;
float power_W = 0;


#define SCREEN_WIDTH 128 
#define SCREEN_HEIGHT 64 
#define OLED_RESET   0
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const char* ssid     = "SSID";
const char* password = "PASSWORD";

IPAddress local_IP(192, 168, 0, 241);
IPAddress gateway(192, 168, 0, 230);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);   
IPAddress secondaryDNS(8, 8, 4, 4); 

void setup()
{
  Serial.begin(115200);

  Wire.begin(SDA, SCL); 

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { 
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Не продолжать, цикл бесконечен
  }

   display.fillScreen(BLACK);
   display.setTextColor(WHITE);
   display.setTextWrap(false);  

  startWiFi(); 
  ina219.begin();


  display.ssd1306_command(SSD1306_DISPLAYOFF);
  delay(5000);
  display.ssd1306_command(SSD1306_DISPLAYON);
  display.println("Awake!");
  display.display();

}


void loop()
{

      shuntvoltage = ina219.getShuntVoltage_mV();
      busvoltage = ina219.getBusVoltage_V();
      current_mA = ina219.getCurrent_mA();
      loadvoltage = busvoltage + (shuntvoltage / 1000);
      current_A = current_mA / 1000;
      power_W = current_A * loadvoltage; 

      Serial.println("");
      Serial.print("Bus Voltage:   "); Serial.print(busvoltage); Serial.println(" V");
      Serial.print("Shunt Voltage: "); Serial.print(shuntvoltage); Serial.println(" mV");
      Serial.print("Load Voltage:  "); Serial.print(loadvoltage); Serial.println(" V");
      Serial.print("Current:       "); Serial.print(current_mA); Serial.println(" mA");
      Serial.print("Power:       "); Serial.print(power_W); Serial.println(" w");
      Serial.println("");

  delay(1000);

  display.stopscroll();
  display.fillScreen(BLACK);
  display.invertDisplay(0);

  testscrolltext("TESTING");    // Рисуем прокручиваемый текст


}

const char* wl_status_to_string(wl_status_t status) {
  switch (status) {
    case WL_NO_SHIELD: return "WL_NO_SHIELD";
    case WL_IDLE_STATUS: return "WL_IDLE_STATUS";
    case WL_NO_SSID_AVAIL: return "WL_NO_SSID_AVAIL";
    case WL_SCAN_COMPLETED: return "WL_SCAN_COMPLETED";
    case WL_CONNECTED: return "WL_CONNECTED";
    case WL_CONNECT_FAILED: return "WL_CONNECT_FAILED";
    case WL_CONNECTION_LOST: return "WL_CONNECTION_LOST";
    case WL_DISCONNECTED: return "WL_DISCONNECTED";
  }
}


void printWifiStatus() {
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  Serial.print("Gateway: ");
  Serial.println(WiFi.gatewayIP());
  Serial.print("Subnet: ");
  Serial.println(WiFi.subnetMask());
  Serial.print("Primary DNS: ");
  Serial.println(primaryDNS);

  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");

  Serial.printf("BSSID: %s\n", WiFi.BSSIDstr().c_str());
  Serial.println("Connected to wifi");
}


void startWiFi() { // Запускаем точку доступа Wi-Fi и пытаемся подключиться к некоторым заданным точкам доступа. Затем дождитесь подключения AP или STA.

typedef enum {
    WL_NO_SHIELD        = 255,   // для совместимости с библиотекой WiFi Shield
    WL_IDLE_STATUS      = 0,
    WL_NO_SSID_AVAIL    = 1,
    WL_SCAN_COMPLETED   = 2,
    WL_CONNECTED        = 3,
    WL_CONNECT_FAILED   = 4,
    WL_CONNECTION_LOST  = 5,
    WL_DISCONNECTED     = 6
} wl_status_t;

  WiFi.begin(ssid, password);
  Serial.print("MAC Address: ");
  Serial.println(WiFi.macAddress());    
  WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
  WiFi.mode(WIFI_STA); 
  Serial.println("Connecting Wifi...");
  delay(5000);

  // Ожидаем соединения
  while (WiFi.status() != WL_CONNECTED) {
    Serial.println("NOT Connected to wifi");
    Serial.print("Status: ");
    Serial.println(wl_status_to_string(WiFi.status()));
    WiFi.begin(ssid, password);     
  WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS);
    WiFi.mode(WIFI_STA); 
    delay(5000);
    ESP.restart();
  }

  //Если соединение успешно, отобразить IP-адрес на последовательном мониторе
  Serial.println("Connected to wifi");
  printWifiStatus();

}

void testscrolltext(char * text) {
  display.clearDisplay();

  display.setTextSize(2); // Рисуем текст в масштабе 2X
  display.setTextColor(WHITE);
  display.setCursor(10, 0);
  display.println(F(text));
  display.display();      // Показ исходного текста
  delay(100);

  // Прокрутка в разных направлениях с паузой между ними:
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
}

ПРИМЕЧАНИЕ. И OLED SSD1306, и INA219 должны использовать один и тот же SDA & Контакты SCL (контакты 21 и 22 на ESP32).

Надеюсь, это поможет всем, у кого такая же проблема, как у меня.

,