Display Oled mit SSD1309 und 2,4"

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
Achim Klein
User
Beiträge: 41
Registriert: Dienstag 21. Februar 2023, 13:57

Hallo
Versuche das Display von EA OLED 128 mit dem Controller SSD 1309 in Betrieb zu nehmen. Verwende diese Progrann dazu:

Code: Alles auswählen

from machine import Pin, I2C
from ssd1309 import Ssd1309I2C # ok
from utime import sleep_ms
# Initialisierung I2C, Bus 0, sda-0, scl-1, Adresse 0x3d, Frequenz 400kHz
SCL_Pin = 1                 # Angabe Pin SCL
SDA_Pin = 0                 # Angabe Pin SDA
Bus = 0                     # Angabe Bus Nr
WIDTH  = 128                # 128 oled display width
HEIGHT = 64                 # 64 oled display height

Oled_address = 0x3d         # Angabe der Bus Adresse - 0x3d, sonst ermitteln
Onboard_LED = Pin(25, Pin.OUT)

i2c_bus = I2C(Bus, scl = Pin(SCL_Pin), sda = Pin(SDA_Pin), freq = 400_000)

# Kontrolle I2C Bus auf Slave vorhanden
if Oled_address not in i2c_bus.scan():
    print('Oled Display nicht gefunden..')
    while True:
        Onboard_LED.toggle() # LED on Board blinken
        sleep_ms(500)        # Pause LED on Board

Oled = Ssd1309I2C(WIDTH, HEIGHT, i2c_bus) # ok

#Hauptprogramm
while True:
    Oled.text('Hello', 0, 0)
    Oled.text('RPi Pico', 10, 12)
    Oled.show()
    sleep_ms(1)
Dazu verwende ich diese Lib.

Code: Alles auswählen

from micropython import const
import framebuf

# Command constants from display datasheet
CONTRAST_CONTROL = const(0x81)
ENTIRE_DISPLAY_ON = const(0xA4)
ALL_PIXELS_ON = const(0xA5)
INVERSION_OFF = const(0xA6)
INVERSION_ON = const(0xA7)
DISPLAY_OFF = const(0xAE)
DISPLAY_ON = const(0xAF)
NOP = const(0xE3)
COMMAND_LOCK = const(0xFD)
CHARGE_PUMP = const(0x8D)

# Scrolling commands
CH_SCROLL_SETUP_RIGHT = const(0x26)
CH_SCROLL_SETUP_LEFT = const(0x27)
CV_SCROLL_SETUP_RIGHT = const(0x29)
CV_SCROLL_SETUP_LEFT = const(0x2A)
DEACTIVATE_SCROLL = const(0x2E)
ACTIVATE_SCROLL = const(0x2F)
VSCROLL_AREA = const(0xA3)
SCROLL_SETUP_LEFT = const(0x2C)
SCROLL_SETUP_RIGHT = const(0x2D)

# Addressing commands
LOW_CSA_IN_PAM = const(0x00)
HIGH_CSA_IN_PAM = const(0x10)
MEMORY_ADDRESSING_MODE = const(0x20)
COLUMN_ADDRESS = const(0x21)
PAGE_ADDRESS = const(0x22)
PSA_IN_PAM = const(0xB0)
DISPLAY_START_LINE = const(0x40)
SEGMENT_MAP_REMAP = const(0xA0)
SEGMENT_MAP_FLIPPED = const(0xA1)
MUX_RATIO = const(0xA8)
COM_OUTPUT_NORMAL = const(0xC0)
COM_OUTPUT_FLIPPED = const(0xC8)
DISPLAY_OFFSET = const(0xD3)
COM_PINS_HW_CFG = const(0xDA)
GPIO = const(0xDC)

# Timing and driving scheme commands
DISPLAY_CLOCK_DIV = const(0xD5)
PRECHARGE_PERIOD = const(0xD9)
VCOM_DESELECT_LEVEL = const(0xDB)


class Ssd1309(framebuf.FrameBuffer):
    def __init__(self, width, height, external_vcc):
        self.width = width
        self.height = height
        self.external_vcc = external_vcc
        self.pages = self.height // 8
        self.buffer = bytearray(self.pages * self.width)
        super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
        self.initial_display()

    def initial_display(self):
        for command in (
            DISPLAY_OFF,
            DISPLAY_CLOCK_DIV,
            0x80,
            MUX_RATIO,
            self.height - 1,
            DISPLAY_OFFSET,
            0x00,
            DISPLAY_START_LINE,
            CHARGE_PUMP,
            0x14,
            MEMORY_ADDRESSING_MODE,
            0x00,
            SEGMENT_MAP_FLIPPED,
            COM_OUTPUT_FLIPPED,
            COM_PINS_HW_CFG,
            0x02
            if (self.height == 32 or self.height == 16) and (self.width != 64)
            else 0x12,
            CONTRAST_CONTROL,
            0xFF,
            PRECHARGE_PERIOD,
            0xF1,
            VCOM_DESELECT_LEVEL,
            0x40,
            ENTIRE_DISPLAY_ON,
            INVERSION_OFF,
            DISPLAY_ON,
        ):
            self.write_command(command)

        self.fill(0)
        self.show()

    def power_off(self):
        self.write_command(DISPLAY_OFF | 0x00)

    def power_on(self):
        self.write_command(DISPLAY_ON | 0x01)

    def contrast(self, contrast):
        self.write_command(CONTRAST_CONTROL)
        self.write_command(contrast)

    def invert(self):
        self.write_command(INVERSION_OFF | INVERSION_ON)

    def show(self):
        coordinates = [0, self.width - 1]
        if self.width == 64:
            # displays with width of 64 pixels are shifted by 32
            coordinates = [32, self.width + 31]
        self.write_command(COLUMN_ADDRESS)
        for coordinate in coordinates:
            self.write_command(coordinate)
        self.write_command(PAGE_ADDRESS)
        self.write_command(0)
        self.write_command(self.pages - 1)
        self.write_data(self.buffer)


class Ssd1309I2C(Ssd1309):
    def __init__(self, width, height, i2c, address=0x3d, external_vcc=False):
        self.i2c = i2c
        self.address = address
        super().__init__(width, height, external_vcc)

    def write_command(self, command):
        # 0x80 -> Co=1, D/C#=0
        self.i2c.writeto(self.address, bytearray([0x80, command]))

    def write_data(self, buffer):
        # 0x40 ->  Co=0, D/C#=1
        self.i2c.writevto(self.address, [b"\x40", buffer])
Die Abfrage auf korrekte Adresse funktioniert. Das Display wird also erkannt. Bei einer anderen Adresse erfolgt eine Anzeige "Kein Display".
Wollte die Lib komplett einbinden, eben als Datei, geht aber nicht ...
Das Display bleibt aber dunkel, keine Funktion. Kann mir jemand dabei helfen?

LG
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich sehe kein poweron -Command.
Achim Klein
User
Beiträge: 41
Registriert: Dienstag 21. Februar 2023, 13:57

Welchen Befehl meinst du damit genau?
Achim Klein
User
Beiträge: 41
Registriert: Dienstag 21. Februar 2023, 13:57

Habe die Lib für den SSD1306 mit einem Display SSD1306 mit 0,96" verglichen und sehe dabei eigentlich keinen Unterschied.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es gibt ein power_on. Steht doch im Code. Benutzt das doch mal. Vielleicht tut sich was.
Achim Klein
User
Beiträge: 41
Registriert: Dienstag 21. Februar 2023, 13:57

Sorry, jetzt weiss ich was du meinst. Habe ich schon getestet, leider ohne Erfolg. Sieht so:

Code: Alles auswählen

from machine import Pin, I2C
from ssd1309 import Ssd1309I2C # ok
from utime import sleep_ms
# Initialisierung I2C, Bus 0, sda-0, scl-1, Adresse 0x3d, Frequenz 400kHz
SCL_Pin = 1                 # Angabe Pin SCL
SDA_Pin = 0                 # Angabe Pin SDA
Bus = 0                     # Angabe Bus Nr
WIDTH  = 128                # 128 oled display width
HEIGHT = 64                 # 64 oled display height

Oled_address = 0x3d         # Angabe der Bus Adresse - 0x3d, sonst ermitteln
Onboard_LED = Pin(25, Pin.OUT)

i2c_bus = I2C(Bus, scl = Pin(SCL_Pin), sda = Pin(SDA_Pin), freq = 400_000)

# Kontrolle I2C Bus auf Slave vorhanden
if Oled_address not in i2c_bus.scan():
    print('Oled Display nicht gefunden..')
    while True:
        Onboard_LED.toggle() # LED on Board blinken
        sleep_ms(500)        # Pause LED on Board

Oled = Ssd1309I2C(WIDTH, HEIGHT, i2c_bus) # ok

Oled.power_on

#Hauptprogramm
while True:
    Oled.text('Hello', 0, 0)
    Oled.text('RPi Pico', 10, 12)
    Oled.show()
    sleep_ms(1)
Es gibt keine Fehlermeldung.
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Vielleicht würde es helfen, die Methode auch aufzurufen. Das wäre der Unterschied zwischen powerOn und powerOn().
Achim Klein
User
Beiträge: 41
Registriert: Dienstag 21. Februar 2023, 13:57

Habe es geändert in

Code: Alles auswählen

oled.power_on()
Leider auch kein Erfolg
Benutzeravatar
sparrow
User
Beiträge: 4195
Registriert: Freitag 17. April 2009, 10:28

Bist du sicher, dass der Code da überhaupt ankommt? Immerhin ist da vorher eine potentielle Endlosschleife.
Benutzeravatar
Dennis89
User
Beiträge: 1156
Registriert: Freitag 11. Dezember 2020, 15:13

Und auf die Groß- und Kleinschreibung achten.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn es mit dem Treiber nicht geht, anderen suchen, und das schließt die (auch nur testweise) Verwendung zb von Arduino ein. Wirklich viel mehr kann man da nicht zu sagen, denn es hat wahrscheinlich keiner das gleiche Display, und dann ist Essig. SSD1306 habe ich einen Sack voll.
Benutzeravatar
Dennis89
User
Beiträge: 1156
Registriert: Freitag 11. Dezember 2020, 15:13

@Achim, ist das eigentlich der Code den wir hier mal geschrieben haben:
https://forum-raspberrypi.de/forum/thre ... /?pageNo=1 ?

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Achim Klein
User
Beiträge: 41
Registriert: Dienstag 21. Februar 2023, 13:57

Ist das selbe Display. Ist der SSD1309. Fast alle Libs die ich bisher gefunden habe sind für SPI. Es gibt nur einen einzigen für I2C. Dafür ist beim SPI die Graphik mit drin. Ja wir haben drüber gesprochen, aber alles ohne Erfolg. Habe darauf hin noch mal alles überprüft im Vergleich zum 1306 und dem Treiber bzw. Lib für AVR. Beim AVR (was funktioniert) sind die Register anders in der Reihenfolge. Der Treiber für den SSD1306 mit einem kleinen Display funktioniert auch. So ein Display mit 0,96 ist einfach zu klein.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich verstehe deine Antwort nicht wirklich. Ist das Display mit Erfolg am AVR betrieben worden? Wenn ja, welche Bibliothek kam zum Einsatz?
Achim Klein
User
Beiträge: 41
Registriert: Dienstag 21. Februar 2023, 13:57

Ja das Display ist mit Erfolg am AVR betrieben worden. Mit verschiedene Textfunktionen und Graphik. Die Lib habe ich mir selber geschrieben, da ich die viele Vorgaben des Herstellers aus dem DB übernommen habe.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Dann musst du den Code für Python Stück für Stück mit deinem abgleichen. Denn dann muss es ja daran liegen. Und im Zweifel mit logic Analyser prüfen, was “hinten” rauskommt.
Achim Klein
User
Beiträge: 41
Registriert: Dienstag 21. Februar 2023, 13:57

Bist du dir sicher das ich das kann? Wenn ich mir das so ansehe, sieht ganz anders aus.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich weiss nicht, was du kannst. Ich weiss nur, das es niemand anders kann, denn weder hat hier jemand deinen funktionierenden AVR Code, noch hat jemand ein SSD1309, das er selbst schonmal zum laufen gebracht hat. Ausser dir kann es also keinen geben, der es sonst kann. Was anderes bleibt dir also uebrig, als zu verstehen, was der da macht, und ob das dem entspricht, was du machst?
Antworten