Problema Arduino nano con dos pantallas OLED SSD1306 - SOLUCIONADO

Nada. Las dos pantallas en negro. :frowning:
No te hará falta direccionar el multiplexor en la dirección 0x70?

Hi,
Adjunto esta la pagina 6 que explica como selecionar el multiplexor y los canales. Como vez para seleccionar la direccion del multiplexor los primero 4 bits = E y los otros 4 bits son la direccion y el bit de write = 0 por lo tanto el byte para selecionar el multiplexor con la direccion de zero es 0xE0. Para seleccionar el canal 0 = 0x01 y para seleccionar el canal 2 = 0x02. Como ya mencione automaticamente el multiplexe va a leer el canal 0. En el setup se initializa solamente el canal zero ya que el canal 1 no va a hacer initializado a menos que no se haga manual. Por eso yo le anadi el begin siempre que selecciona el canal. Pero aparentemente no trabaja.
Adjunto la pagina 6 que expliaca como initializar el multiplexor.No se si se necesita usar la instrucion available para despues enviar los dos bytes.

No se, reconozco que me está fundiendo las neuronas.
Si que puedo decir que el primer programa que he puesto en el post, la asignación de pantallas funciona correctamente salvo que parece que las gestiona como de 32 líneas en vez de 64.

Hi,
Aqui encontre un link que dice que el address es 0x70 y incluye un ejemplo>Te paso el link. No entiendo por que el data sheet dice que el address es 0xE0. Voy a ver el code para ver como hace en este link para cambiar los canales. Trata el sketch usando el address de 0x70.

https://www.instructables.com/TCA9548A-I2C-Multiplexer-Module-With-Arduino-and-N/

Hi,
Por fin encontre un sketch que usa 3 modulos de AM232X y la libreria #include "TCA9548.h". Mira ver si lo puedes adaptar a tu dos pantallas. Este se te va hacer facil aptarlo ya que usa la libreria.

//
//    FILE: TCA9548_demo_AM2320.ino
//  AUTHOR: Rob Tillaart
// PURPOSE: demo TCA9548 I2C multiplexer
//     URL: https://github.com/RobTillaart/TCA9548


#include "AM232X.h"
#include "TCA9548.h"

PCA9546 MP(0x70);
uint8_t channels = 0;

AM232X living;    //  channel 0
AM232X kitchen;   //  channel 1
AM232X outside;   //  channel 2

uint32_t lastTime = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("TCA9548_LIB_VERSION: ");
  Serial.println(TCA9548_LIB_VERSION);
  Serial.print("AM232X_LIB_VERSION: ");
  Serial.println(AM232X_LIB_VERSION);
  Serial.println();

  Wire.begin();
  //  initialize multiplexer
  if (MP.begin() == false)
  {
    Serial.println("Multiplexer error");
  }
  channels = MP.channelCount();

  //  initialize the temperature sensors
  MP.selectChannel(0);
  if (living.begin() == false)
  {
    Serial.println("living error");
  }
  MP.selectChannel(1);
  if (kitchen.begin() == false )
  {
    Serial.println("kitchen error");
  }
  MP.selectChannel(2);
  if (outside.begin() == false )
  {
    Serial.println("outside error");
  }
}


void loop()
{
  if ((millis() - lastTime) > 5000)
  {
    lastTime = millis();
   
    MP.selectChannel(0);
    living.read();
    Serial.print(living.getTemperature(), 1);
    Serial.print("\t");
    
    MP.selectChannel(1);
    kitchen.read();
    Serial.print(kitchen.getTemperature(), 1);
    Serial.print("\t");
  
    MP.selectChannel(2);
    outside.read();
    Serial.print(outside.getTemperature(), 1);
    Serial.print("\n");
  }
}


//  -- END OF FILE --
 

Gracias, es un gran aporte.
El programa modificado con tus cambios funciona bien. Muestra en cada pantalla el texto correspondiente.
Pero con las corrdenadas 0,25, el texto sigue apareciendo en la parte inferior de las pantallas, como si fueras de 32 líneas, y con la fuente como si hubiera líneas en negro entre las blancas que forman la imagen.
¿Puede ser la causa que la libreria Adafruit no se comunique correctamente con estas pantallas en concreto? Porque es extraño lo que ocurre.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "TCA9548.h"

#define OLED_Address 0x3C
#define OLED_RESET -1

#define SCREEN_WIDTH 128 // OLED ancho display
#define SCREEN_HEIGHT 64 // OLED alura display

Adafruit_SSD1306 oled0(OLED_RESET);
Adafruit_SSD1306 oled1(OLED_RESET);

PCA9546 MP(0x70);
uint8_t channels = 0;
uint32_t lastTime = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println(__FILE__);
  Serial.print("TCA9548_LIB_VERSION: ");
  Serial.println(TCA9548_LIB_VERSION);
  Serial.println();

  Wire.begin();
  //  initialize multiplexer
  if (MP.begin() == false)
  {
    Serial.println("Multiplexer error");
  }
  channels = MP.channelCount();

  //  initialize the temperature sensors
  MP.selectChannel(0);
  oled0.begin(SSD1306_SWITCHCAPVCC, OLED_Address);
  oled0.clearDisplay();
  oled0.display();
  if (oled0.begin() == false)
  {
    Serial.println("Oled0 error");
  }
  MP.selectChannel(1);
  oled1.begin(SSD1306_SWITCHCAPVCC,OLED_Address);
  oled0.clearDisplay();
  oled0.display();
  if (oled1.begin() == false )
  {
    Serial.println("Oled1 error");
  }
  
}

void loop()
{
    MP.selectChannel(0);
    oled0.clearDisplay();
    oled0.setTextColor(WHITE);
    oled0.setCursor(0,25);
    oled0.setTextSize(1);
    oled0.println("PANTALLA 0");
    oled0.display();
    
    MP.selectChannel(1);
    oled1.clearDisplay();
    oled1.setTextColor(WHITE);
    oled1.setCursor(0,25);
    oled1.setTextSize(1);
    oled1.println("PANTALLA 1");
    oled1.display();
  
}

Hi,
Ya es un adelanto por lo menos esta cambiando de canal. Trata de hacer un "oled1.begin(SSD1306_SWITCHCAPVCC, OLED_Address)" despues que seleciona el canal 1.Posiblemente en el cambio de canal pierda la inicializacion. Todavia yo no entiendo de donde sale la direccion de 0x70. Segun el manual dice que es E0==1110 a menos que no sea 1110 sino 70. Pero no explican en el manual donde sale el 0x70. Trata el sketch que yo te envie cambiando el addres de 0xE0 a 0x70 para ver si trabaja.

En el setup está inicializado bien, si lo pongo en el loop, como es lógico, obtenemos el mismo resultado, pero con un parpadeo de las pantallas, ya que se inicializan continuamente.

El 70 sale del direccionamiento del PCA 9548A que he utilizado como he mostrado anteriormente, y se explica en la página 6 del manual:

image

Al utilizar un direccionamiento con los pines A0 - A2 a masa, 1110000 es 70 en hexadecimal.

No tiene lógica lo que está ocurriendo.

Hi,
Tu haz intercambiado las pantallas para ver si tienen el mismo problema.? Quita el oled begin despues del select y dejalo solamente en el setup .En cuanto al address para poder salir 0x70 entonces tienes que leerlo de izquierda a derecha seria 0x70. Ahora el 70 va leer el modulo 0 y si es 71 el modulo 1 y hay 8 modulos. Ahora el ultimo bit es para escribir o leer. Como si tienes el address de 70 vaz decirle al modulo que vaz a escribir o a leer. No tienn sentido. Entonces tenemos que aceptar el addres de 70 del aire porque alguien lo dice. Atra cosa que no explican en ningun sitio como decifrar el address del modulo siguiendo los valores de los byte descrito en la pagina 6.

¿Podría ser porque estas pantallas no son totalmente compatibles con la librería? No tiene sentido que presenten datos y comuniquen, pero que los presenten como con una especie de interlineado, como si estuvieran adaptando una resolución inferior.

Hi,
Adjunto un link de uno que tiene 4 pantallas y mira la tercera de izquierda a derecha que tiene diferente color y la primera de la izquierda tiene un dot encima del uno. Creo que el multiplezer tiene problemas de timing o de sincronizacion.

[TCA9548A I2C Multiplexer: ESP32, ESP8266, Arduino | Random Nerd Tutorials]

MUCHAS GRACIAS!!
Te debo una. Este programa SI funciona.
Los caminos del arduino son inexcrutables.
A ver porque este programa funciona, y el anterior no. :grimacing:
Incluso he eliminado alguna sentencia begin() por si podía ser redundante, y sigue sin funcionar.
Sigo sin verle la diferencia para que uno funcione y el otro no. Ambos definen las pantallas, las inicializan, definen el multiplexor y lo inicializan del mismo modo, y se llama a las pantallas igual. :man_shrugging:

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

// Define los parametros de las pantallas
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// Select I2C BUS
void TCA9548A(uint8_t bus){
  Wire.beginTransmission(0x70);  // Dirección TCA9548A A0-A1-A2 a masa
  Wire.write(1 << bus);          // envia datos a los buses seleccionados
  Wire.endTransmission();
  Serial.print(bus);
}
 
void setup() {
  Serial.begin(115200);

  // Inicializa la comunicación con el multiplexor
  Wire.begin();

  // Inicia pantalla en salida 0
  TCA9548A(0);
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  } 
  // Limpia buffer
  display.clearDisplay();

  // Inicia pantalla en salida 1
  TCA9548A(1);
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  } 
  // CLimpia buffer
  display.clearDisplay();
  
  } 
   
void loop() {

  // Escribe en la pantalla en la salida 0
  TCA9548A(0);
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 10);
  // Display static text
  display.println("PANTALLA  EN SALIDA NUM.0");
  display.display(); 

  // Escribe en la pantalla en la salida 1
  TCA9548A(1);
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 10);
  // Display static text
  display.println("PANTALLA  EN SALIDA NUM.1");
  display.display(); 
  
}

Por cierto, no he encontrado un buen manual de la librería de adafruit y he tenido que aprender a manejarla a base de encontrar artículos y trastear ejemplos por aqui y por allá. ¿Conoces alguno?
Veo, por ejemplo, que no parece tener control sobre el brillo de la pantalla.

Hi,
Yo insisto que el problema es en la forma que en el manual explican como configurar el modulo. Todavia no entiendo de donde sale el 70. Otra cosa es como tu le dices al modulo que vaz a leer o escribir. Si manda el address de 70 no puedes decirle si vaz a escribir a leer ???????? ya que el bit 0 es el que indica si escribes o lees.. Me alegro que hayas logrado conseguir que te puedas comunicar con las dos pantallas. Voy a seguir investigando para ver si encuentro alguien que sepa de donde sale el 0x70.. Por fin encontre alguien que explica de donde sale el 70. Haciendo las instrucciones en el sketch es lo unico que debes de hacer para seleccionar el canal.`Por fin encontre donde explican donde sale el 0x70, Adjunto el link.

#define TCAADDR 0x70
void tcaselect(uint8_t i) {
  if (i > 7) return;
   Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();  
}

[Pinouts | Adafruit PCA9548 8-Channel STEMMA QT / Qwiic I2C Multiplexer | Adafruit Learning System]

@tauro0221 El rango de direcciones I2C es de 7 bites, 0x00 a 0x7F.
La dirección del módulo está prefijada en el rango 0x70 a 0x77, no porque "alguien lo dice" sino porque así lo definieron lo diseñadores.
Lo que se ve en la imagen de #28 es la forma en que se envían los datos al chip, primero los 7 bites de dirección seguidos del flag de lectura o escritura.
Si revisas la documentación del PCF8574 (el de las LCD), por nombrar uno conocido, o cualquier otro chip I2C vas a encontrar una imagen similar (cambian los bits de dirección, obvio) porque es lo que fija el estándar.

Hi,
Muchas gracias MaximoEsfuerzo lo que pasa es que cuando te presenta el formato de 1110xxxx imediatamente si sigues la mayoria de los fabricante veras que eso seria 0xE0 ya que mo explican el formato. Ahora si vaz a este link de adafruit veras que lo explican perfectamente. Tambien el bit zero es para determinar si escribes o lees. segun el formato.

[Pinouts | Adafruit PCA9548 8-Channel STEMMA QT / Qwiic I2C Multiplexer | Adafruit Learning System]

No, no es 0xE0, es 0x70 desplazado un bit a la izquierda.
La información es clara, los 7 bites más significativos son los de dirección, el menos significativo es el flag R/-W.
Sería fácil darse cuenta que si la dirección no puede ser mayor a 0x7F, 0xE0 no es una dirección I2C válida.
De todos modos, la transmisión la maneja Wire así que es algo que ni deberías tener en cuenta, solo saber que la dirección del módulo está en el rango 0x70 a 0x77, según se seleccionen los 3 bites de dirección por hardware, y que por defecto es 0x70.

No creo que alguna vez te hayas cuestionado si la dirección de tu LCD con adaptador I2C es 0x27 (ó 0x3F), a pesar de que el bit de dirección también se transmite desplazado 1 bit a la izquierda y se le agrega el flag R/-W. ¿O si? :thinking:

Hi,
Pregunta entonces como tu explica que el bit 0 es para decir si vaz a escribir a leer como lo explica la pagina 6 post 22 cuando mandas el address de 0x70. Donde dices que vaz a escribir o leer como dice en post 22.

wire.write(dato);

Pone el flag en 0

wire.read();

lo pone en 1.

Si yo voy a crear mi propia librería para reemplazar a Wire le presto atención a esa parte de la hoja de datos, sino ¿para qué perder tiempo?

Te repito, ¿alguna vez manejaste "manualmente" el address byte de tu LCD?

Y como respondí en uno de los primeros post, la función pantalla() es la que selecciona a cual de ellas se envían los datos, enviando al módulo (con dirección 0x70), el valor 2^i, donde i es el canal elegido.

HI,
MaximuEsfuerzo yo lo que trato de demostrar que la explicacion en el datasheet no esta correcta ya que porque dice que el bit 0 es para escribir/leer. Yo he escrito driver y nunca me habia encontrado algo mo esto. Sin embargo la explicaccion de adafruit como lo explica esta correctamente facil de entender y sin problemas.. Recuerda que uno recure a las "datasheet " para ver como opera el componente. Yo para leer el DS1307 no uso la libreria uso un driver que yo escribi con dos o tres commandos usando wire..