Zwei SSD1306 Oled Displays anschließen

Hallo,

kann mir jemand verraten wie ich die SSD1306 Oled Display gleichzeitig und unabhängig von einander betreiben kann.
Im Internet habe ich bis jetzt nur Hinweise zum Auflöten von Kontaktbrücken gesehen. Leider haben meine Displays solche nicht.

Lg

Können Sie einen Link zu Ihren Modulen posten?

Es ist ein I2C-Modul, sodass Sie mehrere auf demselben Bus haben können, solange sie unterschiedliche Adressen haben. Die Herausforderung besteht darin, dass es anscheinend nicht möglich ist, verschiedene Adressen festzulegen, sodass Sie eine Komponente verwenden müssten, die dies für Sie erledigt. (siehe zum Beispiel Overview | Working with Multiple Same Address I2C Devices | Adafruit Learning System)

Das wird schwierig es gibt I2C Multiplexer aber ob damit Display's vernünftig funktionieren?

Ich habe da vor längerem mal herumexperimentiert:

Die Lösung dafür ist ein I2C-Switch. Man kann solche Teile kaufen. Wenn man z.B. nach dem Begriff TCA9548 sucht, wird man schnell fündig. Die angebotenen Breakouts basieren auf dem PCA9548 IC. Der PCA9546, PCA9540 sind Alternativen mit weniger Ports (4 bzw. 2 Ports statt 8).

Man kann sich einen I2C-Switch aber auch selber mit ein paar N-Kanal MOSFets, wie dem z.B. BS170, selber zusammenstecken. Das sieht dann so aus:

U1 und U2 im Schaltplan entsprechen einem Pin am Mikrocontroller. SCL und SDA (links) entsprechen dem Signal welches vom I2C Master kommt. I.d.R. ist das der gleiche Mikrocontroller, der auch zum Ansteuern der Mosfets verwendet wird. An den IO_SCLX und IO_SDAX Ausgängen wird jeweils ein I2C Slave angeschlossen. Die 4k7 Widerstände sind Pullups für die I2C Leitungen.

Auf dem Breadboard zusammengesteckt sieht es wie folgt aus:

Ich habe zum ausprobieren zwei OLED-Displays mit dem selbst zusammengesteckten Switch betrieben. Es werden immer zwei MOSFETs paarweise durch einen Pin vom Mikrocontroller geschaltet. Ein Paar entspricht immer einer SCL und einer SDA Leitung. Wird der PIN auf HIGH gesetzt, ist das entsprechende SCL und SDA Leitungspaar aktiv. Ist der Pin auf LOW gesetzt, ist auch das entsprechende Leitungspaar deaktiviert. Durch die Schaltung können beide Displays an einem Controller getrennt betrieben werden, obwohl sie eine identische Adresse haben.

Werden beide Kanalpaare gleichzeitig aktiviert, erfolgt auf beiden Displays eine identische Ausgabe. Die eingestellte Taktfrequenz betrug 400kHz.

Solch einen Switch kann man natürlich auch für Sensoren verwenden. Bei den verwendeten MOSFETS muss unbedingt darauf geachtet werden, was sie für eine Input-Kapazität haben. Diese muss so gering wie möglich sein. Auf einem I2C-Strang darf die Gesamtkapazität 400pF nicht überschreiten. Die BS170 sind mit einer Kapazität von typisch 24 pF und max. 40pF bei 10V angegeben.

Das Beispielprogramm ist aus einem vorgegebenen Beispielprogramm aus der OLED Bibliothek zusammengestuppelt. Nicht schön aber es hats getan. Der "Knackpunkt" ist die Umschaltung zwischen den Displays über die Pins PIN_DISP_1 und PIN_DISP_2

/**************************************************************************
 This is an example for our Monochrome OLEDs based on SSD1306 drivers

 Pick one up today in the adafruit shop!
 ------> http://www.adafruit.com/category/63_98

 This example is for a 128x64 pixel display using I2C to communicate
 3 pins are required to interface (two I2C and one reset).

 Adafruit invests time and resources providing this open
 source code, please support Adafruit and open-source
 hardware by purchasing products from Adafruit!

 Written by Limor Fried/Ladyada for Adafruit Industries,
 with contributions from the open source community.
 BSD license, check license.txt for more information
 All text above, and the splash screen below must be
 included in any redistribution.
 **************************************************************************/
#include <Arduino.h>
#include <avr/sleep.h>//this AVR library contains the methods that controls the sleep modes
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET,400000UL ,100000UL );

#define NUMFLAKES     10 // Number of snowflakes in the animation example

#define LOGO_HEIGHT   16
#define LOGO_WIDTH    16

#define EYE_HEIGHT   64
#define EYE_WIDTH    50

//#define INTERRUPTPIN 2  //Pin we are going to use to wake up the Arduino
#define SWITCH 10       // Display ON/OFF Switch PIN = D10

void testdrawline(void);      // Draw many lines
void testdrawrect(void);      // Draw rectangles (outlines)
void testfillrect(void);      // Draw rectangles (filled)
void testdrawcircle(void);    // Draw circles (outlines)
void testfillcircle(void);    // Draw circles (filled)
void testdrawroundrect(void); // Draw rounded rectangles (outlines)
void testfillroundrect(void); // Draw rounded rectangles (filled)
void testdrawtriangle(void);  // Draw triangles (outlines)
void testfilltriangle(void);  // Draw triangles (filled)
void testdrawchar(void);      // Draw characters of the default font
void testdrawstyles(void);    // Draw 'stylized' characters
void testscrolltext(void);    // Draw scrolling text
void testdrawbitmap(void);    // Draw a small bitmap image
void testdrawEyeLeft(void);
void testdrawEyeRight(void);
void testdrawEyeLeft2(void);
void testdrawEyeRight2(void);
void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h); // Animate bitmaps
void demo(void);              // show Display features
void GoingToSleep(void);      // Goint into Sleep mode
void wakeUp(void);            // Do wakeup
/*
static const unsigned char PROGMEM logo_bmp[] =
{ B00000000, B11000000,
  B00000001, B11000000,
  B00000001, B11000000,
  B00000011, B11100000,
  B11110011, B11100000,
  B11111110, B11111000,
  B01111110, B11111111,
  B00110011, B10011111,
  B00011111, B11111100,
  B00001101, B01110000,
  B00011011, B10100000,
  B00111111, B11100000,
  B00111111, B11110000,
  B01111100, B11110000,
  B01110000, B01110000,
  B00000000, B00110000 };
*/
// 'Auge-Links-klein', 50x64px
const unsigned char epd_bitmap_Auge_Links_klein [] PROGMEM = {
	0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7f, 
	0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x70, 
	0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x07, 
	0x80, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x18, 0x00, 0xff, 0xfc, 0x00, 
	0x00, 0x00, 0x00, 0x03, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x80, 0x00, 0x00, 
	0x00, 0x0e, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x18, 
	0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 
	0x1c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x0e, 0x00, 
	0x00, 0x00, 0xe0, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 
	0xc0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0x80, 0x00, 
	0x00, 0x01, 0x80, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 
	0xc0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x00, 
	0x01, 0x80, 0x07, 0xe0, 0x00, 0x60, 0x00, 0x03, 0x80, 0x0f, 0xf0, 0x00, 0x60, 0x00, 0x03, 0x80, 
	0x1f, 0xf8, 0x00, 0x60, 0x00, 0x01, 0x80, 0x1f, 0xfc, 0x00, 0x60, 0x00, 0x01, 0x80, 0x3f, 0xfe, 
	0x00, 0x70, 0x00, 0x01, 0x80, 0x3f, 0xfe, 0x00, 0x70, 0x00, 0x01, 0x80, 0x3f, 0xff, 0x00, 0x30, 
	0x00, 0x01, 0x80, 0x3f, 0xff, 0x00, 0x30, 0x00, 0x01, 0x80, 0x3f, 0xbf, 0x00, 0x30, 0x00, 0x01, 
	0x80, 0x3f, 0x0f, 0x80, 0x30, 0x00, 0x01, 0xc0, 0x1e, 0x0f, 0x80, 0x30, 0x00, 0x00, 0xc0, 0x1e, 
	0x0f, 0x80, 0x30, 0x00, 0x00, 0xc0, 0x1f, 0x1f, 0x80, 0x30, 0x00, 0x00, 0xc0, 0x1f, 0xff, 0x80, 
	0x70, 0x00, 0x00, 0xe0, 0x0f, 0xff, 0x80, 0x70, 0x00, 0x00, 0x60, 0x07, 0xff, 0x00, 0x60, 0x00, 
	0x00, 0x70, 0x07, 0xff, 0x00, 0x60, 0x00, 0x00, 0x30, 0x03, 0xfe, 0x00, 0x60, 0x00, 0x00, 0x38, 
	0x01, 0xfe, 0x00, 0xe0, 0x00, 0x00, 0x18, 0x00, 0x78, 0x00, 0xc0, 0x00, 0x00, 0x1c, 0x00, 0x00, 
	0x00, 0xc0, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x01, 0x80, 
	0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0x80, 0x00, 0x03, 0x00, 0x00, 0x00, 
	0x01, 0xc0, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xf0, 
	0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x01, 0xf0, 
	0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00
};

// 'Auge-Links-2-klein', 50x64px
const unsigned char epd_bitmap_Auge_Links_2_klein [] PROGMEM = {
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x80, 
	0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x00, 0x00, 
	0x00, 0x01, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x03, 0xfe, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x07, 
	0xf8, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x01, 
	0xe0, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x1f, 0xfc, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x3f, 0x7f, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x01, 0xe0, 0x00, 0x00, 
	0x00, 0x03, 0x80, 0x00, 0x70, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x06, 
	0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 
	0x07, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x03, 0x80, 
	0x00, 0x00, 0x38, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x30, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 
	0x30, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x60, 0x00, 
	0x00, 0x00, 0x60, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 
	0x30, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x38, 0x00, 
	0x00, 0x60, 0x01, 0xf8, 0x00, 0x18, 0x00, 0x00, 0xe0, 0x03, 0xfc, 0x00, 0x18, 0x00, 0x00, 0xe0, 
	0x07, 0xfe, 0x00, 0x18, 0x00, 0x00, 0x60, 0x07, 0xff, 0x00, 0x18, 0x00, 0x00, 0x60, 0x0f, 0xff, 
	0x80, 0x1c, 0x00, 0x00, 0x60, 0x0f, 0xff, 0x80, 0x1c, 0x00, 0x00, 0x60, 0x0f, 0xff, 0xc0, 0x0c, 
	0x00, 0x00, 0x60, 0x0f, 0xff, 0xc0, 0x0c, 0x00, 0x00, 0x60, 0x0f, 0xef, 0xc0, 0x0c, 0x00, 0x00, 
	0x60, 0x0f, 0xc3, 0xe0, 0x0c, 0x00, 0x00, 0x70, 0x07, 0x83, 0xe0, 0x0c, 0x00, 0x00, 0x30, 0x07, 
	0x83, 0xe0, 0x0c, 0x00, 0x00, 0x30, 0x07, 0xc7, 0xe0, 0x0c, 0x00, 0x00, 0x30, 0x03, 0xff, 0xe0, 
	0x1c, 0x00, 0x00, 0x18, 0x03, 0xff, 0xe0, 0x18, 0x00, 0x00, 0x18, 0x01, 0xff, 0xc0, 0x18, 0x00, 
	0x00, 0x1c, 0x01, 0xff, 0xc0, 0x18, 0x00, 0x00, 0x0c, 0x00, 0xff, 0x80, 0x18, 0x00, 0x00, 0x0e, 
	0x00, 0x7f, 0x80, 0x38, 0x00, 0x00, 0x06, 0x00, 0x1e, 0x00, 0x30, 0x00, 0x00, 0x07, 0x00, 0x00, 
	0x00, 0x30, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x60, 
	0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xc0, 0x00, 0x00, 
	0x00, 0x70, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x3c, 
	0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x7c, 
	0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x00
};

// 'Auge-Rechts-klein', 50x64px
const unsigned char epd_bitmap_Auge_Rechts_klein [] PROGMEM = {
	0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 
	0x0f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 
	0xff, 0x80, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x00, 0x00, 
	0x00, 0x1f, 0xf8, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x70, 0x00, 0x00, 0x00, 0xf0, 
	0x0f, 0x80, 0x78, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x38, 0x00, 0x00, 0x07, 0x80, 0x01, 0xe0, 
	0x18, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x78, 0x00, 0x00, 
	0x00, 0x1c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x38, 
	0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 
	0x07, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x03, 0x80, 
	0x00, 0x01, 0xc0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 
	0x80, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x03, 0x80, 0x00, 
	0x00, 0x01, 0xc0, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
	0xc0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x00, 0xe0, 0x00, 
	0x03, 0x00, 0x3f, 0x80, 0x00, 0xe0, 0x00, 0x03, 0x00, 0x7f, 0xc0, 0x00, 0xe0, 0x00, 0x03, 0x00, 
	0xff, 0xe0, 0x00, 0xe0, 0x00, 0x03, 0x01, 0xff, 0xe0, 0x00, 0xe0, 0x00, 0x03, 0x03, 0xff, 0xf0, 
	0x00, 0xe0, 0x00, 0x03, 0x03, 0xff, 0xf0, 0x00, 0xe0, 0x00, 0x03, 0x07, 0xff, 0xf0, 0x00, 0xe0, 
	0x00, 0x03, 0x07, 0xff, 0xf0, 0x00, 0xe0, 0x00, 0x03, 0x07, 0xff, 0xf0, 0x00, 0xe0, 0x00, 0x03, 
	0x07, 0xc7, 0xf0, 0x00, 0xc0, 0x00, 0x03, 0x8f, 0x87, 0xe0, 0x01, 0xc0, 0x00, 0x03, 0x8f, 0x87, 
	0xe0, 0x01, 0xc0, 0x00, 0x01, 0x8f, 0xc7, 0xe0, 0x01, 0xc0, 0x00, 0x01, 0xcf, 0xff, 0xc0, 0x01, 
	0xc0, 0x00, 0x01, 0xc7, 0xff, 0xc0, 0x03, 0x80, 0x00, 0x00, 0xc7, 0xff, 0x80, 0x03, 0x80, 0x00, 
	0x00, 0xe7, 0xff, 0x00, 0x03, 0x80, 0x00, 0x00, 0xe3, 0xfe, 0x00, 0x07, 0x00, 0x00, 0x00, 0x71, 
	0xfc, 0x00, 0x07, 0x00, 0x00, 0x00, 0x70, 0x60, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 
	0x1e, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x38, 0x00, 
	0x00, 0x00, 0x0e, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 
	0x03, 0x80, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xf8, 
	0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

// 'Auge-Rechts-2-klein', 50x64px
const unsigned char epd_bitmap_Auge_Rechts_2_klein [] PROGMEM = {
	0x00, 0x00, 0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 
	0x07, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 
	0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 
	0x00, 0x1f, 0xf8, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x07, 0xc0, 0x00, 0x00, 0x00, 0xf8, 
	0x0f, 0x83, 0xe0, 0x00, 0x00, 0x03, 0xe0, 0x03, 0xc3, 0xe0, 0x00, 0x00, 0x07, 0x80, 0x01, 0xe3, 
	0xe0, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xf1, 0xe0, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x79, 0xe0, 0x00, 
	0x00, 0x1c, 0x00, 0x00, 0x3c, 0xe0, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1c, 0xe0, 0x00, 0x00, 0x38, 
	0x00, 0x00, 0x0e, 0xe0, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 
	0x07, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x03, 0x80, 
	0x00, 0x01, 0xc0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01, 
	0x80, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x03, 0x80, 0x00, 
	0x00, 0x01, 0xc0, 0x00, 0x03, 0x80, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
	0xc0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03, 0x00, 0x0e, 0x00, 0x00, 0xe0, 0x00, 
	0x03, 0x00, 0x3f, 0x80, 0x00, 0xe0, 0x00, 0x03, 0x00, 0x7f, 0xc0, 0x00, 0xe0, 0x00, 0x03, 0x00, 
	0xff, 0xe0, 0x00, 0xe0, 0x00, 0x03, 0x01, 0xff, 0xe0, 0x00, 0xe0, 0x00, 0x03, 0x03, 0xff, 0xf0, 
	0x00, 0xe0, 0x00, 0x03, 0x03, 0xff, 0xf0, 0x00, 0xe0, 0x00, 0x03, 0x07, 0xff, 0xf0, 0x00, 0xe0, 
	0x00, 0x03, 0x07, 0xff, 0xf0, 0x00, 0xe0, 0x00, 0x03, 0x07, 0xff, 0xf0, 0x00, 0xe0, 0x00, 0x03, 
	0x87, 0xc7, 0xf0, 0x00, 0xc0, 0x00, 0x03, 0x8f, 0x87, 0xe0, 0x01, 0xc0, 0x00, 0x03, 0x8f, 0x87, 
	0xe0, 0x01, 0xc0, 0x00, 0x01, 0x8f, 0xc7, 0xe0, 0x01, 0xc0, 0x00, 0x01, 0xcf, 0xff, 0xc0, 0x01, 
	0xc0, 0x00, 0x01, 0xc7, 0xff, 0xc0, 0x03, 0x80, 0x00, 0x00, 0xc7, 0xff, 0x80, 0x03, 0x80, 0x00, 
	0x00, 0xe7, 0xff, 0x00, 0x03, 0x80, 0x00, 0x00, 0xe3, 0xfe, 0x00, 0x07, 0x00, 0x00, 0x00, 0x71, 
	0xfc, 0x00, 0x07, 0x00, 0x00, 0x00, 0x70, 0x60, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 
	0x1e, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x38, 0x00, 
	0x00, 0x00, 0x0e, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 
	0x03, 0x80, 0x01, 0xe0, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xf8, 
	0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

#define PIN_DISP1 2
#define PIN_DISP2 3 

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

  pinMode(PIN_DISP1,OUTPUT);
  pinMode(PIN_DISP2,OUTPUT);   
  digitalWrite(PIN_DISP1,HIGH);
  digitalWrite(PIN_DISP2,LOW);
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  Serial.println("Display 1 OK");
  digitalWrite(PIN_DISP1,LOW);
  digitalWrite(PIN_DISP2,HIGH);
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  Serial.println("Display 2 OK");

}

void loop() {
  delay(1000);
  digitalWrite(PIN_DISP1,HIGH);
  digitalWrite(PIN_DISP2,LOW);
  testdrawEyeLeft();
  digitalWrite(PIN_DISP1,LOW);
  digitalWrite(PIN_DISP2,HIGH);
  testdrawEyeRight();
  delay(1000);
  digitalWrite(PIN_DISP1,HIGH);
  digitalWrite(PIN_DISP2,LOW);
  testdrawEyeLeft2();
  delay(200);
  testdrawEyeLeft();
  delay(1000);
  digitalWrite(PIN_DISP1,LOW);
  digitalWrite(PIN_DISP2,HIGH);
  testdrawEyeRight2();
  delay(200);
  testdrawEyeRight();
  delay(2000);
  digitalWrite(PIN_DISP1,HIGH);
  digitalWrite(PIN_DISP2,LOW);
  display.clearDisplay();
  display.display();
  digitalWrite(PIN_DISP1,LOW);
  digitalWrite(PIN_DISP2,HIGH);
  testdrawcircle();
  digitalWrite(PIN_DISP1,HIGH);
  digitalWrite(PIN_DISP2,LOW);
  testdrawtriangle();
  delay(2000);
  display.clearDisplay();
  display.display();
  digitalWrite(PIN_DISP1,LOW);
  digitalWrite(PIN_DISP2,HIGH);
  display.clearDisplay();
  display.display();
  delay(1000);

  digitalWrite(PIN_DISP1,HIGH);
  digitalWrite(PIN_DISP2,HIGH);
  testscrolltext();

  //demo();
}

void testdrawline() {
  int16_t i;

  display.clearDisplay(); // Clear display buffer

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
    display.display(); // Update screen with each newly-drawn line
    delay(1);
  }
  for(i=0; i<display.height(); i+=4) {
    display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.width(); i+=4) {
    display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=display.width()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=display.height()-1; i>=0; i-=4) {
    display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for(i=0; i<display.height(); i+=4) {
    display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for(i=0; i<display.width(); i+=4) {
    display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(2000); // Pause for 2 seconds
}

void testdrawrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=2) {
    display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
    display.display(); // Update screen with each newly-drawn rectangle
    delay(1);
  }
  delay(2000);
}

void testfillrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2; i+=3) {
    // The INVERSE color is used so rectangles alternate white/black
    display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
    display.display(); // Update screen with each newly-drawn rectangle
    delay(1);
  }

  delay(2000);
}

void testdrawcircle(void) {
  display.clearDisplay();

  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
    display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  //delay(2000);
}

void testfillcircle(void) {
  display.clearDisplay();

  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
    // The INVERSE color is used so circles alternate white/black
    display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
    display.display(); // Update screen with each newly-drawn circle
    delay(1);
  }

  //delay(2000);
}

void testdrawroundrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2-2; i+=2) {
    display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
      display.height()/4, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillroundrect(void) {
  display.clearDisplay();

  for(int16_t i=0; i<display.height()/2-2; i+=2) {
    // The INVERSE color is used so round-rects alternate white/black
    display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
      display.height()/4, SSD1306_INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawtriangle(void) {
  display.clearDisplay();

  for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
    display.drawTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  //delay(2000);
}

void testfilltriangle(void) {
  display.clearDisplay();

  for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
    // The INVERSE color is used so triangles alternate white/black
    display.fillTriangle(
      display.width()/2  , display.height()/2-i,
      display.width()/2-i, display.height()/2+i,
      display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);
    display.display();
    delay(1);
  }
  delay(2000);
}

void testdrawchar(void) {
  display.clearDisplay();

  display.setTextSize(1);      // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(0, 0);     // Start at top-left corner
  display.cp437(true);         // Use full 256 char 'Code Page 437' font

  // Not all the characters will fit on the display. This is normal.
  // Library will draw what it can and the rest will be clipped.
  for(int16_t i=0; i<256; i++) {
    if(i == '\n') display.write(' ');
    else          display.write(i);
  }

  display.display();
  delay(2000);
}

void testdrawstyles(void) {
  display.clearDisplay();

  display.setTextSize(1);             // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);        // Draw white text
  display.setCursor(0,0);             // Start at top-left corner
  display.println(F("Hello, world!"));

  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
  display.println(3.141592);

  display.setTextSize(2);             // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.print(F("0x")); display.println(0xDEADBEEF, HEX);

  display.display();
  //delay(2000);
}

void testscrolltext(void) {
  display.clearDisplay();

  display.setTextSize(2); // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 0);
  display.println(F("Display"));
  display.display();      // Show initial text
  delay(100);

  // Scroll in various directions, pausing in-between:
  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);
}

/*
void testdrawbitmap(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width()  - LOGO_WIDTH ) / 2,
    (display.height() - LOGO_HEIGHT) / 2,
    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  display.display();
  delay(1000);
}
*/

void testdrawEyeLeft(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width()  - EYE_WIDTH) / 2,
    (display.height() - EYE_HEIGHT) / 2,
    epd_bitmap_Auge_Links_klein, EYE_WIDTH, EYE_HEIGHT, 1);
  display.display();
  //delay(1000);
}

void testdrawEyeLeft2(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width()  - EYE_WIDTH) / 2+10,
    (display.height() - EYE_HEIGHT) / 2,
    epd_bitmap_Auge_Links_2_klein, EYE_WIDTH, EYE_HEIGHT, 1);
  display.display();
  //delay(1000);
}

void testdrawEyeRight(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width()  - EYE_WIDTH) / 2+10,
    (display.height() - EYE_HEIGHT) / 2,
    epd_bitmap_Auge_Rechts_klein, EYE_WIDTH, EYE_HEIGHT, 1);
  display.display();
  //delay(1000);
}

void testdrawEyeRight2(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width()  - EYE_WIDTH) / 2,
    (display.height() - EYE_HEIGHT) / 2,
    epd_bitmap_Auge_Rechts_2_klein, EYE_WIDTH, EYE_HEIGHT, 1);
  display.display();
  //delay(1000);
}


#define XPOS   0 // Indexes into the 'icons' array in function below
#define YPOS   1
#define DELTAY 2

void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  int8_t f, icons[NUMFLAKES][3];

  // Initialize 'snowflake' positions
  for(f=0; f< NUMFLAKES; f++) {
    icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
    icons[f][YPOS]   = -LOGO_HEIGHT;
    icons[f][DELTAY] = random(1, 6);
    Serial.print(F("x: "));
    Serial.print(icons[f][XPOS], DEC);
    Serial.print(F(" y: "));
    Serial.print(icons[f][YPOS], DEC);
    Serial.print(F(" dy: "));
    Serial.println(icons[f][DELTAY], DEC);
  }

  for(byte i = 100;i>0;--i) { // Loop forever...
    display.clearDisplay(); // Clear the display buffer

    // Draw each snowflake:
    for(f=0; f< NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
    }

    display.display(); // Show the display buffer on the screen
    delay(200);        // Pause for 1/10 second

    // Then update coordinates of each flake...
    for(f=0; f< NUMFLAKES; f++) {
      icons[f][YPOS] += icons[f][DELTAY];
      // If snowflake is off the bottom of the screen...
      if (icons[f][YPOS] >= display.height()) {
        // Reinitialize to a random position, just off the top
        icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
        icons[f][YPOS]   = -LOGO_HEIGHT;
        icons[f][DELTAY] = random(1, 6);
      }
    }
  }
}

void demo() {
    // Show initial display buffer contents on the screen --
    // the library initializes this with an Adafruit splash screen.
    display.display();
    delay(2000); // Pause for 2 seconds

    // Clear the buffer
    display.clearDisplay();

    // Draw a single pixel in white
    display.drawPixel(10, 10, SSD1306_WHITE);

    // Show the display buffer on the screen. You MUST call display() after
    // drawing commands to make them visible on screen!
    display.display();
    delay(2000);
    // display.display() is NOT necessary after every single drawing command,
    // unless that's what you want...rather, you can batch up a bunch of
    // drawing operations and then update the screen all at once by calling
    // display.display(). These examples demonstrate both approaches...

    testdrawline();      // Draw many lines

    testdrawrect();      // Draw rectangles (outlines)

    testfillrect();      // Draw rectangles (filled)

    testdrawcircle();    // Draw circles (outlines)

    testfillcircle();    // Draw circles (filled)

    testdrawroundrect(); // Draw rounded rectangles (outlines)

    testfillroundrect(); // Draw rounded rectangles (filled)

    testdrawtriangle();  // Draw triangles (outlines)

    testfilltriangle();  // Draw triangles (filled)

    testdrawchar();      // Draw characters of the default font

    testdrawstyles();    // Draw 'stylized' characters

    testscrolltext();    // Draw scrolling text

    testdrawbitmap();    // Draw a small bitmap image
    /*
    // Invert and restore display, pausing in-between
    display.invertDisplay(true);
    delay(1000);
    display.invertDisplay(false);
    delay(1000);

    testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
    */
}

void GoingToSleep(){
  sleep_enable();//Enabling sleep mode
  attachInterrupt(0, wakeUp, LOW);//attaching a interrupt to pin d2
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);//Setting the sleep mode, in our case full sleep
  digitalWrite(LED_BUILTIN,LOW);//turning LED off
  delay(1000); //wait a second to allow the led to be turned off before going to sleep
  sleep_cpu();//activating sleep mode
  Serial.println("just woke up!");//next line of code executed after the interrupt 
  digitalWrite(LED_BUILTIN,HIGH);//turning LED on
}

void wakeUp(){
  sleep_disable();                    //Disable sleep mode
  detachInterrupt(0);                 //Removes the interrupt from pin 2;
}
3 Likes

Schön gemacht, sofort auf die Seite gelegt :wink:
Auf die Schaltidee mit MOSFETs muss man kommen.

Man kann zu Übersicht zweiten Display deklarieren, oder?
Adafruit_SSD1306 display1(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET,400000UL
So mach ich das bei LCD 2004

Ich weiß nicht so recht wie Du das meinst. Aus "Softwaresicht" gibt es nur ein Display. Darum erscheint mir die Erzeugung eines zweiten Displayobjektes für unnötig.

Hast vollkommen Recht haben ja gleiche Adresse nur jeder schreibt nach eignem ermessen, ob das logisch ist, ist andere Sache

Ich hab mal gestöbert.
Herstellerseite

So... und da gibt es Datenblatt.

Da ich keine Ahnung habe, Seite 12.
Pin: D/C# - Type Input - In I2C mode, this pin acts as SA0 for slave address selection.
Da Du nur zwei Displays willst, geht das, denn:

Und wie kommst Du an den Chip dran ?
Vorne und Hinten
Er hat sogar kein schwarzen Klecks drauf.

Ist das Display nicht nur mit doppeltem Klebeband aufgeklebt?
Ablösen und dann Pin 56 suchen.

PS: Ist das tatsächlich so, das der Display Pin 20 und Pin 19 gebrückt ist?

Es gibt OLEDs bei denen ist das möglich, durch "Umsetzen" eines Widerstands, wie z.B. bei diesem hier, die Adresse zu ändern:


Dort kann man zwischen 0x78 und 0x7A wählen. Also, dass das bei dem SSD Controller geht ist klar. Nur wie @fony schon zurecht fragt, ist das nicht bei allen angebotenen Modellen so ohne Weiteres möglich die Adresse zu ändern.

Ein Blick auf die Rückseite des Modells vom TO würde vielleicht mehr Aufschluss geben. Aber er schreibt ja, dass er da nichts gefunden hat.

Das Klebt so stark das keine Möglichkeit das Ding zerlegen

Ich wurde noch einen kaufen der hat die möglichkeit Adresse ändern

Ich habe so ähnliche, die "hören" mit dem Widerstand auf der 0x78 Seite trotzdem nur auf 0x3C
Umlöten habe ich noch nicht probiert...

Das ist genau ein bit verschoben.
Wenn Du 7 bit nimmst und das achte auffüllst, stimmt es.

Wen Dir bei Umlöten der Widerstand stört oder nicht zu finden ist, nimm einfach dienen Draht oder tropfen Zinn, die Dinger haben 0 Ohm :wink:

Bis jetzt bin ich immer mit einem Display ausgekommen. :smiley:

Eigentlich sollen die 128x64er doch auf 0x3D hören...