Forum: Projekte & Code SSD1306/1309 Library zum Darstellen von Text auf OLED Displays


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Harry L. schrieb:
> Der Code sollte auf jedem System mit jeder Codepage zum selben Ergebnis
> führen.

Die Zeit von „Codepages“ ist (zumindest in meiner Welt) vorbei. Der 
einzige Nachteil von UTF-8 an dieser Stelle ist es eben, dass dort die 
Umlaute dann Multibyte-Zeichen werden, sodass man sie nicht mehr in 
einem einfachen "char" abspeichern und verarbeiten kann. Für ein kleines 
Werkzeug auf einem Controller ist sowas natürlich lästig, da hätte man 
gern alle Zeichen in 8 Bit passend.

Wenn der Compiler UTF-8 als host character set akzeptiert, dann geht 
allerdings obiges auch so zu schreiben:
1
#define ä "\xe4"
2
#define ß "\xdf"
3
4
   ...
5
   printf("Verl"ä ß"lich");

Bekomme ich mit dem GCC aber gerade nicht akzeptiert, während der Clang 
es klaglos schluckt. Vorgeblich sollte GCC es zumindest mit -std=c99 
(oder höher) auch akzeptieren.

M. K. schrieb:
> Würde nur mit deinem Font nicht funktionieren da da ä als 0x84 definiert
> ist und ß mit 0xe1.

Dass diese Definitionen mit dem Font zusammenpassen müssen, sollte 
sonnenklar sein.

von M. K. (sylaina)


Lesenswert?

Jörg W. schrieb:
> Bei dieser Variante ist man halt komplett unabhängig vom host und
> execution charset.

Nö, ist man nicht. Ist das charset so eingestellt dass ein ä als 0x84 
dargestellt wird, wie das beim verwendeten Font von Harry der Fall ist, 
führt das zu einer fehlerhaften Ausgabe da sein Font kein Zeichen mit 
dem Code 0xe4 kennt ;)
Man kann natürlich Glück haben, dass die Defaulteinstellungen vom input 
so sind, dass ein ä ein 0xe4 ist und vom exec so, dass ein ä ein 0x84 
ist aber das wäre schlicht purer Zufall. Aber hat man Pech wird aus 
einem 0xe4 ein 0xe4 und dann sagt der Mikrocontroller nur "Das Zeichen 
ist im Font nicht enthalten."
Jörg W. schrieb:
> Dass diese Definitionen mit dem Font zusammenpassen müssen, sollte
> sonnenklar sein.

Eben das ist aber dem Harry nicht klar. Deshalb diskutieren wir ja 
darüber. Er meint ja, dass es besser wäre dem Compiler im Font besser 
den Hexcode zu geben als das Zeichen. In der main aber, so meine 
Meinung, wird man weniger mit hexcode den Font schreiben wollen als mit 
Zeichen. Daher ist es IMO sinniger im Font auch die Zeichen anzugeben 
und dem Compiler eben das korrekte Charset mitzuteilen. Dafür gibts ja 
extra flags beim gcc. Warum also sie nicht nutzen und sich somit das 
Leben leichter machen?

: Bearbeitet durch User
von Harry L. (mysth)


Lesenswert?

M. K. schrieb:
> Eben das ist aber dem Harry nicht klar. Deshalb diskutieren wir ja
> darüber. Er meint ja, dass es besser wäre dem Compiler im Font besser
> den Hexcode zu geben als das Zeichen. In der main aber, so meine
> Meinung, wird man weniger mit hexcode den Font schreiben wollen als mit
> Zeichen. Daher ist es IMO sinniger im Font auch die Zeichen anzugeben
> und dem Compiler eben das korrekte Charset mitzuteilen. Dafür gibts ja
> extra flags beim gcc. Warum also sie nicht nutzen und sich somit das
> Leben leichter machen?

Natürlich ist mir der Zusammenhang klar, aber meine IDE verwendet UTF-8 
- und jetzt?

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

Harry L. schrieb:
> Natürlich ist mir der Zusammenhang klar, aber meine IDE verwendet UTF-8
> - und jetzt?

Ja, deine IDE. Und wenn sich nun jemand dein Projekt im Github runter 
läd und seine IDE benutzt nicht UTF-8 sondern z.B. Ansi (Windows 
Standard-Charset) oder Latin-1? Wie gesagt, der GCC kennt ja Flags zur 
Vorgabe der Charsets, warum also sie nicht benutzen wenn sie schon da 
sind? ;)

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ihr beiden dreht euch schon wieder im Kreise.  Lasst's doch mal gut 
sein.  Dass die Optionen für die Umwandlung der Zeichen offenbar nicht 
in jeder Umgebung funktionieren, ist ja nun auch klar geworden, damit 
sind auch die Kommandozeilenoptionen kein „Allheilmittel“. Wichtig ist 
daher, dass sich jeder dessen gewahr ist, um sich mit seinem Sourcecode 
passend drauf einstellen zu können.

von Simon X. (simon1720)


Lesenswert?

M. K. schrieb:
> Joachim B. schrieb:
>> freut mich, ich habe auch noch 2 nachbestellt
>
> So, ich hab meine SH1106er nun auch endlich bekommen und konnte heute
> experimentieren. Library ist angepasst, Fehler möglich ;).
> Es werden nun OLED-Displays mit SSD1306 und SH1106 Controller
> unterstützt, entsprechend einzustellen in der jeweiligen Header-Datei.

Funktioniert diese Library auch mit einem Atmega2560 ohne Arduino mit 
Atmelstudio 7 ? oder was für Anpassungen müsste man vornehmen, damit es 
funktionieren würde?

Danke im Voraus

von M. K. (sylaina)


Lesenswert?

Simon X. schrieb:
> Funktioniert diese Library auch mit einem Atmega2560 ohne Arduino mit
> Atmelstudio 7 ? oder was für Anpassungen müsste man vornehmen, damit es
> funktionieren würde?

Es müsste auch auf einem Atmega2560 funktionieren. Dazu muss lediglich 
in der i2c.h die Prozessorinformation ergänzt werden (gehört also ein 
(_defined_ATmega2560_) zum entsprechenden #if dazu). Das habe ich 
grade mal bei der Library ergänzt und sollte nun gehen.
Die Library kannst du mit der Arduino IDE, dem Atmel Studio oder auch 
jeder anderen IDE benutzen. Denke nur daran, dass es eine C-Library ist. 
Willst du sie in einem C++ Projekt verwenden musst du sie mit

[c]extern "C" {
    #include "lcd.h"
}

includieren ;)

von M. K. (sylaina)


Lesenswert?

Habe heute ein kleines Update aufgespielt.
Man kann nun in der Header-Datei (lcd.h) ein #define BIGCHAR setzen 
wodurch die Schriftgröße verdoppelt wird.
Bisher funktioniert das fehlerfrei auf SSD1306 und SH1106 Displays im 
Grafik- und Textmode. Lediglich die Displaygröße wird noch nicht bei 
Verwendung der BIGCHARs mit berücksichtigt (man kann also quasi über den 
Displayrand schreiben...mit allen Konsequenzen, die das jeweilige 
Display dabei bedingt).

von M. K. (sylaina)


Angehängte Dateien:

Lesenswert?

Noch eine kleine Änderung eingefügt, es lässt sich nun der Font in 
normaler Größe und doppelter Größe gleichzeitig nutzen.

Lib liegt unter

https://github.com/Sylaina/oled-display

zum Download bereit.

von privat (Gast)


Lesenswert?

Sehr schön lesbare Zeichen. Jetzt wird es eine Anzeige für das E-Bike 
werden.

von Tillmaier (Gast)


Lesenswert?

Sehr gute Arbeit  M. K., ich danke dafür.
Hab noch eine Frage dazu, da ich noch nicht so gut programmieren kann:

Köntest Du eine Beispielzeile für die Verwendung von Sonderzeichen wie 
Ä, Ü
geben?

Was mir noch aufgefallen ist:
Auf Github in der readme.md sind zwei Beispiele. Im zweiten Beispiel 
liegt die Ausgabe in der main loop. Im ersten Beispiel vor der main 
loop?
Das erste Beispiel ist richtig, oder?

von M. K. (sylaina)


Lesenswert?

Es sind beide Beispiele richtig wenn auch der Code im zweite Beispiel 
nicht zwingend im Mainloop liegen muss.
Ob Code für das Display im Mainloop liegen muss oder nicht hängt 
letztendlich vom konkreten Programm ab. Als Regel kann man aber sagen: 
Text des Displays, der sich zur Programmlaufzeit nicht ändert, muss 
nicht im Mainloop liegen.

Ich hab den Code mal aus dem Mainloop raus genommen damit es nicht 
weiter zu Verwirrung führt.

Tillmaier schrieb:
> Köntest Du eine Beispielzeile für die Verwendung von Sonderzeichen wie
> Ä, Ü
> geben?

Einfach im Code benutzen und beachten, dass der Compiler entsprechend 
eingestellt ist (vergleiche Makefile Line 114, angegebene Compiler-Flags 
setzen).
1
...
2
  // irgendwo im Code, bei dem Text gedruckt werden soll
3
  lcd_puts_p(PSTR("Wäre doch alles so\r\n"));
4
  lcd_puts_p(PSTR("einfach."));
5
...

von Tillmaier (Gast)


Lesenswert?

Hallo M. K., danke für Deine Erleuterung.
Jetzt läuft alles wie es soll.

von Simon (Gast)


Angehängte Dateien:

Lesenswert?

M. K. schrieb:


Ich habe den code mal hinein kopiert. Jedoch beim compilieren auf 
(ATMega2560) kommen mehrere gleiche Fehler wie auf dem Bild (F_CPU 
undeclared) obwohl definiert oder fehlt da noch was?

von M. K. (sylaina)


Lesenswert?

Wie lautet deine Fehlermeldung genau? Auf den ersten Blick würde ich 
sagen 1 MHz System-Clock und 100 kHz I2C-Clock passen nicht zusammen, da 
müsste das TWBR out of Range gehen.
Vom Atmel Studio hab ich zudem wenig Ahnung, es könnte auch sein, dass 
F_CPU an dieser Stelle noch unbekannt ist, wird da aber gebraucht.

von Simon (Gast)


Angehängte Dateien:

Lesenswert?

M. K. schrieb:
> Wie lautet deine Fehlermeldung genau? Auf den ersten Blick würde
> ich
> sagen 1 MHz System-Clock und 100 kHz I2C-Clock passen nicht zusammen, da
> müsste das TWBR out of Range gehen.
> Vom Atmel Studio hab ich zudem wenig Ahnung, es könnte auch sein, dass
> F_CPU an dieser Stelle noch unbekannt ist, wird da aber gebraucht.

Hier die genaue Fehlermeldung: in jedem File sozusagen

von Simon (Gast)


Lesenswert?

Es kommt mir vor, wie wen file Verknüpfungen nicht existieren jedoch 
vorhanden sind.

von M. K. (sylaina)


Lesenswert?

Wie ich mir schon dachte, TWBR ist außerhalb des zulässigen Bereiches. 
Du musst die erste Fehlermeldung erst mal bearbeiten. Dass F_CPU nicht 
definiert ist, ist ein Folgefehler.

Reduziere einmal F_I2C auf z.B. 40000

von Simon (Gast)


Lesenswert?

M. K. schrieb:
> 40000

Die Frequenz zu verändern auf 40000 hat nichts gebracht. Fehlermeldung 
erscheint immer noch.

von M. K. (sylaina)


Lesenswert?

Dann liegt es wohl doch daran, dass er F_CPU an dieser Stelle nicht 
kennt. Ich kenne mich mit dem Studio leider zu wenig aus, ich arbeite 
mit einem Macintosh.
Was sagt den Google dazu wie man im Studio ein Symbol dem gesamten 
Projekt bekannt machen kann?

EDIT: Schau mal hier, vielleicht hilft es:
Beitrag "define F_CPU in AVR Studio 5, nur wo?"

: Bearbeitet durch User
von Dieter F. (Gast)


Lesenswert?

M. K. schrieb:
> Dann liegt es wohl doch daran, dass er F_CPU an dieser Stelle nicht
> kennt.

Projekt - Properties - AVR/GNU C Compiler - Symbols - "F_CPU=16000000UL"

von Simon (Gast)


Lesenswert?

Das habe ich versucht die Fehler sind nicht mehr da compiliert auch so 
wie sollte. Jedoch bleibt das Display schwarz (Prozessor ATMeaga2560 
16Mhz)
SDA und SCL Pins richtig angeschlossen mit Pull up.

von Dieter F. (Gast)


Lesenswert?

Simon schrieb:
> Das habe ich versucht die Fehler sind nicht mehr da compiliert auch so
> wie sollte. Jedoch bleibt das Display schwarz (Prozessor ATMeaga2560
> 16Mhz)

Stell mal bitte Dein Projekt (komplett) ein.

von Simon (Gast)


Lesenswert?

Dieter F. schrieb:
> Simon schrieb:
>> Das habe ich versucht die Fehler sind nicht mehr da compiliert auch so
>> wie sollte. Jedoch bleibt das Display schwarz (Prozessor ATMeaga2560
>> 16Mhz)
>
> Stell mal bitte Dein Projekt (komplett) ein.

Ich konnte das Problem mit einem neuen Display losen. Weiss nicht wie 
dies so gekommen ist, dass es nicht mehr geht. Sieht super aus und lässt 
sich einiges darstellen. Doch wie schreibt man einen Parameter auf das 
Display z.B. eine sich hochzählende Zahl oder eine Temperatur.

von Stefan F. (Gast)


Lesenswert?

Simon schrieb:
> Doch wie schreibt man einen Parameter auf das
> Display z.B. eine sich hochzählende Zahl oder eine Temperatur.

itoa
ltoa
utoa
ultoa
sprintf

oder etwas selbst gebautes. Man muss dabei nur den ASCII Zeichensatz 
anwenden.
1
int i=5;
2
char c='0'+i;  // ergibt "5"

Auf alles Weitere müsstest du mit Nachdenken, Divisionen und Modulus 
Operator kommen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Stefanus F. schrieb:
> Divisionen und Modulus Operator

Da Division und Modulus eigentlich immer gemeinsam berechnet werden, 
spart man sich eine zusätzliche Operation, wenn man gleich die 
(Standard-)Funktion div() benutzt.

Aber wenn mich nicht Platzgründe dazu zwingen, würde ich nicht ohne Not 
etwas anderes als sprintf() benutzen … das ist schlicht die bequemste 
(und flexibelste) Variante.

von M. K. (sylaina)


Lesenswert?

Simon schrieb:
> Doch wie schreibt man einen Parameter auf das
> Display z.B. eine sich hochzählende Zahl oder eine Temperatur.

Du musst dir im vorfeld überlegen, wieviele Stellen wird die Zahl wohl 
maximal haben. Um einen Wert auf dem Display auszugeben musst du die 
Zahl in eine Zeichenfolge umwandeln, dafür musst du ein char-Array zur 
Verfügung stellen. Je nachdem ob du einen Integer darstellen möchtest 
oder einen Float-Wert gibt es zur Umwandlung unterschiedliche 
Funktionen. Hier mal ein Beispiel wie das in C aussehen kann:
1
#include <stdlib.h>
2
#include "lcd.h"
3
4
int main(void){
5
  char valueToPrint[5]; // char-Array das später die darzustellende Zahl enthalten soll, es muss mindestens so lang sein wie die darzustellenden Stellen plus dem String-Ende-Zeichen \0
6
  uint8_t myInteger = 123;
7
  float myFloat = 1.23;
8
  
9
  lcd_init(LCD_DISP_ON);
10
  lcd_clrscr();
11
  itoa(myInterger,   // Zahl, die umgewandelt werden soll
12
       valueToPrint, // char-Array, dass die Umwandlung aufnehmen soll
13
       10);          // Zahlenbasis, die zur Darstellung benutzt werden soll, hier dezimales System, oktal (8) und hexadezimal (16) ginge auch wenn ich mich recht entsinne
14
  lcd_puts_p(PSTR("Integer: "));
15
  lcd_puts(valueToPrint);
16
  lcd_puts_p(PSTR("\r\n"));
17
  dtostrf(myFloat, // Zahl, die umgewandelt werden soll, kann auch ein Interger sein
18
          4,       // Anzahl der darzustellenden Stellen incl. Komma, Komma ist auch eine Stelle ;)
19
          2,       // Anzahl der Nachkommastellen
20
          valueToPrint); // char-Array, der die Umwandlung aufnehmen soll
21
  
22
  lcd_puts_p(PSTR("Float: "));
23
  lcd_puts(valueToPrint);
24
  for(;;){
25
    // main-loop
26
  }
27
  return 0;
28
}
Hoffe, ich hab in dem Code jetzt keinen Fehler drin, schreib das grade 
vom iPad aus von unterwegs.
Auf dem Diplay sollte dann stehen:

Integer: 123
Float: 1.23

: Bearbeitet durch User
von Peter (Gast)


Lesenswert?

Also ich finde möglichst schnellen und kleinen Code optimal, da ich 
meistens auf einem Controller auch noch andere Dinge tute, als nur das 
Display zu bespaßen...aber das beisst sich mit der Bequemlichkeit, 
welche eine flexible und voller Funktionen steckende Libray bietet. Hier 
einen Kompromiss zu finden ist sicherlich schwer. Ich orientiere mich 
meistens nur daran, was ich konkret an Funktionalität benötige, um die 
Komplexität zu reduzieren, und werfe überflässigen Overhead raus!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter schrieb:
> Also ich finde möglichst schnellen und kleinen Code optimal, da ich
> meistens auf einem Controller auch noch andere Dinge tute, als nur das
> Display zu bespaßen

Das macht ja wohl so ziemlich jeder, wer baut schon ein reines serielles 
Terminal oder sowas?

Meist bringen aber ohnehin andere Randbedingungen (nötige Peripherie 
etc.) einen Controller mit sich, bei dem es gar auf das letzte Kilobyte 
an Flashverbrauch ankommt, weil am Ende noch genügend frei bleibt. Für 
nicht benutzten Flash bekommt man ja kein Geld zurück. ;-)

Allerdings habe ich die genannten OLED-Displays bislang immer (zumindest 
teilweise) grafisch benutzt, da braucht man dann ohnehin die im 
Eingangspost genannten 1 KiB an Display-Puffer (shadow buffer) und damit 
mindestens sowas wie einen ATmega328. Flashnutzung ist dann oft nur bei 
10 oder 20 %.

Wenn man mit einem ATtiny2313 auskommen möchte, sieht das anders aus. 
Andererseits ist der Preisunterschied zwischen einem ATtiny2313 und 
einem ATmega328 so verschwindend gering, dass man schon ziemliche 
Stückzahlen braucht, damit sich der höhere Aufwand lohnt im Vergleich zu 
„Komfort-Funktionen“ mit etwas mehr Flashverbrauch …

von Bernd (Gast)


Lesenswert?

Hallo M. K.

Ich hab mal ne Frage wegen Bitmaps.

Hatte vor ein paar Monaten diese Library ausprobiert, welche nebenbei 
gesagt mal richtig gut ist, und hatte auch ein paar Bitmaps mit dem 
weiter oben geposteten Programm Oledbm.exe generiert und das 
funktionierte ganz gut, auch für dieses Progi ein herzlichen Dank.

Jetzt habe ich die neueste Version der Library compiliert und musste 
feststellen, das sich die draw_bitmaps Funktion um 3 weitere Variablen 
erweitert hat und meine Bitmaps nun nicht mehr korrekt angezeigt werden.

Hab hier ein Bitmap mit 64x64 Pixeln und wenn ich bei Width und Height 
64, 64 angebe gibts nur ein komplett verpixeltes Bild mit der Grösse.

Für einen guten Tip wäre ich sehr dankbar.
Bernd

von Max M. (maxmicr)


Lesenswert?

Besitzt jemand das Font-Array für die längere Version des SSD1306-OLEDs 
(das 128x32 Pixel misst)?
Auf dem 128x64 funktioniert das aktuelle einwandfrei, nur bei dem 
längeren ist die Schrift nicht gut erkennbar.

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Was hat der Font mit der Display-Breite zu tun?

von Max M. (maxmicr)


Angehängte Dateien:

Lesenswert?

Ich dachte, der Font wäre an das Seitenverhältnis des 128x64-Displays 
angepasst.

Welche Gründe könnte es noch haben, dass der Font abgeschnitten 
aussieht?
Das soll "HALLO" heißen.

von Stefan F. (Gast)


Lesenswert?

Ich schätze dass du hier versuchst, Text zwischen zwei Zeilen auszugeben 
und das kann diese Library wohl nicht.

Schreibe den Text mal ganz oben in die äusserste Ecke (ab Position 0,0). 
Wenn das auch nicht geht, wurde der Display Controller wohl falsch 
initialisiert. Da gleiche Problem müsste dann auch mit Linien erkennbar 
sein. Zeichne mal einfach ein großes X quer über das gesamte Display. 
Wird das auch Lückenhaft dargestellt?

Die richtige Initialisierungs-Sequenz kannst du meinem (anderen) 
Quelltext entnehmen: http://stefanfrings.de/esp8266/WIFI-Kit-8-OLED.zip

von Daniel B. (daniel_3d)


Angehängte Dateien:

Lesenswert?

Max M. schrieb:
> Welche Gründe könnte es noch haben, dass der Font abgeschnitten
> aussieht?

Mir sind schon mal Displays mit gebrochenen Ecken geliefert worden. Dort 
sah die Schrift dann ähnlich aus wie bei dir.

von Max M. (maxmicr)


Angehängte Dateien:

Lesenswert?

Stefanus F. schrieb:
> Da gleiche Problem müsste dann auch mit Linien erkennbar
> sein. Zeichne mal einfach ein großes X quer über das gesamte Display.
> Wird das auch Lückenhaft dargestellt?

Ich weiß nicht?

Daniel B. schrieb:
> Mir sind schon mal Displays mit gebrochenen Ecken geliefert worden.

Also die Ecken sind nicht gebrochen, aber im angehängten Foto erkennt 
man, dass das silber Reflektierende im Display gebrochen aussieht. Keine 
Ahnung, ob das so etwas verursachen kann.

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

Bernd schrieb:
> Hallo M. K.
>
> Ich hab mal ne Frage wegen Bitmaps.
>
> Hatte vor ein paar Monaten diese Library ausprobiert, welche nebenbei
> gesagt mal richtig gut ist, und hatte auch ein paar Bitmaps mit dem
> weiter oben geposteten Programm Oledbm.exe generiert und das
> funktionierte ganz gut, auch für dieses Progi ein herzlichen Dank.
>
> Jetzt habe ich die neueste Version der Library compiliert und musste
> feststellen, das sich die draw_bitmaps Funktion um 3 weitere Variablen
> erweitert hat und meine Bitmaps nun nicht mehr korrekt angezeigt werden.
>
> Hab hier ein Bitmap mit 64x64 Pixeln und wenn ich bei Width und Height
> 64, 64 angebe gibts nur ein komplett verpixeltes Bild mit der Grösse.
>
> Für einen guten Tip wäre ich sehr dankbar.
> Bernd

Hm, das muss ich mir mal anschaun, da schau ich morgen mal. Eigentlich 
müsste es funktionieren. Hast du vielleicht etwas Beispielcode?

Max M. schrieb:
> Besitzt jemand das Font-Array für die längere Version des SSD1306-OLEDs
> (das 128x32 Pixel misst)?
> Auf dem 128x64 funktioniert das aktuelle einwandfrei, nur bei dem
> längeren ist die Schrift nicht gut erkennbar.

Hm, wie schon gesagt wurde ist der Font nicht vom Display abhängig. Es 
sieht in der Tat so aus als stimmt irgend etwas mit deinem Display 
nicht. Bei dem "Hallo-Beispiel" sieht es so aus als würde die ein und 
andere Zeile fehlen, bei dem "X-Beispiel" sieht es so aus als würde jede 
zweite Spalte fehlen.

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

Bernd schrieb:
> Hab hier ein Bitmap mit 64x64 Pixeln und wenn ich bei Width und Height
> 64, 64 angebe gibts nur ein komplett verpixeltes Bild mit der Grösse.

Ich habs mir nun mal angeschaut und habe eine Vermutung:

Hast du deinem Bitmap auch das Attribut mitgegeben, dass es im Flash 
liegen bleiben soll? Über den "Fehler" bin ich grad bei mir gestolpert, 
viel mir aber sofort auf weil sich der Pixelsalat unabhängig vom Bild 
nicht änderte ;)
Die lcd_drawBitmap() erwartet das Bitmap nämlich im Flash ;)

Folgender Code sollte mit der aktuellen Library einen Pacmen aufs 
Display malen:
1
//****main.c****//
2
#include "lcd.h"
3
#include <util/delay.h>
4
5
6
const uint8_t PacMen[] PROGMEM=
7
{
8
//127x64  
9
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
10
    ,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
11
    ,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
12
    ,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
13
    ,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
14
    ,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
15
    ,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
16
    ,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
17
    ,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
18
    ,0xff,0xff,0xff,0xff,0xe0,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
19
    ,0xff,0xff,0xff,0xf0,0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
20
    ,0xff,0xff,0xff,0xe0,0x00,0x00,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
21
    ,0xff,0xff,0xff,0xc0,0x00,0x00,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
22
    ,0xff,0xff,0xff,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
23
    ,0xff,0xff,0xfe,0x00,0x00,0x00,0x07,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
24
    ,0xff,0xff,0xf8,0x00,0x00,0x00,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
25
    ,0xff,0xff,0xf8,0x00,0x00,0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
26
    ,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
27
    ,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
28
    ,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
29
    ,0xff,0xff,0xc0,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
30
    ,0xff,0xff,0x80,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
31
    ,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
32
    ,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
33
    ,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
34
    ,0xff,0xfc,0x00,0x00,0x00,0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
35
    ,0xff,0xfc,0x00,0x00,0x00,0x00,0x07,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
36
    ,0xff,0xfc,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
37
    ,0xff,0xfc,0x00,0x00,0x00,0x00,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
38
    ,0xff,0xfc,0x00,0x00,0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
39
    ,0xff,0xfc,0x00,0x00,0x00,0x07,0xff,0xf0,0xff,0x83,0xfc,0x1f,0xf8,0x3f,0xe0,0xff
40
    ,0xff,0xfc,0x00,0x00,0x00,0x0f,0xff,0xf0,0x7f,0x03,0xf8,0x1f,0xf0,0x3f,0xc0,0xff
41
    ,0xff,0xf8,0x00,0x00,0x00,0xff,0xff,0xe0,0x3e,0x03,0xf0,0x1f,0xe0,0x1f,0x80,0xff
42
    ,0xff,0xf8,0x00,0x00,0x01,0xff,0xff,0xe0,0x3e,0x01,0xf0,0x0f,0xe0,0x1f,0x80,0x7f
43
    ,0xff,0xf8,0x00,0x00,0x03,0xff,0xff,0xc0,0x3e,0x03,0xf0,0x1f,0xe0,0x3f,0x80,0xff
44
    ,0xff,0xf8,0x00,0x00,0x03,0xff,0xff,0xe0,0x3e,0x03,0xf0,0x1f,0xe0,0x3f,0x80,0xff
45
    ,0xff,0xf8,0x00,0x00,0x00,0xff,0xff,0xe0,0x7f,0x07,0xf8,0x3f,0xf0,0x7f,0xc1,0xff
46
    ,0xff,0xfc,0x00,0x00,0x00,0x1f,0xff,0xf9,0xff,0xcf,0xfe,0x7f,0xfc,0xff,0xf3,0xff
47
    ,0xff,0xfc,0x00,0x00,0x00,0x07,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
48
    ,0xff,0xfc,0x00,0x00,0x00,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
49
    ,0xff,0xfc,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
50
    ,0xff,0xfc,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
51
    ,0xff,0xfc,0x00,0x00,0x00,0x00,0x07,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
52
    ,0xff,0xfc,0x00,0x00,0x00,0x00,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
53
    ,0xff,0xfe,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
54
    ,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
55
    ,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
56
    ,0xff,0xff,0x80,0x00,0x00,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
57
    ,0xff,0xff,0x80,0x00,0x00,0x00,0x00,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
58
    ,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
59
    ,0xff,0xff,0xe0,0x00,0x00,0x00,0x00,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
60
    ,0xff,0xff,0xf0,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
61
    ,0xff,0xff,0xf8,0x00,0x00,0x00,0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
62
    ,0xff,0xff,0xfc,0x00,0x00,0x00,0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
63
    ,0xff,0xff,0xfe,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
64
    ,0xff,0xff,0xff,0x80,0x00,0x00,0x1f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
65
    ,0xff,0xff,0xff,0xe0,0x00,0x00,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
66
    ,0xff,0xff,0xff,0xf0,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
67
    ,0xff,0xff,0xff,0xff,0x80,0x1f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
68
    ,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
69
    ,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
70
    ,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
71
    ,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
72
    ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
73
};
74
75
int main(void){
76
  lcd_init(LCD_DISP_ON);    // init lcd and turn on
77
  
78
lcd_puts_p(PSTR("BMP-Test"));
79
    lcd_display();
80
    _delay_ms(2000);
81
    lcd_clrscr();
82
#if defined GRAPHICMODE
83
  lcd_drawBitmap(0,0,PacMen, 127, 64,WHITE); // draw bitmap to buffer
84
  lcd_display();                       // send buffer to display
85
#endif
86
  for(;;){
87
    //main loop
88
  }
89
  return 0;
90
}
Einzige Änderung, die ich heute an der lcd_drawBitmap() gemacht habe 
ist, dass nun Bitmaps auch invertiert gezeichnet werden wenn als Color 
nicht WHITE sondern BLACK angegeben wird.

: Bearbeitet durch User
von Adrian E. (ahsd)


Lesenswert?

Bei mir spuckt der Compiler immer folgende Fehlermeldungen aus. Im 
TEXTMODE funktioniert die Ansteuerung trotzdem. Im GRAPHICMODE nicht. 
Was hat das zu bedeuten?
1
lcd.c:91:0: warning: ignoring #pragma mark LCD [-Wunknown-pragmas]
2
 #pragma mark LCD COMMUNICATION
3
 ^
4
Makefile:405: die Regel für Ziel „lcd.o“ scheiterte
5
lcd.c:108:0: warning: ignoring #pragma mark  [-Wunknown-pragmas]
6
 #pragma mark -
7
 ^
8
lcd.c:109:0: warning: ignoring #pragma mark GENERAL [-Wunknown-pragmas]
9
 #pragma mark GENERAL FUNCTIONS
10
 ^
11
lcd.c:252:0: warning: ignoring #pragma mark  [-Wunknown-pragmas]
12
 #pragma mark -
13
 ^
14
lcd.c:253:0: warning: ignoring #pragma mark GRAPHIC [-Wunknown-pragmas]
15
 #pragma mark GRAPHIC FUNCTIONS
16
 ^
17
lcd.c: In function ‘lcd_display’:
18
lcd.c:356:5: error: expected declaration or statement at end of input
19
     lcd_data(&displayBuffer[0][0], DISPLAY_WIDTH*DISPLAY_HEIGHT/8);
20
     ^
21
make: *** [lcd.o] Fehler 1
22
Kompilierung fehlgeschlagen.

von M. K. (sylaina)


Lesenswert?

Die
1
#pragma mark...

Zeilen dienen der Strukturierung in Xcode, sie erleichtern mir ein wenig 
das Navigieren.

Die Fehlermeldung ist merkwürdig, hast die die Library 
verändert/modifiziert? Ein Beispiel wäre sicher gut. Ich hab grade die 
aktuelle Library herunter geladen und in allen Variationen kompiliert 
(nur Graikmode, für SSD1306 und SH1106) und es wird bei mir immer 
fehlerfrei kompiliert. Der AVR-GCC 4.8.1 warnt bei mir nur wegen der 
#pragma marks.

von Adrian E. (ahsd)


Lesenswert?

Ich habe die Library noch mal frisch heruntergeladen, nur das minimalste 
konfiguriert und jetzt kompiliert sie ohne Probleme.

Ich muss nochmal schauen was ich beim letzten Mal falsch gemacht habe..

Danke trotzdem :)

: Bearbeitet durch User
von Adrian E. (ahsd)


Lesenswert?

Moin,

ich habe in der i2c.c heute den Atmega16 hinzugefügt. Im Textmode hat 
das ohne Probleme funktioniert. (Von 1 - 16 MHz) Der Graphicmode spuckt 
allerdings nur einen Block gequirlte Zeichen aus.

Hat jemand eine Idee, wo man da ansetzen müsste?

Liebe Grüße,
Adrian

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Adrian E. schrieb:
> Hat jemand eine Idee, wo man da ansetzen müsste?

Signalqualität messen.

von Adrian E. (ahsd)



Lesenswert?

Stefanus F. schrieb:
> Signalqualität messen.

Alle Einstellungen bis auf F_CPU = 16 MHz und die Erlaubnis, für 
Atmega16 zu kompilieren unverändert zum original Code

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Die Signale steigen im Graphic Mode wesentlich langsamer an, als im Text 
Mode. Man beachte die Form der oberen Spitzen vom SCL Signal. Das ist 
aber komisch.

Normalerwesie hängt das von den Pull-Up Widerständen ab, nicht vom 
Programm. Welche Werte haben deine Pull-Up Widerstände? Ich würde 
ungefähr 2,2k Ohm Empfehlen.

von Adrian E. (ahsd)


Lesenswert?

Stefanus F. schrieb:
> Die Signale steigen im Graphic Mode wesentlich langsamer an, als im Text
> Mode. Man beachte die Form der oberen Spitzen vom SCL Signal. Das ist
> aber komisch.


SORRY! Ich habe einen Flüchtigkeitsfehler gemacht. Ich wollte kürzere 
Kabel verwenden, habe dabei so umgesteckt dass es keine Pull-Ups mehr 
gab.
Ich verwende 10k Pull-Ups. Screenshots tausche ich in einer Minute aus. 
Jetzt sehen die Signale qualitativ gleich aus.

von Stefan F. (Gast)


Lesenswert?

Adrian E. schrieb:
> Jetzt sehen die Signale qualitativ gleich aus.

Ok, dann ist der Fehler wohl doch in der Software zu suchen.

von Adrian E. (ahsd)


Angehängte Dateien:

Lesenswert?

Im Textmode wird ein einziges mal der Bildschirminhalt gesendet, im 
Graphicmode resettet er sich kontinuierlich..

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

Adrian E. schrieb:
> Im Textmode wird ein einziges mal der Bildschirminhalt gesendet, im
> Graphicmode resettet er sich kontinuierlich..

Öhm...das liegt dann aber an deinem Aufbau/Programm. Im Textmode wird 
jedes Zeichen direkt an das Display gesendet, im Graphicmode wird der 
komplette Displayinhalt nur bei Aufruf von lcd_display(); ans Display 
gesendet (dann die kompletten 1024 Bytes).

von RAM Prüfer (Gast)


Lesenswert?

Adrian E. schrieb:
> Im Textmode wird ein einziges mal der Bildschirminhalt gesendet, im
> Graphicmode resettet er sich kontinuierlich..

Reicht denn die RAM-Grösse des Atmega16 aus?
Einfach mal nach dem Kompilieren die Grösse kontrollieren.

von M. K. (sylaina)


Lesenswert?

RAM Prüfer schrieb:
> Reicht denn die RAM-Grösse des Atmega16 aus?
> Einfach mal nach dem Kompilieren die Grösse kontrollieren.

Nur wenn getrickst wird. Ich bin jetzt davon ausgegangen, dass er die 
Lib ein wenig geändert hat. Ist natürlich auch denkbar, dass er gar nix 
an der Lib verändert hat, dann passt das mit dem Graphicmode aber gar 
nicht da man mindestens 1027 Bytes RAM braucht, der Atmega16 aber nur 
1024 Bytes besitzt. Ich muss das mal ändern bei Zeiten sodass man 
zumindest ein Warning erhält.

von RAM Prüfer (Gast)


Lesenswert?

M. K. schrieb:
> Nur wenn getrickst wird.

Ist sowieso Schwachsinn auf so einem kleinen Controller
graphische Dinge zu machen. Was soll das Sinnvolles bringen?

Mir fällt da nix ein ....

von M. K. (sylaina)


Lesenswert?

RAM Prüfer schrieb:
> Ist sowieso Schwachsinn auf so einem kleinen Controller
> graphische Dinge zu machen. Was soll das Sinnvolles bringen?

Wenn er genügend RAM hat, warum denn nicht? Zur Visualisierung? Fiktives 
Beispiel: Multimeter. Man kann eine Digitalanzeige machen, klar. Manch 
einem gefällt aber eine Zeigeranzeige besser. Schwachsinn würde ich das 
also nicht nennen wollen. Da kann es schon ganz schicke Projekte für 
geben.

von RAM Prüfer (Gast)


Angehängte Dateien:

Lesenswert?

M. K. schrieb:
> Da kann es schon ganz schicke Projekte für geben.

Ja, is doch schick wenn der Stack in den Framebuffer reinschreibt.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

RAM Prüfer schrieb:
> M. K. schrieb:
>> Da kann es schon ganz schicke Projekte für geben.
>
> Ja, is doch schick wenn der Stack in den Framebuffer reinschreibt.

Ist noch ausbaufähig: welche Stackbelegung liefert einen schönen 
QR-Code? :.)

von Adrian E. (ahsd)


Lesenswert?

M. K. schrieb:
> RAM Prüfer schrieb:
>> Reicht denn die RAM-Grösse des Atmega16 aus?
>> Einfach mal nach dem Kompilieren die Grösse kontrollieren.
>
> Nur wenn getrickst wird. Ich bin jetzt davon ausgegangen, dass er die
> Lib ein wenig geändert hat. Ist natürlich auch denkbar, dass er gar nix
> an der Lib verändert hat, dann passt das mit dem Graphicmode aber gar
> nicht da man mindestens 1027 Bytes RAM braucht, der Atmega16 aber nur
> 1024 Bytes besitzt. Ich muss das mal ändern bei Zeiten sodass man
> zumindest ein Warning erhält.

Danke für die Antworten! Nein ich gebe zu, ich habe erst mal gar nichts 
an der Library geändert. Mir war nicht bewusst dass der ATMega16 
aufgrund des zu kleinen RAM gar nicht dafür geeignet ist. Dann werde ich 
auf diesem Controller nur den Textmode verwenden.

von M. K. (sylaina)


Lesenswert?

Adrian E. schrieb:
> Danke für die Antworten! Nein ich gebe zu, ich habe erst mal gar nichts
> an der Library geändert. Mir war nicht bewusst dass der ATMega16
> aufgrund des zu kleinen RAM gar nicht dafür geeignet ist. Dann werde ich
> auf diesem Controller nur den Textmode verwenden.

Der Atmega32 hätte wieder genug RAM auch für den Graphicmode und ist IMO 
pinkompatibel zum Atmega16 ;)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

M. K. schrieb:
> Der Atmega32 hätte wieder genug RAM auch für den Graphicmode und ist IMO
> pinkompatibel zum Atmega16 ;)

ATmega644 und 1284 sind auch pinkompatibel, allerdings nicht mehr 
Code-kompatibel (nicht einmal auf Sourcecodeebene komplett).

von oberallgeier (Gast)


Lesenswert?

M. K. schrieb:
> Noch eine kleine Änderung eingefügt ..
> normaler Größe und doppelter Größe gleichzeitig ...
> .. Lib .. zum Download bereit.

Perfekt, prima, vielen Danke, vor allem für die saubere Bereitstellung 
des Codes. Es klappte bei mir auf Anhieb auf nem 1306 (NEIN :-/ - erst 
nachdem ich die richtige Adresse eingefügt hatte), siehe unten. Ich bin 
begeistert.  Bisher hatte ich das als lausiger C(äh)Programmierer nur 
sehr bescheiden mit veröffentlichten Codes in cpp hinbekommen. Aber nun 
:
https://dl.dropbox.com/s/igqyyhpnnvajayz/oled_4217-50%25.jpg?dl=0

Nun war ich zwei Tage dran den Code von DoubleSize auf 4fachSize zu 
bemühen - wegen drei, vier Zahlen irgendwo mittendrin in meinem archie. 
Aber da finde ich mich nicht wirklich zurecht. Gibts so etwas, jetzt 
oder zukünftig?

Nochmal herzlichen Dank für Dein Projekt

grüßt der
oberallgeier
(aus dem obern Allgäu)

von Walter J. (oberallgeier)


Lesenswert?

Sorry, war nicht angemeldet.
Beste Grüße

von M. K. (sylaina)


Lesenswert?

Zukünftig gibts sowas vielleicht mal, derzeit mangelt es mir aber ein 
wenig an der Zeit. Ich hab einfach zu viele andere Projekte noch am 
laufen die erst mal fertig werden müssen ;)

von oberallgeier (Gast)


Lesenswert?

M. K. schrieb:
> .. vielleicht mal .. zu viele andere Projekte ..
> .. die erst mal fertig werden müssen ;)
Ach ja, kenne ich. Sowas gibt sich wohl nie (nicht mal bei mir als 
Rentner).

Danke für die schnelle Antwort.

von Jan H. (janiiix3)


Lesenswert?

Moin,

ich klinke mich hier mal mit ein..
Hat jemand schon mal den "Effekt" gehabt das sich der Bildschirminhalt 
nach unbestimmter Zeit einfach mal um 180° dreht? Oder das die oberste 
Zeile einfach mal ein Stück weit unten wieder raus kommt?

von M. K. (sylaina)


Lesenswert?

Wahrscheinlich ist der Text, den du auf das Display ausgeben willst, zu 
groß so dass der Speicher quasi überläuft. Diesbezüglich sind in der 
Library nur wenig Überprüfungen implementiert.

Hast du vielleicht Beispiel-Code der die Fehler zeigt? Dann kann ich mal 
schauen ob ich das raus gefixt bekomme.

von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

M. K. schrieb:
> Wahrscheinlich ist der Text, den du auf das Display ausgeben willst, zu
> groß so dass der Speicher quasi überläuft. Diesbezüglich sind in der
> Library nur wenig Überprüfungen implementiert.
>
> Hast du vielleicht Beispiel-Code der die Fehler zeigt? Dann kann ich mal
> schauen ob ich das raus gefixt bekomme.

Also der Fehler ist nach wie vor noch da.. :(
Anbei mal meine Lib für den "SSD1306"..
Vielleicht findest Du ja was.

von M. K. (sylaina)


Lesenswert?

Ach, das ist ja gar nicht meine Lib. Ich dachte du benutzt meine Lib.

Was mir bei deiner verwendeten Lib auffällt ist z.B. dass es egal ist wo 
x und y liegt, so ein Display hat ja idR 128*64 Pixel Größe, bei der Lib 
hindert mich aber nichts daran auch bei x > 128 und y > 64 was zu 
zeichnen.

Ist hier im Thread etwas OT aber wie schon gesagt, es kommt einfach auch 
drauf an wohin du im RAM des Displays was reinschreibst und wie sich 
dann die Displays verhalten. Genaueres steht im Datenblatt, das ist echt 
etwas umfangreich, z.B. kennt das SSD1306 einen automatischen 
Zeilenumbruch, man muss also nichts dazu tun um einen Zeilenumbruch zu 
erwirken. Meine Lib ist allerdings so aufgebaut dass man hierbei nicht 
vom automatischen Zeilenumbruch des SSD1306 profitieren kann. Sinn 
dahinter war/ist dass die Befehle dann für das SH1106, dass keinen 
automatischen Zeilenumbruch kennt, die selben sind. ;)

von Paul (Gast)


Lesenswert?

Hallo Gemeinde
habe den Artikel gelesen, tolle Sachen dabei. Habe aber ein Problem 
damit. Ihr geht vom SSD1306 und einem Display von 0,96`` aus. Moderne 
bzw. andere Displays haben den SSD1309 drin. Der kling ähnlich. Wie weit 
ist er ähnlich? Kann ich die Libs einfach für ein grösseres Display 
nutzen? Sicher muss ich was dazu anpassen. Die Displays haben 128x64.
LG Paul

von Stefan F. (Gast)


Lesenswert?

Vergleiche die Datenblätter der beiden Chips. Da steht drin, wie sie 
funktionieren und initialisiert werden sollen.

von Paul (Gast)


Lesenswert?

Das sieht nicht so gut aus mit deinem Hinweis. Da ich alles in C mache 
konnte ich keinerlei Info dazu finden

von Au Weia (Gast)


Lesenswert?

Paul schrieb:
> Das sieht nicht so gut aus mit deinem Hinweis.

Das sieht nicht so gut aus mit deinem Vorhaben. Du bist
zu faul zum Lesen des Datenblatts.

von Stefan F. (Gast)



Lesenswert?

Das hat doch mit der Programmiersprache nicht zu tun. Zur 
Initialisierung muss eine Folge von Kommandos (das sind einfache Zahlen, 
teils mit Pausen dazwischen) an den Controller gesendet werden.

Diese Sequenzen sind im Datenblatt des Displays in Form von 
Flussdiagrammen dargestellt. Jedes einzelne Kommando ist im Datenblatt 
des Controllers beschrieben.

Zu prüfen wäre aber auch, ob der Bildspeicher anders organisiert ist.

Ich habe mal die Doku von einem 0,96" SSD1306 Display angehängt.

von Heinzi(Gast) (Gast)


Lesenswert?

Der gute Paul(Gast) will eine mundgerechte Lösung in C und hat keine 
Lust, sich durch den Datenblattwust zu kämpfen ;-)

von Stefan F. (Gast)


Lesenswert?

Wenn ich das kann, dann er das auch. Denn bin schon ziemlich faul.

von M. K. (sylaina)


Lesenswert?

Heinzi(Gast) schrieb:
> Der gute Paul(Gast) will eine mundgerechte Lösung in C und hat
> keine
> Lust, sich durch den Datenblattwust zu kämpfen ;-)

Wer hat schon Lust sich durch den Datenblattwust zu kämpfen. Ich würde 
auch erstmal schaun obs nicht was Mundgerechtes gibt ;)

von Paul (Gast)


Lesenswert?

Mit der Faulheit kann man geteilter Meinung sein. Habe das Datenblatt 
angeschaut und versucht es zu verstehen. Ab einem Punkt bin ich 
gescheitert, war zu viel für mich.
Das mit Flussdiagramm habe ich gesehen. Habe auch schon versucht etwas 
umzusetzen. Es gibt einige Anfänge dazu. Sind zu kaotisch um sie zu 
zeigen. Leider ohne Erfolg. Im Datenblatt des Herstellers ist auch eine 
Routine dazu drin. Bin am entschlüsseln was wozu ist.
Beim SSD1306 ist ja auf eine andere Grösse bezogen. Wollte es eigentlich 
als Grundstein für des SDD1309 nehmen. Einiges scheint zu passen anderes 
nicht.

von Jan L. (ranzcopter)


Lesenswert?

Paul schrieb:
> Mit der Faulheit kann man geteilter Meinung sein. Habe das Datenblatt

In der Tat; wenn ein Display nur Mittel zum Zweck sein soll, täte ich 
mich „sogar“ nach was Vorhandenem umschauen, z.B. die Uglib2, oder 
Sparkfun 
https://github.com/sparkfun/HyperDisplay_SSD1309_ArduinoLibrary.

Würde  ich eine Lib erweitern oder ergänzen wollen, würde ich mir 
sicherlich zuerst die Init-Routinen vorhandener Libs (s.o.) anschauen...


> angeschaut und versucht es zu verstehen. Ab einem Punkt bin ich
> gescheitert, war zu viel für mich.
> Das mit Flussdiagramm habe ich gesehen. Habe auch schon versucht etwas
> umzusetzen. Es gibt einige Anfänge dazu. Sind zu kaotisch um sie zu
> zeigen. Leider ohne Erfolg. Im Datenblatt des Herstellers ist auch eine
> Routine dazu drin. Bin am entschlüsseln was wozu ist.
> Beim SSD1306 ist ja auf eine andere Grösse bezogen. Wollte es eigentlich
> als Grundstein für des SDD1309 nehmen. Einiges scheint zu passen anderes
> nicht.

von Paul (Gast)


Lesenswert?

Jan L. schrieb:
> Sparkfun
> https://github.com/sparkfun/HyperDisplay_SSD1309_ArduinoLibrary.

Danke, hat schon was gebracht. Die Stelle kannte ich noch nicht

von Reinhard O. (Firma: privat) (flug52)


Lesenswert?

Wer hat schon Lust sich durch den Datenblattwust zu kämpfen. Ich würde
auch erstmal schaun obs nicht was Mundgerechtes gibt ;)

Niemand muß doch einen Beitrag schreiben, wenn er es nicht möchte, lässt 
er es eben. Wenn er etwas anfängt, wäere es schön, es zu vollenden (ohne 
dass das in Stress ausartet, natürlich). Nicht jeder ist in der Lage, 
das Datenblatt umzusetzen. Die Lebenszeit ist endlich. Wenn jeder 
Erdenbürger bei Null, in der Urzeit anfangen wollte, alles dagewesene 
neu zu erfinden, wird nichts fertig oder besser wie das dagewesene. So 
eine Lib ist eben meist nur Teil eines Ganzen. Ein Baubetrieb setzt auch 
Fertigzement ein und brennt ihn nicht selber. Der Baumensch ist deshalb 
nicht faul. So geht eben Fortschritt.
Der Autor der Lib sollte natürlich immer genannt werden. Sein Lohn ist 
es, als Berühmtheit in die Geschichte einzugehen.
Gruß
Reinhard

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

Paul schrieb:
> Hallo Gemeinde
> habe den Artikel gelesen, tolle Sachen dabei. Habe aber ein Problem
> damit. Ihr geht vom SSD1306 und einem Display von 0,96`` aus. Moderne
> bzw. andere Displays haben den SSD1309 drin. Der kling ähnlich. Wie weit
> ist er ähnlich? Kann ich die Libs einfach für ein grösseres Display
> nutzen? Sicher muss ich was dazu anpassen. Die Displays haben 128x64.
> LG Paul

Ich hab mich jetzt ein wenig damit beschäftigt und mir auch mal ein 
SSD1309-Display beschafft. Das erste, dass mir auffiel ist, dass das 
Display standard-mäßig für SPI konfiguriert ist. Meine Library geht aber 
von einem I2C-Bus aus, an dem das Display klemmt.
Ich hab mal noch ein wenig aufgeräumt im Code, will nun mal schaun wie 
ich das Ganze umschreiben kann sodass es auch mit SPI läuft. Man kann 
die SSD1309-Displays anscheinend auch an I2C betreiben, ich bekomme 
meins da aber nicht an den Start. Das Suchen nach der I2C-Adresse 
schlägt bei mir immer wieder fehl. Und ja, ich hab auch die Widerstände 
umgelötet, das Reset-Signal geschickt und CS auf GND gepinnt.
Vom Programmaufruf/-ablauf an sich scheinen SSD1306 und SSD1309 
identisch zu sein, ich konnte beim Überfliegen der Datenblätter 
diesbezüglich keine Unterschiede feststellen, d.h. wenn man die 
Kommunikation auf SPI umschreibt müsste auch ein SSD1309-Display mit der 
Library funktionieren.

von M. K. (sylaina)


Lesenswert?

Ich bin dazu gekommen zu testen und hab meine Library mal von I2C auf 
SPI umgeschrieben (nur rudimentär zum testen). Damit lässt sich dann, 
wenn die Library auf SSD1306-Displays eingestellt ist, auch ein 
SSD1309-Display ansteuern. Das funktioniert. Mal schaun ob ich die Tage 
dazu komme, die Library ganz allgemein auf SPI umzuschreiben sodass man 
zwischen I2C und SPI wählen kann.

von M. K. (sylaina)


Lesenswert?

Die Github-Version ist nun erweitert und kann ab sofort die Displays 
auch via SPI ansprechen und unterstützt nun auch 
SSD1309-Displaycontroller ;)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

M. K. schrieb:
> unterstützt nun auch SSD1309-Displaycontroller

Soll ich dir das mal in der Überschrift ergänzen?

von M. K. (sylaina)


Lesenswert?

Jörg W. schrieb:
> M. K. schrieb:
>> unterstützt nun auch SSD1309-Displaycontroller
>
> Soll ich dir das mal in der Überschrift ergänzen?

Oh, das wäre sehr gut. Danke dir, Jörg ;)

von Äd Franzis (Gast)


Lesenswert?

Hallo Sylaina,


herzlichen Dank, wirklich eine tolle Arbeit.

Ist die Lib auch für ESP32 verwendbar? Bzw., wird es eine Anpassung 
geben?
Aktuell verwende ich die U8g2lib.h, aber ich bekomme es nicht in den 
Griff, dass immer beim Überschreiben die Zeichen nicht komplett 
überschrieben werden  (z.b. wenn 0 mit 1 überschrieben wird, bleiben am 
linken Rand des Zeichens Punkte stehen). Dies tritt z.B. bei einer 
Uhrzeitausgabe auf.
Erhoffe mir, dass das Problem bei deinem Verfahren nicht auftritt.


MfG.
Äd

von M. K. (sylaina)


Lesenswert?

Hallo Äd Franzis,

die Library kann mit Anpassungen auch beim ESP verwendet werden. Hierzu 
musst du lediglich die Kommunikations-Funktionen in lcd_data, 
lcd_command und lcd_init anpassen.
Ich selbst habe noch keinen ESP und es wird bei mir dieses Jahr auch 
kein ESP mehr ins Haus kommen. Grund dafür ist, dass ich noch einige 
andere Baustellen habe und mir keine weitere aufmachen will. Es liegt 
also nicht daran, dass ich den ESP doof finde, mir fehlt es schlicht nur 
an Zeit. ;)

Zu deinem Problem:

Die U8G2lib ist eigentlich sehr gut (leider auch sehr umfangreich 
weshalb ich diese Lib nur für SSD1306/SSD1309/SH1106 schrieb). Ich denke 
also, dass dein beobachteter Fehler nicht von der Lib herrührt sondern 
von deinem Code. Ich kann dir daher empfehlen, dir deinen Code noch mal 
genau anzuschaun und auf einem Blatt Karo-Papier und Bleistift mal die 
Zeichenfunktionen gemäß dem Code durchzuspielen. Ich denke dann wirst du 
den Fehler entdecken ;)

Grüße

Michael

von Äd Franzis (Gast)


Lesenswert?

Vielen Dank, Michael, für deine Informationen.

Viel Code ist da ja nicht, da ich ausschließlich Text ausgeben. Habe 
mich an einem "Hallo Welt"-Beispiel orientiert.
Ich verwende das Board "WIFI_Kit_32  HTIT-WB32" von Heltec. Darauf 
enthalten ist ein 0.96'' 128*64 Display, das über I2C angeschlossen ist.

Hier mal die relevanten Code-Fagmente (alles, was mit dem OLED zu tun 
hat):
1
/*
2
 * BEGIN OF DECLARATIONS from 0.92'' OLED
3
*/
4
5
#include <Arduino.h>
6
#include <U8g2lib.h>
7
8
9
// the OLED used
10
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ 15, /* data=*/ 4, /* reset=*/ 16);
11
12
/*
13
 * END  OF DECLARATIONS from 0.92'' OLED (128x64)
14
*/
15
16
const char *pSW_Version = "v1.0.0.01";
17
18
void DisplayTime() {
19
  //wird alle 500ms von loop() aufgerufen
20
  char buf[12];
21
22
23
  snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
24
           hour(), minute(), second());
25
  u8g2.drawStr(6*9,43,buf);   
26
  u8g2.sendBuffer();                  
27
28
}  //END OF DisplayTime()
29
30
void DisplayDate() {
31
32
  //wird einmalig nach Setzen der Uhr und jew. um Mitternacht in loop() aufgerufen
33
34
  String sWeek_day[8] = {"Mon.,  ", "Dien., ", "Mitt., ", "Donn., ", 
35
                         "Frei., ", "Sams., ", "Sonn., ", "??tag, "};
36
37
  date_th    date;
38
  date_th*   p_date =&date;
39
40
41
  p_date->day      =(uint8_t)day();
42
  p_date->month    =(uint8_t)month();
43
  p_date->year     =(uint16_t)year();
44
  p_date->week_day =(uint8_t)weekday();
45
  Date_Calc_Calweek(p_date);  //calender week and leap year calculation
46
47
  char buf[50];
48
49
  snprintf(buf, sizeof(buf), "%s %02d.%02d.%04d",
50
           sWeek_day[(int)p_date->week_day], p_date->day, p_date->month, p_date->year);
51
52
  
53
  u8g2.drawStr(0,32,buf);   
54
  u8g2.sendBuffer();                  
55
56
  snprintf(buf, sizeof(buf), "WD: %1d CW: %2d LJ: %1d",
57
                                    p_date->week_day,
58
                                    p_date->calweek,
59
                                    p_date->leapjear);
60
61
 
62
 u8g2.drawStr(0,54,buf);   
63
 u8g2.sendBuffer();  
64
  
65
}  //END OF DisplayTime()
66
67
68
69
void setup() {
70
  
71
/*
72
 * BEGIN OF SETUP() from 0.92'' OLED
73
*/
74
  u8g2.begin();
75
  
76
  u8g2.clearBuffer();                 // clear the internal memory
77
  u8g2.setFont(u8g2_font_ncenB08_tr); // choose a suitable font  oder u8g2_font_helvB08_tr
78
  u8g2.setFontMode(0);
79
  u8g2.drawStr(0,10,pSW_Version);      // write something to the internal memory
80
  u8g2.sendBuffer();                  // transfer internal memory to the display
81
/*
82
 * END OF SETUP() from 0.92'' OLED
83
*/
84
85
86
//[... ... ... ...]
87
88
  String s0 =WiFi.localIP().toString();
89
  
90
  u8g2.drawStr(0,21,s0.c_str());   
91
  u8g2.sendBuffer(); 
92
93
//[... ... ... ...]
94
95
}

Problem: Wenn z.B. 1 auf 0 und 7 auf 6 folgt bleiben bei der 1 links 
Punkte von der 0 und bei der 7 rechts Punkte von der 6 über. Ganz wild 
sieht es aus, wenn die Wochentage überschrieben werden. Das ist dann gar 
nicht mehr lesbar.


Vielen Dank.
MfG.
Äd

von M. K. (sylaina)


Lesenswert?

Wenn ich das richtig sehe löschst du nie den Zeichenbuffer sondern 
überschreibst ihn einfach. Das ist dein Problem: Wenn im neuen String 
ein Pixel aus sein soll, im alten aber ein Pixel an ist dann wird dieser 
Pixel nicht ausgeschaltet. Am besten immer erst mal den Zeichenbuffer 
löschen und dann neu reinschreiben, so wie das im Setup ja auch gemacht 
wird ;)

von Äd Franzis (Gast)


Lesenswert?

Hallo Sylaina,


herzlichen Dank, das ist ein ganz wichtiger Hinweis.

Das heißt dann aber auch, ich kann immer nur den kompletten 
Display-Bereich schreiben, oder wie? Ich habe jezt SW-Version und IP in 
der initialisierung Datumsangaben nur um Mitternacht und die Uhrzeit 
halt alle 500ms geschrieben. Ich dachte, es ist effizienter, als immer 
alles zu beschreiben. So habe ich es immer beim LCD-Display gemacht.

Oder kann ich auch einen Teil des Buffers löschen, also immer die Zeile, 
die ich auch neu beschreibe will.

Oder anders gefragt: Wird eh jedesmal mit u8g2.sendBuffer() der gesamte 
Buffer geschickt, d.h. immer die gleiche Datenmenge. Dann würde ich 
natürlich  durch mein vorgehen eh nichts sparen.

MfG.
Äd

von M. K. (sylaina)


Lesenswert?

Äd Franzis schrieb:
> Wird eh jedesmal mit u8g2.sendBuffer() der gesamte
> Buffer geschickt, d.h. immer die gleiche Datenmenge.

Ja, wird es. u.a. deshalb habe ich die Library entwickelt, im Textmode 
ist meine Library erheblich schneller als die u8g-Library da ich im 
Textmode nur an der Stelle ins Display schreibe, in der ich Daten ändern 
will, und nicht den gesamten Displayinhalt neu beschreiben muss.

von Äd Franzis (Gast)


Lesenswert?

Hallo Sylaina,


vielen Dank. Dann schließt sich jetzt der Kreis und ich komme wieder zu 
der Frage:

Äd schrieb:
> Ist die Lib auch für ESP32 verwendbar? Bzw., wird es eine Anpassung geben?

und:
Äd schrieb:
> Erhoffe mir, dass das Problem bei deinem Verfahren nicht auftritt.

Ist denn bei deiner Lib auch das Problem, dass ich trotzdem den ganzen 
Buffer vor dem Überschreiben löschen muss? Oder kann ich auch 
zeilenweise löschen und nicht nur schreiben.


MfG.
Äd

von Hugo H. (hugohurtig1)


Lesenswert?

Äd Franzis schrieb:
> Oder kann ich auch
> zeilenweise löschen und nicht nur schreiben

Jein - Du kannst zeilenweise Leerzeichen reinschreiben und dann das, was 
Du dort sehen willst.

von M. K. (sylaina)


Lesenswert?

Äd Franzis schrieb:
> Dann schließt sich jetzt der Kreis und ich komme wieder zu
> der Frage:

Die hatte ich schon beantwortet: Ja, du musst nur die lcd_command, 
lcd_data und lcd_init bzgl. der Kommunikation für den ESP anpassen ;)

Äd Franzis schrieb:
> Ist denn bei deiner Lib auch das Problem, dass ich trotzdem den ganzen
> Buffer vor dem Überschreiben löschen muss?

Im Grafikmode: Jain (du müsstest mit meiner Lib den Bereich löschen, der 
neu beschrieben werden soll).
Im Textmode: Nein, da gibts keinen Buffer, da wird direkt ins Display 
geschrieben.

von Bob H. (bob3150)


Lesenswert?

Hallo,

ich hoffe hier kann mir jemand bei meinem Anliegen helfen, ich möchte 
ein OLED-Display als Statusanzeige (wie die serielle Console von 
Arduino) benutzen und würde immer gerne die letzen 7 Zeilen anzeigen. 
Mit folgendem Code werden die ersten 7-Zeilen angezeigt, aber der Rest 
wird nicht mehr angezeigt!
1
display.println("Statustext");
2
display.display();

Bitte um dringende Hilfe!

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Bob H. schrieb:
> Bitte um dringende Hilfe!

Bitte einen eigenen Thread in "Microcontroller + Elektronik" öffnen.

Bitte Netiquette beachten, insbesondere viel mehr Details zu deinem 
Problem schreiben.

von Äd Franzis (Gast)


Lesenswert?

Hallo M.K.


M. K. schrieb:
> Die hatte ich schon beantwortet: Ja, du musst nur die lcd_command, lcd_data und 
lcd_init bzgl. der Kommunikation für den ESP anpassen ;)
ups, stimmt, hattest du schon beantwortet. Vor lauter, lauter...
Werde mir das später mal anschauen, ob ich das anpassen kann. Bin auch 
erst Einsteiger. Wenn nur die digitalen Ausgänge anzupassen, wäre das ja 
schnell gemacht, aber I2C direkt ansteuern habe ich bisher noch nicht 
gemach. Würde dann schon gerne deine schlanke lib verwenden.


Hallo Hugo

Hugo H. schrieb:
> Jein - Du kannst zeilenweise Leerzeichen reinschreiben und dann das, was Du dort 
sehen willst.
Bei der U8g2lib genügt das leider nicht. Ich hab's probiert; Ergebnis 
ist unverändert. Es bleiben also immer noch einzelne Pixel stehen. 
Vermute, auch das Leerzeichen ist quasi transparent. Man müsste ein 
schwarzen Leerzeichen haben.
Habe nun auf die U8x8lib gewechselt, da funzt es genau so, wie du sagst. 
Aber dann passen immer nur 16 Zeichen in einer Zeile. Schade, aber OK.

Im Moment läuft die OLED-Ausgabe mal zufriedenstellend. Wäre schön, wenn 
ich die LIB aus diesem Thread hier für ESP umschreiben kann. Ansonsten 
werde ich später doch wieder zur U8g2lib  zurückkehren, und dann jeweils 
vor'm Schreiben einer Zeile die Pixel mit einem schwarzen Rechteck 
"löschen".
Ich lasse es euch wissen, wird aber etwas dauern.

Herzlichen Dank euch allen.


Liebe Grüße,
Äd.

von M. K. (sylaina)


Lesenswert?

Äd Franzis schrieb:
> lcd_init bzgl. der Kommunikation für den ESP anpassen ;)
> ups, stimmt, hattest du schon beantwortet. Vor lauter, lauter...
> Werde mir das später mal anschauen, ob ich das anpassen kann. Bin auch
> erst Einsteiger. Wenn nur die digitalen Ausgänge anzupassen, wäre das ja
> schnell gemacht, aber I2C direkt ansteuern habe ich bisher noch nicht
> gemach. Würde dann schon gerne deine schlanke lib verwenden.

Das muss man sich nur einmal an einem ruhigen Nachmittag anschaun, dann 
sieht man recht zügig, dass I2C doch eigentlich schon mega einfach ist 
was u.a. den Charme von dieser Schnittstelle aus macht. Also keine 
Furcht davor ;)

von Äd Franzis (Gast)


Lesenswert?

Hallo M. K.

M. K. schrieb:
> Also keine Furcht davor ;)
Danke für's Mutmachen. :)


Ja, schaue es mir gerne an. Habe vorher noch ein paar andere Steine aus 
dem Weg zu rollen (das OLED ist nicht die einzige Baustelle), aber dann 
wird dieser Nachmittag mal kommen. Vielleicht komme ich dann aber auch 
nochmal mit 'ner Frage hierher. Denke, dass dann dein LIB auch für 
andere ESP-User von Nutzen sein wird.


Liebe Grüße,
Äd.

von Rüdiger S. (ruediger9)


Angehängte Dateien:

Lesenswert?

Beitrag "Re: SSD1306 Library zum Darstellen von Text auf OLED Displays"

Wegen einer Nachfrage habe ich das OledBm-Tool zum Generieren des 
C-Codes noch erweitert. Es kann jetzt zusätzlich auch noch den Binärcode 
als Datei rausschreiben. Für eine 128x64 Bitmap wird also eine 1.024 
Byte große Datei erstellt.

Zudem noch der Sourcecode dazu, ist C# und z.B. mit VS 2019 
kompilierbar.

von Daniel I. (Gast)


Lesenswert?

Hallo Sylaina,
Diese Library ist der Hammer. Ich bin Anfänger und fand mich gut 
zurecht! Wirklich ausgezeichnete Arbeit. Was mich sehr freuen würde, 
wäre eine Funktion für das Ausgeben von einer Zahl und Zahlen mit 
Kommastellen. Ich dachte zuerst das ich einfach anstelle einen Text auch 
eine Variabel nehemen könnte. Aber dies funktionierte nur ein mal 
leider. Dan wird die Zahl nicht mehr aktualisiert. Dan habe ich ein 
wenig herumprobiert aber musste schlussendlich aufgebe. Mit meinen 
Kentnissen konnte ich das nicht bewältigen. Wäre somit der Hammer wen 
die Library um diese Funkton erweitert werden könnte.

Mit freundlichen Grüssen

Daniel

von Stefan F. (Gast)


Lesenswert?

Daniel I. schrieb:
> Was mich sehr freuen würde,
> wäre eine Funktion für das Ausgeben von einer Zahl und Zahlen mit
> Kommastellen.
1
char puffer[5];
2
sprintf(puffer, "%0.2f", 0.99);
3
lcd_puts(puffer);

https://www.tutorialspoint.com/c_standard_library/c_function_sprintf.htm

Achtung: Der Puffer muss mindestens ein Zeichen größer sein, als die 
längste erwartete Textausgabe. Das heisst in diesem Fall, dass die Zahl 
im Bereich 0.00 bis 9.99 liegen muss, sonst gibt es einen 
Speicher-Überlauf.

von M. K. (sylaina)


Lesenswert?

sprintf ist die eine Möglichkeit.

Für Integer gibt es z.B. itoa(), für Fließkomma benutze ich dtostrf():
1
...
2
#include <stdlib.h> // benoetigt fuer itoa() und dtostrf()
3
...
4
int main(void){
5
  ...
6
  char valueAsString[5];
7
  ...
8
  // einen Integer in einen String wandeln
9
  itoa(123,
10
       valueAsString,
11
       10);
12
  // einen float/double in einen String wandeln
13
  dtostrf(1.23,
14
          4,    // Anzahl der Stellen incl. Komma
15
          2,    // Anzahl der Nachkommastellen
16
          valueAsString);
17
   ...
18
   // und auf dem LCD ausgeben 
19
   lcd_prints(valueAsString);
20
   #ifdef GRAPHICMODE
21
   lcd_display();
22
   #endif
23
   ...

Um genauer sagen zu können, wo es bei dir klemmt, Daniel, müsste man den 
Code sehen.

: Bearbeitet durch User
von Begeisterter (Gast)


Lesenswert?

Hallo!

Frage zum Verwenden von 128 X 32 Oleds (also die Kleinen).

funktioniert das mit der gegebenen Library schon (Wenn ja einfach diesen 
Beitrag ignorieren)? Ansonsten habe ich da eine sehr einfache Lösung. Es 
muss lediglich in der Initalisierung was geändert werden, ansonsten 
bleibt alles gleich...

von Begeisterter (Gast)


Lesenswert?

Nachtrag: Ich meine die SSD1306 displays mit 128X32

von Begeisterter (Gast)


Lesenswert?

Hier kurz die Änderung:

In der Initialiserungssequenz muss folgendes abgeändert werden:

Von derzeit:
0xDA, 0x12,      // Set com pins hardware configuration

Auf:

0xDA, 0x02,      // Set com pins hardware configuration

zudem muss dann natürlich noch in den DEFINES der Wert für 
DISPLAY_HEIGHT entsprechend auf 32 geändert werden.

von M. K. (sylaina)


Lesenswert?

Begeisterter schrieb:
> Hier kurz die Änderung:
>
> In der Initialiserungssequenz muss folgendes abgeändert werden:
>
> Von derzeit:
> 0xDA, 0x12,      // Set com pins hardware configuration
>
> Auf:
>
> 0xDA, 0x02,      // Set com pins hardware configuration
>
> zudem muss dann natürlich noch in den DEFINES der Wert für
> DISPLAY_HEIGHT entsprechend auf 32 geändert werden.

So schaut es aus ;)

von Bernhard65 (bernhard65)



Lesenswert?

Hallo Sylaina,
ich möchte dir zuerst mal Danken für die tolle Lib und zweites noch eine 
Rückmeldung zur Verwendung mit einem OLED 0,91" 128x32 Display geben.

Angeschlossen habe ich das ganze an einem Arduino Nano zuerst mit der 
bekannten Adafruit_SSD1306 und der Adafruit-GFX-Library.
Das Display funktioniert da ja soweit ganz gut jedoch 'fressen' mir die 
beiden Lib's in meinem Projekt den restlichen Speicher auf.
Da ich aber eh nur Textausgaben machen will, würde mir deine Lib sehr 
helfen.
Jedoch ist die Darstellung so nicht zu gebrauchen (siehe Image1). Sieht 
alles irgendwie zu klein aus und in die untere Hälfte verschoben.
In der LCD.h habe ich folgende Werte angepasst:
1
  /* TODO: define bus */
2
#define I2C          // I2C or SPI  
3
#define SSD1306       // SH1106 or SSD1306, check datasheet of your display
4
#define TEXTMODE      // TEXTMODE for only text to display,
5
#define FONT     ssd1306oled_font  // set font here, refer font-name at font.h/font.c
6
#define LCD_I2C_ADR  (0x78 >> 1)   // 7 bit slave-adress without r/w-bit
Als kleines Testprogramm habe ich nur folgende Zeilen:
1
#include <font.h>
2
#include <i2c.h>
3
#include <lcd.h>
4
5
void setup() {
6
    
7
    lcd_init(LCD_DISP_ON);
8
    lcd_clrscr();
9
    lcd_set_contrast(0x00);
10
    lcd_charMode(NORMALSIZE);
11
    lcd_gotoxy(0,0);
12
    lcd_puts("Normal Size");
13
    lcd_charMode(DOUBLESIZE);
14
    lcd_gotoxy(0,1);
15
    lcd_puts("DoubleSize");       
16
}
17
18
void loop() {
19
  // put your main code here, to run repeatedly:
20
21
}
Da das Display und die Ausgaben in den Adafruit-Libs richtig 
funktioniert, hab ich mal auf die Suche gemacht, warum es mit deiner Lib 
nicht gehen soll.

Aufgefallen ist mir dabei ein Unterschied in der Init-Sequenz:
In der Adafruit_SSD1306.cpp steht beim Init u.A. folgendes:
1
if((WIDTH == 128) && (HEIGHT == 32)) {
2
    comPins = 0x02;
3
    contrast = 0x8F;
4
  } else if((WIDTH == 128) && (HEIGHT == 64)) {
5
    comPins = 0x12;
6
    contrast = (vccstate == SSD1306_EXTERNALVCC) ? 0x9F : 0xCF;
7
  } else if((WIDTH == 96) && (HEIGHT == 16)) {
8
    comPins = 0x2;    // ada x12
9
    contrast = (vccstate == SSD1306_EXTERNALVCC) ? 0x10 : 0xAF;
10
  } else {
11
    // Other screen varieties -- TBD
12
  }
 D.h.: Bei einem Display mit 32 Pixel Höhe wird comPins mit 0x02 
initalisiert und bei 64 Pixels mit 0x12.
 In deiner LCD.c hab ich dann die Init-Sequenz mal geändert
1
    0x02,      // Set com pins hardware configuration for Display 128x32
2
   //0x12,      // Set com pins hardware configuration for Display 128x64
Und siehe da, die Ausgabe passt jetzt (siehe Image 2).

Event. hilft die Info ja jemanden weiter bzw. kannst du in einem Update 
das mal einpflegen.

Danke und Gruß,
Bernardo

von Stefan F. (Gast)


Lesenswert?

Das scheint eine Besonderheit bei deinem Display zu sein.

Meine 128x32 Displays funktionieren richtig, wenn ich mit 0x12 
initialisieren.

Ich habe deinen Hinweis mal als Kommentar in meine (das ist eine andere) 
Bibliothek eingebaut, dann findet man es später schneller.

von Bernhard65 (bernhard65)


Lesenswert?

Ob das ein bessonderes Display ist kann ich nicht sagen, aber in der 
Library von Adadfruit SSD1306 (Adafruit_SSD1306.cpp  s.o.), ist das fest 
für 128x32 Displays eingestellt (wenn ich das richtig Überblicke).
Und diese Library wird von sehr vielen verwendet.

Event. geht dein Display ja auch mit der Einstellung comPins 0x02 ?

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Ja, in der Adafruit Library ist der Wert 0x02.

von Stefan F. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Meine 128x32 Displays funktionieren richtig, wenn ich mit 0x12
> initialisieren.

Sorry ich habe das etwas verwechselt. Ich habe auch mit 0x02 
initialisiert.

Beitrag #6181523 wurde vom Autor gelöscht.
Beitrag #6181524 wurde von einem Moderator gelöscht.
von M. K. (sylaina)


Lesenswert?

Hallo Bernhard,

ich muss mich unbedingt noch mal hinsetzen und meine Lib überarbeiten. 
Sie ist, wie schon einigen aufgefallen ist, für die 128x64er Displays 
geschrieben, für Displays mit anderer Auflösung muss die Library 
angepasst werden und das fängt schon in der Init-Routine an aber auch in 
den Zeichenroutinen und Co muss z.B. die Abfragen der Art
1
...
2
if((WIDTH == 128) && (HEIGHT == 64)) {
3
...

angepasst werden. Ich danke dir für deine Rückmeldung, ich werde mal 
schaun dieser Tage die Ergänzung für die Init-Sequence einfließen zu 
lassen.

von Jörg F. (jopelabln)


Lesenswert?

Für den Fall, dass jemand die Anzeige um 180° verdreht eingebaut hat:
1
void lcd_flip(uint8_t flip){
2
    uint8_t commandSequence[2];
3
    if (flip != YES) {
4
        commandSequence[0] = 0xA1;      // normal
5
        commandSequence[1] = 0xC8;
6
    } else {
7
        commandSequence[0] = 0xA0;      // gedreht
8
        commandSequence[1] = 0xC0;
9
    }
10
    lcd_command(commandSequence, 2);

von M. K. (sylaina)


Lesenswert?

Oh, das muss ich mal ausprobieren. Passt das dann immer noch mit den 
Zeilen und Spalten Abfragen (also diese Teile: if( x > DISPLAY_WIDTH-1 
|| y > (DISPLAY_HEIGHT-1)) return; // out of Display)? Ich denke nicht, 
oder? Ich schätze mal WIDTH und HEIGHT muss man dann auch tauschen.

von Jörg F. (jopelabln)


Lesenswert?

Nö, die Drehung ist doch 180°.
DISPLAY_WIDTH und DISPLAY_HEIGHT werden nur bei 90° bzw. 270° 
vertauscht.
Das ist dann aber komplizierter.
Edit:
Ist nicht auf meinem Mist gewachsen, sondern stammt aus der 
u8g2/u8x8-Lib.
Ich konnte auf dieser Weise mein Layout retten.
Edit2:
Ich habe nur den TEXTMODE benutzt

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

Jörg F. schrieb:
> Nö, die Drehung ist doch 180°.

Achja, stimmt ja, ist ja Flip...war schon zu spät gestern für mich.

Jörg F. schrieb:
> Ich habe nur den TEXTMODE benutzt

Sollte im Graphicsmode auch gehen denn die Funktion dreht am RAM-Inhalt 
des Displays ;)

von Jörg F. (jopelabln)


Lesenswert?

Der Text steht nach dem Flip zwar auf dem Kopf ist aber in 
Spiegelschrift.
Nach einem lcd_clear und der neuen Ausgabe des Textes ist aber wieder 
alles OK. Ich denke den Flip benutzt man ähnlich den init nur ein 
einziges Mal im Programm, da das Display ja nicht auf einem 
Rotationteller ist.

von Benedikt M. (bmuessig)


Lesenswert?

M. K. schrieb:
> Wie soll das funktionieren also ohne Puffer funktionieren?

Ich könnte mir einen FIFO mit Zeichenbefehlen vorstellen. Hierbei könnte 
eine Scanline gepuffert werden und alle Zeichenkommandos dann Scanline 
für Scanline abgearbeitet und zeilenweise an's Display übertragen 
werden. Hierfür muss man nur die übliche y-Schleife der Zeichenbefehle 
in eine finale Zeichnen & Senden-Funktion auslagern.
Da hier im Flash gespeicherte Bitmaps und Fonts einfach per Adresse 
referenziert werden können und für Linien und Formen einfach die 
Eckkoordinaten gespeichert werden können, kann solch eine Vorgehensweise 
recht effizient sein. Hier muss jedoch bei jeder Änderung eines 
Bildschirmbereiches dieser Teil neu gezeichnet werden. Die Erzeugung des 
Zeichenbefehlspuffers muss also in jedem Frame passieren. Die 
Übertragungssoftware könnte dann immer den kleinstmöglichen Bereich 
rendern und zeilenweise übertragen.

von M. K. (sylaina)


Lesenswert?

Benedikt M. schrieb:
> Hier muss jedoch bei jeder Änderung eines
> Bildschirmbereiches dieser Teil neu gezeichnet werden.

Und genau das ist ja der Knackpunkt. Wenn man den Displayinhalt nicht 
löschen will ist man gezwungen mit dem Puffer zu arbeiten da man die 
Displays typischerweise nicht auslesen kann (könnte man sie auslesen 
wäre es einfach ;)).

von Benedikt M. (bmuessig)


Lesenswert?

M. K. schrieb:
> Und genau das ist ja der Knackpunkt. Wenn man den Displayinhalt nicht
> löschen will ist man gezwungen mit dem Puffer zu arbeiten

Doch, das Problem ist damit ja auch adressiert. Wenn man den 
Bildschirminhalt nur teilweise verändert, kann man die (nach 
Einschätzung des Entwicklers) gleich geliebenen Bildschirmteile nicht 
aktualisieren, dafür aber die veränderten Regionen. Wenn die Elemente im 
Puffer in den zu aktualisierenden Bereichen gleich bleiben, kann man die 
Updates problemlos in den aktuellen Bildschirminhalt einfügen.

Beispiel: Bitmap mit Textoverlay. Der Text soll geändert werden.
Hier reicht es, nur den Teil mit dem Text erneut an das Display zu 
senden.
Im Puffer ist dasselbe Bitmap weiterhin an derselben Stelle vorhanden.
Ändert man nun den Text, können exklusiv die Scanlinien, die Bitmap und 
Text enthalten haben, einfach neu berechnet und an den Framebuffer im 
Display gesendet werden. Da der Output deterministisch ist, funktioniert 
das auch ohne Update des gesamten Bildschirms, oder Lesen des 
Framebuffers.

> (könnte man sie auslesen wäre es einfach ;))
Einfach ist doch langweilig ;-)

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

Benedikt M. schrieb:
> Beispiel: Bitmap mit Textoverlay. Der Text soll geändert werden.
> Hier reicht es, nur den Teil mit dem Text erneut an das Display zu
> senden.

Und hier jetzt der Gedankenanstoß: Man will nicht den Text, der da schon 
im Display steht, löschen sondern einfach einen weiteren Text drüber 
schreiben. Schon hast du ein Problem wenn du nicht weißt, welcher Text 
da schon drin steht.
OK, bei Text ist das nicht unbedingt sinnvoll aber wenn man irgend etwas 
x-beliebiges zeichnet kann ich mir schon vorstellen, dass man das schon 
Gezeichnete nicht löschen will sondern einfach drüber zeichnen will, 
Beispiel Koordinatensystem mit verschiedenen Kurvenverläufen und Gitter 
usw. (bedenke: Diese Displays können auch nicht ein einzelnes Pixel 
ändern, es sind immer mindestens 8 Pixel)

Natürlich kann man vom Puffer bei speziellen Anwendungen weg kommen, die 
Textversion ist ja sowas quasi, aber allgemein kommst du nicht um den 
Puffer rum wenn du keine Informationen verlieren willst.

von Viking (Gast)


Lesenswert?

Hallo Michael,

ich habe schon vor einiger Zeit benutzt und fand die shon richtig 
klasse!
Nun habe ich ein kleines Problem mit der Initialisierung des kleineren 
Displays (64x48).
Ich habe die entspr. Befehle 0x21 - Set column address und 0x22 - Set 
page address gefunden. Ich weiß allerdings nicht wo ich das einbauen 
muss.

Ich habe bereits an folgender Stelle ausprobiert und gesehen, dass die 
anzeige sich auch verschiebt. Sobald ich auch die Displaygröße von 
128x64 auf 64x48 einstelle sehe ich meine gezeichnete Linie nicht mehr.
Wie ich sehen konnte ist das nicht die richtige stelle, da du in 
weiteren Funktionen den Pointer (im Display) veränderst.
1
void lcd_data(uint8_t data[], uint16_t size) {
2
#if defined I2C
3
//Test set memory area
4
    const uint8_t def_mem_area [] = {    // Adressbereich für kleiner Displays als 128x64
5
        0x21,   //Set column address
6
        32,     //Start column
7
        95,     //End column
8
        0x22,   //Set page address
9
        2,      //Start page
10
        7       //End page
11
    };
12
    lcd_command(def_mem_area, sizeof(def_mem_area));
13
// Test Ende
14
15
    i2c_start((LCD_I2C_ADR << 1) | 0);
16
    i2c_byte(0x40);    // 0x00 for command, 0x40 for data
17
    for (uint16_t i = 0; i<size; i++) {
18
        i2c_byte(data[i]);
19
    }
20
    i2c_stop();

Ich habe deine Lib (nicht die aktuellste) auf diesem (64x48) und auf 
einem noch kleineren (48x32)Display ausprobiert. Buffer war dabei auf 
128x64 gesetzt. Dabei habe ich gesehen, dass die sichtbaren Zellen des 
Displays immer horizontal zentriert und vertikal am unteren Rand des 
RAMs des Kontrollers ausgerichtet sind. Somit kann den ganzen Display 
RAM ansprechen, sehe dann aber nur den 'sichtbaren' Teil der Ausgabe.

Was kann ich ich machen, an welchen Stellen müsste ich ansetzen?

von M. K. (sylaina)


Lesenswert?

Viking schrieb:
> Was kann ich ich machen, an welchen Stellen müsste ich ansetzen?

Viking schrieb:
> Ich habe deine Lib (nicht die aktuellste)

Erstelle eine Sicherung deines Projektes und verwende dann mal die 
aktuelle Version der Lib. In der alten Version gab es in der Tat 
Probleme bei anderen Displaygrößen, dass aber inzwischen bearbeitet 
wurde. Ggf. funktionieren deine Displays aus mit der aktuellen Lib 
fehlerfrei.

von Viktor (Gast)


Lesenswert?

HalloMichael,

danke für deine schnelle Antwort. Ich habe es vielleicht 
missverständlich geschrieben. Ich habe schon die aktuelle Version von 
github verwendet.

Ich werde nochmals ausprobieren und mit einem Foto dokumentieren.

Einen interessanten Ansatz habe ich hier gefunden.
http://www.technoblogy.com/show?WNM

Ein Teil deiner Init. scheint keine Auswirkung zu haben. Laut Datenblatt 
sind die Befehle welche die Start page und column festlegen nur bei der 
page Adressierung wirksam.

Ich schreibe gerade von meinem Handy, daher mit spärlichen Infos. Ich 
werde mich die Tage melden sobald ich es getestet habe.

Danke und bis dahin...

von Viking (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Michael,

ich habe nochmals die aktuelle Lib (github) passend für das Display 
konfiguriert. Für die Ausgabe habe habe ich dein Beispiel aus der Main.c 
verwendet. (s. Bild - Aktuelle_Lib.jpg)
1
 
2
int main(void)
3
{
4
  lcd_init(LCD_DISP_ON);    // init lcd and turn on
5
  
6
  lcd_puts("Hello World");  // put string from RAM to display (TEXTMODE) or buffer (GRAPHICMODE)
7
  lcd_gotoxy(0,2);          // set cursor to first column at line 3
8
  lcd_puts_p(PSTR("String from flash"));  // puts string form flash to display (TEXTMODE) or buffer (GRAPHICMODE)
9
  #if defined GRAPHICMODE
10
  lcd_drawCircle(64,32,7,WHITE); // draw circle to buffer white lines
11
  lcd_display();                 // send buffer to display
12
  #endif
13
    /* Replace with your application code */
14
    while (1) 
15
    {
16
    }
17
}

Die Konfiguration für das Display sieht so aus:
#define DISPLAY_WIDTH        64
#define DISPLAY_HEIGHT       48

Im zweiten Bild (alte_Lib.jpg) habe ich die frühere version der Lib 
verwendet. Die Ausgabe auf dem Display täuscht allerdings. Ich musste 
Buffer mit 128x64 pix initialisieren. Mit folgendem Code habe ich auch 
rausgefunden wie die kleineren Displays an den Kontroller angebunden 
sind.
ACHTUNG!: Der Codeschnipsel ist jedoch auf die Ausgabe auf dem noch 
kleineren Display (64x32) angepasst. Im Bild ist eine 64x48 Display zu 
sehen.
1
#if defined GRAPHICMODE
2
  lcd_drawPixel(32,32,WHITE);   //quasi 0.0 (x.y)
3
  lcd_drawPixel(95,32,WHITE);   // x-ende
4
  lcd_drawPixel(32,63,WHITE);   // x-ende, y-start 
5
  lcd_drawPixel(95,63,WHITE);   // x,y-ende
6
  lcd_gotoxy(6,4);
7
  lcd_puts_p(PSTR("1. Zeile")); //start ab dem 2. Zeichen
8
  lcd_gotoxy(6,5);
9
  lcd_puts_p(PSTR("2. Zeile"));
10
  lcd_gotoxy(6,6);
11
  lcd_puts_p(PSTR("3. Zeile"));
12
  lcd_display();                // send buffer to display
13
#endif

Zusammenfassung:
Atmel Studio 7.0.1645
Atmega328P (20MHz)

von M. K. (sylaina)


Lesenswert?

Hab jetzt schon ein paar Tage hier nicht reingeschaut, ich muss mal bei 
Gelegenheit ein Testaufbau mit dem Display umsetzen. Was mir aber hier 
jetzt auf Anhieb auffiel war, dass du z.B. schriebst:

Viking schrieb:
>
1
lcd_gotoxy(6,6);

Da dein Display 48 Pixel hoch ist und jede Zeile 8 Pixel hoch ist hat 
man zwar 6 Zeilen aber die 6. Zeile hat den Index 5, es müsste also 
heißen
1
...
2
lcd_gotoxy(6,5);
3
...
um in die 6. Zeile zu schreiben. Ich weiß grad nicht, ob das eigentlich 
von der Lib aufgefangen werden sollte.

Auch nicht so gut ist

Viking schrieb:
>
1
lcd_drawPixel(95,32,WHITE);   // x-ende

da du ja selbst schriebst, dass dein Display nur 64 Pixel breit ist. Da 
als X 95 nun anzugeben kann auch "knallen" (das müsste abgefangen sein 
und dürfte nicht zu Ausführung kommen).

Zudem muss die Initialisierung angepasst werden, ich hab ja nur eine 
Initialisierung für 64 Pixel Displayhöhe und für 32 Pixel Displayhöhe. 
Das könnte sich auch beißen wenn man als Displayhöhe 48 angibt.

von Arduino (Gast)


Lesenswert?

M. K. schrieb:
> Hab jetzt schon ein paar Tage hier nicht reingeschaut,

Gibt es eine fertige .ino, die unter Arduino Hello World in 
unterschiedlichen Größen darstellt?

von Stefan F. (Gast)


Lesenswert?

Arduino schrieb:
> Gibt es eine fertige .ino, die unter Arduino Hello World in
> unterschiedlichen Größen darstellt?

Worauf willst du den Text darstellen?

Meine Gegenfrage soll klar machen, dass es nicht nur eine ino für 
diesen Zweck geben kann.

von Arduino (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Worauf willst du den Text darstellen?

Auf dem OLED, wie lautet der Titel vom Thread?
(Library zum Darstellen von Text auf OLED Displays)

> Meine Gegenfrage soll klar machen, dass es nicht nur eine ino für
> diesen Zweck geben kann.

Deine Gegenfrage ergibt für mich keinen Sinn.

von Stefan F. (Gast)


Lesenswert?

Arduino schrieb:
> Deine Gegenfrage ergibt für mich keinen Sinn.

Es gibt viele unterschiedliche Displaygrößen, die man mit der Library 
ansteuern kann. Ein Testprogramm würde nur Sinn ergeben, wenn es an den 
Display-Typ und die Display-Größe angepasst ist.

von Arduino (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Es gibt viele unterschiedliche Displaygrößen,
> die man mit der Library ansteuern kann.

M. K. schrieb:
> Ich habe eine kleine Library für den Displaycontroller SSD1306
> geschrieben, wie er häufig bei den 0.96" OLED-Displays eingesetzt wird.

Genau dieses, Standard-Chinese in Schwarz-Weiß.

von M. K. (sylaina)


Lesenswert?

Arduino schrieb:
> Gibt es eine fertige .ino, die unter Arduino Hello World in
> unterschiedlichen Größen darstellt?

Ne INO dafür habe ich nicht aber du kannst den Code so eins-zu-eins in 
die INO schreiben, die Lib muss dann im selben Ordner liegen, und das 
ganze Kompilieren. Die Arduino IDE kann nämlich auch C ;)

Alternativ kannst du auch weiterhin der typischen Syntax der Arduino-IDE 
folgen, die Library ist inzwischen angepasst, dass sie ohne Änderung in 
der Arduino-IDE benutzt werden kann.

Ich rate dir dich mal damit zu beschäftigen wie man das genau macht. Es 
ist nicht schwer, sogar sehr einfach und du wirst es wohl noch öfter 
benötigen wenn du Libs von anderen Quellen als Arduino benutzen 
möchtest. Gehört IMO zu den Grundlagen die man beherrschen sollte bei 
der Programmierung von Mikrocontrollern.

von Viking (Gast)


Lesenswert?

Hallo Michael,
ich komme in letzter Zeit auch nur sporadisch dazu und auch ich habe 
lange hier nicht reingeschaut.

Ich habe einwenig experementiert und folgendes ist dabei herausgekommen.

Ich habe die Initialiesierung etwas entschlackt, soweit ich mich 
errinere waren da noch Befehle enthalten welche nur für page addressing 
gedacht sind. Mit "TODO" habe ich bei mir noch die stelle markiert wo 
man die Grenzen des sichtbaren Bereichs im RAM setzen muss, hier 64x48.

Initialisierung:
- einiges ist noch auskommentiert, da ich mich damit noch nicht 
beschäftigt habe.
1
const uint8_t init_sequence [] PROGMEM = {    // Initialization Sequence
2
    0xAE,           // --Display OFF (sleep mode)
3
    0x8D,           // --Charge pump enable
4
    0x14,
5
    0x20,           // --Set Memory Addressing Mode
6
    0b00,           // 00=Horizontal Addressing Mode; 01=Vertical Addressing Mode;
7
                    // 10=Page Addressing Mode (RESET); 11=Invalid
8
9
    //TODO: automatisch anhand des Displays berechnen 
10
    0x21,           // --Set column address
11
    32,             //Start column
12
    95,             //End column
13
    0x22,           // --Set page address
14
    2,              //Start page
15
    7,              //End page                
16
    //^^^^^
17
                
18
    0xA1,           // --Set Segment Re-map. (0xA0/0xA1 flip horizontally)
19
    0xC8,           // --Set COM Output Scan Direction (0xC0/0xC8 flip vertically)
20
    0xD9,           // --Set pre-charge period
21
    0xF1,           // (orig. 0x22)
22
    0x81,           //--Set contrast control register
23
    0x3F,
24
    0xDB,           // --Set vcomh
25
    0x20,           // 0x20,0.77xVcc
26
27
    0xAF            // --Display On
28
    
29
    /* //Origanle init
30
    0x81, 0x3F,      // Set contrast control register
31
    0xA6,            // Set display mode. A6=Normal; A7=Inverse
32
    0xA8, DISPLAY_HEIGHT-1, // Set multiplex ratio(1 to 64)
33
    0xA4,            // Output RAM to Display
34
           // 0xA4=Output follows RAM content; 0xA5,Output ignores RAM content
35
    0xD3, 0x00,      // Set display offset. 00 = no offset
36
    0xD5,            // --set display clock divide ratio/oscillator frequency
37
    0xF0,            // --set divide ratio
38
    // Set com pins hardware configuration
39
#if DISPLAY_HEIGHT==64
40
    0xDA, 0x12,      
41
#elif DISPLAY_HEIGHT==32
42
    0xDA, 0x02,
43
#endif
44
*/
45
};

Da ich nur die Grafikfunktionen verwende habe ich was eigenes gebaut 
bzw. zusammenkopiert. Da die Grenzen des Displays bereits bei der Init 
eingestellt werden und die Größe des Buffer da rein passt funktioniert 
das wunderbar! Ich aktualieseiere dabei immer die gesammte Anzeige.

Ausgabe Buffer:
1
#define BUFFER_SIZE (DISPLAY_HEIGHT * DISPLAY_WIDTH)/8
2
unit8_t buffer[BUFFER_SIZE];
3
4
// Display buffer
5
void lcd_display_buffer(void){
6
    i2c_start((LCD_I2C_ADR << 1) | 0);
7
    i2c_byte(0x40);    // 0x00 for command, 0x40 for data
8
    for (uint16_t i = 0; i < BUFFER_SIZE; i++){
9
        i2c_byte(buffer[i]);
10
    }
11
    i2c_stop();
12
}

von Rolf L. (dj7th)


Lesenswert?

Suche eine solche Library für den Bascom Compiler. Bin für jeden Hinweis 
dankbar.

von R. F. (inet_surfer88)


Lesenswert?

Hallo,

ich habe auf der oben verlinkten Github-Seite die Library 
heruntergeladen. Ich steuere damit ein 0.96" Display mit 128x64 Pixel.

Ich schreibe mit
1
lcd_init(LCD_DISP_ON);
2
lcd_gotoxy(0,0);
3
lcd_puts("123");

Daten zum Testen auf das Display. Ich habe mittlerweile auch ein 
umfangreiches Programm mit dem noch viel mehr Daten auf das Display 
geschrieben werden. Es funktioniert alles ohne Probleme.

Jetzt habe ich mir folgendes Display mit 0.49" und 64x32 Pixel gekauft.
https://www.amazon.de/gp/product/B07QGZ4SRF/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1

Ich bekomme mit dem oben stehenden Testcode keine Anzeige auf das kleine 
Display. Da ich schon einen defekt oder falsche I2C-Adresse vermutet 
habe habe ich extra die Arduino-IDE gestartet (zum Programmieren nehm 
ich Atmel Studio). In Arduino gibt es einen I2C-Sniffer. Der gibt mir 
die Adresse 0x3c zurück, die gleiche wie das große Display.
In der lcd.h habe ich folgendes angepasst:
1
#define LCD_I2C_ADR         0x3c
2
#define DISPLAY_WIDTH         64
3
#define DISPLAY_HEIGHT        32

Ich bekomme einfach keine Anzeige auf das Display.
Controller ist bei beiden Displays ssd1306.

Hat jemand noch eine Idee was man noch überprüfen könnte???

: Bearbeitet durch User
von Joachim B. (jar)


Lesenswert?

arduino nutzt nur rechtsshift Adressen 0-127
Mit AVR Studio habe ich angefangen und das write Bit selber behandelt!

http://www.peterfleury.epizy.com/avr-software.html?i=1

Du musst schon wissen wie du die I2C Adressen behandelst.
In den Datenblättern von I2C devices ist immer 8 Bit genannt, die 
obersten 7 Bit sind die Adresse, Bit 0 ist das WR Bit.

Arduino 0-127 AVR 0-255 und Bit0 ausklammern

#if (ARDUINO>0)
  DEBUG_PRINTLN(F(" -> Scanning..."));
  char _i2c_key=0;
  byte error, address;
  int nDevices=0;
  for(address = 1; address < 127; address++ ) { // The i2c_scanner uses 
the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0) {
      DEBUG_PRINT(F("I2C device found at address 0x"));
      if (address<16)
        DEBUG_PRINT(F("0"));
      DEBUG_PRINT_DEC_HEX(address,HEX);
      DEBUG_PRINT(F("; "));
      if (address<64)
        DEBUG_PRINT(F("0"));
      DEBUG_PRINT_DEC_HEX(address,BIN);
      DEBUG_PRINT(F("x; << 0x"));
      DEBUG_PRINT_DEC_HEX((address<<1),HEX);
      DEBUG_PRINT(F("; "));
      if ((address<<1)<128)
        DEBUG_PRINT(F("0"));
      DEBUG_PRINT_DEC_HEX((address<<1),BIN);
      DEBUG_PRINT(F("; "));

      switch(address<<1) {
        case 0x40:
          //i2c_test_flags|=(1<<I2C_TASTATUR);
          i2c_test_flags|=(1<<I2C_TASTATUR_8574);
          _i2c_key=' ';
          DEBUG_PRINTLN(F("PCF8574  Tastatur"));
          break;
        case 0x70:
          //i2c_test_flags|=(1<<I2C_TASTATUR);
          i2c_test_flags|=(1<<I2C_TASTATUR_8574A);
          _i2c_key='A';
          DEBUG_PRINTLN(F("PCF8574A Tastatur"));
          break;
        case 0x78:
          DEBUG_PRINTLN(F("I2C OLED"));
          break;
        case 0xA0:
        case 0xA1:
        case 0xA2:
        case 0xA3:
        case 0xA4:
        case 0xA5:
        case 0xA6:
        case 0xA7:
          DEBUG_PRINTLN(F("I2C_EEPROM"));
          i2c_test_flags|=(1<<I2C_EEPROM);
DEBUG_PRINT(F("VOR eep_address FIND: ")); 
DEBUG_PRINTLN_DEC_HEX(eep_address, HEX);
          eep_address=(address);
DEBUG_PRINT(F("NACH eep_address FIND: ")); 
DEBUG_PRINTLN_DEC_HEX(eep_address, HEX);
          break;
        case 0xD0:
          Wire.beginTransmission(DS1307_ID);
          Wire.write(0x3F);
          if(Wire.endTransmission())
            i2c_test_flags|=(1<<I2C_RTC_3231);
          if(i2c_test_flags&(1<<I2C_RTC_3231))
            DEBUG_PRINTLN(F("DS3231 RTC"));
          break;
        default:
          DEBUG_PRINTLN();
          break;
      }
      nDevices++;
    } // if (error == 0)
    else if (error==4) {
      DEBUG_PRINT(F("Unknow error at address 0x"));
      if (address<16)
        DEBUG_PRINT(F("0"));
      DEBUG_PRINTLN_DEC_HEX(address,HEX);
    } // ! if(error==4)
  } // for(address = 1; address < 127; address++ )
  if (nDevices == 0)
    DEBUG_PRINTLN(F("No I2C devices found"));
  else
    DEBUG_PRINTLN(F("done"));
  DEBUG_PRINTLN();
#else // kein Arduino hier andere Methode einbinden
#endif // #if (ARDUINO>0)

: Bearbeitet durch User
von R. F. (inet_surfer88)


Lesenswert?

0x3c ist ja die 0x78 um eine Stelle geschoben. Ich habe auch schon beide 
Varianten ausprobiert. Arduino erkennt das kleine und das große Display 
als 0x3c. Von daher müsste es ja ok sein wenn ich das kleine mit dem 
Atmel Studio auch mit 0x3c anspreche, beim großen funktioniert es ja 
auch mit 0x3c (wie gesagt, beide geben im Sniffer ja auch den 
identischen Wert zurück).

von Joachim B. (jar)


Lesenswert?

R. F. schrieb:
> 0x3c ist ja die 0x78 um eine Stelle geschoben. Ich habe auch schon beide
> Varianten ausprobiert.

na denn weisst du ja bescheid

Ich habe aber auch einige I2C OLEDs gehabt die sich ums verrecken nicht 
ansprechen liessen, entweder ich bin zu dusslig oder mir wurde Mist 
geliefert, ist aus China auch schon öfter vorgekommen, aber wegen <=10€ 
macht man keinen Aufriss.

von R. F. (inet_surfer88)


Lesenswert?

Ich bin ein klein wenig weiter gekommen.

Ich habe jetzt erst mal das AVR Studio beiseite gelegt und die 
ArduinoIDE genommen.

Mein 0.96 lässt sich mit dem HelloWorld Beispiel und folgender 
Displaydefinition zum Leben erwecken.
1
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);

Für das 0.49 habe ich dann das genommen - funktioniert nicht
1
U8X8_SSD1306_64X32_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);

Nach ein wenig "rumspielen" hat folgende Zeile den Erfolg gebracht:
1
U8X8_SSD1306_64X32_1F_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);

Weis jemand was der Unterschied zwischen diesem NONAME und 1F ist?
Über die Doku zur Library auf https://github.com/olikraus/u8g2 bin ich 
bisher nicht weiter gekommen.

von Joachim B. (jar)


Lesenswert?

R. F. schrieb:
> Weis jemand was der Unterschied zwischen diesem NONAME und 1F ist?

schau doch in den Code!

von R. F. (inet_surfer88)


Lesenswert?

Joachim B. schrieb:
> schau doch in den Code!

Da werd ich bei meinen derzeitigen Programmierkenntnissen nicht schlau 
draus. Das einzige was mir bisher aufgefallen ist wäre eine 
unterschliedliche multiplex ratio.

Hier steht in
1
u8x8_d_ssd1306_64x32_noname_init_seq[] =
1
U8X8_CA(0x0a8, 0x02f), /* multiplex ratio: changed from 0x1f to 0x2f */

und in
1
u8x8_d_ssd1306_64x32_1f_init_seq[] =
1
U8X8_CA(0x0a8, 0x01f), /* multiplex ratio: changed from 0x1f to 0x2f, 23 Sep 17: changed back to 1f */

Laut dem müsste es also 1f sein.

In der c-Library die ich verwende steht:
1
0xA8, DISPLAY_HEIGHT-1, // Set multiplex ratio(1 to 64)

Da ich bei DISPLAY_HEIGHT den Wert 32 eingebe wäre das Ergebnis 31. Und 
das ergibt in HEX 1F. Demnach wäre das der richtige Wert welcher mit dem 
Display funktionieren sollte.

von Joachim B. (jar)


Lesenswert?

R. F. schrieb:
> Da werd ich bei meinen derzeitigen Programmierkenntnissen nicht schlau
> draus.
dann musst du tiefer schauen, hier ist nicht zu sehen,
dort ist gehts weiter:
R. F. schrieb:
> U8X8_CA(

von R. F. (inet_surfer88)


Lesenswert?

In der Arduino-Library habe ich noch folgendes gefunden.
1
U8X8_CA(0x0da, 0x012),    /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */[c/]
2
3
In der Library von hier steht
4
[c]#if DISPLAY_HEIGHT==64
5
    0xDA, 0x12,      
6
#elif DISPLAY_HEIGHT==32
7
    0xDA, 0x02,

Da mein DISPLAY_HEIGHT den Wert 32 hat steht bei mir dann 0x02.
Das habe ich jetzt auf 0x12 geändert. Der Unterschied ist ja genau das 
5. Bit vom Kommentar (disable left/right remap). Jetzt habe ich die 
Hälfte vom Display sichtbar.

Bei der derzeitigen Schriftgröße bekomme ich 10 Zeichen in eine Zeile.
Wenn ich den Sting "1234567890" ausgebe, dann steht in der linken Hälfte 
vom Display "567890". Die rechte Hälfte ist leer.

von Stefan F. (Gast)


Lesenswert?

Suche mal das Datenblatt von dem Display, da müsste die korrekte 
Initialisierungssequenz drin stehen. Die hängt nämlich ganz stark davon 
ab, wie die Pixel mit dem Chip verbunden sind. Da gibt es mehrere 
Möglichkeiten, deswegen lässt das Datenblatt des Chips diesen Teil 
offen.

von R. F. (inet_surfer88)


Lesenswert?

Stefan ⛄ F. schrieb:
> Suche mal das Datenblatt von dem Display

Das ist das Problem. Ich habe nur die Angaben auf Amazon. Über den 
genannten Hersteller werde ich bei Google auch nicht weiter fündig. 
Deswegen bestelle ich meine Displays normalerweise bei AZ Delivery. Da 
gibt es eine vernünftige Doku. Und der Preisaufschlag ist bei meinen 
paar Displays jetzt auch nicht entscheident. Aber bei AZ Delivery gibt 
es keine so kleinen Displays. Selbst die I2C Adresse war schon 
"Rätselraten".

von Stefan F. (Gast)


Lesenswert?

Guck mal bei Vishay: 
https://www.vishay.com/docs/37971/oled064o032alpp3n00000.pdf

Irgendwo findest du bei diesem Hersteller vielleicht auch die passende 
Initialisierungssequenz. Leider nicht in diesem PDF.

von Stefan F. (Gast)


Lesenswert?


von R. F. (inet_surfer88)


Angehängte Dateien:

Lesenswert?

Ic

Stefan ⛄ F. schrieb:
> Habe was gefunden:
> https://www.buydisplay.com/download/manual/ER-OLED0.49-1_Series_Datasheet.pdf

Nach der Doku bin ich jetzt mal vorgegangen, gleiches Ergebnis. Irgend 
wie habe ich da wohl ein merkwürdiges Display mit etwas anderer 
Konfiguration erwischt als die "Standard-Teile".

Aktuell schreibe ich folgendes auf das Display. Von der Breite her 
müsste das exakt auf das Display passen.
1
lcd_gotoxy(0,0);
2
lcd_puts("HelloWorld");
3
4
lcd_gotoxy(0,2);
5
lcd_puts("1234567890");

Das Ergebnis sieht man auf dem Bild "64x32", WIDTH 64, HEIGHT 32

Dann habe ich einfach das Display getauscht, ohne die Definitionen 
anzupassen. Das Ergebnis auf dem Bild "128x64_falsch"

Der Text landet also korrekt auf dem Controller, nur ist der Inhalt beim 
kleinen Display irgend wie nach links verschoben.

Zuletzt noch das Bild mit den korrekten Einstallungen für das große 
Display "128x64_ok" WIDTH 128, HEIGHT 64

von Joachim B. (jar)


Lesenswert?

128x64_ok.jpg sieht doch gut aus, wie ist deine Frage?

versuche
R. F. schrieb:
> lcd_gotoxy(0,0);
> lcd_puts("HelloWorld, i am OK");
>
> lcd_gotoxy(0,2);
> lcd_puts("12345678901234567890");

von R. F. (inet_surfer88)


Lesenswert?

Joachim B. schrieb:
> 128x64_ok.jpg sieht doch gut aus, wie ist deine Frage?

128x64 ist auch nicht das Problem, wollte damit nur Zeigen das der Code 
generell funktioniert. Das Problem ist das der gleiche Code auf dem 
64x32 nicht läuft, bzw. die Anzeige verschoben ist. Ich muss auf dem 
kleinen Display alles ein Stück nach rechts rücken, aber ich finde 
einfach nicht die passende Stellschraube in der Library (auch mangels 
Datenblatt vom Display). Von den WIDTH und HEIGHT Definitionen mal 
abgesehen. Aber die habe ich ja angepasst.

von Joachim B. (jar)


Lesenswert?

R. F. schrieb:
> 128x64.....

ich versteh dich nicht und kann zu dem
Beitrag "Re: SSD1306/1309 Library zum Darstellen von Text auf OLED Displays"

nichts mehr hinzufügen

von Stefan F. (Gast)



Lesenswert?

Ich habe dir das Datenblatt vom SSD1306 angehängt. Da sind alle 
Initialisierungsparameter beschrieben.

von R. F. (inet_surfer88)


Angehängte Dateien:

Lesenswert?

Joachim B. schrieb:
> ich versteh dich nicht und kann zu dem
> Beitrag "Re: SSD1306/1309 Library zum Darstellen von Text auf OLED
> Displays"
>
> nichts mehr hinzufügen

Uppps, hatte übersehen das du in meinen zitierten Text etwas hinzugefügt 
hast.
1
lcd_gotoxy(0,0);
2
lcd_puts("HelloWorld, i am OK");
3
4
lcd_gotoxy(0,2);
5
lcd_puts("12345678901234567890");

Bei der Einstellung WIDHT 64, HEIGHT 32:
Bild "64x32" kleines Display
Bild "128x64_falsch" großes Display

Bei der Einstellung WIDHT 128, HEIGHT 32:
Bild "128x64_ok" großes Display

von R. F. (inet_surfer88)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich habe dir das Datenblatt vom SSD1306 angehängt. Da sind alle
> Initialisierungsparameter beschrieben.

Ich habe gedacht ich wär auf der Seite 24 bei Punkt 8.4 und 8.3 auf 
Seite 23 auf der richtigen Spur. Alles ohne Erfolg. Bei dem einen Punkt 
"FR synchronization" beginnt das Display nur zu flackern (bei 
nochmaligem, genauerem lesen wurde auch klar warum), bei dem Punkt 
"Oscillator Circuit and Display Time Generator" verschieben sich die 
Zeilen in ihrer vertikalen Position. Ich müsste aber Horizontal 
verschieben.

Das Datenblatt muss ich die nächsten Tage nochmals genauer anschauen.

von Joachim B. (jar)


Lesenswert?

R. F. schrieb:
> Bei der Einstellung WIDHT 128, HEIGHT 32:
> Bild "128x64_ok" großes Display

siehste, nun weisst du es wie es richtig geht!
und musst für das warum nicht mehr suchen!

: Bearbeitet durch User
von R. F. (inet_surfer88)


Lesenswert?

Joachim B. schrieb:
> siehste, nun weisst du es wie es richtig geht!
> und musst für das warum nicht mehr suchen!

Irgend wie reden wir glaube ich aneinander vorbei, oder stehe ich 
komplett auf der Leitung???
Wie schon geschrieben, mein großes Display läuft ohne Probleme, mein 
Problem ist das kleine Display, das 64x32. Und da bekomme ich trotz 
WIDTH 64 und HEIGHT 32 keine vernünftige Anzeige, siehe Bild "64x32"

von Joachim B. (jar)


Lesenswert?

R. F. schrieb:
> Irgend wie reden wir glaube ich aneinander vorbei

möglich denn besonders klar finde ich deine seltenen Aussagen nicht, man 
weiss nie worauf du dich beziehst, du hast es im Kopf, für dich ist 
alles klar und hier bleiben bei mir nur ?????? über.

R. F. schrieb:
> Da ich bei DISPLAY_HEIGHT den Wert 32 eingebe wäre das Ergebnis 31. Und
> das ergibt in HEX 1F. Demnach wäre das der richtige Wert welcher mit dem
> Display funktionieren sollte.

"welcher mit dem Display"

aha, wie war das in der Schule, einen vollständigen Satz mit
"Subjekt Prädikat Objekt"
Wie beim Notruf
www
Wer
Wo
Was

meldet!

hier brennts ist zwar richtig aber nicht zielführend.

Wo ist deine Systematik?
sich Stück für Stück einem Fehler zu nähern und dabei zu lernen.

vermutlich bekomme ich dafür wieder Dankespunkte.

von M. K. (sylaina)


Lesenswert?

R. F. schrieb:
> Wie schon geschrieben, mein großes Display läuft ohne Probleme, mein
> Problem ist das kleine Display, das 64x32. Und da bekomme ich trotz
> WIDTH 64 und HEIGHT 32 keine vernünftige Anzeige, siehe Bild "64x32"

Ich tippe auf die Initialisierungs-Routine. Die ist u.a. abhängig von 
der Dislay-Größe. Ich hab nur die 128*64er Displays hier und hab die Lib 
darauf angepasst, wahrscheinlich muss da in der Initialisierung noch 
etwas geändert werden damit es für ein 64*32 Display passt. Wenns klappt 
bau ich die Lösung gerne in die Lib mit ein.

von R. F. (inet_surfer88)


Lesenswert?

Ich bin an der Sache noch dran, werde da aber erst im Januar weiter 
machen. Mittlerweile habe ich auch eine "provisorische Lösung" gefunden, 
damit die Texte korrekt auf dem Display angezeigt werden. Allerdings als 
Bastel- und nicht als saubere Dauerlösung.

Ich werde im Januar mal alles ausführlich erklärt hier posten. Kann also 
noch ein paar Tage dauern, bis ich mich wieder melde.

von Jan (Gast)


Angehängte Dateien:

Lesenswert?

Hallo community,

ich versuche gerade ein SSD1306 Display welches ich bei Ebay gekauft 
habe in Betrieb zu nehmen, es klappt aber nicht ganz. Ich hoffe jemand 
kann mir helfen. Die hardware ist atmega328p mit 8MHz RC osc.

Die Library habe ich vom
https://github.com/Sylaina/oled-display

Folgende Zeilen habe ich modifiziert :

lcd.h zeile 61
1
//#define SH1106  
2
#define SSD1306

lcd.h zeile 72
1
//#define LCD_I2C_ADR         (0x7a >> 1)    // 7 bit slave-adress without r/w-bit
2
#define LCD_I2C_ADR         (0x78 >> 1)    // 7 bit slave-adress without r/w-bit

Ich hoffe die Slave-Adresse (0x78 >> 1) ist richtig.
Immerhin tut sich was mit dieser Adresse.
Wenn ich es mit (0x7a >> 1) ausprobiere tut sich nichts. Ich finde keine 
Dokumentation von meinem Display.

Beim compilieren bekomme ich den folgenden Fehler :
1
..
2
avr-gcc (GCC) 4.7.2
3
Copyright (C) 2012 Free Software Foundation, Inc.
4
This is free software; see the source for copying conditions.  There is NO
5
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
6
Compiling: main.c
7
avr-gcc -c -mmcu=atmega328p -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 -DF_CPU=16000000UL -finput-charset=utf-8 -fexec-charset=iso-8859-15 -MD -MP -MF .dep/main.o.d main.c -o main.o
8
cc1.exe: error: no iconv implementation, cannot convert from UTF-8 to iso-8859-15
9
make.exe: *** [main.o] Error 1

Was kann ich gegen diesen Fehler machen?

Nach dem ich die folgende Zeile im Makefile auskommentiere :

# CFLAGS += -finput-charset=utf-8 -fexec-charset=iso-8859-15

lässt es sich kompilieren, es gibt aber Warnungen :
1
-------------- Build: Debug in EmcExcelRelay (compiler: GNU GCC Compiler for AVR)---------------
2
3
Checking if target is up-to-date: make.exe -q -f makefile 
4
Running command: make.exe -f makefile 
5
-------- begin --------
6
avr-gcc (GCC) 4.7.2
7
Copyright (C) 2012 Free Software Foundation, Inc.
8
This is free software; see the source for copying conditions.  There is NO
9
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
Compiling: main.c
11
avr-gcc -c -mmcu=atmega328p -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 -DF_CPU=16000000UL -MD -MP -MF .dep/main.o.d main.c -o main.o
12
Compiling: i2c.c
13
avr-gcc -c -mmcu=atmega328p -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=i2c.lst  -std=gnu99 -DF_CPU=16000000UL -MD -MP -MF .dep/i2c.o.d i2c.c -o i2c.o
14
lcd.c:102:0: warning: ignoring #pragma mark LCD [-Wunknown-pragmas]
15
lcd.c:139:0: warning: ignoring #pragma mark  [-Wunknown-pragmas]
16
lcd.c:140:0: warning: ignoring #pragma mark GENERAL [-Wunknown-pragmas]
17
Compiling: lcd.c
18
avr-gcc -c -mmcu=atmega328p -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=lcd.lst  -std=gnu99 -DF_CPU=16000000UL -MD -MP -MF .dep/lcd.o.d lcd.c -o lcd.o
19
Compiling: font.c
20
avr-gcc -c -mmcu=atmega328p -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=font.lst  -std=gnu99 -DF_CPU=16000000UL -MD -MP -MF .dep/font.o.d font.c -o font.o
21
font.c:126:6: warning: multi-character character constant [-Wmultichar]
22
font.c:126:5: warning: large integer implicitly truncated to unsigned type [-Woverflow]
23
font.c:127:6: warning: multi-character character constant [-Wmultichar]
24
font.c:127:5: warning: large integer implicitly truncated to unsigned type [-Woverflow]
25
font.c:128:6: warning: multi-character character constant [-Wmultichar]
26
font.c:128:5: warning: large integer implicitly truncated to unsigned type [-Woverflow]
27
font.c:129:6: warning: multi-character character constant [-Wmultichar]
28
font.c:129:5: warning: large integer implicitly truncated to unsigned type [-Woverflow]
29
font.c:130:6: warning: multi-character character constant [-Wmultichar]
30
font.c:130:5: warning: large integer implicitly truncated to unsigned type [-Woverflow]
31
font.c:131:6: warning: multi-character character constant [-Wmultichar]
32
font.c:131:5: warning: large integer implicitly truncated to unsigned type [-Woverflow]
33
font.c:132:6: warning: multi-character character constant [-Wmultichar]
34
font.c:132:5: warning: large integer implicitly truncated to unsigned type [-Woverflow]
35
font.c:133:6: warning: multi-character character constant [-Wmultichar]
36
font.c:133:5: warning: large integer implicitly truncated to unsigned type [-Woverflow]
37
font.c:134:6: warning: multi-character character constant [-Wmultichar]
38
font.c:134:5: warning: large integer implicitly truncated to unsigned type [-Woverflow]
39
Linking: main.elf
40
avr-gcc -mmcu=atmega328p -I. -gdwarf-2   -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o  -std=gnu99 -DF_CPU=16000000UL -MD -MP -MF .dep/main.elf.d main.o i2c.o lcd.o font.o  --output main.elf -Wl,-Map=main.map,--cref    -lm
41
Creating load file for Flash: main.hex
42
avr-objcopy -O ihex -R .eeprom main.elf main.hex
43
Creating load file for EEPROM: main.eep
44
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
45
  --change-section-lma .eeprom=0 -O ihex main.elf main.eep
46
c:\Elektrotechnik\avr-gcc-4.7.2-mingw32\bin\avr-objcopy.exe: --change-section-lma .eeprom=0x00000000 never used
47
Creating Extended Listing: main.lss
48
avr-objdump -h -S main.elf > main.lss
49
Creating Symbol Table: main.sym
50
avr-nm -n main.elf > main.sym
51
Size after:
52
main.elf  :
53
section           size      addr
54
.data               14   8388864
55
.text             2538         0
56
.bss                 3   8388878
57
.stab             1740         0
58
.stabstr           110         0
59
.comment            17         0
60
.debug_aranges     216         0
61
.debug_info       4051         0
62
.debug_abbrev     1218         0
63
.debug_line       1310         0
64
.debug_frame       732         0
65
.debug_str         566         0
66
.debug_loc        2847         0
67
.debug_ranges       96         0
68
Total            15458
69
Errors: none

Der Text auf dem Display ist aber verschoben und es gibt Artefakte.

(In dem Angehängten Bild wird nur der Textmodus getestet)
Im Graphik mode gibt es nur noch diese Artefakte zu sehen,
der Text ist nur ganz kurz im Einschaltaugenblick zu sehen, dann nur 
noch die Artefakte )

Ich habe auch mit der Compilerversion avr-gcc (GCC) 9.2.0 versucht.
Das Ergebnis war aber gleich.

Vielleicht hatte jemand ein ähnliches Problem ?


Danke im Voraus.
Jan

[Mod: C- und code-Tags ergänzt.]

: Bearbeitet durch Moderator
von R. F. (inet_surfer88)


Lesenswert?

Hallo Jan,

du schreibst das dein Controller mit 8MHz läuft.
In deiner Ausgabe welche du gepostet hast steht
1
-DF_CPU=16000000UL
Das heißt in deiner Entwicklungsumgebung sind 16MHz eingestellt.
Das solltest du auf jeden Fall anpassen (in der Entwicklungsumgebung 
korrekt eintragen).

Die Meldung
1
no iconv implementation, cannot convert from UTF-8 to 
2
iso-8859-15
hatte ich auch schon. Ich habe dann ebenfalls
1
-finput-charset=utf-8 -fexec-charset=iso-8859-15
wieder gelöscht, dann hat es funktionert. Allerdings kann ich dadurch 
ä,ö,ü,ß nicht darstellen. Hier wäre ich ebenfalls an einer Lösung 
interessiert.

Gruß Rüdiger

von Stefan F. (Gast)


Lesenswert?

Speichere deine Quelltexte entweder im ISO-8859-15 Zeichensatz oder 
ersetze die Umlaute durch Escape Sequenzen wie
1
"L\xFCffelbisquit"

FC = ü
DC = Ü
E4 = ä
C4 = Ä
F6 = o
D6 = O
B0 = °
DF = ß

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Stefan ⛄ F. schrieb:

>
1
> "L\xFCffelbisquit"
2
>
>
> FC = ü
> DC = Ü
> E4 = ä
> C4 = Ä
> F6 = o
> D6 = O
> B0 = °
> DF = ß

Geht etwas lesbarer:
1
#define ae "\xE4"
2
#define oe "\xF6"
3
// ...
4
5
   lcd_write(..., "L"oe"ffelbisquit");

von Stefan F. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> F6 = o
> D6 = O

Oh, ich sehe gerade, dass die Punkte vom ö und Ö fehlen. Die 
Hexadezimal-Codes stimmen aber.

von Jan (Gast)


Angehängte Dateien:

Lesenswert?

Danke für die Antworten und Erkläerungen.

das mit dem Zeichensatz werde ich später angehen. Erstmal wollte ich 
soweit kommen das es das Anzeigt was es anzeigen soll.

R. F. (inet_surfer88) schrieb :

>du schreibst das dein Controller mit 8MHz läuft.
>In deiner Ausgabe welche du gepostet hast steht
>-DF_CPU=16000000UL
>Das heißt in deiner Entwicklungsumgebung sind 16MHz eingestellt.
>Das solltest du auf jeden Fall anpassen (in der Entwicklungsumgebung
>korrekt eintragen).

Ich habe F_CPU = 8000000UL gesetzt.

Wie man im Anhang sieht läuft die Kommunikation mit 100KHz, das Display 
antwortet auch.
(Der erste Zugriff nach dem Reset ist im Bild zu sehen)

Ich überlege ob es nicht ein Hardware Probleme ist und Frage mich auch 
mit welcher Spannung das Display betrieben werden soll.
In der Beschreibung bei Ebay stand 3-5V.
Im Dattenblatt vom SSD1306 steht Power supply o VDD = 1.65V to 3.3V for 
IC logic.
Ich habe es erstmal mit 5V versucht, danach habe ich es mit 3.3V 
versucht.

Das Display zeigt immer diesen verschobenen Text und die Artefakte.

Schade das das hex file nicht im github dabeit ist. Das würde ich gerne 
flashen um es auszuprobieren.

Vielleicht ist jemand so freundlich und kann es hochladen.
(Also das hex file vom  Ausgangs Projekt 
https://github.com/Sylaina/oled-display  für den atmega328p )
(ob die F_CPU auf 16MHz oder 8MHz steht sollte erstmal keine Rolle 
spielen, es läuft dann halt mit der halben Geschwindigkeit)

Danke im Voraus,
Jan

von Joachim B. (jar)


Lesenswert?

Jan schrieb:
> Das Display zeigt immer diesen verschobenen Text

hatte ich mal bei falscher Controllerwahl
aber in welcher Lib? adafruit oder diese?

vergessen!

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Jan schrieb:
> Ich überlege ob es nicht ein Hardware Probleme

Die steigenden Flanken der Signale sind stark abgerundet. 400 kHz würden 
sicher gar nicht mehr funktionieren, obwohl das Display eigentlich sogar 
500 kHz schafft.

Vermutlich sind deine Pull-Up Widerstände and SCL und SDA zu hochohmig. 
Versuche mal 2,2kΩ oder 3,3kΩ.

> Frage mich auch mit welcher Spannung das Display betrieben werden soll.

Der Display-Controller braucht ungefähr 3,3V. Die meisten Module 
enthalten einen Spannungsregler, der aus einer höheren 
Versorgungsspannung bis 6V diese 3,3V bereit stellt.

Trotzdem ist es wichtig, dass die Signale am I²C Bus nicht mehr als 3,3V 
haben. Die Pull-Up Widerstände müssen daher auf 3,3V gehen, nicht auf 
5V!

von Jan (Gast)


Angehängte Dateien:

Lesenswert?

Vielen Dank für die Antworten.
Den Fehler habe ich gefunden. Ich habe es auf SH1106 umgestellt und es 
funktioniert.

Danke an Joachim B für den Tip mit mit der falschen Controllerwahl.
Ich bin davon ausgegangen das ich einen SSD1306 habe.

F. (stefanus) schrieb :
>Vermutlich sind deine Pull-Up Widerstände and SCL und SDA zu hochohmig.
>Versuche mal 2,2kΩ oder 3,3kΩ.

6.8KOhm habe ich drin, und sie sind auch an 5V angeschlossen.
Ich muss das noch ändern und sie an die VDD vom display anschliessen.
Vermutlich ist auf der Displayplatine ein Spannungsregler, ich muss mir 
das noch genau angucken.
Siehe Anhang

Danke nochmals.
Grüße,
Jan

von Joachim B. (jar)


Lesenswert?

Jan schrieb:
> Ich habe es auf SH1106 umgestellt und es
> funktioniert.
>
> Danke an Joachim B für den Tip mit mit der falschen Controllerwahl.
> Ich bin davon ausgegangen das ich einen SSD1306

ja jetzt fällt es mir wieder ein, der Unterschied war wie du schreibst!
SH1106 <-> SSD1306 :)))

von M. K. (sylaina)


Lesenswert?

Jan schrieb:
> Danke an Joachim B für den Tip mit mit der falschen Controllerwahl.
> Ich bin davon ausgegangen das ich einen SSD1306 habe.

Meiner Beobachtung bisher ist es übrigens so, dass die 0.96" Displays 
den SSD1306 drin haben während die 1.3" Displays den SH1106 Controller 
drin haben.

Jan schrieb:
> 6.8KOhm habe ich drin

Die sind für 400kHz und mehr definitiv zu hoch. Meiner einer hat 
üblicherweise 4k7 drin, für 1 MHz geh ich typischer Weise auf 2k2.

von M. K. (sylaina)


Lesenswert?

Jan schrieb:
> Schade das das hex file nicht im github dabeit ist. Das würde ich gerne
> flashen um es auszuprobieren.

Das Hex-File kann man sich ja selbst erstellen und "make all" ausführen, 
das Makefile liegt ja mit bei ;)

von Stefan F. (Gast)


Lesenswert?

M. K. schrieb:
> Meiner Beobachtung bisher ist es übrigens so, dass die 0.96" Displays
> den SSD1306 drin haben während die 1.3" Displays den SH1106 Controller
> drin haben.

Hmm, ich habe neulich ein paar 1.3" Displays bestellt und die laufen 
prima mit den Settings für den SSD1306. Allerdings habe ich das nur mit 
meiner eigenen OLED Klasse 
(http://stefanfrings.de/arduino_oled/index.html) ausprobiert.

Bei mir gibt es nur einen kleinen Unterschied bei der Datenübertragung 
vom RAM zum Display:
1
        // Set memory address to fill
2
        i2c.beginTransmission(i2c_address);
3
        i2c.write(0x00); // command
4
        if (isSH1106)
5
        {
6
            i2c.write(0xB0 + page); // set page
7
            i2c.write(0x00); // lower columns address =0
8
            i2c.write(0x10); // upper columns address =0
9
        }
10
        else
11
        {
12
            i2c.write(0xB0 + page); // set page
13
            i2c.write(0x21); // column address
14
            i2c.write(0x00); // first column =0
15
            i2c.write(width - 1); // last column
16
        }
17
        i2c.endTransmission();
18
19
        // send one page of buffer to the display
20
        ...

Ich habe irgendwo gelesen, dass beim SH1106 jede Page in einer eigenen 
I2C Transaktion übertragen werden muss, während man beim SSD1306 alles 
in einem Rutsch übertragen kann.

von Stefan F. (Gast)


Lesenswert?

Komisches Angebot, da hält sich der Händler beide Optionen offen:
https://www.ebay.de/itm/OLED-Display-1-3-weiss-blau-tuerkis-SH1106-SSD1306-128x64-I2C-Modul-Arduino-/272942171612

Und AZ-Delivery hat einen neuen Chip erfunden, den "SSH 1106":
https://www.az-delivery.de/products/1-3zoll-i2c-oled-display

Ich muss mal etwas loswerden. Bei den chinesischen Produkt nervt es mich 
kollosal, dass die Händler keine klaren Angaben dazu machen, was man da 
eigentlich kauft. Selbst auf die Fotos ist kein Verlass - die Ware 
weicht ob in Details davon ab.

Bei Boards mit STM32F1, ESP8266 und ESP32 wird auch wild gemischt.

von Joachim B. (jar)


Lesenswert?

Stefan ⛄ F. schrieb:
> Und AZ-Delivery hat einen neuen Chip erfunden

ruf doch mal an und frage....

kleiner Scherz am Rande, ne das habe ich alles durch, die wissen nicht 
mal was sie verkaufen, ist aber bei vielen deutschen Onlinehändlern auch 
nicht anders, die Leute am Telefon wissen nicht mal was in den Kisten im 
Lager ist.

von M. K. (sylaina)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ich habe irgendwo gelesen, dass beim SH1106 jede Page in einer eigenen
> I2C Transaktion übertragen werden muss, während man beim SSD1306 alles
> in einem Rutsch übertragen kann.

Das ist u.a. einer der Unterschiede. Auch der ein und andere Spass mit 
dem Cursor muss man etwas anders behandeln wenn ich mich recht entsinne. 
Hat am Ende alles Auswirkung auf Bildwiederholrate und Co, da ist der 
SSD1306 gegenüber dem SH1106 im Vorteil.

von Bernhard S. (bernhard)


Angehängte Dateien:

Lesenswert?

Mal eine kleine Frage an die Spezialisten, wenn ich per TWI/I2C ein FFh 
sende, dann werden 8 vertikale Pixel dargestellt.

Kann man mit FFh auch 8 horizontale Pixel darstellen?

Wenn ja, wie?

Danke

Bernhard


Kleine Anmerkung:

TWI_BIT_RATE=0, TWI_PRESCALER=0

Display Clear, Takt 16MHz, SCL 444,444kHz, 1024Byte (128x64:8) in 11,6ms

mit Assembler

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Bernhard S. schrieb:
> Kann man mit FFh auch 8 horizontale Pixel darstellen?

Nein.

von Paul (Gast)


Lesenswert?

Hallo
hat jemand die Anpassung vom SSD1306 zum SSD1309 gemacht?

von John Doe (Gast)


Lesenswert?

Paul schrieb:
> Hallo
> hat jemand die Anpassung vom SSD1306 zum SSD1309 gemacht?

Was machen Deine eigenen Versuche nach den Hinweisen von gestern?

von Paul (Gast)


Lesenswert?

Bin nach euren Hinweisen und diesem Beispiel sehr viel weiter gekommen. 
Konnte meine Fehler von ca. 100 auf 7 reduzieren. Was ich nicht verstehe 
ist das:
1
void lcd_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color)
2
  {
3
    if( ((x1 || x2) > DISPLAY_WIDTH-1) || ((y1 || y2) > DISPLAY_HEIGHT-1) ) return;
4
    int dx =  abs(x2-x1), sx = x1<x2 ? 1 : -1;
5
    int dy = -abs(y2-y1), sy = y1<y2 ? 1 : -1;
6
    int err = dx+dy, e2; /* error value e_xy */
7
    while(1)
8
    {
9
        lcd_drawPixel(x1, y1, color);
10
        if (x1==x2 && y1==y2) break;
11
        e2 = 2*err;
12
        if (e2 > dy) { err += dy; x1 += sx; } /* e_xy+e_x > 0 */
13
        if (e2 < dx) { err += dx; y1 += sy; } /* e_xy+e_y < 0 */
14
      }
15
  }
Dieser Teil bringt eine Fehlermeldung:
1
if( ((x1 || x2) > DISPLAY_WIDTH-1) || ((y1 || y2) > DISPLAY_HEIGHT-1) ) return;
Fehlermeldung:
Severity  Code  Description  Project  File  Line
Warning    comparison of constant '127' with boolean expression is 
always false [-Wbool-compare]  ATB_I2C_OLED_L128  D:\AAA 
Technik\Programme AVR 
Studio\ATB_I2C_OLED_L128\ATB_I2C_OLED_L128\oledl128.c  465
Warning    comparison of constant '63' with boolean expression is always 
false [-Wbool-compare]  ATB_I2C_OLED_L128  D:\AAA Technik\Programme AVR 
Studio\ATB_I2C_OLED_L128\ATB_I2C_OLED_L128\oledl128.c  465
[/c]
nicht klar warum das kommt.

von John Doe (Gast)


Lesenswert?

Paul schrieb:
> Dieser Teil bringt eine Fehlermeldung:
>
1
> if( ((x1 || x2) > DISPLAY_WIDTH-1) || ((y1 || y2) > DISPLAY_HEIGHT-1) ) 
2
> return;
3
>
> Fehlermeldung:
> Severity  Code  Description  Project  File  Line
> Warning    comparison of constant '127' with boolean expression is
> always false [-Wbool-compare]  ATB_I2C_OLED_L128  D:\AAA
> Technik\Programme AVR
> Studio\ATB_I2C_OLED_L128\ATB_I2C_OLED_L128\oledl128.c  465
> Warning    comparison of constant '63' with boolean expression is always
> false [-Wbool-compare]  ATB_I2C_OLED_L128  D:\AAA Technik\Programme AVR
> Studio\ATB_I2C_OLED_L128\ATB_I2C_OLED_L128\oledl128.c  465
> [/c]
> nicht klar warum das kommt.

Steht doch da (Tip: Besorg Dir ein C-Buch...):
Der Ausdruck (x1 || x2) liefert true oder false. Also 1 oder 0 und das 
ist immer < Deiner Display_Width oder Heigth.
Schreib das in vernünftigem C, dann geht das...

von Heini (Gast)


Lesenswert?

... und wieder die Empfehlung ein C Buch zu kaufen

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Paul schrieb:
> Dieser Teil bringt eine Fehlermeldung:

Dieser Teil sieht auch komplett sinnlos aus.

Es wird eine logische ODER-Verknüpfung gemacht (die kann nur 0 oder 1 
liefern, Wahrheitswerte halt), und deren Ergebnis wird dann mit Höhe 
oder Breite des Displays verglichen.

Was zum Geier™ wolltest du damit eigentlich ausdrücken?

von John Doe (Gast)


Lesenswert?

Jörg W. schrieb:
> Paul schrieb:
>> Dieser Teil bringt eine Fehlermeldung:
>
> Dieser Teil sieht auch komplett sinnlos aus.
>
> Es wird eine logische ODER-Verknüpfung gemacht (die kann nur 0 oder 1
> liefern, Wahrheitswerte halt), und deren Ergebnis wird dann mit Höhe
> oder Breite des Displays verglichen.
>
> Was zum Geier™ wolltest du damit eigentlich ausdrücken?

Ziemlich offensichtlich wollte er:
1
if( (x1 > (DISPLAY_WIDTH-1)) || (x2 > (DISPLAY_WIDTH-1))...
schreiben...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

John Doe schrieb:
> Ziemlich offensichtlich wollte er:

OK, überzeugt. :-)

Gut'nacht!

von Paul (Gast)


Lesenswert?

Nicht ganz so schnell. Versuche die Sache zu begreiffen.

Paul schrieb:
> void lcd_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2,
> uint8_t color)
>   {
>     if( ((x1 || x2) > DISPLAY_WIDTH-1) || ((y1 || y2) >
> DISPLAY_HEIGHT-1) ) return;

Wenn ich das richtig verstehe erfolgt die Eimgabe für eine Linie als 
Anfangspunkt und Endpunkt in der Richtung x und y. Dabei wird 
kontrolliert das die eingebenen Punkte nicht ausserhalb der zulässigen 
angebenen Grösse liegen, ansonsten Begrenzung?

von John Doe (Gast)


Lesenswert?

Paul schrieb:
> Wenn ich das richtig verstehe erfolgt die Eimgabe für eine Linie als
> Anfangspunkt und Endpunkt in der Richtung x und y. Dabei wird
> kontrolliert das die eingebenen Punkte nicht ausserhalb der zulässigen
> angebenen Grösse liegen, ansonsten Begrenzung?

Nö, nix Begrenzung.

von Paul (Gast)


Lesenswert?

Es ist doch eine Begrenzung mit x und y drin. Wie wird das sonst 
gemacht?

von Dr. MCU (Gast)


Lesenswert?

Paul schrieb:
> Es ist doch eine Begrenzung mit x und y drin. Wie wird das sonst
> gemacht?

Mal abgesehen von Deinen falschen Statements springst Du mit return 
einfach zurück, wenn x- oder der y-Wert ausserhalb der 
Displaykoordinaten liegen.
Zudem hast Du eine void-Funktion und somit erkennt der Aufrufer auch 
nicht, ob da nun was gezeichnet wurde.
Besser wäre (je nach gewünschtem Effekt):
- Entweder bei Überschreiten der Max-Werte einfach den Max-Wert als 
Koordinate setzen
- Oder einen Boolean-Wert zurückgeben, der anzeigt, ob ein Fehler 
vorliegt oder nicht

von M. K. (sylaina)


Lesenswert?

Paul schrieb:
> void lcd_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2,
> uint8_t color)
> 2  {
> 3    if( ((x1 || x2) > DISPLAY_WIDTH-1) || ((y1 || y2) >
> DISPLAY_HEIGHT-1) ) return;

Das ist doch nicht meine aktuelle drawLine-Funktion. Schau doch noch mal 
ins github und lade dir die aktuelle Library. ;)

Dr. MCU schrieb:
> Mal abgesehen von Deinen falschen Statements springst Du mit return
> einfach zurück, wenn x- oder der y-Wert ausserhalb der
> Displaykoordinaten liegen.

Genau das war die Idee meines Gedankens: Ich wollte nur nicht außerhalb 
des Displays zeichnen. Auf Return-Werte hatte ich hier übrigens bewusst 
verzichtet getreu dem Motto keep it simple, natürlich wäre es sauberer 
wenn man zumindest einen Bool-Wert zurückgeben würde um zu sehen ob die 
Funktion zumindest fehlerfrei abgearbeitet wurde.

An die Bereichsüberprüfung wollte ich mich eh noch mal ran setzen da ich 
meine, dass sie in der drawPixel-Methode völlig ausreichen würde, die 
Überprüfungen in den anderen Zeichenfunktionen sind eigentlich 
überflüssig wenn ich das recht in Erinnerung habe.

von Paul (Gast)


Lesenswert?

M. K. schrieb:
> https://github.com/Sylaina/oled-display

Dann ist das neuste von dir. Da hab ich wohl was altes geholt.
Du verwendest auch die Datein zum I2C Bus. Das klappt bei mir nicht. Da 
ich noch andere Module im Bus anschliesse verwende ich eine andere 
Ansteuerung.
Wie kann man das am besten lösen?

LG Paul

von M. K. (sylaina)


Lesenswert?

Welche I2C-Library du verwendest bleibt dir überlassen. Du kannst meine 
Library benutzen um auch deine anderen Devices zu verwenden, du kannst 
auch deine Library benutzen, dann musst du nur in der lcd.c die 
Funktionen lcd_init (hier wird lediglich i2c initialisiert, 
initialisierst du den i2c woanders kannst du diesen Teil 
löschen/auskommentieren), lcd_command und lcd_data entsprechend 
anpassen.

von Paul (Gast)


Lesenswert?

Danke für deine Info, werde es testen. Betreibe mit dem I2C Bus noch 
eine ganze Reihe anderer Module, z.B. ein TFT Farbdisplay 3,2" mit 64000 
Farben. Teilweise sind recht anspruchsvolle Libs dabei.
Paul

von M. K. (sylaina)


Lesenswert?

I2C ist recht überschaubar bzgl Anspruch. ;)

von Stefan F. (Gast)


Lesenswert?

M. K. schrieb:
> I2C ist recht überschaubar bzgl Anspruch.

Ja. Wahrscheinlich meint er, dass die Bibliothek die er benutzen muss 
eine Menge Voraussetzungen hat, die erfüllt sein müssen.

von Paul (Gast)


Lesenswert?

Habe es ausprobiert. Ganz so einfach scheint es doch nicht zu sein. 
Kommen noch eine Reihe von Fehlermeldungen. z.B. Graphicmode, i2ccommand 
usw.
Versuche es durch auskommentieren erst mal zu einer Anzeige zu kommen.
Es klingt so, als ob die Datein von Peter Fleury nichts taugen, da ich 
diese verwende.
Paul

von M. K. (sylaina)


Lesenswert?

Paul schrieb:
> Es klingt so, als ob die Datein von Peter Fleury nichts taugen

Das klingt aber wirklich nur so. Was Peter gemacht hat ist richtig 
richtig gut finde ich.

Beginne bei der Fehlersuche immer beim ersten Fehler, der dir angezeigt 
wird. Viele der Fehler werden nämlich nur Folgefehler sein.

von Joachim B. (jar)


Lesenswert?

M. K. schrieb:
> Was Peter gemacht hat ist richtig
> richtig gut finde ich.

ganz genau, habe selber mit I2C von Fleury angefangen und viel gelernt 
dadurch.
Fehlerhaft, kann nicht sein, die LIB funktioniert perfekt seit 
mindestens 1 Jahrzehnt!

von Tuffi (Gast)


Lesenswert?

Hallo! Tolle Library, habe ich eingebunden funktioniert super. Ich nutze 
auch das 128x32 dank den HInweisen die Anpassung vorgenommen lief 
sofort. Auch die Bitmap-Funktion und die Exe klappt super.

ABER: 1 Problem habe ich. Ich habe nur die Schrift 6x8 von M. Köhler. 
Wie kann ich andere Schriftgrößen erhalten (oder erstellen)? Ich brauche 
am besten 2 weitere, eine die doppelt so groß ist und eine 4x so große.

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.