Forum: Mikrocontroller und Digitale Elektronik Richtiges OLED-Display, SSD1306 vs. SH1106


von Lutz S. (lutzs)


Lesenswert?

Hallo,

ich bin dabei, dieses Projekt nachzubauen:

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

https://github.com/VK2ARH/Pi-PicoRx

0,96" Display mit SSH1306 hatte ich da, damit funktioniert es. Ich würde 
aber gern ein Display mit 1,3" einsetzen (auf der Platine vorgesehen), 
finde aber nur Displays mit SH1106.

Im Sourcecode finde ich nur die Library für den 1306, in der BOM wird 
aber auch 1106 erwähnt.

Bin etwas verwirrt. Sind die weitgehend kompatibel, so dass es mit 
beiden funktionieren kann?

Danke für eure Tips.

von Nemopuk (nemopuk)


Angehängte Dateien:

Lesenswert?

Lutz S. schrieb:
> Sind die weitgehend kompatibel

Weitgehend, aber ganz ohne Codeänderung wird es nicht gehen. Beide 
Controller kann man gleich initialisieren, aber die Datenübertragung ins 
Display-RAM geht etwas anders.

Ich zeige dir das relevante Fragment aus meinem Arduino Code. Ich habe 
Feedback erhalten, dass er mit SH1106 funktioniert, selbst aber nur mit 
SSD1306 getestet.
1
void OLED::display()
2
{
3
    size_t index = 0;
4
    for (uint_fast8_t page = 0; page < pages; page++)
5
    {
6
        // Set memory address to fill
7
        i2c.beginTransmission(i2c_address);
8
        i2c.write(0x00); // command
9
        if (isSH1106)
10
        {
11
            i2c.write(0xB0 + page); // set page
12
            i2c.write(0x00); // lower columns address =0  // Some displays might need 0x02 here
13
            i2c.write(0x10); // upper columns address =0
14
        }
15
        else
16
        {
17
            i2c.write(0xB0 + page); // set page
18
            i2c.write(0x21); // column address
19
            i2c.write(0x00); // first column =0
20
            i2c.write(width - 1); // last column
21
        }
22
        i2c.endTransmission();
23
24
        // send one page of buffer to the display
25
        i2c.beginTransmission(i2c_address);
26
        i2c.write(0x40); // data
27
        for (uint_fast8_t column = 0; column < width; column++)
28
        {
29
            // Split the transaction into chunks of 32 bytes because that is a limitation of Arduino
30
            if (column>0 && (column % 31 == 0) )
31
            {
32
                i2c.endTransmission();
33
                i2c.beginTransmission(i2c_address);
34
                i2c.write(0x40); // data              
35
            }
36
            
37
            i2c.write(buffer[index++]);
38
        }
39
        i2c.endTransmission();
40
        yield(); // to avoid that the watchdog triggers
41
    }
42
}

Der Buffer wird hier verwendet, um das ganze Bild im RAM aufzubauen und 
es danach mit der oben gezeigten Funktion an das Display zu senden. Die 
Struktur entspricht dem Display.
1
width and height = Anzahl der Pixel vom Display
2
pages = (height + 7) / 8
3
bufsize = pages * width (Größe vom Buffer in Bytes)

Eine Page ist ein Balken, der 8 Pixel hoch ist und die ganze Breite des 
Display abdeckt. Jedes Byte steht für 8 untereinander liegende Pixel. 
Also wenn das Display 128 Pixel breit ist, dann ist jede Page 8 * 128 
Pixel groß, also 128 Bytes. Wenn das Display 32 Pixel hoch ist, dann hat 
es 4 Pages (vier Balken jeweils 8 Pixel hoch).

Die Stelle mit
> if (isSH1106) ...
ist für die Unterschiede zwischen den beiden Chips wichtig.

Der Kommentar
> Some displays might need 0x02 here
bezieht sich auf folgendes Fehlerbild: Das ganze Bild erscheint 
horizontal um zwei Pixel verschoben und am Rand erscheint ein zwei Pixel 
schmaler vertikaler Balken mit zufälligen Inhalt.

Die Zeilen 29-36 könnte man weg lassen, wenn Arduino nicht dieses blöde 
Limit auf maximal 32 Bytes pro I2C Transaktion hätte.

: Bearbeitet durch User
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.