Как подключить несколько устройств 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 работать одновременно?
Пожалуйста, помогите...
@wieb, 👍0
Обсуждение3 ответа
Лучший ответ:
Я использовал 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
Я думаю, что проблема связана с инициализацией 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
Вот код для подключения 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).
Надеюсь, это поможет всем, у кого такая же проблема, как у меня.
- C++ против языка Arduino?
- avrdude ser_open() can't set com-state
- Как читать и записывать EEPROM в ESP8266
- Float печатается только 2 десятичных знака после запятой
- устаревшее преобразование из строковой константы в 'char*'
- Запрограммировать ATMega328P и использовать его без платы Arduino.
- Разница между print() и println()
- Как исправить: Invalid conversion from 'const char*' to 'char*' [-fpermissive]
почему ваш код содержит функции Wi-Fi? .... сократите свой код до минимума..... отобразите фиксированный текст на OLED и прочитайте одно значение из INA219, @jsotola
почему вы используете два экземпляра TwoWire? I2C — это шина. подключите оба устройства к одной и той же паре контактов, @Juraj