Forum: Mikrocontroller und Digitale Elektronik Display"fehler" bei OLED Module IIC I2C 128x64


von Christoph K. (chriskuku)


Angehängte Dateien:

Lesenswert?

Ich betreibe ein
1.3" OLED LCD 4Pin Display Module IIC I2C 128x64 3-5V
an einem STM32F103C8T6 und einer Library von
https://controllerstech.com/oled-display-using-i2c-stm32/
Auf dem Display (s. Bild) sieht man am rechten Rand so ein Gegrissel, 
auf dessen Zustandekommen ich mir keinen Reim machen kann. Es gab mal 
einen Zustand im Verlauf der Programmierung, da war es plötzlich weg, 
aber im Moment bleibt es hartnäckig präsent. Der beteiligte Code:
1
  SSD1306_Init (); // initialize the display
2
  SSD1306_Clear();
3
  SSD1306_UpdateScreen();  // habe ich noch hinzugefügt, bringt aber nichts
4
  SSD1306_GotoXY (10,10); // goto 10, 10
5
  SSD1306_Puts ("Key", &Font_11x18, 1); 
6
7
  SSD1306_UpdateScreen(); // update screen

Betriebsspannung ist 3,3V. Hat jemand eine Idee?

von Achim H. (pluto25)


Lesenswert?

Sicher das kein 1305 verbaut ist? der macht 132 Punkte und würde beim 
Clear des 1306 die letzten Spalten nicht löschen.
Stimmt die Pos 0,0?

von Christoph K. (chriskuku)


Angehängte Dateien:

Lesenswert?

A. H. schrieb:
> Sicher das kein 1305 verbaut ist? der macht 132 Punkte und würde beim
> Clear des 1306 die letzten Spalten nicht löschen.
> Stimmt die Pos 0,0?

Hatte jetzt gerade mal Power weggenommen und den Reset Knopf gedrückt. 
Jetzt ist alles gecleart. Leider sieht man es dem Chip nicht an, was es 
ist. Ist von DIYMore. Werde mal ein Rechteck malen:

SSD1306_DrawRectangle(0, 0, 127, 63, 1);

ergibt das 1. Bild

und

SSD1306_DrawRectangle(2, 2, 129, 63, 1);

das 2. Bild

: Bearbeitet durch User
von Lynx (Gast)


Lesenswert?

Ich hab Module die genau so aussehen - nur ist da ein SH1106 verbaut...

von Christoph K. (chriskuku)


Lesenswert?

Lynx schrieb:
> Ich hab Module die genau so aussehen - nur ist da ein SH1106 verbaut...
Jetzt, wo Du es sagst, erkenne ich schwach auf dem Rand des Displays 
N201102C.
Wahrscheinlich hat die Lib noch ein Clipping der Parameter eingebaut. 
Müßte mal in die Source schauen. Sowas tut es auch noch:

SSD1306_DrawRectangle(2, 0, 132, 65, 1);

Aber

SSD1306_DrawRectangle(1, 0, 132, 65, 1);

schneidet vorne die schmale Seite ab.

Gibt es alternative Libraries zu dem Chip?

: Bearbeitet durch User
von Christoph K. (chriskuku)


Angehängte Dateien:

Lesenswert?

Das Problem ist noch nicht gelöst (s. Bild)
Ich kann nicht in diesen Bereich hineinmalen.
In der Source wird ein Pixelbuffer von WIDTHxHEIGHT von 128x64 
definiert, der mit 0 gefüllt wird.Setze ich in der Lib source die 
SSD1306_WIDTH=132, wird der Bereich nicht gecleart (FILL).

von J. S. (jojos)


Lesenswert?

Da würde ich am ehesten auf eine falsche Initialisierung tippen. Man 
muss nicht unbedingt eine andere Lib nehmen, erstmal den init Code gegen 
anderen austauschen, vor allem wenn der für einen andere Controller war.
Ansonsten sind eben die Adafruit_GFX oder andere für Arduino sehr 
ausgereift, allerdings in C++.

von Steve van de Grens (roehrmond)


Lesenswert?

Offenbar ist da der RAM Puffer versus Display um 2 Pixel verschoben. Das 
liegt bestimmt an der Initialisierung des Displays.

Vielleicht magst du mal einen schnelle Gegentest machen: 
http://stefanfrings.de/arduino_oled/index.html

Wenn es damit geht kannst du die Initialisierungs-Sequenz der beiden 
Quelltexte vergleichen.

Nachtrag: Mach mal 2,2kΩ Pull-Up Widerstände an SCL und SDA. Die 
Widerstände auf meinem Display sind arg hochohmig. Deine vielleicht 
auch.

: Bearbeitet durch User
von gelöscht (Gast)


Lesenswert?

Christoph K. schrieb:
> wird der Bereich nicht gecleart

Ist dein Problem jetzt geeatet?

von Christoph K. (chriskuku)


Lesenswert?

gelöscht schrieb:
> Christoph K. schrieb:
>> wird der Bereich nicht gecleart
>
> Ist dein Problem jetzt geeatet?

Nee, noch nicht gegessen. Bin im
Moment fern von meinem Schreibtisch. Vielleicht komme ich heute abend 
noch dazu oder sonst morgen. Danke.

von Manfred (Gast)


Lesenswert?

Christoph K. schrieb:
> Auf dem Display (s. Bild) sieht man am rechten Rand so ein Gegrissel,

Sowas hatte ich am Arduino, kurz bevor mir der Kram wegen Mangel an 
freiem RAM komplett abgeflogen ist.

von J. S. (jojos)


Lesenswert?

ich würde sagen das ist kein SSD1306 sondern SSH1106 und auch nicht mit 
132 sondern 128 Pixeln.
https://www.diymore.cc/collections/led-display-module/products/diymore-1-3-inch-oled-lcd-display-module-4pin-iic-i2c-interface-ssh1106-128-64-128-64-for-arduino-raspberry-pi-3-3v-5v

Ein SSD1306 haben die auch im Programm, da sind die Pins aber anders 
beschriftet (VIN statt VCC).

Da gibt es die Erklärung zum Unterschied (von Oli Kraus, Autor der 
u8glib):
https://forum.arduino.cc/t/whats-the-difference-between-adafruit-ssd1306-and-sh1106/247368/4

von Joachim B. (jar)


Lesenswert?

Christoph K. schrieb:
> Auf dem Display (s. Bild) sieht man am rechten Rand so ein Gegrissel

falsch initialisiert! Anderer Controller!

J. S. schrieb:
> Da gibt es die Erklärung zum Unterschied (von Oli Kraus, Autor der
> u8glib):
> 
https://forum.arduino.cc/t/whats-the-difference-between-adafruit-ssd1306-and-sh1106/247368/4

soweit ich mich erinnere!

von Christoph K. (chriskuku)


Lesenswert?

Steve van de Grens schrieb:

> Vielleicht magst du mal einen schnelle Gegentest machen:
> http://stefanfrings.de/arduino_oled/index.html
>

Schnellen Gegentest gemacht. Programm läuft, aber die Grafik im Display 
ist zeilenweise um ein paar Bits verschoben, paßt also nicht.

von Steve van de Grens (roehrmond)


Lesenswert?

Dann liegt es wohl wirklich daran, dass dein Display einen anderen Chip 
hat.

Da ich nur SSD1306 Displays habe wäre ich dir dankbar, wenn du an deinem 
Display etwas für mich ausprobieren würdest:

Ändere:
1
OLED display(Wire, 0x3C, NO_RESET_PIN, 128, 64);
auf:
1
OLED display(Wire, 0x3C, NO_RESET_PIN, 128, 64, true);

Wenn das bei dir klappt, lässt sich deine nicht funktionierende 
Bibliothek wahrscheinlich schnell anpassen. Du kannst in meinem Code 
sehen, dass nur wenige Zeilen beim SH1106 anders sind.

Unter anderen beeinflusst das, an welche Position der Pufferspeicher für 
jede Zeile in das RAM des Displays kopiert wird. Das klingt doch 
verdächtig, oder?

: Bearbeitet durch User
von Axel R. (axlr)


Lesenswert?

Christoph K. schrieb:
> Das Problem ist noch nicht gelöst (s. Bild)
> Ich kann nicht in diesen Bereich hineinmalen.
> In der Source wird ein Pixelbuffer von WIDTHxHEIGHT von 128x64
> definiert, der mit 0 gefüllt wird.Setze ich in der Lib source die
> SSD1306_WIDTH=132, wird der Bereich nicht gecleart (FILL).
Kann ja auch nicht. In der LIB wird diese 132Pixel Sonderfall garnicht 
behandelt. Hängt aich mit der Drehung des Display im Portrait oder 
Landsape-Mode zusammen. Da werden die üblichen 64x128, 128x64, usw. 
aufgeführt und die switch case Strukturen wuseln dann da hin, aber 132 
wird schlicht nicht breücksichtigt.
Ich hatte leider den Fall, ein OLED bestellt zu bekommen und das war am 
ENde kein 128x64, sondern ein 64x128. Da musste ich auch in der LIB 
händisch eingreifen und bei der Gelegenheit sämtliche "I2C/SPI-Abfragen" 
rausschmeissen, weil ich kein SPI brauchte, dass den Treiber aber derart 
aufgebläht hatte, dass es in den 32U4 nicht mehr reinpasste. Ist eh ein 
Whansinn, was der Treiber(LIB), den man hier oft sieht, sich an Extras 
gönnt und wie das alles kompliziert mit dieversen h-Dateien 
hinzugebastelt wurde, nur damit das universell betrieben werden kann.
Leider muss ich jetzt den branch extra Pflegen, bzw. darf da nicht mehr 
ran, weil sonst die anderen Projekte nicht mehr laufen. KlasseSache, 
echt - man wird schnell fertig, wenn man kleine Dinge zu erledigen hat. 
Aber wehe, es tanzt mal was aus der Reihe, muss man sich gefühlt für 
jedes "Projekt" einen eigenen Rechner anschaffen, um die ganzen 
Bibliotheken auseinanderhalten zu können. 😂

ich gehe mal fest von einer Aruino-Umgebung aus, oder?

von Christoph K. (chriskuku)


Lesenswert?

Axel R. schrieb:
> Christoph K. schrieb:
>> Das Problem ist noch nicht gelöst (s. Bild)
>> Ich kann nicht in diesen Bereich hineinmalen.
>> In der Source wird ein Pixelbuffer von WIDTHxHEIGHT von 128x64
>> definiert, der mit 0 gefüllt wird.Setze ich in der Lib source die
>> SSD1306_WIDTH=132, wird der Bereich nicht gecleart (FILL).
> Kann ja auch nicht. In der LIB wird diese 132Pixel Sonderfall garnicht
>...
>
> ich gehe mal fest von einer Aruino-Umgebung aus, oder?

Nein, Arduino hatte ich nur für den Schnelltest hinzugezogen. Target ist 
aber STM32F103C8T6 unter STM32CubeIDE.

von Christoph K. (chriskuku)


Lesenswert?

Steve van de Grens schrieb:


> Ändere:
>
1
> OLED display(Wire, 0x3C, NO_RESET_PIN, 128, 64);
2
>
> auf:
>
1
> OLED display(Wire, 0x3C, NO_RESET_PIN, 128, 64, true);
2
>
>
> ...

Auf welche LIB beziehst Du Dich? Ich finde die Zeile nirgends.

von Steve van de Grens (roehrmond)


Lesenswert?

Christoph K. schrieb:
> Auf welche LIB beziehst Du Dich? Ich finde die Zeile nirgends.

http://stefanfrings.de/arduino_oled/OLED.zip

Datei OLED.ino

von Christoph K. (chriskuku)


Angehängte Dateien:

Lesenswert?

Steve van de Grens schrieb:
> Christoph K. schrieb:
>> Auf welche LIB beziehst Du Dich? Ich finde die Zeile nirgends.
>
> http://stefanfrings.de/arduino_oled/OLED.zip
>
> Datei OLED.ino

Ah, ok. Gemacht und Bild sieht besser aus, aber immer noch um ca. 2 
Pixel nach links verschoben. Bei Contrast ist links das C angeschnitten 
und rechts in den letzten Spalten "Gegrissel".

von Steve van de Grens (roehrmond)


Lesenswert?

Christoph K. schrieb:
> aber immer noch um ca. 2 Pixel nach links verschoben

Hmm, schade. Ein passendes Datenblatt vom Display (nicht vom COG) wäre 
jetzt nicht schlecht, wo die Parameter zur Initialisierung und 
Speicherzuordnung angegeben wären.

von Christoph K. (chriskuku)


Angehängte Dateien:

Lesenswert?

Steve van de Grens schrieb:
> Christoph K. schrieb:
>> aber immer noch um ca. 2 Pixel nach links verschoben
>
> Hmm, schade. Ein passendes Datenblatt vom Display (nicht vom COG) wäre
> jetzt nicht schlecht, wo die Parameter zur Initialisierung und
> Speicherzuordnung angegeben wären.

Datenblatt konnte ich noch nicht auftreiben.  Habe noch ein zweites 
Exemplar getestet, um auszuschließen, daß es ein Fehler im Teil selbst 
ist.  Gleicher Effekt. Es ist auch so, daß beim scrollenden 
unterstrichenen Hello World-Beispiel der Unterstrich und die untere 
Pixelzeile des "Hello" nicht mitscrollen.
Es handelt sich mit ziemlicher Sicherheit um dieses Bauteil:
https://www.diymore.cc/collections/led-display-module/products/diymore-1-3-inch-oled-lcd-display-module-4pin-iic-i2c-interface-ssh1106-128-64-128-64-for-arduino-raspberry-pi-3-3v-5v?variant=14648256561210

Ob man von denen ein Datenblatt kriegt?
2,2K Pullup an SDA und SCL haben nichts verändert.
Und noch etwas: wenn das Ding als 128x64 beschrieben wird, warum sollte 
es 132 pixel in X haben?

Auf der Produktseite steht, es sei ein SH1106 verarbeitet. Dazu findet 
man ein Datenblatt.

: Bearbeitet durch User
von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Christoph K. schrieb:
> Auf der Produktseite steht, es sei ein SH1106 verarbeitet. Dazu findet
> man ein Datenblatt.

Das alleine reicht aber nicht, weil man auch wissen müsste, wie das 
Display an den Controller angeschlossen ist. Das kann man ja von außen 
durch angucken nicht herausfinden.

Ich hänge mal als Beispiel eins an, da wird es ab Seite 20 interessant. 
SO etwas bräuchtest du für dein Display.

von Christoph K. (chriskuku)


Lesenswert?

Stefan F. schrieb:
> Christoph K. schrieb:
>> Auf der Produktseite steht, es sei ein SH1106 verarbeitet. Dazu findet
>> man ein Datenblatt.
>
> Das alleine reicht aber nicht, weil man auch wissen müsste, wie das
> Display an den Controller angeschlossen ist. Das kann man ja von außen
> durch angucken nicht herausfinden.
>
> Ich hänge mal als Beispiel eins an, da wird es ab Seite 20 interessant.
> SO etwas bräuchtest du für dein Display.

Das Pendant für den vermeintlich verbauten SH1106 wäre dann:

https://www.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf

Nur entzieht es sich im Moment meiner Kenntnis, daraus 
Programmierinformationen für eine Library zu destillieren.

Übrigens wird im letztgenannten Dokument immer von 8080 und 6800 ports 
geredet. Das sind doch längst verjährte µPs? Oder sind da immer noch 
sowas wie 8255 oder 6821 auf den Chips?

von Stefan F. (Gast)


Lesenswert?

Christoph K. schrieb:
> Das Pendant für den vermeintlich verbauten SH1106 wäre dann:
> https://www.velleman.eu/downloads/29/infosheets/sh1106_datasheet.pdf

Eben nicht, das ist das Datenblatt des COG. Es gibt aber viele 
unterschiedliche Gläser die man dort unterschiedlich anschließen kann. 
Die dazu nötigen konkreten Konfigurationsparameter nennt dieses 
Datenblatt nicht (kann es auch nicht, hängt ja vom Display ab).

Christoph K. schrieb:
> Übrigens wird im letztgenannten Dokument immer von 8080 und 6800 ports
> geredet. Das sind doch längst verjährte µPs?

Das sind zwei Mikroprozessoren mit parallelem Bus, die etwa 
unterschiedliche Steuersignale haben. Die Busse der meisten 
Mikroprozessoren, die danach auf den Markt kamen, waren an einen der 
beiden angelehnt.

von Christoph K. (chriskuku)


Lesenswert?

Habe festgestellt, daß bereits der Call

SSD1306_Init ();

zum Löschen des Displays führt und dabei genau zwei Pixelspalten mit 
Randomdaten stehenbleiben. Der darauffolgende

SSD1306_Clear();

hat keine Wirkung.

von Axel R. (axlr)


Lesenswert?


von Christoph K. (chriskuku)


Lesenswert?

Axel R. schrieb:
> vielleicht hilft das weiter
> Beitrag "128 x 64 SH1107 OLED mit eingeschränktem Sichtfeld"

Danke für den Tipp. Ich versuche das gerade nachzustellen. Habe einen 
Arduino Nano angeschlossen. Das Testprogramm von Stefanus läuft gerade 
drauf, mit eben den besagten Displayfehlern. Könntest Du mir noch die 
weiteren "Zutaten" nennen? Welche Arduino lib (AdaFruitGFX)? Wie sieht 
Dein Testprogramm aus?

von Christoph K. (chriskuku)


Lesenswert?

Kann noch Folgendes hinzufügen: Ein Beispiel aus der AdaFruit SH110X 
Library (auf Arduino Nano), sh1106_128x64_i2c.ino, läuft aus dem Stand 
ohne irgendwelchen Versatz oder falschen Pixeln oder sonstigen falschen 
Ergebnissen mit meinem DIY OLED Display 1.3" 128x64.

Wie kriege ich das jetzt transformiert nach STM32CubeIDE und STM32F103 ?

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Da musst du dich selbst rein fuchsen. Fange damit an, die 
Initialisierungssequenzen zu vergleichen.

von Peter Z. (hangloose)


Lesenswert?

Hast du die Init aus deiner AdaFruit Library "sh1106_128x64_i2c.ino" 
schon auf dem STM ausprobiert?
1
  
2
#if defined SH1106_128_64
3
    // Init sequence for 128x64 OLED module
4
    SH1106_command(SH1106_DISPLAYOFF);                    // 0xAE
5
    SH1106_command(SH1106_SETDISPLAYCLOCKDIV);            // 0xD5
6
    SH1106_command(0x80);                                  // the suggested ratio 0x80
7
    SH1106_command(SH1106_SETMULTIPLEX);                  // 0xA8
8
    SH1106_command(0x3F);
9
    SH1106_command(SH1106_SETDISPLAYOFFSET);              // 0xD3
10
    SH1106_command(0x00);                                   // no offset
11
  
12
    SH1106_command(SH1106_SETSTARTLINE | 0x0);            // line #0 0x40
13
    SH1106_command(SH1106_CHARGEPUMP);                    // 0x8D
14
    if (vccstate == SH1106_EXTERNALVCC) 
15
      { SH1106_command(0x10); }
16
    else 
17
      { SH1106_command(0x14); }
18
    SH1106_command(SH1106_MEMORYMODE);                    // 0x20
19
    SH1106_command(0x00);                                  // 0x0 act like ks0108
20
    SH1106_command(SH1106_SEGREMAP | 0x1);
21
    SH1106_command(SH1106_COMSCANDEC);
22
    SH1106_command(SH1106_SETCOMPINS);                    // 0xDA
23
    SH1106_command(0x12);
24
    SH1106_command(SH1106_SETCONTRAST);                   // 0x81
25
    if (vccstate == SH1106_EXTERNALVCC) 
26
      { SH1106_command(0x9F); }
27
    else 
28
      { SH1106_command(0xCF); }
29
    SH1106_command(SH1106_SETPRECHARGE);                  // 0xd9
30
    if (vccstate == SH1106_EXTERNALVCC) 
31
      { SH1106_command(0x22); }
32
    else 
33
      { SH1106_command(0xF1); }
34
    SH1106_command(SH1106_SETVCOMDETECT);                 // 0xDB
35
    SH1106_command(0x40);
36
    SH1106_command(SH1106_DISPLAYALLON_RESUME);           // 0xA4
37
    SH1106_command(SH1106_NORMALDISPLAY);                 // 0xA6
38
  #endif

Bei mir funktioniert diese Init am STM32F072

: Bearbeitet durch User
von Christoph K. (chriskuku)


Lesenswert?

Habe versucht, den Teil der Init in meine ssd1306 Init hineinzuziehen.
Es gibt noch eine Variable, die unbekannt ist, nämlich vccstate. Dies 
ist eine Variable in der SH1106 Init Funktion, die markiert, ob der Chip 
eine externe Vcc hat. Wie soll ich da verfahren. Einfach ignorieren?

von Steve van de Grens (roehrmond)


Lesenswert?

Christoph K. schrieb:
> Habe versucht, den Teil der Init in meine ssd1306 Init
> hineinzuziehen.
> Es gibt noch eine Variable, die unbekannt ist, nämlich vccstate. Dies
> ist eine Variable in der SH1106 Init Funktion, die markiert, ob der Chip
> eine externe Vcc hat. Wie soll ich da verfahren. Einfach ignorieren?

Schau nach, welchen Wert die Variable im Lauffähigen System hat. 
Notfalls mit einer printf Ausgabe.

Wahrscheinlich benutzt dein Display die Ladepumpe, also keine externe 
Versorgung. Oder legst du da irgendwo noch eine zweite Spannung >5V an?

Die beiden Kontrastwerte unterhalb von "SETCONTRAST" kommen mir recht 
hoch vor. Im Sinne der Lebensdauer würde mit mit kleinen Werten (z.B. 
0x20) starten und nur höher gehen, wenn es wirklich nötig ist.

: Bearbeitet durch User
von Hermann Kokoschka (Gast)


Lesenswert?

Warum jetzt plötzlich das Thema "Kontrast/VCC"?
Das Display zeigt doch ansonsten korrekt und lesbar an!
Es gibt überhaupt keinen Grund für so einen Nebenkriegsschauplatz.

Ich würde mal in die "clear"-Routine schauen, ob die
a) "genug" 0-Bytes schreibt oder
b) eine LCD-Interne Löchfunktion verwendet (die nicht immer perfekt 
greift)

Ich hatte mal so einen Effekt, das lag an a), allerdings mit eigenen 
Routinen denn ich nutze niemals irgendwelche "Libs".

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Peter Z. schrieb:
> Hast du die Init aus deiner AdaFruit Library
> "sh1106_128x64_i2c.ino" schon auf dem STM ausprobiert?
> (C-Quelltext)
> Bei mir funktioniert diese Init am STM32F072

Ich habe das mal mit meinem Code verglichen, der bei mir funktioniert, 
aber beim TO nicht. Habe nur zwei Unterschiede gefunden:

Adafruit:
>  SH1106_command(SH1106_SETPRECHARGE);                  // 0xd9
>  if (vccstate == SH1106_EXTERNALVCC)
>  { SH1106_command(0x22); }
>  else
>  { SH1106_command(0xF1); }

>  SH1106_command(SH1106_SETVCOMDETECT);                 // 0xDB
>  SH1106_command(0x40);

Mein Code:
>  i2c.write(0xD9); // pre-charge period
>  i2c.write(0x22);

>  i2c.write(0xDB); // set vcomh deselect level
>  i2c.write(0x20);


Kommando D9 ist Beschrieben als: "This command is used to set the 
duration of the pre-charge period. The interval is counted in number of
DCLK, where RESET equals 2 DCLKs." Ich habe keine Ahnung was das 
bewirkt. Auffällig ist, dass das Datenblatt von Allvision den rot 
markierten Wert früher mal anders hatte. Der chinesische Text heißt 
übersetzt "Register (0xD9) Parameter 0x1F auf 0xF1 geändert".

Kommand0 DB ist Beschrieben als: "This command adjusts the VCOMH 
regulator output." Ich wage ich zu behaupten, dass es keine Rolle für 
das aktuelle Problem spielt. Hier empfiehlt das Datenblatt abweichend 
den Wert 0x30.

von Christoph K. (chriskuku)


Lesenswert?

Hermann Kokoschka schrieb:
> Warum jetzt plötzlich das Thema "Kontrast/VCC"?
> Das Display zeigt doch ansonsten korrekt und lesbar an!
> Es gibt überhaupt keinen Grund für so einen Nebenkriegsschauplatz.
>
> Ich würde mal in die "clear"-Routine schauen, ob die
> a) "genug" 0-Bytes schreibt oder
> b) eine LCD-Interne Löchfunktion verwendet (die nicht immer perfekt
> greift)
>
> Ich hatte mal so einen Effekt, das lag an a), allerdings mit eigenen
> Routinen denn ich nutze niemals irgendwelche "Libs".

1) es sind noch mehr Stellen, wo abhängig vom vccstate unterschiedliche 
Commands geschrieben werden, nicht nur contrast.
2) da ist noch die Sache mit dem Offset, um den der Nullpunkt verschoben 
ist.

Ich poste gleich mal die Sequenz, die geht (aber mit dem Offsetfehler 
und den random bits)  und die neue (SH1106), die nicht geht.

: Bearbeitet durch User
von Hermann Kokoschka (Gast)


Lesenswert?

Hier ist meine Init-Sequenz für 1306, für beide Orientierungen.
Die laufen an allen meinen OLED einwandfrei.
1
SSD1306_INI1: .DB 21,0xA8,0x3F,0xD3,0x00,0x40,0xA1,0xC8,0xDA,0x12,0x81,0x7F,0xA4,0xA6,0x2E,0x20,0x00,0xD5,0x80,0x8D,0x14,0xAF   
2
3
SSD1306_INI2: .DB 21,0xA8,0x3F,0xD3,0x00,0x40,0xA0,0xC0,0xDA,0x12,0x81,0x7F,0xA4,0xA6,0x2E,0x20,0x00,0xD5,0x80,0x8D,0x14,0xAF

von Hermann Kokoschka (Gast)


Lesenswert?

Ergänzung zu meiner Init:
Der ERSTE Wert gehört NICHT dazu, sondern gibt nur die Anzahl der 
Folgebytes an!

von Stefan F. (Gast)


Lesenswert?

Noch was zum pre-charge Wert: Der Default Wert nach einem Reset ist 
0x22, was meinem (kopiertem) Code entspricht.

von Christoph K. (chriskuku)


Angehängte Dateien:

Lesenswert?

s. Anhang

von Stefan F. (Gast)


Lesenswert?

Hermann Kokoschka schrieb:
> SSD1306_INI1: .DB
> 21,0xA8,0x3F,0xD3,0x00,0x40,0xA1,0xC8,0xDA,0x12,0x81,
> 0x7F,0xA4,0xA6,0x2E,0x20,0x00,0xD5,0x80,0x8D,0x14,0xAF

Entspricht meinem Code.

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe einen vielversprechenden Unterschied zwischen meinem Code (der 
den Versatz hat) und 
https://github.com/lorneb/Adafruit_SH1106/blob/master/Adafruit_SH1106_STM32.h 
gefunden. Siehe den TODO Marker im Anhang (den habe ich gerade 
eingefügt).

Ich habe mit Google beide Varianten (0x00 und 0x02) mehrmals gefunden. 
Scheint hardware-abhängig zu sein.

Das könnte des Rätsels Lösung sein.

von Christoph K. (chriskuku)


Angehängte Dateien:

Lesenswert?

Hermann Kokoschka schrieb:
> Hier ist meine Init-Sequenz für 1306, für beide Orientierungen.
> Die laufen an allen meinen OLED einwandfrei.
>
>
1
> SSD1306_INI1: .DB 
2
> 21,0xA8,0x3F,0xD3,0x00,0x40,0xA1,0xC8,0xDA,0x12,0x81,0x7F,0xA4,0xA6,0x2E,0x20,0x00,0xD5,0x80,0x8D,0x14,0xAF
3
> 
4
> SSD1306_INI2: .DB 
5
> 21,0xA8,0x3F,0xD3,0x00,0x40,0xA0,0xC0,0xDA,0x12,0x81,0x7F,0xA4,0xA6,0x2E,0x20,0x00,0xD5,0x80,0x8D,0x14,0xAF
6
>

Beide Deiner Sequenzen funktionieren derart, daß sie zwar das Display 
anschalten und meine Malerei erscheint, aber beide zeigen das 
"Gegrissel".
Die zweite Sequenz stelle das Bild auf den Kopf.'tschuldigung für die 
Bilderflut. Hochladen war zu langsam, sodaß ich zuviel abgschickt habe.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Christoph K. schrieb:
> IMG_4630.jpg

Fehlt nur noch ein Touch Sensor, dann können Ameisen Klavier spielen.

von Christoph K. (chriskuku)


Lesenswert?

Stefan F. schrieb:
> Ich habe einen vielversprechenden Unterschied zwischen meinem Code (der
> den Versatz hat) und
> https://github.com/lorneb/Adafruit_SH1106/blob/master/Adafruit_SH1106_STM32.h
> gefunden. Siehe den TODO Marker im Anhang (den habe ich gerade
> eingefügt).
>
> Ich habe mit Google beide Varianten (0x00 und 0x02) mehrmals gefunden.
> Scheint hardware-abhängig zu sein.
>
> Das könnte des Rätsels Lösung sein.

Ich sehe nur in meiner Sequenz nicht die Stelle, wo ich eine 00 
testweise in eine 02 ändern könnte:
1
#undef   SH1106_128_64
2
#ifndef  SH1106_128_64  /* Init LCD */
3
  SSD1306_WRITECOMMAND(0xAE); //display off
4
  SSD1306_WRITECOMMAND(0xD5); //--set display clock divide ratio/oscillator frequency
5
    SSD1306_WRITECOMMAND(SH1106_MEMORYMODE);    // 0x20
6
  SSD1306_WRITECOMMAND(0x10); //00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
7
  SSD1306_WRITECOMMAND(0xB0); //Set Page Start Address for Page Addressing Mode,0-7
8
  SSD1306_WRITECOMMAND(0xC8); //Set COM Output Scan Direction
9
  SSD1306_WRITECOMMAND(0x00); //---set low column address
10
  SSD1306_WRITECOMMAND(0x10); //---set high column address
11
  SSD1306_WRITECOMMAND(0x40); //--set start line address
12
  SSD1306_WRITECOMMAND(0x81); //--set contrast control register
13
  SSD1306_WRITECOMMAND(0xFF);
14
  SSD1306_WRITECOMMAND(0xA1); //--set segment re-map 0 to 127
15
  SSD1306_WRITECOMMAND(0xA6); //--set normal display
16
  SSD1306_WRITECOMMAND(0xA8); //--set multiplex ratio(1 to 64)
17
  SSD1306_WRITECOMMAND(0x3F); //
18
  SSD1306_WRITECOMMAND(0xA4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
19
  SSD1306_WRITECOMMAND(0xD3); //-set display offset
20
  SSD1306_WRITECOMMAND(0x00); //-not offset
21
  SSD1306_WRITECOMMAND(0xF0); //--set divide ratio
22
  SSD1306_WRITECOMMAND(0xD9); //--set pre-charge period
23
  SSD1306_WRITECOMMAND(0x22); //
24
  SSD1306_WRITECOMMAND(0xDA); //--set com pins hardware configuration
25
  SSD1306_WRITECOMMAND(0x12);
26
  SSD1306_WRITECOMMAND(0xDB); //--set vcomh
27
  SSD1306_WRITECOMMAND(0x20); //0x20,0.77xVcc
28
  SSD1306_WRITECOMMAND(0x8D); //--set DC-DC enable
29
  SSD1306_WRITECOMMAND(0x14); //
30
  SSD1306_WRITECOMMAND(0xAF); //--turn on SSD1306 panel
31
  
32
  SSD1306_WRITECOMMAND(SSD1306_DEACTIVATE_SCROLL);

von Stefan F. (Gast)


Lesenswert?

Du bist immer noch bei der Initialisierung.

Schau in die Prozedur, welche die Daten in den Speicher des Displays 
überträgt. Bei mir und bei Adafruit heißt die display().

Das erste Byte ist 0xB0 + Pagenummer, die beiden Bytes danach sind die 
spannenden, danach kommen die eigentlichen Nutzdaten.

von Hermann Kokoschka (Gast)


Lesenswert?

> Die zweite Sequenz stelle das Bild auf den Kopf
1) Das IST ja beabsichtigt damit ich die Einbaulage wählen kann.

2) Lies mal den Beitrag von stefanus von vorhin!

3) Mach mal die I2C-Taktrate sehr langsam UND lege zwischen allen 
INIT-Bytes
eine Timing-Pause ein, teils benötigen die Kommandos etwas Zeit.

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Korrekturvorschlag in dem Code aus dem Link im Eröffnungsbeitrag.

Ich finde ziemlich beschissen dass diese Bibliothek offenbar schon für 
den SH1106 modifiziert wurde, aber im Quelltext immer noch überall 
SSD1306 steht.

Das erkenne ich daran, dass hier 3 Bytes gesendet werden. Beim SD1306 
müssten es 4 Bytes sein. Siehe mein vorheriger Screenshot von 18:06.

von Hermann Kokoschka (Gast)


Lesenswert?

AN WAS arbeiten wir hier eigentlich physikalisch konkret,
ich bin inzwischen komplett verwirrt durch diesen CMD-MIX.

SH1106
oder
SSD1306

von Stefan F. (Gast)


Lesenswert?

Offenbar eine speziellen Variante von einem OLED mit SH1106 und 128x64 
Pixeln.

von Christoph K. (chriskuku)


Angehängte Dateien:

Lesenswert?

OK, das hat es jetzt gebracht, zumindest, was die unvolständige Löschung 
des Displays betrifft:
1
void SSD1306_UpdateScreen(void) {
2
  uint8_t m;
3
  
4
  for (m = 0; m < 8; m++) {
5
    SSD1306_WRITECOMMAND(0xB0 + m);
6
    SSD1306_WRITECOMMAND(0x02); //<<<<<<<<<<
7
    SSD1306_WRITECOMMAND(0x10);
8
    
9
    /* Write multi data */
10
    ssd1306_I2C_WriteMulti(SSD1306_I2C_ADDR, 0x40, &SSD1306_Buffer[SSD1306_WIDTH * m], SSD1306_WIDTH);
11
  }
12
}
Und auch ein SSD_DrawRectangle(0,0,127,63,1); sieht vernünftig aus.

von Stefan F. (Gast)


Lesenswert?

Na also, geht doch!

von Christoph K. (chriskuku)


Lesenswert?

Ich danke allen.

von Joachim B. (jar)


Lesenswert?

Christoph K. schrieb:
> Ich danke allen.

und wir würden dir Danken wenn du als Letztes mal genau schreibst was du 
nun geändert hast, das würde ALLEN mit dem selben Problem helfen ohne 
den ganzen Thread noch mal von vorn durchzuarbeiten!
Mit Nennung von deinem Display Link und Type und mit der LIB Name Link 
und Änderung.

so blickt doch keiner mehr durch der aktuell nicht daran beteiligt ist!

von Christoph K. (chriskuku)


Lesenswert?

Also, noch mal zusammengefaßt:

Es geht physikalisch um folgendes Bauteil:

https://www.diymore.cc/products/diymore-1-3-inch-oled-lcd-display-module-4pin-iic-i2c-interface-ssh1106-128-64-128-64-for-arduino-raspberry-pi-3-3v-5v?variant=14648256561210

Angefangen hatte ich mit folgender oled.zip (dort zum Download 
verfügbar),:

https://controllerstech.com/oled-display-using-i2c-stm32/

zu dem Zeitpunkt nicht wissend, daß es sich um ein Bauteil mit einem 
SH1106 und nicht SH1306 handelte. Die Verwendung dieser Library geschah 
unter STM32CubeIDE. Dabei zeigte sich die unvollständige Initialisierung 
des Displayinhalts und auch ein Versatz in den Ursprungskoordinaten (um 
2 pixel in x).

Lösung von Stefan F. (stefanus):
1
void SSD1306_UpdateScreen(void) {
2
  uint8_t m;
3
  
4
  for (m = 0; m < 8; m++) {
5
    SSD1306_WRITECOMMAND(0xB0 + m);
6
    SSD1306_WRITECOMMAND(0x02); //<<<<<<<< von 00 auf 02 ändern
7
    SSD1306_WRITECOMMAND(0x10);
8
    
9
    /* Write multi data */
10
    ssd1306_I2C_WriteMulti(SSD1306_I2C_ADDR, 0x40, &SSD1306_Buffer[SSD1306_WIDTH * m], SSD1306_WIDTH);
11
  }
12
}

: Bearbeitet durch User
von Steve van de Grens (roehrmond)


Lesenswert?

Hermann Kokoschka schrieb:
> Warum jetzt plötzlich das Thema "Kontrast/VCC"?
> Das Display zeigt doch ansonsten korrekt und lesbar an!

Ich bin darauf gekommen, weil das die einzigen Unterschiede in der 
Initialisierung sind, die mir dort aufgefallen sind. Ich stimme dir zu, 
dass wir auf diesem Weg nicht weiter kommen.

Inzwischen wurde die Lösung ja schon ganz woanders gefunden. Das 
bestätigt deine Annahme.

von Christoph K. (chriskuku)


Lesenswert?

Meinte SH1106 und SSD1306 in meinem Resumee (nicht SH1306). Konnte es 
nicht mehr korrigieren.

von Joachim B. (jar)


Lesenswert?

Christoph K. schrieb:
> Also, noch mal zusammengefaßt:
>
> Es geht physikalisch um folgendes Bauteil:

https://www.diymore.cc/products/diymore-1-3-inch-oled-lcd-display-module-4pin-iic-i2c-interface-ssh1106-128-64-128-64-for-arduino-raspberry-pi-3-3v-5v?variant=14648256561210

Angefangen hatte ich mit folgender oled.zip (dort zum Download
verfügbar),:

https://controllerstech.com/oled-display-using-i2c-stm32/

zu dem Zeitpunkt nicht wissend, daß es sich um ein Bauteil mit einem
SH1106 und nicht SSD1306 handelte. Die Verwendung dieser Library 
geschah
unter STM32CubeIDE. Dabei zeigte sich die unvollständige Initialisierung
des Displayinhalts und auch ein Versatz in den Ursprungskoordinaten (um
2 pixel in x).

Lösung von Stefan F. (stefanus):void SSD1306_UpdateScreen(void) {
  uint8_t m;

  for (m = 0; m < 8; m++) {
    SSD1306_WRITECOMMAND(0xB0 + m);
    SSD1306_WRITECOMMAND(0x02); //<<<<<<<< von 00 auf 02 ändern
    SSD1306_WRITECOMMAND(0x10);

    /* Write multi data */
    ssd1306_I2C_WriteMulti(SSD1306_I2C_ADDR, 0x40,
    &SSD1306_Buffer[SSD1306_WIDTH * m], SSD1306_WIDTH);
   }
 }

so also korrigiert? (sollte als Abschluß und als Letztes stehen, sonst 
übersieht man das wieder!)

: Bearbeitet durch User
von J. S. (jojos)


Lesenswert?

das Ganze hättet ihr wesentlich eher haben können wenn ihr meinen 
Kommentar bzw. Link auf den Beitrag von Oli Kraus gelesen hättet.
Beitrag "Re: Display"fehler" bei OLED Module IIC I2C 128x64"

von m.n. (Gast)


Lesenswert?

J. S. schrieb:
> das Ganze hättet ihr wesentlich eher haben können wenn ihr meinen
> Kommentar bzw. Link auf den Beitrag von Oli Kraus gelesen hättet.

Zumal ja schon schnell klar war, daß es sich ganz einfach um einen 
Offset handeln mußte.
Letztlich aber ein gutes Beispiel, was beim Zusammenklicken von LIBs 
herauskommen kann. Eine Woche hat das gedauert :-(

von Christoph K. (chriskuku)


Lesenswert?

Christoph K. schrieb:
> OK, das hat es jetzt gebracht, zumindest, was die unvolständige Löschung
> des Displays betrifft:
>
1
> void SSD1306_UpdateScreen(void) {
2
>   uint8_t m;
3
> 
4
>   for (m = 0; m < 8; m++) {
5
>     SSD1306_WRITECOMMAND(0xB0 + m);
6
>     SSD1306_WRITECOMMAND(0x02); //<<<<<<<<<<
7
>     SSD1306_WRITECOMMAND(0x10);
8
> 
9
>     /* Write multi data */
10
>     ssd1306_I2C_WriteMulti(SSD1306_I2C_ADDR, 0x40, 
11
> &SSD1306_Buffer[SSD1306_WIDTH * m], SSD1306_WIDTH);
12
>   }
13
> }
14
>
> Und auch ein SSD_DrawRectangle(0,0,127,63,1); sieht vernünftig aus.

Kleine Korrektur:
SSD_DrawRectangle(0,0,**128**,**64**,1);

(Markdown Bold Darstelluung funktioniert hier im Forum zwar in der 
mobilen Ansicht, aber nicht im Browser auf Desktops)

: Bearbeitet durch User
von Steve van de Grens (roehrmond)


Lesenswert?

Christoph K. schrieb:
> Markdown Bold Darstelluung funktioniert ... nicht

Mal geht es, mal nicht. Da scheint ein ungewollter Zufallsgenerator drin 
zu stecken.

von mitlesa (Gast)


Lesenswert?

Lese hier leise mit und gebe mal meinen Senf abseits des
eigentlichen Problems dazu. Die Lib um den Display-Controller
ist ja nicht die schlechteste, zumal man sie nicht unter irgend-
welchen Arduino-IDEs verwenden muss. Ist schon bemerkenswert da
sehr viele Vorschläge sich immer auf Arduino beziehen.

Aber ein paar Kleinigkeiten sind schon "bemerkenswert". Sie
fallen nur nicht ins Gewicht da ja die Anbindung über I2C nicht
besonders hohe Display-Raten zulässt.
1
void ssd1306_I2C_WriteMulti (uint8_t address, uint8_t reg, 
2
                             uint8_t* data, uint16_t count)
3
{
4
  uint8_t dt[256];
5
  dt[0] = reg;
6
  uint8_t i;
7
  for (i = 0; i < count; i++)
8
    dt[i+1] = data[i];
9
  HAL_I2C_Master_Transmit(&hi2c1, address, dt, count+1, 10);
10
}

Die gezeigte Funktion zeigt zwei "Besonderheiten".

- hier wird ein temporäres Array von 256 Bytes angelegt was
in komplexeren Anwendungen schon mal zu einem Stack-Problem
werden könnte. Ausserdem ist es zu gross da maximal 128 Bytes
plus ein Kommando-Byte (Register-Adressierung) im Buffer
stehen (müssen).

- das Umkopieren des zu schreibenden Buffers in das Ziel-
Array kostet zusätzlich Zeit, was in einer schnellen Display-
Anwendung sicherlich hinderlich wäre. Hier aber wohl nicht da
der I2C-Bus-Verkehr der ausschlaggebende Bremsfaktor ist.
Den Buffer zu vermeiden ist wohl nicht ganz einfach da das
Register-Byte vorangestellt werden muss und dieses in einem
Flow mit den Daten gesendet werden muss. Wäre eventuell
nützlich um das "horse" noch etwas schneller rennen lassen
zu können. Ansonsten natürlich ohne Belang in dieser Anwendung.

meine 2ct, SCNR

von Steve van de Grens (roehrmond)


Lesenswert?

mitlesa schrieb:
> Ausserdem ist es zu gross da maximal 128 Bytes
> plus ein Kommando-Byte (Register-Adressierung) im Buffer
> stehen (müssen).

Stimmt. Der Code war offenbar für SSD1306 vorgesehen, bei dem kann man 
mehr Bytes am Stück senden.

von Hugo H. (hugo_hu)


Lesenswert?

mitlesa schrieb:
> da ja die Anbindung über I2C nicht
> besonders hohe Display-Raten zulässt

;-)

https://www.youtube.com/watch?v=DVmTeQ6u3jQ

von mitlesa (Gast)


Lesenswert?

Steve van de Grens schrieb:
> Stimmt. Der Code war offenbar für SSD1306 vorgesehen, bei dem kann man
> mehr Bytes am Stück senden.

Sollten wirklich 256 Bytes am Stück gesendet werden dann wäre der
reservierte Buffer um 1 zu klein da das Kommando-Byte (Register-
Adressierung) am Anfang "'rein muss" und dann erst die 256 Bytes
Nutzdaten. Dann schreibt die Funktion irgendwo hin ....

von mitlesa (Gast)


Lesenswert?

mitlesa schrieb:
> irgendwo hin ....

.... wo sie nicht soll bzw. nicht darf.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.