Ecran Bizarre ssd1306

Bonjour à tous, amis Arduiniens, j'ai commencé un projet de mesure de longueur de filament version digitale pour imprimante 3D.
(Equipé d'un encodeur rotatif et une carte SD, je souhaite afficher sur 12 écrans différents les valeurs de longueur de chaque fil.)

Sauf que j'ai un souci concernant les ssd1306.
Souci d'alimentation, tampon etc... je n'en ai aucune idée. Ils sont alimentés en 3.3v sur une Arduino Uno.
J'ai deux écrans qui affiche bien les valeurs, mais dès que je met le troisième en route, les premiers écrans n'écrivent plus que sur une seule ligne en mélangeant les valeurs... bref, fouilli...

Je vous joint des photos et mon code pour avoir votre avis.

Je sais que mon code n'est pas du tout optimisé, je suis encore un peu débutant malgré mes quelques projets réalisés.


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

#define OLED_RESET 4

Adafruit_SSD1306 ecran1(OLED_RESET);
Adafruit_SSD1306 ecran2(OLED_RESET);
Adafruit_SSD1306 ecran3(OLED_RESET);
//Adafruit_SSD1306 ecran4(OLED_RESET);
//Adafruit_SSD1306 ecran5(OLED_RESET);
//Adafruit_SSD1306 ecran6(OLED_RESET);

int voila = 335;

void TCA9548A(uint8_t bus) {
  Wire.beginTransmission(0x70);
  Wire.write(1 << bus );
  Wire.endTransmission();
}

void displayd() {

  //ecran1.display();
  //delay(500);
  
  ecran1.clearDisplay();
  ecran1.setTextColor(WHITE);
  ecran1.setTextSize(2);
  ecran1.setCursor(20, 0);
  delay(50);

  ecran2.clearDisplay();
  ecran2.setTextColor(WHITE);
  ecran2.setTextSize(2);
  ecran2.setCursor(20, 0);
  delay(50);

  ecran3.clearDisplay();
  ecran3.setTextColor(WHITE);
  ecran3.setTextSize(2);
  ecran3.setCursor(20, 0);
delay(50);
 /* ecran4.clearDisplay();
  ecran4.setTextColor(WHITE);
  ecran4.setTextSize(2);
  ecran4.setCursor(20, 0);
delay(50);
  ecran5.clearDisplay();
  ecran5.setTextColor(WHITE);
  ecran5.setTextSize(2);
  ecran5.setCursor(20, 0);
delay(50);
  ecran6.clearDisplay();
  ecran6.setTextColor(WHITE);
  ecran6.setTextSize(2);
  ecran6.setCursor(20, 0);
delay(50);  */

  //////////////////////////////////////
/*
  //ecran2.display();
  //delay(500);
  ecran2.clearDisplay();
  ecran2.setTextColor(WHITE);
  ecran2.setTextSize(2);
  ecran2.setCursor(0, 0);
  //ecran2.setCursor(40, 0);
*/
}
void setup() {
  Wire.begin();

  TCA9548A(1);
  ecran1.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  //ecran1.clearDisplay();
 //ecran1.display();
  TCA9548A(2);
  ecran2.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  //ecran2.clearDisplay();
  //ecran2.display();
  TCA9548A(3);
  ecran3.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  //ecran3.clearDisplay();
  //ecran3.display();
 /* TCA9548A(4);
  ecran4.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  //ecran4.clearDisplay();
  //ecran4.display();
  TCA9548A(5);
  ecran5.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  //ecran5.clearDisplay();
  //ecran5.display();
  TCA9548A(6);
  ecran6.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  //ecran6.clearDisplay();
  //ecran6.display();
*/}

void loop() {
  displayd();

  TCA9548A(1);
  ecran1.setTextSize(1);
  ecran1.print("PLA BLANC");
  ecran1.setCursor(20, 15);
  ecran1.setTextSize(2);
  ecran1.print(voila);
  ecran1.display();
  //delay(1000);
  //ecran1.clearDisplay();

  TCA9548A(2);
  ecran2.print("PETG NOIR");
  ecran2.setCursor(0, 18);
  ecran2.print(voila);
  ecran2.display();
  //delay(1000);

TCA9548A(3);
  ecran3.print("PETG NOIR");
  ecran3.setCursor(0, 18);
  ecran3.print(voila);
  ecran3.display();
  //delay(1000);

/*  TCA9548A(4);
  ecran4.print("PETG NOIR");
  ecran4.setCursor(0, 18);
  ecran4.print(voila);
  ecran4.display();
  //delay(1000);

  TCA9548A(5);
  ecran5.print("PETG NOIR");
  ecran5.setCursor(0, 18);
  ecran5.print(voila);
  ecran5.display();
  //delay(1000);

  TCA9548A(6);
  ecran6.print("PETG NOIR");
  ecran6.setCursor(0, 18);
  ecran6.print(voila);
  ecran6.display();
  //delay(1000);
*/
  /*ecran1.display();
  ecran2.display();
  ecran3.display();
  ecran4.display();
  ecran5.display();
  ecran6.display();
 */


}

Bonjour,

Comment sont alimentés tes écrans et ton TCA9548?

Il est fort probable que tu utilises toute la mémoire de ton processeur
La librairie alloue un buffer pour chaque écran de

buffer = (uint8_t *)malloc(WIDTH * ((HEIGHT + 7) / 8))

Quelle est la résolution des écrans que tu utilises?
Tu utilises un constructeur qui est obsolète.
As-tu bien spécifié la taille de l'écran dans la librairie.
Les constructeurs suggérés maintenant indique la taille de l'écran dans la déclaration

  // NEW CONSTRUCTORS -- recommended for new projects
  Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi = &Wire,
                   int8_t rst_pin = -1, uint32_t clkDuring = 400000UL,
                   uint32_t clkAfter = 100000UL);
  Adafruit_SSD1306(uint8_t w, uint8_t h, int8_t mosi_pin, int8_t sclk_pin,
                   int8_t dc_pin, int8_t rst_pin, int8_t cs_pin);
  Adafruit_SSD1306(uint8_t w, uint8_t h, SPIClass *spi, int8_t dc_pin,
                   int8_t rst_pin, int8_t cs_pin, uint32_t bitrate = 8000000UL);

Quelle carte utilises tu?
@fdufnews a sans doute raison, la mémoire n'est pas suffisante pour trois instances de Adafruit_SSD1306.
Mais tu n'as pas besoin de trois instances, tu peux utiliser une seule instance

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

#define OLED_RESET -1

Adafruit_SSD1306 ecran(OLED_RESET);

int voila = 335;

void TCA9548A(uint8_t bus) {
  Wire.beginTransmission(0x70);
  Wire.write(1 << bus );
  Wire.endTransmission();
}

void setup() {
  Wire.begin();

  TCA9548A(1);
  ecran.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  //ecran.clearDisplay();
  //ecran.display();
  TCA9548A(2);
  ecran.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  //ecran.clearDisplay();
  //ecran.display();
  TCA9548A(3);
  ecran.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  //ecran.clearDisplay();
  //ecran.display();
  /* TCA9548A(4);
    ecran4.begin(SSD1306_SWITCHCAPVCC, 0x3C);
    //ecran4.clearDisplay();
    //ecran4.display();
    TCA9548A(5);
    ecran5.begin(SSD1306_SWITCHCAPVCC, 0x3C);
    //ecran5.clearDisplay();
    //ecran5.display();
    TCA9548A(6);
    ecran6.begin(SSD1306_SWITCHCAPVCC, 0x3C);
    //ecran6.clearDisplay();
    //ecran6.display();
  */
}

void loop() {
  ecran.setTextColor(WHITE);

  TCA9548A(1);
  ecran.clearDisplay();
  ecran.setCursor(0, 0);
  ecran.setTextSize(1);
  ecran.print("PLA BLANC");
  ecran.setCursor(0, 18);
  ecran.setTextSize(2);
  ecran.print(voila);
  ecran.display();
  delay(1000);
  //ecran.clearDisplay();

  TCA9548A(2);
  ecran.clearDisplay();
  ecran.setCursor(0, 0);
  ecran.setTextSize(1);
  ecran.print("PETG NOIR");
  ecran.setCursor(0, 18);
  ecran.setTextSize(2);
  ecran.print(voila);
  ecran.display();
  delay(1000);

  TCA9548A(3);
  ecran.clearDisplay();
  ecran.setCursor(0, 0);
  ecran.setTextSize(1);
  ecran.print("PETG NOIR 2");
  ecran.setCursor(0, 18);
  ecran.setTextSize(2);
  ecran.print(voila);
  ecran.display();

  delay(1000);

  /*  TCA9548A(4);
    ecran4.print("PETG NOIR");
    ecran4.setCursor(0, 18);
    ecran4.print(voila);
    ecran4.display();
    //delay(1000);

    TCA9548A(5);
    ecran5.print("PETG NOIR");
    ecran5.setCursor(0, 18);
    ecran5.print(voila);
    ecran5.display();
    //delay(1000);

    TCA9548A(6);
    ecran6.print("PETG NOIR");
    ecran6.setCursor(0, 18);
    ecran6.print(voila);
    ecran6.display();
    //delay(1000);
  */
  /*ecran.display();
    ecran.display();
    ecran.display();
    ecran4.display();
    ecran5.display();
    ecran6.display();
  */


}

@AdminArchon parle d'une UNO

Je n'avais pas vu. Dans ce cas, effectivement la mémoire est franchement insuffisante pour trois instances.

La librairie AdaFruit est connue pour cela.

Dans la dernière version begin() retourne false si le buffer ne peut être alloué. Une bonne habitude à prendre est de tester :

  if (ecran1.begin(SSD1306_SWITCHCAPVCC, 0x3C) == false) {
    Serial.println("Adafruit_SSD1306::begin failed");
    while (1);
  }

Si on veut afficher uniquement du texte, je recommande la librairie SSD1306Ascii qui utilise peu de mémoire.

Absolument. Pour une application identique j'avais relevé ceci :
Avec AdaFruit :
Les variables globales utilisent 1544 octets (75%) de mémoire dynamique, ce qui laisse 504 octets pour les variables locales. Le maximum est de 2048 octets.
Avec Greiman :
Les variables globales utilisent 274 octets (13%) de mémoire dynamique, ce qui laisse 1774 octets pour les variables locales. Le maximum est de 2048 octets.

Remarque : pas de routines graphiques pour la librairie Greiman.

Bonjour et merci pour vos réponses. J'avoue être perdu,
Je suis sur une Arduino Uno, et j'utilise des 128 x 64 monté en i2c avec un TCA9548A comme vous l'avez vu pour 6 d'entre eux qui seront à l'adresse 0x70 et 6 autres sur la 0x71 sauf que je ne sais pas comment les déclarer, je pense que c'est un peu pareil que le LCD1206 : LiquidCrystal_I2C lcd(16 , 2 , 0x27); Mais là, c'est un peu du chinois pour les SSD

 Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi = &Wire,
                   int8_t rst_pin = -1, uint32_t clkDuring = 400000UL,
                   uint32_t clkAfter = 100000UL);
  Adafruit_SSD1306(uint8_t w, uint8_t h, int8_t mosi_pin, int8_t sclk_pin,
                   int8_t dc_pin, int8_t rst_pin, int8_t cs_pin);
  Adafruit_SSD1306(uint8_t w, uint8_t h, SPIClass *spi, int8_t dc_pin,
                   int8_t rst_pin, int8_t cs_pin, uint32_t bitrate = 8000000UL);

ça je sais pas comment le remplir.

Je souhaitez afficher les 12 ecrans en même temps, je possède une MEGA si jamais le buffer est plus important. Quelqu'un peut m'expliquer comment ça fonctionne pour les déclarer ?

Merci a vous pour vos réponses

J'ai téléchargé la libraire SSD ASCII. Je trouve pas d'exemple de cette librairie, c'est normal ?
Mon programme ne compile pas, donc je me doute que ce n'est pas les bonnes déclarations puisque ce n'est plus "ADAFRUIT". Comment je peut trouver les syntaxes ?

Et pourtant il y en a un sacré nombre :

Essaies la solution que je t'ai proposée au post #4, c'est la plus simple.

Bonsoir a tous, oui, c'est ce que j'ai fait Kamill, je n'ai declarer qu'un seul Adafruit_SSD1306 ecran, j'ai effacé tous les numéros, lancé ma fonction displayd() pour clear a chaque passage dans la loop et a chaque changement de bus TCA. Mais au lieu de ça, seul 4 écrans se sont allumés mais avec des pixels allumés un peu partout aléatoirement. Pas d'image ni de texte. Je pense tester aussi la librairie ascii proposée maintenant que vous m'avez fourni des exemples de code. Moi j'avais cherché dans le logiciel arduino "exemple" pas sur le net.
Merci à vous Bachetti pour ça.
Mon but était vraiment de tous les allumés en même temps, vous pensez que c'est possible ?
Car dans la réalisation, une nano va gérer l'encodeur rotatif, envoyer la valeur à la UNO qui va la transmettre a l'écran sélectionné et l'enregistrer sur une SD à intervalles de 5 minutes ou plus peut-être afin de lire cette valeur et de l'envoyer à la nano à chaque démarrage ou changement de sélection dans le filament.
Sur le papier, ça a l'air de marcher.
Une idée, un discord pour m'aider plus facilement dans mon projet ?
Je cherche à m'améliorer grandement dans l'arduino, c'est devenu ma passion du soir.
Je suis preneur de vos idées afin de trouver des formations ou des cours car avant il y avait Openclassroom mais plus maintenant.

Merci à vous de votre soutien pour mon projet

Essaie le programme que je t'ai proposé.

Bonjour AdminArchon

Questions câblage, l'Arduino est-il tout près des TCA9548, sinon quelle qualité de câble utilises-tu?
Quelle est la plus grande distance entre le TCA9548 et l'affichage OLED, Même remarque concernant la qualité de câble.
As-tu mis des résistances de PULL_UP sur les bus i2C "secondaires" du TCA9548, le TCA9548 n'en a pas, regardes ici page 18 figure 14.

Pour ce qui est de la qualité du câble, pour des distances plus grandes que 1 mètre, j'utilise du câble pour installations téléphoniques U72 4 fils, il est torsadé. Ca se trouve facilement dans les GSB.

Cordialement
jpbbricole

Bonjour a tous, pour répondre a jpbbricole, le Uno se trouve à environ 70 cm du TCA du haut, et 40 cm de celui du bas.
La distance entre les TCA et les OLED les plus éloignés sont à 25 cm maxi.
Pour ce qui est des résistances sur le TCA j'ai vu que je devais en mettre mais ça m'est sorti de la tête. 4.7 OHM suffisent non puisque c'est du pull up.
Les références de cable je ne l'ai ai pas sous la main mais c'est un simple fil en monobrin.

Pour répondre a kamill, je vais tester le code que vous m'avez envoyé directement pour voir plutôt que d'utiliser celui que j'ai corrigé en me basant à vous. Mes displayd() sont enlevés dans votre partie à vous, cest peut-être ça qui foire tout chez moi.
Je testerai dès que je peut.

Pour ce qui est des Discord ou des formations, quelqu'un a une piste ?

Merci à vous, cordialement

Tout dépend si l'on parle d'un TCA9548A sous forme de chip ou de module. Normalement les résistances de PULL-UP sont présentes sur les modules, ainsi que sur les SSD1306 (en général 10K).

Bonjour AdminArchon

Je suppose 4.7 kOhms?
Pour ce qui est des distances, 70 cm avec du simple fil, ça devient limite mais doit aller. Tu verras assez vite si tu as des perturbations.
Le meilleur à faire, c'est de mettre les pull up et de démarrer les essais avec les fils les plus courts pour assurer, après mets le tout dans son contexte final avec les bonnes longueurs de ils et tu verras assez rapidement s'il y a des perturbations.
L'avantage du câble U72, c'est qu'il est torsadé ce qui permet de plus grandes longueurs.

C'est quoi?

Cordialement
jpbbricole