Wie kann ich 27 Oled Displays an einen Arduino anschließen?

Hallo,

ich versuche gerade für ein "Lego" Projekt 27 OLED Displays 1,3" mit einem Arduino zu verbinden, die dann gewisse Bilder anzeigen sollen.

Dazu habe ich jetzt an mehreren MultiPlexern jeweils mehrere OLED Displays angeschlossen.

Das funktioniert mit bis zu 11 Displays einwandfrei, aber sobald in das 12. Display anschließe, zeigt kein Display mehr irgendetwas an.

Ich vermute, dass ich entweder an die Grenze der Stromversorgung gekommen bin oder das Signal für die Steuerung der Displays reicht nicht mehr aus.

Als Stromversorgung nutze ich aktuell die 5V des Arduino. Ich habe auch schon versucht das externe Power Panel einzusetzen, da bekomme ich aber scheinbar überhaupt nichts mit hin.

Hat jemand eine Idee an welche "Grenze" ich gestoßen sein kann und wie man das nun beheben könnte?

Danke für eure Hilfe.

LG
kay899

kay899:
ich versuche gerade für ein "Lego" Projekt 27 OLED Displays 1,3" mit einem Arduino zu verbinden, die dann gewisse Bilder anzeigen sollen.

Ist ja ne Hausnummer...

Ich vermute, dass ich entweder an die Grenze der Stromversorgung gekommen bin
[..]
Als Stromversorgung nutze ich aktuell die 5V des Arduino. Ich habe auch schon versucht das externe Power Panel einzusetzen, da bekomme ich aber scheinbar überhaupt nichts mit hin.

Hat jemand eine Idee an welche "Grenze" ich gestoßen sein kann und wie man das nun beheben könnte?

Speise die OLED nicht über den Arduino. Versorge die extern.
Wenn der Arduino über USB versorgt wird, ist der USB-Power das Maximum für alles. Incl. Board und Zubehör. Bei USB 2.0 500mA - Ausnahmen mal rausgelassen.

Selbst bei 8V Versorgung des Arduino und damit Nutzung des Abwärtsreglers ist irgendwann Schluss. Da bist mit dem bisherigen was funktioniert schon recht gut bei....

@TO: Die Grenze der Stromversorgung hast Du auf alle Fälle erreicht.
Wenn Du auf jedem Display etwas anderes anzeigen willst, könntest Du je nach Komplexität und Vorgehensweise auch bald das Ende des RAM erreichen.

Welchen Arduino benutzt Du und was willst Du wie anzeigen?

Gruß Tommy

Hier mal ein paar Bilder was ich baue und warum es ausgerechnet 27 Displays sein müssen. Es sollen hinterher auf den Displays kleine Grafiken durchlaufen und eine “Anwahl Sequenz” eines Stargates aus der Serie “Stargate Atlantis”, simulieren.

Es gibt 35 diesen Glyphen (Sprich Bilder), da müssen wir später schauen, wie das mit dem RAM ausschaut.

Aber erstmal muss ich alle Displays ans leuchten bringen, sonst brauch ich da gar nicht weitermachen.

Also, wie genau kann ich denn die Displays mit Strom versorgen? Ich habe so ein Arduino Starterkit von Eleegoo und da ist auch ein Power Supply dabei. Habe schon versucht das auf das Breadboard zu stecken, aber dann machen die Bildschirme leider gar nichts. Wir genau müsste man das anstellen?

Danke für eure Hilfe!

LG
kay899

kay899:
Hier mal ein paar Bilder[...]

Also, wie genau kann ich denn die Displays mit Strom versorgen? Ich habe so ein Arduino Starterkit von Eleegoo und da ist auch ein Power Supply dabei. Habe schon versucht das auf das Breadboard zu stecken, aber dann machen die Bildschirme leider gar nichts. Wir genau müsste man das anstellen?

Also ich glaube, es wird sehr schwer, wenn Du nicht liest, was Dir geschrieben wurde.
Es fehlen sogar die Bilder - Jetzt sind sie da :wink: ich kann mir aber vorstellen, was Du vor hast.

Nochmal:
Die Displays sollen über eine externe Versorgung betrieben werden.
Das kann z.B. auch eine Powerbank sein.
GND der externen Versorgung ist mit GND des Arduino zu verbinden.
Das könnte der Grund sein, warum das bei Deinem versuch nicht funktionierte.

Um Dir weiter zu helfen:
Was für Displays benutzt Du? - Bitte einen klickbaren link machen. ( Im Editor oben das Kettensymbol )

Hier das sind die Displays, davon 27:

kay899:
Hier das sind die Displays, davon 27:
https://www.amazon.de/gp/product/B07V9SLQ6W/

gut, ich hab mal einen Link draus gemacht - ist ein az 1,3 oled 128x64

Datenblatt dazu:

Jedes Display benötigt 40 (45) mA.
11 Display -> 440 (495) mA

Damit ist die 500mA Grenze ausgereizt.

Das Pinout (Datenblatt Seite 5) sagt Dir, wie Du +5V und GND anschliessen musst.
Entweder ein externes einfaches - aber möglichst stabiles - Netzteil, welches ausgelegt ist für die Anzahl der Displays-> 27 * 45mA -> 5V / 1,5A Netzteil oder eine Powerbank, die das dauerhaft liefert.

GND hatte ich erwähnt.
I2C Leitungslängen und Beschaltungen beachten.

[edit] Typo

Zwar hast Du uns Foto und das Modell des Displays geliefert.

Aber es fehlen immernoch Infos

Welchen Arduino hast Du?
Gibst Du uns den Sketch?
Hast Du Pullups-Widerstände auf dem I2C Bus und welche?
Welche Multiplexer verwendest Du?

Grüße Uwe

Mir bereitet die Länge der I2C-Kabel Sorge, denn eigentlich sollten die für die Kommunikation in der Nähe sein.

Ich habe folgenden Arduino:

Dann verwende ich diese Multiplexer:

Pullups-Widerstände auf dem I2C Bus: keine Ahnung was das bedeutet. Ich habe nichts angepasst oder geändert.

Klar könnt ihr gern den Sketch sehen:

#include "Wire.h"
#include <U8glib.h>
#include "glyphs.h"
#include "LinkedList.h"
 
#define DISP_COUNT 11
 
typedef struct _DISP {
  uint8_t id; // arbitrary numeric ID of display
  uint8_t MUXAddress; // TCA9548A MUX address to which display is conneted
  uint8_t I2CChannel; // i2c channel of display
  byte g; // Integer value for Glyph loop
} DISP;
 
typedef struct _TASK {
  uint8_t displayId;
  uint8_t glyphNum;
  unsigned long startedAt;
  unsigned long startAt;
  unsigned long finishAt;
} TASK;
 
LinkedList<TASK*> tasksList = LinkedList<TASK*>();
 
DISP displays[DISP_COUNT];
 
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_FAST);  // Fast I2C / TWI
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_FAST);
 
#define GLYPH_WIDTH 128
#define GLYPH_HEIGHT 64
 
// Array of Glyphs to show
unsigned char* glyphs[] = {glyph1, glyph2, glyph3};
const int glyphCount = 3;
 
void drawGlyph(uint8_t ind) {
  if(ind > glyphCount) return;
  u8g.firstPage();
  do {
    u8g.drawBitmapP( 0, 0, 16, 64, glyphs[ind]);
  } while( u8g.nextPage() );
  //u8g.drawXBMP(0, 0, 128, 64, glyphs[ind]);
}
 
// Disable all i2c channels
void disableMUX(uint8_t MUXAddress) {
  Wire.beginTransmission(MUXAddress);
  Wire.write(0);
  Wire.endTransmission();
}
 
// Initialize I2C buses using TCA9548A I2C Multiplexer
/**
 * _display - used to get DISP pointer in return. If it is not needed, set this param to NULL
 */
boolean tcaselect(uint8_t displayId, DISP** _display) {
  if(displayId == 0)
    return false;
  
  // Stop propagating i2c stream to displays
  disableMUX(0x70);
  disableMUX(0x72);
 
  for(int i=0; i<DISP_COUNT; i++) {
    if(displays[i].id == displayId) {
      if(_display != NULL)
        *_display = &displays[i];
      Wire.beginTransmission(displays[i].MUXAddress);
      Wire.write(1 << displays[i].I2CChannel);
      Wire.endTransmission();
      return true;
    }
  }
 
  return false;
}
 
// Get DISP pointer by device ID
DISP* getDisp(uint8_t displayId) {
  if(displayId == 0)
    return NULL;
  
  for(int i=0; i<DISP_COUNT; i++) {
    if(displays[i].id == displayId) {
      return &displays[displayId];
    }
  }
 
  return NULL;
}
 
void setup() {
  Serial.begin(115200);
  DisplayInit(); // Initialize the displays
 
  Serial.println(String("Data Size check: ") + sizeof(unsigned long));
}
 
// Add new display to 'displays' array
/**
 * index - array index [0 .. DISP_COUNT]
 * id - any numeric value
 * MUXAddress - TCA9548A i2c address
 * I2CChannel - channel for display [0 .. 7]
 */
void addDisplay(uint8_t index, uint8_t id, uint8_t MUXAddress, uint8_t I2CChannel) {
  displays[index].id = id;
  displays[index].MUXAddress = MUXAddress;
  displays[index].I2CChannel = I2CChannel;
}
 
// Initialize the displays 
void DisplayInit() {
  memset(&displays, 0, sizeof(displays));
 
  addDisplay(0, 101, 0x70, 0);
  addDisplay(1, 102, 0x70, 1);
  addDisplay(2, 103, 0x70, 2);
  addDisplay(3, 104, 0x70, 3);
  addDisplay(4, 105, 0x70, 4);
  addDisplay(5, 106, 0x70, 5);
  addDisplay(6, 107, 0x70, 6);
  addDisplay(7, 108, 0x70, 7);
  addDisplay(8, 109, 0x72, 0);
  addDisplay(9, 110, 0x72, 1);
  addDisplay(10, 111, 0x72, 2);
  //addDisplay(11, 112, 0x72, 4);
 
  int initCount = 0;
  for(int i=0; i<DISP_COUNT; i++) {
    if(tcaselect(displays[i].id, NULL)) {
  		u8g.firstPage();
      do {
        u8g.begin();  // Initialize display
      } while( u8g.nextPage() );
      initCount++;
    }
  }
 
  Serial.print("Displays init: OK (");
  Serial.print(initCount);
  Serial.println(")");
 
}
 
void clearDisplay(){
    u8g.firstPage();  
    do {
    } while( u8g.nextPage() );
}
 
/**
 * Add display task to list
 * 
 * displayId  - id of display, i.e. 100, 200,..
 * glyphNum   - index of Glyph in glyphs[] array
 * startIn    - time should pass before start showing glyph(in milliseconds), i.e. 1000 - start showing in 1 second
 * duration   - thime to show glyph(in milliseconds), display will be cleared after it pass
 */
void addTask(uint8_t displayId, uint8_t glyphNum, uint16_t startIn, uint16_t duration) {
 
  TASK* task = (TASK*)malloc(sizeof(TASK));
  memset(task, 0, sizeof(TASK));
 
  task->displayId = displayId;
  task->glyphNum = glyphNum;
  task->startAt = startIn + millis();
  task->finishAt = task->startAt + duration;
 
  //Serial.println("ADD TASK");
  //Serial.println(String("displayId:") + task->displayId);
  //Serial.println(String("glyphNum:") + task->glyphNum);
  //Serial.println(String("startAt:") + task->startAt);
  //Serial.println(String("finishAt:") + task->finishAt);
  //Serial.println("--------");
 
  tasksList.add(task);
}
 
/**
 * Go through tasks list, execute tasks and remove finished from list
 */
void loopTasks() {
  unsigned long currentTime = millis();
  for(int i=0; i<tasksList.size(); i++) {
    TASK* task = tasksList.get(i);
 
    if(task->startAt <= currentTime && task->startedAt == 0) {
      
      task->startedAt = currentTime;
 
      // TODO display action
      if(tcaselect(task->displayId, NULL)) {
        drawGlyph(task->glyphNum);
      } else {
        // display not found. Maybe it is mistake. Removing from tasks list
        // removing from tasks list
        TASK* t = tasksList.remove(i);
        free(t);
        i--;
      }
 
    } else if(task->startedAt != 0 && task->finishAt <= currentTime) {
 
      if(tcaselect(task->displayId, NULL)) {
        clearDisplay();
      }
 
      // removing from tasks list
      TASK* t = tasksList.remove(i);
      free(t);
      i--;
    }
  }
}
 
void fillDemoTasks() {
   addTask(101, 0, 0, 5000);
   addTask(102, 0, 0, 5000);
   addTask(103, 0, 0, 5000);
   addTask(104, 0, 0, 5000);
   addTask(105, 0, 0, 5000);
   addTask(106, 0, 0, 5000);
   addTask(107, 0, 0, 5000);
   addTask(108, 0, 0, 5000);
   addTask(109, 0, 1000, 5000);
   addTask(110, 0, 1000, 5000);
   addTask(111, 0, 1000, 5000);
   //addTask(112, 0, 1000, 5000);
 }
 
void setupTasks() {
}
 
void loop() {
  
  loopTasks();
 
   if(tasksList.size() == 0) {
     delay(2000);
     fillDemoTasks();
   }
    
    setupTasks();
}

Die Displays werden ab Zeile 117 “angemeldet” und die Aufgaben (also was welches Display wann wie lang zeigt), wird ab Zeile 219 eingestellt.

Zusätzlich muss ich die aktuelle Anzahl der Displays noch in Zeile 6 definieren.

kay899:
Ich habe folgenden Arduino:

Klar könnt ihr gern den Sketch sehen:

Nachdem ich schon vorhin die URL auf Link geändert und das Nötigste gekürzt habe, jetzt auch noch mit Code auf irgendwelchen Drittseiten - Warum kannst Du das hier nicht genauso einbetten, wie es Dir die Forensoftware anbietet. Mit Codetags und bis zu einer Gesamtlänge von 9000 Zeichen direkt - darüber hinaus als Attachment.

Bei U8glib lese ich: "Note: There will be no more development for U8glib. Please use u8g2."

Warum verwendest Du eine veraltete Bibliothek?

my_xy_projekt:
Nachdem ich schon vorhin die URL auf Link geändert und das Nötigste gekürzt habe, jetzt auch noch mit Code auf irgendwelchen Drittseiten - Warum kannst Du das hier nicht genauso einbetten, wie es Dir die Forensoftware anbietet. Mit Codetags und bis zu einer Gesamtlänge von 9000 Zeichen direkt - darüber hinaus als Attachment.

Habs eingebunden :slight_smile:

agmue:
Bei U8glib lese ich: "Note: There will be no more development for U8glib. Please use u8g2."

Warum verwendest Du eine veraltete Bibliothek?

Das Projekt lag jetzt fast ein Jahr brach, weil ich kaum Zeit dazu hatte und ich hatte damals mit ein wenig Hilfe diesen Code bekommen, der erstmal das tat was er tut. Kann man sich sicherlich nochmal ansehen, aber ich glaube mein aktuelles Problem ist ja eher in der Stromversorgung, statt im Code zu suchen, oder?

my_xy_projekt:
Jedes Display benötigt 40 (45) mA.
11 Display → 440 (495) mA

Damit ist die 500mA Grenze ausgereizt.

Das Pinout (Datenblatt Seite 5) sagt Dir, wie Du +5V und GND anschliessen musst.
Entweder ein externes einfaches - aber möglichst stabiles - Netzteil, welches ausgelegt ist für die Anzahl der Displays-> 27 * 45mA → 5V / 1,5A Netzteil oder eine Powerbank, die das dauerhaft liefert.

GND hatte ich erwähnt.
I2C Leitungslängen und Beschaltungen beachten.

ok, also ich habe ja noch dieses Power Panel, wie auf dem beigefügten Foto:
kann ich dieses einfach auf ein Breadboard stecken, auf 5V schalten mit dem Jumper und dann alle roten Kabel “Strom bei den Displays” auf die Stromführende Verbindung auf dem zweiten Breadboard umstecken?

Die GND Verbindungen sollen ja auf dem ersten Breadboard bleiben und damit zum Arduino gehen, korrekt?


Und Du glaubst so ein Power Board kann mehr als 500mA liefern?
Grüße Uwe

uwefed:


Und Du glaubst so ein Power Board kann mehr als 500mA liefern?
Grüße Uwe

Ich entnehme Deiner Frage mal, dass es das wohl nicht kann. Ok das schließt diesen Weg schonmal aus.

Wenn ich sowas wüsste, dann würde ich diese Fragen ja hier nicht stellen.

Wie kann man denn eine Stromquelle so mit den Displays verbinden, das die benötigte Strommenge übertragen werden kann?

Du nimmst ein 5V Netzteil.
Mehr als 5V brauchst Du in Deiner Schaltung ja nicht (soweit ich das verstanden habe).

Du solltest Dich auch in den Gebrauch des I2C einlesen. Wahrscheinlich brauchst Du keine oder nicht so viele Multiplexer. Pullup-Widerstände sind essentiell für das Funktionieren des I2C Busses. Darum muß man auch den richtigen Wert für den Pullup wählen. Der richtige Wert hängt von Typ des Kabels, dessen Länge, der Anzahl der angesteuerten I2C Devices.

Grüße Uwe

kay899:
Wenn ich sowas wüsste, dann würde ich diese Fragen ja hier nicht stellen.

Und warum liest du nicht das Datenblatt zu deinen Teilen ?
Da steht alles drin.

uwefed:
Du nimmst ein 5V Netzteil.
Mehr als 5V brauchst Du in Deiner Schaltung ja nicht (soweit ich das verstanden habe).

Du solltest Dich auch in den Gebrauch des I2C einlesen. Wahrscheinlich brauchst Du keine oder nicht so viele Multiplexer. Pullup-Widerstände sind essentiell für das Funktionieren des I2C Busses. Darum muß man auch den richtigen Wert für den Pullup wählen. Der richtige Wert hängt von Typ des Kabels, dessen Länge, der Anzahl der angesteuerten I2C Devices.

Grüße Uwe

Hallo Uwe,

sorry jetzt steh ich komplett auf dem Schlauch. Ich hab keinen Elektrotechnikhintergrund und verstehe daher viele Prinzipien nicht, die euch anderen natürlich sehr geläufig sind.

Ich habe verstanden, dass ich die Displays extern mit Strom versorgen muss. Soweit so gut. Mein letztes Bild zeigt einen Power Supply der mit einem 9V Netzteil angeschlossen ist. Dieses habe ich mit den Jumpern auf 5V gesetzt. Deswegen gehe ich davon aus, das ich nun im BreadBoard auf den roten Linien jeweils 5V zur Verfügung stehen habe, oder ist das nicht der Fall?

Irgendwie muss ich ja die ganzen Kabel der insgesamt 27 Displays in irgendeiner Art mit dem Strom verbinden und das wollte ich auf diesem zweiten BreadBoard machen. Ist das der falsche Weg? Wie müsste ich das richtig machen?

Danke für eure Hilfe.

LG
kay899

Theoretisch ist deine Schaltung schon OK.
Allerdings ist der Regler auf diesem Board nicht für den Strom geeignet, den deine gesamten Displays benötigen.

Du brauchst ein 5Volt Netzteil mit dem du die Displays speist, oder einen geeigneten Spannungsregler der auch den Strom bzw. die Verlustleistung verträgt.