• Hallo Zusammen, Aufgrund der aktuellen Situation setzten wir die Möglichkeit aus, sich mit Gmail zu registrieren. Wir bitten um Verständnis Das RCMP Team

Praxisbericht 128 x 64 Pixel 1,3 Zoll OLED I2C Display für Arduino

BAXL

Admin
Mitarbeiter
Das 128 x 64 Pixel 1,3 Zoll OLED I2C Display für Arduino habe ich zwar schon an anderer Stelle, im Rahmen eines Projektes erwähnt, allerdings war dort nicht der Platz, um die vielen kleinen Fußangeln zu beschreiben, die mir dieses Display gelegt hat. Außerdem ist es hilfreicher, wenn all diese Sachen konzentriert und nur auf das Display bezogen in einem Thema zu finden sind.

Zur Einstimmung erstmal ein Foto von dem Display, um das es hier geht:



Das Display habe ich von AZ-Delivery und zwar dieses hier. Achtung, das ist keine Schleichwerbung, ich musste das Teil mit harten Euros bezahlen. Ich verlinke nur deshalb, weil es eine Vielzahl von OLED-Displays gibt und die alle so ihre Spezialitäten haben.

Der Anschluß war recht einfach, weil die Pinbeschriftung bereits alle erforderlichen Informationen enthält. Man muß allerdings wissen, wo die Anschlüsse an den Arduino gehören.
Angeschlossen wird VDO -> +5V, GND -> GND, SCK -> A5, SDA -> A4 am Arduino. Weiters findet man in meinem Post im Thema zu Sensoren und Module (Da ist auch ein Beispielsketch) für den Arduino.


Kommen wir zur Fußangel Nr. 1:
Die OLED-Displays haben einen Treiberchip, derer mehrere im Umlauf sind. Es gibt einmal den SSD1306, für den es eine Adafruit-Library gibt und wir haben den SH1106 Controller-Chip, so wie mein Display.

Man braucht also die richtige Library, sonst hat man nur ganz viele weiße Punkte auf dem Display und könnte meinen, dass das Ding kaputt ist, ist es aber nicht :).

Für mein Display, verrät mir AZ-Delivery etwas versteckt auf deren Internetshopseitenblog, braucht es die Lib U8g2 Bibliothek von Oliver Kraus.

Also runtergeladen und in die Arduino IDE eingebunden. Super!


Fußangel 2:
AZ-Delivery gibt als Beispielprogram "Datei" -> "Beispiele" -> "u8g2" -> "full_buffer" -> "GraphicsTest" an.
Ganz davon abgesehen, dass ich das Programm über den Pfad nicht gefunden habe, sondern etwas suchen mußte, wurde ich zuerst von einer sehr beunruhigenden Meldung des Compilers überrascht.

Nämlich:
Der Sketch verwendet 9962 Bytes (32%) des Programmspeicherplatzes. Das Maximum sind 30720 Bytes.
Globale Variablen verwenden 1605 Bytes (78%) des dynamischen Speichers, 443 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
Wenig Arbeitsspeicher verfügbar, es können Stabilitätsprobleme auftreten.

Ich habe das Programm trotzdem hochgeladen und gestartet. Heissa, was flimmerten, flackerten und hopsten tolle Grafilen da herum. Nur, was soll ich damit? :rolleyes: Und vor allen Dingen, wo sollte überhaupt noch die eigene Applikation Platz finden, wenn der Speicher bereits mit dem Zeugs für Zappelgrafiken voll ist.

Aber auch dafür hat AZ-Delivery eine Lösung parat. Einfach ein anderes beispielprogramm nehmen, nämlich dann dieses hier: "Datei" -> "Beispiele" -> "U8g2" -> "page_buffer" -> "GraphicsTest"

Ganz ehrlich, der Bringer ist das auch nicht und verflixt ich will kein Videogame auf einer Briefmarke programmieren, sondern schlicht ein paar mehr Messwerte darstellen können.

Nach einigem Herumstochern in den Beispielen bin ich dann auf ein Beispielprogramm gestoßen, das "HelloWorld" heißt und als Library nicht das grafiküberfrachtete Ungetüm vom Oliver Kraus benötigt, sondern als schlanken Fuß dessen U8x8lib.h benötigt. Damit kann man wirklich nur Zeichen ausgeben - wirklich, mehr nicht.


Fußangel 3:
Als Übergabeparameter akzeptiert die "Druckfunktion" der Lib eigentlich nur irgendwelche zeichen, die in Hochkommas sind. z.B. "Test", "123 Testtext" usw.. Versucht man aber eine Zeichenkette in eine Stringvariable zu packen und der Druckfunktion zu übergeben, gibt es eine charmante Fehlermeldung.
Auch bei irgendwelchen Zahlen, egal ob vom Typ Byte, Integer oder Fließkommazahlen, weigert sich die Ausgabefunktion beharrlich. Man bekommt beim kompilieren zwar keine Fehlermeldung, es erscheint aber auch nichts auf dem Display, oder nur irgendetwas Sinnloses.

Um es kurz zu machen, die Lösung des Problems geht nur über ein Datenfeld, in dem der Datentyp char (für character oder Zeichen) gespeichert wird. Ein String ist eigentlich auch nichts Anderes als ein eindimensionales Datenfeld, in dem nur Zeichen gespeichert sind. Damit soll es wohl funktionieren. Es klappt natürlich, das verrate ich bevor ich erzähle wie es geht.


Fußangel 4:
Die Umwandlung von Zahlen in ein Char array ist nun doch nicht mal eben so gemacht. Je nach Zahlentyp muß man andere Wege gehen, manchmal auch Umwege. Am Ende ist aber entscheident, dass man das auf dem Display darstellen kann, was man haben will.

Den Code dafür poste ich noch, komme in diesem Augenblick aber gerade nich da dran ;).

Edit:
Es geht hier schon weiter, keine Sorge, aber ab und zu muss ich meine Brötchen verdienen und manchmal lässt mir das keine Zeit für was Anderes. :)
 
Zuletzt bearbeitet:

BAXL

Admin
Mitarbeiter
Ich komme jetzt zu der Lösung der Fußangel 4, die Umwandlung der Zahlenwerte in einen String, bzw. in ein Zeichenfeld (char Array).

Je nach Zahlentyp, muß man einen unterschiedlichen Weg gehen.

Am einfachsten geht es, wenn man mit "ganzen Zahlen" operiert, also Zahlen ohne Nachkommastellen. In dem Fall definiert man einfach eine Stringvariable und weißt im Programmablauf dieser Stringvariablen einen Zahlenwert zu.

Dazu definiert man im Vereinbarungsteil des Programms z.B:

String
ZahlString; // ZahlString ist hier die Variable und String weist dieser Variablen den Datentyp String zu
char ZahlCharArray[16]; // ZahlCharArray ist ein Zeichenfeld mit 16 Speicherplätzen, d.h., ich kann dort einen String mit maximal 16 Zeichen unterbringen z.B. "Teststring123456"

Im Programmablauf hat man dann einen (ganzzahligen) Zahlenwert, z.B.: Messstelle. Messstelle soll im Programmablauf als Inhalt die Zahl 25 haben. Diese Zahl kann aber beliebig sein.

Durch einen einfachen Befehl:

ZahlString = Messstelle;

wandelt das Programm die 25 als Zahlenwert in einen String "25" um. Damit sind wir aber noch nicht fertig, weil das OLED gerne ein Zeichenarray (char array) haben möchte, in dem jedes einzelne Zeichen (Buchstabe usw.) in einer getrennten Speicherstelle des Arrays stecken muß.

Dazu verwendet man den Befehl:

ZahlString.toCharArray(ZahlCharArray,16);

D.h., die "25 " wird auseinandergepflückt und in zwei Speicherstellen des Arrays gepackt. In Speicherstelle 0 steckt nun die "2" und in Speicherstelle 1 steckt die "5".
Also ZahlCharArray(0) enthält die 2, ZahlCharArray(1) enthält die 5.

Um die "25" nun auf dem OLED-Display darzustellen bedarf es nur noch den Befehl:

u8x8.drawString(Spalte,Zeile,ZahlCharArray); // Spalte gibt die Spaltenposition und Zeile die Zeilenposition an, ab der die 25 ausgegeben wird. Achtung, das Display fängt bei beiden mit 0 (Null) an zu zählen. Die oberste linke Ecke wäre dann

u8x8.drawString(0,0,ZahlCharArray);

Bei Zahlen mit Nachkommastellen ist es etwas umständlicher (wenngleich nicht sonderlich viel).

In meinem Programm rechne ich mit nicht mehr als 8 Zeichen (inkl. des Dezimalpunktes). Bei (positiven) Temperaturen mit zwei Nachkommastellen reichen eigentlich 5 Zeichen, aber ich bin vorsichtig ;).

Ich benötige für die Umwandlung von Kommazahlen also ein char array mit 8 Speicherstellen. Im Vereinbarungsteil definiere ich deshalb:

char floatChar[8];

Der Name floatchar ist willkürlich von mir gewählt und hätte auch NachkommaZahl, Schlumpf oder sonstwie lauten können. Wichtig ist das Wörtchen char davor und in Klammern die gewünschte Anzahl Speicherzellen.

Bei der Umwandlung einer Nachkommazahl verwende ich nun einen anderen Befehl.

dtostrf(Waerme, 5, 2,floatChar );

In Waerme steckt eine Zahl wie z.B.: 21,37, was der Temperatur 21,37°C entsprechen soll.

Die 5 gibt an, wieviel Zeichen insgesamt entstehen sollen und die 2, wieviele Nachkommastellen entstehen sollen. floatchar enthält nach dem Funktionsaufruf dann in einzelnen Speicherzellen jeweils:

floatchar[0] = "2", floatchar[1] = "1", floatchar [2] = ".", floatchar[3] = "3", floatchar[4] = "7".

Nach der Umwandlung kann man dann wieder die Druckfunktion für das OLED-Display aufrufen:

u8x8.drawString(Spalte,Zeile+1,floatChar);

Die Funktionen für die Zahlenumwandlungen sind bereits in der Basislib der Arduino-IDE enthalten und brauchen werder selbst geschrieben, oder extra eingebunden zu werden.
 
Zuletzt bearbeitet:

Sensi-1

Neuer Benutzer
Hallo BAXL, ich bin neu in diesem Forum und kämpfe mit diesem Display. Deine Beschreibung der stolperstricke finde ich sehr gut. Bei der Umsetzung der folgenden Beschreibung fehlen mir als Anfänger einige Infos. Gibt es zufällig schon einen fertigen Sketch zu deiner Beschreibung? Ich möchte Messwerte von 2 Sensoren auslesen und anzeigen lassen. Gruß Sensi-1
 

BAXL

Admin
Mitarbeiter
Hallo Sensi-1,

es müsste etwas in meinem ongoing Projet zur Hausautomation stehen, da müsste ich selbst mal nachsehen, wollte Dich aber nicht so lange auf eine Antwort warten lassen.
Wenn alle Stricke reißen müsste ich einfach mal den Sketch aus meinem Projekt posten. (Heute Abend, weil ich gerade nich an den Rechner drankomme) Da müsstest Du Dich allerdings selbst durchwuseln.

Ich nehme das aber als Anregung auf, einen einfachen Beispielsketch zu schreiben.
Aber nicht jetzt und nicht heute :).

Edit:
guck mal hier https://www.rc-modellbau-portal.de/...en-vorstellung-und-beispiele.5880/post-161255
ob das schon hilft.
Code:
//  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)

#include <Arduino.h>
#include <U8x8lib.h>

// Please UNCOMMENT one of the contructor lines below
// U8x8 Contructor List
// The complete list is available here: https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
// Please update the pin numbers according to your setup. Use U8X8_PIN_NONE if the reset pin is not connected

U8X8_SH1106_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);

byte zeile = 0;
char z[4];
char TestText[9] = "Testtext";
int IntZahl;
char ZahlCharArray[16];
String ZahlString;

void setup(void)

{

  u8x8.begin();
  u8x8.setPowerSave(0);

}

void loop(void)
{
  u8x8.setFont(u8x8_font_chroma48medium8_r);
  u8x8.drawString(0,0,"Hello World!");
  u8x8.drawString(0,1,"Hallo Welt!");
  u8x8.drawString(0,2,"ABCDEFGHIJKLMNOP");
  u8x8.drawString(0,3,"Zeile 4");
  u8x8.drawString(0,4,"Zeile 5");
  u8x8.drawString(0,5,"Zeile 6");
  u8x8.drawString(0,6,"Zeile 7");
  u8x8.drawString(0,7,"Zeile 8");
  delay(2000);
  u8x8.clear();

for (byte ii=0; ii<7; ii++){
   u8x8.drawString(0,ii,"Ich wandere");
   u8x8.clearLine(ii-1);
   delay(200);
}
u8x8.clear();

for (byte ii=0; ii<8; ii++){

    ZahlString = (ii+1)*100;
    ZahlString.toCharArray(ZahlCharArray,16);
    u8x8.drawString(0,ii,ZahlCharArray);

   delay(800);
}
u8x8.clear();

}
 

RC-Freund

Autor
Hallo @Sensi-1

Die Librarys bringen meist auch immer ein paar Beispiel-Sketche mit. Davon ist das einfachste immer das "Hello World" Sketch. Darauf kann man gut aufbauen.
Außerdem kommen die auch oft als Grafik- oder reine Textversion. Davon immer die Text-Version verwenden. Die hat am wenigsten Ballast.

Gruß,
RC-Freund
 

BAXL

Admin
Mitarbeiter
Hallo RC-Freund,

die Beispiele habe ich auch ausprobiert, die sind aber in diesem speziellen Fall nicht sonderlich hilfreich, mein eingefügter Code im Beitrag oben sollte funktionieren. Es müsste allerdings noch die Anpassung erfplgen, weil Sensi eigene Messwerte anzeigen lassen will. Die Umrechnung, bzw. Umwandlucng der Messwerte in String habe ich bei den Fußangeln beschrieben.
 

RC-Freund

Autor
Beispiele habe ich auch ausprobiert, die sind aber in diesem speziellen Fall nicht sonderlich hilfreich
Ok, das mag sein, dass die "Brauchbarkeit" von Library zu Library unterschiedlich ist.

weil Sensi eigene Messwerte anzeigen lassen will. Die Umrechnung, bzw. Umwandlucng der Messwerte in String habe ich bei den Fußangeln beschrieben.
Ja das ist auch gut (mit den Fußangeln). Aber man muss nicht zwingend Messwerte in Strings schreiben um diese dann auf dem Display auszugeben. Meist gibt es auch auch eine print-Funktion, die den Inhalt einer Variablen (z.B. eines Integers) ohne Wandlung auf dem Display ausgibt.

Gruß,
RC-Freund
 

BAXL

Admin
Mitarbeiter
Ok, das mag sein, dass die "Brauchbarkeit" von Library zu Library unterschiedlich ist.



Ja das ist auch gut (mit den Fußangeln). Aber man muss nicht zwingend Messwerte in Strings schreiben um diese dann auf dem Display auszugeben. Meist gibt es auch auch eine print-Funktion, die den Inhalt einer Variablen (z.B. eines Integers) ohne Wandlung auf dem Display ausgibt.

Gruß,
RC-Freund
Das habe ich ausprobiert und hat nicht funktioniert, weil die Lib das nicht unterstützt. Darum habe ich in meinem Bericht meiner Erfahrung geteilt, weil andere garantiert mit der sehr stark eingedampften Lib auf dasselbe Problem stoßen werden.
Fußangel 3:
Als Übergabeparameter akzeptiert die "Druckfunktion" der Lib eigentlich nur irgendwelche zeichen, die in Hochkommas sind. z.B. "Test", "123 Testtext" usw.. Versucht man aber eine Zeichenkette in eine Stringvariable zu packen und der Druckfunktion zu übergeben, gibt es eine charmante Fehlermeldung.
Auch bei irgendwelchen Zahlen, egal ob vom Typ Byte, Integer oder Fließkommazahlen, weigert sich die Ausgabefunktion beharrlich. Man bekommt beim kompilieren zwar keine Fehlermeldung, es erscheint aber auch nichts auf dem Display, oder nur irgendetwas Sinnloses.
Hast Du dass denn mal mit dem Display probiert? Vielleicht hast Du eine Lib, die geschmeidiger läuft und trotzdem kein "Speicherfressmonster" ist. Das würde mir auch helfen.
 

RC-Freund

Autor
Hast Du dass denn mal mit dem Display probiert? Vielleicht hast Du eine Lib, die geschmeidiger läuft und trotzdem kein "Speicherfressmonster" ist. Das würde mir auch helfen.
Nein. Mit diesem 128x64 Display nicht. Ich hatte mich in der letzten Zeit vorwiegend mit einem 128x32 Display befasst, und wie ich es möglichst ressourcen-schonend mit einem ATTiny85 nutzen kann. Ich hatte verschiedene Libs ausprobiert und auch abgemagerte Versionen für die I2C-Kommunikation. Insbesondere schlucken die Fonts extrem Speicher. Je hübscher die Schriftart, desto mehr Speicherverbrauch. Aber wie gesagt, meine Erfahrungen betreffen nur spezielle Versionen für den ATTiny, die wahrscheinlich auf dem Arduino nicht laufen.

Demnächst möchte ich hier in diesem schönen Forum auch meine konfigurierbaren Schaltmodule zeigen, welche auf dem ATTiny85 basieren, ebenso wie die zugehörige Programmierkarte. Hier auf dem Bild ist auch das Display zu sehen:

RCuniSwitch-M1.jpgRCuniSwitch-M1.jpg
 

BAXL

Admin
Mitarbeiter
Wie wahr, die Fonts sind übel. Auf die ATTiny Beiträge freue ich mich. Da wollte ich auch mal dran habe irgendwie nicht den Dreh bekommen bzw. keine praktische Applikation zum Probieren.
 
Top Bottom