Mini-OLED-Display 128x32

Atmega 328 mit BASCOM und FORTH programmieren
Antworten
Heinrichs
Beiträge: 173
Registriert: Do 21. Okt 2010, 18:31

Mini-OLED-Display 128x32

Beitrag von Heinrichs » Di 10. Dez 2019, 12:51

Neben dem OLED-Display mit 128x64 Pixeln gibt es auch eine Variante, die nur halb so groß ist. Den Dreier-Pack bekommt man für weniger als 4,50 Euro. Das Mini-Display funktioniert praktisch genauso wie sein größerer Bruder.

oled_128x32_klein.jpg
128x32-OLED
oled_128x32_klein.jpg (33 KiB) 14057 mal betrachtet

Hier ein BASCOM-Programm für das Nano-Board, welches Zeichenketten (mit maximal 16 Zeichen) in einzelne Zeilen schreiben kann:

Code: Alles auswählen

' Datei für Nano-Board
' Über die zu zugehörige Konfigurationsdatei werden automatisch Voreinstellungen
' für die Kompilierung übernommen; diese betreffen z. B. die Taktfrequenz, die
' Baudrate, die Anschlüsse von LCD, I2C- und SPI-Modulen.

' Programm nach I. Dobson, Sonal Pinto und Ben Zijlstra & Theo Kleijn
' OLED display 128x32 OLED_091 (www.diymore.cc)

' SCL -> C.5
' SDA -> C.4

' Pull-Up-Widerstände befinden sich auf dem Display-Board!

' Text (Alle ASCII-Zeichen von Code 32 bis 127 plus Umlaute und ß) auf Oled anzeigen
' Zeichenketten dürfen max. 16 Zeichen lang sein!

' Die Ausgabe einer Textzeile dauert weniger als 3 Hunderstel Sekunde.

'----------------------------------------------------------------------------

$regfile = "m328pdef.dat"                                   'Dadurch wird auch das Pin Layout bestimmt
$crystal = 16000000

$framesize = 64
$swstack = 32
$hwstack = 64

'**********************************************************
'******************* Deklarationen ************************

Dim Kontrast As Byte
Dim Write_adresse_oled As Byte

Dim X1 As Byte
Dim X0 As Byte
Dim Page As Integer
Dim Buchstabe As String * 1
Dim Q As Integer
Dim H As Integer
Dim Temp As Integer
Dim Senden As Byte
Dim Pause As Byte
Dim Laenge As Byte
Dim I As Byte

Dim Zeile As String * 16
Dim Zahl As String * 16

Declare Sub Zeige_zeile(byval X As Byte , Byval Y As Byte , Byval S As String * 16)
Declare Sub Init
Declare Sub Loeschen

' Seltsam: Ob das Programm korrekt arbeitet,
' hängt von der Reihenfolge der Deklarationen der Variablen ab!
' Zeichenketten als Letztes!

'**********************************************************
'****************** Initialisierung ***********************

Ddrb.5 = 1                                                  'Kontroll-LED ansteuerbar

Kontrast = 100
Write_adresse_oled = &H78                                   'OLED 128*32;
Config I2cdelay = 1                                         'I2C-Taktung möglichst rasch
Pause = 1                                                   'ggf. 20

'**********************************************************
'******************** Hauptprogramm ***********************

Call Init
Call Loeschen

'Zunächst 4 Textzeilen...
Call Zeige_zeile(0 , 1 , ">Hallo Welt 1.1<")
Call Zeige_zeile(0 , 2 , "----> OLED <----")
Call Zeige_zeile(8 , 3 , "SSD1306 128x32")
Call Zeige_zeile(20 , 4 , "ÄÖÜ -ß- äöü")

Wait 5

'Jetzt die Zahlen von 1 bis 100 in der untersten Zeile...
Call Zeige_zeile(0 , 4 , "")                                'Zeile 4 löschen
For I = 1 To 100
  Zahl = "Zahl --> " + Str(i)
  Call Zeige_zeile(20 , 4 , Zahl)
Next I

End

'**********************************************************
'******************** Unterprogramme **********************

Sub Init
  I2cstart
  I2cwbyte Write_adresse_oled
  If Err = 0 Then Portb.5 = 1                               'LED bei B.5 an, wenn OLED gefunden
  I2cstop
  Waitms 500
  Portb.5 = 0                                               'LED aus

  I2cstart
  I2cwbyte Write_adresse_oled

  I2cwbyte &H00                                             'Command Stream(nötig -------------??)

  I2cwbyte &HAE                                             'DISPLAYOFF ------------------------OK

  I2cwbyte &HD5                                             'SETDISPLAYCLOCKDIV ----------------OK
  I2cwbyte &H80                                             'ratio 0x80

  I2cwbyte &HA8                                             'Set MUX
  I2cwbyte &H1F                                             '&H1F for 128x32; &H3F for 128x64

  I2cwbyte &HD3                                             'SETDISPLAYOFFSET ------------------OK
  I2cwbyte &H00

  I2cwbyte &H40                                             'SETSTARTLINE ----------------------OK

  I2cwbyte &H8D                                             'CHARGEPUMP ------------------------OK
  I2cwbyte &H14                                             'vccstate H14 for chargepump

  I2cwbyte &H20                                             'MEMORYMODE ------------------------OK
  I2cwbyte &H00                                             'horizontal addr mode

  I2cwbyte &HA1                                             'SEGREMAP links-rechts A0/A1 -------OK

  I2cwbyte &HC8                                             'COMSCANDEC (&HC0 vert. gesp.) -----OK

  I2cwbyte &HDA                                             'SETCOMPINS ------------------------OK
  I2cwbyte &H02                                             '&H12 for 64 rows

  I2cwbyte &H81                                             'SETCONTRAST -----------------------OK
  I2cwbyte Kontrast                                         'value 1-->256

  I2cwbyte &HD9                                             'SETPRECHARGE ----------------------OK
  I2cwbyte &HF1                                             'vccstate  F1

  I2cwbyte &HDB                                             'SETVCOMDETECT ---------------------OK
  I2cwbyte &H30                                             '&H30 -> 0.83*VCC; bei Arduino &H40 ??

  I2cwbyte &HA4                                             'DISPLAYALLON_RESUME ---------------OK

  I2cwbyte &HA6                                             'NORMALDISPLAY

  I2cwbyte &HAF                                             'Display on ------------------------OK
  I2cstop
  Waitms 100
End Sub

Sub Zeige_zeile(byval X As Byte , Byval Y As Byte , Byval S As String * 16)
  Laenge = 16 - Len(s)
  Zeile = S + Space(laenge)
  X0 = X Mod 16
  X1 = X / 16
  X1 = X1 + &H10
  I2cstart
  I2cwbyte Write_adresse_oled
  I2cwbyte &H00                                             'command stream ------------------nötig?
  I2cwbyte X0                                               'Spalte x Low Nibble
  I2cwbyte X1                                               'Spalte x High Nibble
  I2cstop

  Page = Y + 175
  I2cstart
  I2cwbyte Write_adresse_oled
  I2cwbyte &H80
  I2cwbyte Page                                             'Bestimmung Page (Y)
  I2cstop

  I2cstart
  I2cwbyte Write_adresse_oled
  I2cwbyte &H80
  I2cstop

  I2cstart
  I2cwbyte &H78
  I2cwbyte &H40

  'Umwandlung von Buchstaben zu Asciiwert für Columndata der Datenbank
  For Q = 1 To 16                                           'Zeichenkette besteht aus 16 Zeichen
    Buchstabe = Mid(zeile , Q , 1)
    Temp = Asc(buchstabe)
    If Temp > 127 Then
      Select Case Temp
        Case 228 : Temp = 128                               'ä
        Case 246 : Temp = 129                               'ö
        Case 252 : Temp = 130                               'ü
        Case 196 : Temp = 131                               'Ä
        Case 214 : Temp = 132                               'Ö
        Case 220 : Temp = 133                               'Ü
        Case 223 : Temp = 134                               'ß
        Case Else : Temp = 32                               'SPACE
      End Select
    End If
    Temp = Temp - 32
    Temp = Temp * 8
    For H = 1 To 8
      Senden = Lookup(temp , Asciitab)
      I2cwbyte Senden
      Incr Temp
    Next H
    Waitms Pause
  Next Q
  I2cstop
End Sub

Sub Loeschen                                                'speziell für SH1106
 For X0 = 0 To 7
  X1 = &HB0 + X0
  I2cstart
  I2cwbyte Write_adresse_oled
  I2cwbyte &H80                                             'Single Command
  I2cwbyte X1                                               'Page (Y) &HB0 = Col0
  I2cstop

  I2cstart
  I2cwbyte Write_adresse_oled
  I2cwbyte &H00                                             'command stream
  I2cwbyte &H02                                             'Select start column 0; offset 2
  I2cwbyte &H10
  I2cstop

  I2cstart
  I2cwbyte Write_adresse_oled
  I2cwbyte &H40                                             'Datenstrom für das RAM
  For Temp = 0 To 127
    I2cwbyte 0
  Next Temp
  I2cstop
 Next X0
End Sub

'**********************************************************
'******************Interruptroutinen***********************



'**********************************************************

Asciitab:
    Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0,                     'ASCII-Code 32
    Data 0 , 0 , 6 , 95 , 6 , 0 , 0 , 0,                    'ASCII-Code 33
    Data 0 , 7 , 3 , 0 , 7 , 3 , 0 , 0,                     '...
    Data 0 , 36 , 126 , 36 , 126 , 36 , 0 , 0,              '#
    Data 0 , 36 , 43 , 106 , 18 , 0 , 0 , 0,
    Data 0 , 99 , 19 , 8 , 100 , 99 , 0 , 0,
    Data 0 , 54 , 73 , 86 , 32 , 80 , 0 , 0,
    Data 0 , 0 , 7 , 3 , 0 , 0 , 0 , 0,
    Data 0 , 0 , 62 , 65 , 0 , 0 , 0 , 0,                   'ASCII-Code 40
    Data 0 , 0 , 65 , 62 , 0 , 0 , 0 , 0,
    Data 0 , 8 , 62 , 28 , 62 , 8 , 0 , 0,
    Data 0 , 8 , 8 , 62 , 8 , 8 , 0 , 0,
    Data 0 , 0 , 224 , 96 , 0 , 0 , 0 , 0,
    Data 0 , 8 , 8 , 8 , 8 , 8 , 0 , 0,
    Data 0 , 0 , 96 , 96 , 0 , 0 , 0 , 0,
    Data 0 , 32 , 16 , 8 , 4 , 2 , 0 , 0,
    Data 0 , 62 , 81 , 73 , 69 , 62 , 0 , 0,
    Data 0 , 0 , 66 , 127 , 64 , 0 , 0 , 0,
    Data 0 , 98 , 81 , 73 , 73 , 70 , 0 , 0,                'ASCII-Code 50
    Data 0 , 34 , 73 , 73 , 73 , 54 , 0 , 0,
    Data 0 , 24 , 20 , 18 , 127 , 16 , 0 , 0,
    Data 0 , 47 , 73 , 73 , 73 , 49 , 0 , 0,
    Data 0 , 60 , 74 , 73 , 73 , 48 , 0 , 0,
    Data 0 , 1 , 113 , 9 , 5 , 3 , 0 , 0,
    Data 0 , 54 , 73 , 73 , 73 , 54 , 0 , 0,
    Data 0 , 6 , 73 , 73 , 41 , 30 , 0 , 0,
    Data 0 , 0 , 108 , 108 , 0 , 0 , 0 , 0,
    Data 0 , 0 , 236 , 108 , 0 , 0 , 0 , 0,
    Data 0 , 8 , 20 , 34 , 65 , 0 , 0 , 0,                  'ASCII-Code 60
    Data 0 , 36 , 36 , 36 , 36 , 36 , 0 , 0,
    Data 0 , 0 , 65 , 34 , 20 , 8 , 0 , 0,
    Data 0 , 2 , 1 , 89 , 9 , 6 , 0 , 0,
    Data 0 , 62 , 65 , 93 , 85 , 30 , 0 , 0,
    Data 0 , 126 , 17 , 17 , 17 , 126 , 0 , 0,
    Data 0 , 127 , 73 , 73 , 73 , 54 , 0 , 0,
    Data 0 , 62 , 65 , 65 , 65 , 34 , 0 , 0,
    Data 0 , 127 , 65 , 65 , 65 , 62 , 0 , 0,
    Data 0 , 127 , 73 , 73 , 73 , 65 , 0 , 0,
    Data 0 , 127 , 9 , 9 , 9 , 1 , 0 , 0,                   'ASCII-Code 70
    Data 0 , 62 , 65 , 73 , 73 , 122 , 0 , 0,
    Data 0 , 127 , 8 , 8 , 8 , 127 , 0 , 0,
    Data 0 , 0 , 65 , 127 , 65 , 0 , 0 , 0,
    Data 0 , 48 , 64 , 64 , 64 , 63 , 0 , 0,
    Data 0 , 127 , 8 , 20 , 34 , 65 , 0 , 0,
    Data 0 , 127 , 64 , 64 , 64 , 64 , 0 , 0,
    Data 0 , 127 , 2 , 4 , 2 , 127 , 0 , 0,
    Data 0 , 127 , 2 , 4 , 8 , 127 , 0 , 0,
    Data 0 , 62 , 65 , 65 , 65 , 62 , 0 , 0,
    Data 0 , 127 , 9 , 9 , 9 , 6 , 0 , 0,                   'ASCII-Code 80
    Data 0 , 62 , 65 , 81 , 33 , 94 , 0 , 0,
    Data 0 , 127 , 9 , 9 , 25 , 102 , 0 , 0,
    Data 0 , 38 , 73 , 73 , 73 , 50 , 0 , 0,
    Data 0 , 1 , 1 , 127 , 1 , 1 , 0 , 0,
    Data 0 , 63 , 64 , 64 , 64 , 63 , 0 , 0,
    Data 0 , 31 , 32 , 64 , 32 , 31 , 0 , 0,
    Data 0 , 63 , 64 , 60 , 64 , 63 , 0 , 0,
    Data 0 , 99 , 20 , 8 , 20 , 99 , 0 , 0,
    Data 0 , 7 , 8 , 112 , 8 , 7 , 0 , 0,
    Data 0 , 113 , 73 , 69 , 67 , 0 , 0 , 0,                'ASCII-Code 90
    Data 0 , 0 , 127 , 65 , 65 , 0 , 0 , 0,
    Data 0 , 2 , 4 , 8 , 16 , 32 , 0 , 0,
    Data 0 , 0 , 65 , 65 , 127 , 0 , 0 , 0,
    Data 0 , 4 , 2 , 1 , 2 , 4 , 0 , 0,
    Data 128 , 128 , 128 , 128 , 128 , 128 , 128 , 128,
    Data 0 , 0 , 3 , 7 , 0 , 0 , 0 , 0,
    Data 0 , 32 , 84 , 84 , 84 , 120 , 0 , 0,
    Data 0 , 127 , 68 , 68 , 68 , 56 , 0 , 0,
    Data 0 , 56 , 68 , 68 , 68 , 40 , 0 , 0,
    Data 0 , 56 , 68 , 68 , 68 , 127 , 0 , 0,               'ASCII-Code 100
    Data 0 , 56 , 84 , 84 , 84 , 8 , 0 , 0,
    Data 0 , 8 , 126 , 9 , 9 , 0 , 0 , 0,
    Data 0 , 24 , 164 , 164 , 164 , 124 , 0 , 0,
    Data 0 , 127 , 4 , 4 , 120 , 0 , 0 , 0,
    Data 0 , 0 , 0 , 125 , 64 , 0 , 0 , 0,
    Data 0 , 64 , 128 , 132 , 125 , 0 , 0 , 0,
    Data 0 , 127 , 16 , 40 , 68 , 0 , 0 , 0,
    Data 0 , 0 , 0 , 127 , 64 , 0 , 0 , 0,
    Data 0 , 124 , 4 , 24 , 4 , 120 , 0 , 0,
    Data 0 , 124 , 4 , 4 , 120 , 0 , 0 , 0,                 'ASCII-Code 110
    Data 0 , 56 , 68 , 68 , 68 , 56 , 0 , 0,
    Data 0 , 252 , 68 , 68 , 68 , 56 , 0 , 0,
    Data 0 , 56 , 68 , 68 , 68 , 252 , 0 , 0,
    Data 0 , 68 , 120 , 68 , 4 , 8 , 0 , 0,
    Data 0 , 8 , 84 , 84 , 84 , 32 , 0 , 0,
    Data 0 , 4 , 62 , 68 , 36 , 0 , 0 , 0,
    Data 0 , 60 , 64 , 32 , 124 , 0 , 0 , 0,
    Data 0 , 28 , 32 , 64 , 32 , 28 , 0 , 0,
    Data 0 , 60 , 96 , 48 , 96 , 60 , 0 , 0,
    Data 0 , 108 , 16 , 16 , 108 , 0 , 0 , 0,               'ASCII-Code 120
    Data 0 , 156 , 160 , 96 , 60 , 0 , 0 , 0,
    Data 0 , 100 , 84 , 84 , 76 , 0 , 0 , 0,
    Data 0 , 8 , 62 , 65 , 65 , 0 , 0 , 0,
    Data 0 , 0 , 0 , 119 , 0 , 0 , 0 , 0,
    Data 0 , 0 , 65 , 65 , 62 , 8 , 0 , 0,
    Data 0 , 2 , 1 , 2 , 1 , 0 , 0 , 0,
    Data 0 , 60 , 38 , 35 , 38 , 60 , 0 , 0,                'ASCII-Code 127
    Data 0 , 32 , 85 , 84 , 85 , 120 , 0 , 0,               'ä
    Data 0 , 56 , 69 , 68 , 69 , 56 , 0 , 0,                'ö
    Data 0 , 60 , 65 , 32 , 125 , 0 , 0 , 0,                'ü
    Data 0 , 125 , 18 , 17 , 18 , 125 , 0 , 0,              'Ä
    Data 0 , 61 , 66 , 65 , 66 , 61 , 0 , 0,                'Ö
    Data 0 , 60 , 65 , 64 , 65 , 60 , 0 , 0,                'Ü
    Data 0 , 254 , 9 , 73 , 78 , 48 , 0 , 0                 'ß (134)
    Data 0 , 126 , 9 , 73 , 73 , 54 , 0 , 0                 'ß (135)
Die Übertragung ist recht schnell: Das folgende Video zeigt, dass für eine Zeile nur etwa 3/100 Sekunden benötigt werden.

oled_128x32_video.wmv
Video
(688.28 KiB) 1170-mal heruntergeladen

Übrigens: Wenn man das 128x64-OLED-Display mit demselben Programm betreibt, erhält man auf diese Weise gut lesbare große Buchstaben; es werden jetzt nur die Pixel aus jeder zweiten Zeile angesteuert.

OLED_große_Schrift_2.jpg
Große Schrift beim 128x64-OLED
OLED_große_Schrift_2.jpg (51.95 KiB) 14051 mal betrachtet
.
Zuletzt geändert von Heinrichs am Mo 1. Mär 2021, 17:49, insgesamt 1-mal geändert.

Heinrichs
Beiträge: 173
Registriert: Do 21. Okt 2010, 18:31

Re: Mini-OLED-Display 128x32

Beitrag von Heinrichs » Mo 1. Mär 2021, 17:13

An anderer Stelle wurde folgendes Problem aufgeworfen: Ich will ein SSD1306 in einen Ruhezustand/Standby versetzten. Ziel ist es, den Stromverbrauch (Batterie!) zu minimieren. Setze ich die Anzeigefarbe auf black, reduziert sich der gezogene Strom von ca.3mA auf ca.1,7mA ..... was mir zu wenig ist. Wenn's keine Möglichkeit gibt, muss ich mit einem Transistor den Strom weg schalten.

Im Internet findet man zu diesem Problem die unterschiedlichsten (teilweise konträren) Aussagen. Deswegen bin ich der Frage einmal selbst nachgegangen. Dabei habe ich das Mini-OLED-Display 128x32 aus dem letzten Beitrag benutzt. Zwischen dem 5V-Anschluss des nano-Boards und dem Vcc-Anschluss des Display-Boards habe ich ein Stromstärke-Messgerät geschaltet.

Zunächst habe ich die Stromstärken bei unterschiedlichen Belastungen gemessen; dazu habe ich von den folgenden Zeilen (mit ungefähr gleich vielen Pixeln)

Code: Alles auswählen

Call Zeige_zeile(0 , 1 , ">Hallo Welt 1.1<")
Call Zeige_zeile(0 , 2 , "----> OLED <----")
Call Zeige_zeile(8 , 3 , "SSD1306 128x32")
Call Zeige_zeile(20 , 4 , "ÄÖÜ -ß- äöü")
unterschiedliche Anzahlen von Zeilen zur Anzeige gebracht und die zugehörigen Stromstärken gemessen:

Code: Alles auswählen

Anzahl der Zeilen  | Stromstärke in mA
----------------------------------------------
4                  | 7,20
3                  | 6,12
1                  | 3,36
0                  | 1,96
stromstaerke_messung.jpg
stromstaerke_messung.jpg (12.55 KiB) 9459 mal betrachtet

Man sieht, dass die Stromstärke mit fallender Belastung abnimmt. Aber: Selbst wenn kein einziges Pixel angezeigt wird (0 Zeilen), liegt immer noch ein Strom von ca. 2 mA vor. Dies ist insbesondere hinderlich, wenn Mikrocontroller und Display mit Hilfe einer Batterie über einen längeren Zeitraum versorgt werden sollen, um nur ab und zu (auf Anfrage) einen Messwert anzuzeigen.

In diesem Fall lohnt es sich, in den Phasen der Inaktivität das Display auszuschalten. Dies lässt sich über den DISPLAY_OFF-Command (Code: &HAE) bewirken, z. B. mit Hilfe des folgenden Unterprogramms:

Code: Alles auswählen

Sub Display_off
  I2cstart
  I2cwbyte Write_adresse_oled
  I2cwbyte &H80                                             'Single Command
  I2cwbyte &HAE                                             'Display Off
  I2cstop
End Sub
In diesem ausgeschalteten Zustand zeigt mein Stromstärke-Messgerät 0,00 mA im Messbereich mA (bzw. 3 uA im Messbereich uA) an!

Zum Einschalten benutzt man den DISPLAY_ON-Command (Code: &HAF). Hier ein passendes Unterprogramm:

Code: Alles auswählen

Sub Display_on
  I2cstart
  I2cwbyte Write_adresse_oled
  I2cwbyte &H80                                             'Single Command
  I2cwbyte &HAF                                             'Display On
  I2cstop
End Sub
Nach dem Unterprogrammaufruf zeigt das Display denselben Inhalt an wie unmittelbar vor dem Ausschalten. Will man anschließend nicht nur Zeilen ergänzen, sondern auch ändern, muss wie immer erst gelöscht werden.

.

Antworten