Forum: Mikrocontroller und Digitale Elektronik Zeichnen eines Punktes mit LCD_Plot_Point


von Heinz (Gast)


Lesenswert?

Hallo
mit diesem Programm sollte ein Punkt an eine bestimmte Stelle auf dem 
Display erscheinen. Die Angabe der Position erfolgt mit x und y. Das 
geht.
Mit y_dots sollte die Grösse des Punktes angegeben werden. Es erscheint 
aber nur ein Pixel auf dem Display. Der Code lässt sich ohne 
Fehlermeldung ausführen. Der Aufruf erfolgt damit:
1
LCD_Plot_Point(20, 20, 5);    // Setzt Punkt an diese Position
1
void LCD_Plot_Point(uint8_t x, uint8_t y,uint8_t y_dots)    
2
  {
3
  // set Beginn X-Position (Display-Top)
4
  uint8_t xpos;
5
  uint8_t ypos;
6
  xpos = x;
7
  ypos = (y/8)*2;
8
  uint8_t disp_data = y_dots;
9
  // make 2 Bytes from disp_data
10
  uint16_t disp_data1 = 0;
11
  for (uint8_t j=0; j<=8; j++)
12
    {
13
    uint16_t bit1 = disp_data & (1<<j);
14
    disp_data1 += (bit1 << j);
15
    }
16
  uint16_t disp_data2 = (disp_data1<<1);
17
  disp_data1 += disp_data2;
18
  uint8_t disp_data_h = (disp_data1>>8);
19
  uint8_t disp_data_l = (disp_data1&0b11111111);
20
  
21
  // High und Low Byte ans Display senden
22
  lcd_moveto_xy(ypos,xpos);
23
  lcd_data(disp_data_l);
24
  lcd_moveto_xy(++ypos,xpos);
25
  lcd_data(disp_data_h);
26
}
Die Funktion habe ich damit eingebunden.
1
void LCD_Plot_Point(uint8_t x, uint8_t y,uint8_t y_dots);
Es erscheint aber nur ein Punkt mit einem Pixel. Jemand eine Idee wo der 
Fehler liegt?
LG Heinz

von leo (Gast)


Lesenswert?

Heinz schrieb:
> xpos = x;

Wieso speicherst du die Funkionsparameter um?

>   for (uint8_t j=0; j<=8; j++)

Off by one.

Mehr habe ich mir auf die Schnelle nicht angesehen.

leo

von Stefan F. (Gast)


Lesenswert?

Führe es im Debugger aus und schau Dir dabei die Variablen an. Dann 
siehst du den Fehler sicher. Es sei denn, du hast den Algorithmus ohne 
Nachdenken abgeschrieben.

Wenn du deinen µC nicht debuggen kannst, dann mache einfach ein 
gewöhnliches PC Programm daraus, welches die lcd_xxx Aufrufe 
protokolliert:
1
#include <stdio.h>
2
#include <stdint.h>
3
4
void LCD_Plot_Point(uint8_t x, uint8_t y,uint8_t y_dots)
5
  {
6
  // set Beginn X-Position (Display-Top)
7
  uint8_t xpos;
8
  uint8_t ypos;
9
  xpos = x;
10
  ypos = (y/8)*2;
11
  uint8_t disp_data = y_dots;
12
  // make 2 Bytes from disp_data
13
  uint16_t disp_data1 = 0;
14
  for (uint8_t j=0; j<=8; j++)
15
  {
16
    uint16_t bit1 = disp_data & (1<<j);
17
    disp_data1 += (bit1 << j);
18
  }
19
  uint16_t disp_data2 = (disp_data1<<1);
20
  disp_data1 += disp_data2;
21
  uint8_t disp_data_h = (disp_data1>>8);
22
  uint8_t disp_data_l = (disp_data1&0b11111111);
23
24
  // High und Low Byte ans Display senden
25
  printf("lcd_moveto_xy(%d,%d)\n",ypos,xpos);
26
  printf("lcd_data(%d)\n",disp_data_l);
27
  printf("lcd_moveto_xy(%d,%d)\n",++ypos,xpos);
28
  printf("lcd_data(%d)\n",disp_data_h);
29
}
30
31
int main()
32
{
33
    printf("Start\n");
34
    LCD_Plot_Point(20, 20, 5);
35
    printf("Ende\n");
36
    return 0;
37
}

Das kannst du prima in der C IDE deines Vertrauens (z.B. QT Creator) 
debuggen. Bei mir erzeugt es diese Ausgabe:
1
Start
2
lcd_moveto_xy(4,20)
3
lcd_data(51)
4
lcd_moveto_xy(5,20)
5
lcd_data(0)
6
Ende

Musst du nicht einer einer Wiederholschleife auf das LCD zugreifen, 
welche die Kreisfläche aus zahlreichen Linien zusammensetzt?

von leo (Gast)


Lesenswert?

Heinz schrieb:
> Die Angabe der Position erfolgt mit x und y. Das
> geht.
> Mit y_dots sollte die Grösse des Punktes angegeben werden.

BTW: das gibt es schon, vielfach und richtig, nennt sich z.B. 
"fillCircle()".
Nimm sowas und fertig.

leo

von Heinz (Gast)


Lesenswert?

Hallo
leo schrieb:
> BTW: das gibt es schon, vielfach und richtig, nennt sich z.B.
> "fillCircle()".
> Nimm sowas und fertig.
Habe nach Beispielen gesucht und einiges gefunden. Teilweise 
unverständlich für mich da es einfach zu gross und kompliziert ist oder 
nur ein paar Zeilen ohne Zusammenhang. Kennst du was einfaches was ich 
auch verstehe?

von Heinz (Gast)


Lesenswert?

Habe einiges vereinfacht. Fehler werden nicht angezeigt und habe eine 
Begrenzung eingebaut, Die zweite fehlt noch. Das Programm sieht jetzt so 
aus:
1
void LCD_Plot_Point(uint8_t x, uint8_t y,uint8_t ydots)
2
  {
3
  // Begrenzung Y 0-25x4
4
  y= (y/4);
5
  // make high- and low-Byte
6
  uint16_t ydots_low = 0;
7
  for (uint8_t j=0; j<=8; j++)
8
    {
9
    uint16_t bit1 = ydots & (1<<j);
10
    ydots_low += (bit1 << j);
11
    }
12
  uint16_t ydots_high = (ydots_low<<1);
13
  ydots_low += ydots_high;
14
  ydots_high = (ydots_low >> 8);
15
  ydots_low = (ydots_low & 0b11111111);
16
  // sende high und low Byte zum display
17
  lcd_moveto_xy(y,x);
18
  lcd_data(ydots_low);
19
  lcd_moveto_xy(++y,x);
20
  lcd_data(ydots_high);
21
  }
Die Eingabe mit lcd_moveto_xy klappt ohne Probleme. Wenn ich das richtig 
sehe wird ydots in einem high und low Bit gespeichert.
Wie wird dabei ein grösserer Punkt gezeichnet, versteh ich nicht?
Bitte um etwas Aufhellung oder Fehler?
LG Heinz

von Egonwalter M. (heiner1234)


Lesenswert?

Hallo

Du hast übrigens IMMER NOCH den Fehler drin, den leo in Beitrag #2 
bemängelt hat - solltest die Beiträge genauer durchlesen ...

von c-hater (Gast)


Lesenswert?

Egonwalter M. schrieb:

> Du hast übrigens IMMER NOCH den Fehler drin, den leo in Beitrag #2
> bemängelt hat - solltest die Beiträge genauer durchlesen ...

Der will doch garnix lesen, denken oder lernen. Der will nur eins: 
fertigen Code, den er C&Pen kann.

Ein typischer Arduidiot halt.

von Heinz (Gast)


Lesenswert?

leo schrieb:
>>   for (uint8_t j=0; j<=8; j++)
>
> Off by one.

Sorry, habe das Stück gelesen und noch mal in mein C-Buch geschaut. Mir 
ist leider unklar was das für ein Fehler ist. Die schreibweise stimmt 
genau mit dem Buch überein. Ich will einen Code nicht einfach kopieren, 
ich will in (soweit möglich) auch verstehen.

von Egonwalter M. (heiner1234)


Lesenswert?

Du kopierst Dir anscheinend alles irgendwo zusammen.

Hast Du Dir mal diese FOR Schleife GENAU angesehen? Offensichtlich 
nicht, Bücher bringen da nix, da da nicht die Lösung explizit aufgeführt 
ist.

Tipp: schau Dir die Bereichsgrenzen mal GENAU an - speziell WIE WEIT 
Dein "j" läuft (aber jetzt mußte es kapiert haben).

c-hater hat wohl recht ...

c-hater schrieb:
> Der will doch garnix lesen, denken oder lernen. Der will nur eins:
> fertigen Code, den er C&Pen kann.

von zitter_ned_aso (Gast)


Lesenswert?

Die for-Schleife wird 9 mal durchlaufen.

ein uint8_t-Datentyp hat 8 bits. Du jonglierst dort doch mit einzelen 
Bytes oder?

von Johann J. (johannjohanson)


Lesenswert?

c-hater schrieb:
> Der will nur eins:
> fertigen Code, den er C&Pen kann.

Hat er doch:

Beitrag "Re: Library für EA-DOGM Grafikdisplays inkl. Font-Generator"

Mit der Anpassung hapert es halt.

von Yalu X. (yalu) (Moderator)


Lesenswert?

@Heinz:

Ich glaube, du hast nicht verstanden, was die Funktion LCD_Plot_Point
überhaupt tut, zumal ihr Name irreführend gewählt ist. Hier ist mal eine
kurze Beschreibung:

1
Argumente:
2
  x:      x-Koordinate 0, 1, 2, 3, ... 159
3
  y:      y-Koordinate 0, 8, 16, 24 ... 96 (sollte durch 8 teilbar sein)
4
  ydots:  Bitmuster, die einzelnen Bits b0, b1, b2 ... b7 repräsentieren
5
          jeweils ein Pixel. Ein 1-Bit wird dabei in der Vordergrund-,
6
          ein 0-Bit in der Hintergrundfarbe des Displays dargestellt.
7
8
Die Funktion schreibt das 8-Bit-Bitmuster ydots wie folgt auf das
9
Display:
10
11
       0    1    2            x           158  159
12
    ┌────┬────┬────┬ ─ ─ ─ ┬────┬ ─ ─ ─ ┬────┬────┐
13
 0  │    │    │    │       │    |       │    │    │
14
    ├────┼────┼────┼ ─ ─ ─ ┼────┼ ─ ─ ─ ┼────┼────┤
15
 1  │    │    │    │       │    |       │    │    │
16
    ├────┼────┼────┼ ─ ─ ─ ┼────┼ ─ ─ ─ ┼────┼────┤
17
 2  │    │    │    │       │    |       │    │    │
18
    ├────┼────┼────┼ ─ ─ ─ ┼────┼ ─ ─ ─ ┼────┼────┤
19
    ╎    ╎    ╎    ╎       ╎    ╎       ╎    ╎    ╎
20
    ╎    ╎    ╎    ╎       ╎    ╎       ╎    ╎    ╎
21
    ├────┼────┼────┼ ─ ─ ─ ┼────┼ ─ ─ ─ ┼────┼────┤
22
 y  │    │    │    │       │ b0 |       │    │    │
23
    ├────┼────┼────┼ ─ ─ ─ ┼────┼ ─ ─ ─ ┼────┼────┤
24
y+1 │    │    │    │       │ b1 |       │    │    │
25
    ├────┼────┼────┼ ─ ─ ─ ┼────┼ ─ ─ ─ ┼────┼────┤
26
y+2 │    │    │    │       │ b2 |       │    │    │
27
    ├────┼────┼────┼ ─ ─ ─ ┼────┼ ─ ─ ─ ┼────┼────┤
28
y+3 │    │    │    │       │ b3 |       │    │    │
29
    ├────┼────┼────┼ ─ ─ ─ ┼────┼ ─ ─ ─ ┼────┼────┤
30
y+4 │    │    │    │       │ b4 |       │    │    │
31
    ├────┼────┼────┼ ─ ─ ─ ┼────┼ ─ ─ ─ ┼────┼────┤
32
y+5 │    │    │    │       │ b5 |       │    │    │
33
    ├────┼────┼────┼ ─ ─ ─ ┼────┼ ─ ─ ─ ┼────┼────┤
34
y+6 │    │    │    │       │ b6 |       │    │    │
35
    ├────┼────┼────┼ ─ ─ ─ ┼────┼ ─ ─ ─ ┼────┼────┤
36
y+7 │    │    │    │       │ b7 |       │    │    │
37
    ├────┼────┼────┼ ─ ─ ─ ┼────┼ ─ ─ ─ ┼────┼────┤
38
    ╎    ╎    ╎    ╎       ╎    ╎       ╎    ╎    ╎
39
    ╎    ╎    ╎    ╎       ╎    ╎       ╎    ╎    ╎
40
    ├────┼────┼────┼ ─ ─ ─ ┼────┼ ─ ─ ─ ┼────┼────┤
41
102 │    │    │    │       │    |       │    │    │
42
    ├────┼────┼────┼ ─ ─ ─ ┼────┼ ─ ─ ─ ┼────┼────┤
43
103 │    │    │    │       │    |       │    │    │
44
    └────┴────┴────┴ ─ ─ ─ ┴────┴ ─ ─ ─ ┴────┴────┘

Um ein einzelnes Pixel an einer beliebigen x-y-Position zu setzen, muss
in ydots  genau 1 Bit an der gewünschten y-Position gesetzt sein. Um zu
verhindern, dass beim Schreiben dieses Bitmusters die vertikal
benachbarten Pixel gelöscht werden, muss das bestehende Bitmuster mit
dem neuen bitweise ODER-verknüpft werden. Betreibst du das DIsplay im
I²C-Modus, kannst du das bestehende Bitmuster aus dem Display auslesen.
In den SPI-Modi hingegen ist kein Lesezugriff möglich, weswegen du eine
Kopie des Displayinhalts in einem Array auf deinem µC vorhalten musst.
Wie das genau geht, zeigt dir der restliche Code aus der Quelle, von der
du LCD_Plot_Point kopiert hast.

von Johann J. (johannjohanson)


Lesenswert?

Yalu X. schrieb:
> Um ein einzelnes Pixel an einer beliebigen x-y-Position zu setzen, muss
> in ydots  genau 1 Bit an der gewünschten y-Position gesetzt sein. Um zu
> verhindern, dass beim Schreiben dieses Bitmusters die vertikal
> benachbarten Pixel gelöscht werden, muss das bestehende Bitmuster mit
> dem neuen bitweise ODER-verknüpft werden.

Die Funktion ist aus meiner Sicht nur für Rolfs Zwecke (eine "Waveform" 
mit möglichst wenig Speicherverbrauch und ohne Puffer zeichnen) 
sinnvoll. Zumal auch er erkannt hat, dass diese noch fehlerhaft ist 
("Pixelfehler"). Übrigens kann ich nicht erkennen, dass er etwas 
"verodert" - kann aber auch sein, dass meine Brille nicht richtig sitzt 
:-)

Sinnvoll wären x- und y-Angabe und die Funktion macht den Rest. Das gibt 
es in vielen Librarys, wenn man es nicht selbst erstellen kann oder mag.

Eigentlich müsste die Funktion heißen:

LCD_Plot_Column_Byte(...)

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

Johann J. schrieb:
> Übrigens kann ich nicht erkennen, dass er etwas
> "verodert" - kann aber auch sein, dass meine Brille nicht richtig sitzt
> :-)

Nicht hier, aber dort, wo diese Funktion aufgerufen wird. Falls Heinz
die Funktion von hier

https://www.mikrocontroller.net/attachment/179061/Draw_Waveform.c

hat (was ich vermute), dann geschieht die Veroderung in LCD_Plot_Line.
Deswegen auch mein Hinweis

Yalu X. schrieb:
> Wie das genau geht, zeigt dir der restliche Code aus der Quelle, von der
> du LCD_Plot_Point kopiert hast.

Da gibt es noch eine weitere Version, die etwas logischer aufgebaut ist
und wohl eher dem entspricht, was Heinz sucht:

  https://www.mikrocontroller.net/attachment/179232/Plot_Wave_with_Buffer.c

Ich habe sie mir aber nicht im Detail angeschaut.

von Johann J. (johannjohanson)


Lesenswert?

Yalu X. schrieb:
> Nicht hier, aber dort, wo diese Funktion aufgerufen wird.

Deas zeigt der TO nicht und weiß es mit Sicherheit auch nicht.

Yalu X. schrieb:
> Falls Heinz
> die Funktion von hier
>
> https://www.mikrocontroller.net/attachment/179061/Draw_Waveform.c
>
> hat (was ich vermute), dann geschieht die Veroderung in LCD_Plot_Line.
> Deswegen auch mein Hinweis

Das hat aber dann nichts mit dem "LCD_Plot_Point" zu tun, woran er 
"nagt" ...

von Heinz (Gast)


Lesenswert?

Es stimmt. Ich "nage" an verschiedenen Problemen. Andere Probleme habe 
ich in den Griff bekommen. Warum darf ich nachfragen, wenn man etwas 
nicht versteht. Manche von euch haben es studiert, andere arbeiten seit 
Jahren damit. Andere (so wie ich) betreiben es als Hobby und versuchen 
etwas damit zu machen. Dadurch erreiche ich mene Grenzen recht schnell. 
Manche Sachen verstehe ich und mache einiges selber. Dies versteh ich 
"noch" nicht und frage bei euch nach. Es gibt Probleme, die sind für ein 
Hobbybastler nicht so schnell zu verstehen. Hoffe auf eure Hilfe dabei.
Es stimmt genau, die Sachen stammen von den Seiten. Habe sie kopiert und 
in mein Programm eingebunden. Bestimmte Stellen habe ich angepasst. Die 
main habe ich selber geschrieben und teste zur Zeit alle Befehle in wie 
weit sie funktionieren und wie die Eingabeparameter sind. Schreibe dann 
noch einige Begrenzungen dazu und teste weiter.
Danke für eure Hinweise, werde alles lesen und hoffentlich auch 
verstehen.
LG Heinz

von Johann J. (johannjohanson)


Lesenswert?

Heinz schrieb:
> Es stimmt.

Hallo Heinz,

es kommt halt nicht so gut an, wenn Du etwas darstellst, als wäre es 
"auf Deinem Mist gewachsen" und Du hast nur ein kleines Problem.

Schreibe, was Du machen willst, mit welchem Microcontroller (z.B. 
Atmega328), in Deinem Fall welchem Display (Link zum Hersteller) und 
welcher Library (Link zur Library) Du das lösen willst. Dann kann Dir 
vielleicht geholfen werden.

Hier weiß  niemand, was Du womit genau machst und wo Dein Problem ist. 
Hilfreich sind immer auch Schaltpläne - oder falls nicht möglich - 
"scharfe" Bilder Deines Aufbaus. Hier besitzt niemand die berühmte 
Glaskugel.

VG
Johann

von Heinz (Gast)


Angehängte Dateien:

Lesenswert?

Sorry, das ich das nicht gemacht habe. Arbeite mit einem Atmega 128 mit 
16MHz in C, mit dem I2C Bus mit 100kHz, verwende ein Display von EA DOG 
XL160W-7 mit Hintergrundbeleuchtung RGB mit der Betriebsart I2C Bus. Das 
Display wird vom Bus erkannt und angesprochen z.B. Schrift oder BMP.
Das Datenblatt des Herstellers habe ich angehängt. Leider ist das so 
ziemlich das einzigste was der Hersteller reingestellt hat. Auch im Netz 
findet man nur sehr wenig zu diesem Graphik Display (ausser Werbung und 
Verkauf). Daher muss ich einige Sachen von allgemeinen Programmen 
ableiten und das hat wohl nicht geklappt.

von Heinz (Gast)


Lesenswert?

Sorry, vergessen. Vom Hersteller gibt es keine Lib dazu. Habe nur das 
gefunden was auch ihr angegeben habt

von Yalu X. (yalu) (Moderator)


Lesenswert?

Heinz schrieb:
> dogxl160-7_Datenblatt.pdf
> ...
> Leider ist das so ziemlich das einzigste was der Hersteller
> reingestellt hat.

Nicht ganz.

Wenn du heruntergeladene Bibliotheksroutinen für das Display besser
verstehen möchtest oder deine eigenen schreiben möchtest, solltest du
dir zusätzlich das Datenblatt des Displaycontrollers (UC1610) zu Gemüte
führen:

  https://www.lcd-module.de/fileadmin/eng/pdf/zubehoer/uc1610_v1_36.pdf

Dieser Controller ist Bestandteil des Displaymoduls und das Bindeglied
zwischen deinem ATmega128 und dem eigentlichen LCD. Im Datenblatt ist
u.a. der Befehlssatz des Controllers und die Organisation des
Displayspeichers beschrieben. Solange du diese beiden Dinge nicht
halbwegs verstanden hast, wirst du bei der Displayprogrammierung immer
wieder auf Schwierigkeiten stoßen.

Wenn du nach weiterer Software für das DOGXL-Display suchst, kannst du
stattdessen auch nach Software für den UC1610 suchen.

von Heinz (Gast)


Lesenswert?

Das werde ich machen.

Yalu X. schrieb:
> Dieser Controller ist Bestandteil des Displaymoduls und das Bindeglied
> zwischen deinem ATmega128 und dem eigentlichen LCD. Im Datenblatt ist
> u.a. der Befehlssatz des Controllers und die Organisation des
> Displayspeichers beschrieben. Solange du diese beiden Dinge nicht
> halbwegs verstanden hast, wirst du bei der Displayprogrammierung immer
> wieder auf Schwierigkeiten stoßen.

Den Befehlssatz dieses Controllers versteh ich nicht. Da fehlt bei mir 
noch eine ganze Menge dazu.

von Johann J. (johannjohanson)


Lesenswert?

Heinz schrieb:
> Den Befehlssatz dieses Controllers versteh ich nicht. Da fehlt bei mir
> noch eine ganze Menge dazu.

Das war doch schon ein prima Hinweis - google doch mal nach z.B. Arduino 
und UC1610 ...

Es gibt oft eine "Vielzahl" von Displays, welche mit dem gleichen 
Befehlssatz angesprochen werden können (gleicher Controller). Dazu gibt 
es dann auch ggf. Librarys, welche bei der Nutzung hilfreich sind.

: Bearbeitet durch User
von Heinz (Gast)


Lesenswert?

Habe nach dem UC1610 gesucht. Entweder gleiche Problem oder andere 
Probleme, ansonsten nicht viel zu finden, leider, such weiter

von Stefan F. (Gast)


Angehängte Dateien:

Lesenswert?

Heinz schrieb:
> Wie wird dabei ein grösserer Punkt gezeichnet, versteh ich nicht?

Tja, die Frage hatte ich bereits an dich gerichtet. Es ist schließlich 
dein Code, oder doch nicht?

Wenn du von jemandem Kopiert hast, dann frage doch den Autor.

Ich hänge Dir mal einen funktionierenden Algorithmus an, den ich von 
Wikipedia habe. Da kannst du gut sehen, dass die Kreisfläche aus einer 
Reihe von Linien zusammengesetzt wird.

von Johann J. (johannjohanson)


Lesenswert?

Heinz schrieb:
> nicht viel zu finden

Merkwürdig

https://www.google.com/search?q=arduino+UC1610&oq=arduino+UC1610&aqs=chrome..69i57j69i59.3855j0j7&sourceid=chrome&ie=UTF-8

kann es sein, dass Du mit "Englisch" nicht so gut zurecht kommst?

Das wirst Du in der Microcontroller-Welt aber brauchen. Zur Not hilft 
das Browser-Übersetzungstool oder Google-Sprachtools oder ...

: Bearbeitet durch User
von Heinz (Gast)


Lesenswert?

Habe nicht nach Arduino gesucht.
Es stimmt genau, durfte kein englisch lernen. War vom System nicht 
erwünscht. Jetzt fällt es mir sehr schwer damit. Benutze ein übersetzer 
und hoffe das was da raus kommt ich auch versteh.

von Heinz (Gast)


Lesenswert?

Hatte schon mehrmals drauf hingewiesen das der Code nicht von mit stammt 
und den Autor angegeben und die Stellen im Netz dazu

von Heinz (Gast)


Lesenswert?

Wenn ich das richtig verstanden habe besteht das Display aus

x = 0-159 Zeilen , sind 160 Zeilen
y = 0-103 Spalten, sind 104 Spalten

In jedes Feld bestehen aus der x und y Adresse wird ein Wert gesetzt. 
Bei diesem display kann das 0 oder 4 sein, entweder aus - keine 
Hintergrundfarbe oder 4 - Feld hat Hintergrundfarbe - dunkel.
Nach Angabe des Herstellers sind auch 2 und 3 möglich - unterschiedliche 
Grautöne.
1
lcd_moveto_xy(y,x);
2
  lcd_data(ydots_low);
3
  lcd_moveto_xy(++y,x);
4
  lcd_data(ydots_high);
mit diesem Code wird an der Adresse moveto_xy ein Feld gesetzt bzw. 
daneben.
Muss mal was grundsätzliches fragen: wird mit dem Code ein Punkt mit 
einem Pixel gesetz oder ein grösserer Punkt mit Angabe des Durchmessers 
(ydot)?
Würde Teil 2 sagen.
Beim Rest bin ich am schauen

von Yalu X. (yalu) (Moderator)


Lesenswert?

Heinz schrieb:
> Muss mal was grundsätzliches fragen: wird mit dem Code ein Punkt mit
> einem Pixel gesetz oder ein grösserer Punkt mit Angabe des Durchmessers
> (ydot)?

Ich habe oben versucht, dies anhand einer Skizze zu erklären:

Yalu X. schrieb:
> Die Funktion schreibt das 8-Bit-Bitmuster ydots wie folgt auf das
> Display:
>
> ...

Wie du richtig erkannt hast, wird im UC1610 jedes Pixel durch 2 Bits
repräsentiert, um 4 Graustufen, nämlich weiß, hellgrau, dunkelgrau und
schwarz darstellen zu können. Das DOGGXL kann das wohl nur weiß (beide
Bits 0) und schwarz (beide Bits 1), d.h. jedes Bit aus ydots muss
verdoppelt werden, was in diesem Ausschnitt von LCD_Plot_Point getan
wird:

Heinz schrieb:
> int16_t ydots_low = 0;
>   for (uint8_t j=0; j<=8; j++)
>     {
>     uint16_t bit1 = ydots & (1<<j);
>     ydots_low += (bit1 << j);
>     }
>   uint16_t ydots_high = (ydots_low<<1);
>   ydots_low += ydots_high;

Wenn also bspw.

  ydots = 01001110₂

dann ist

  ydots_low = 0011000011111100₂.

Dieser 16-Bit-Wert wird als 2 Bytes in den Displayspeicher geschrieben
und auf dem LCD an der gewünschten Stelle als

1
    W
2
    S
3
    W
4
    W
5
    S
6
    S
7
    S
8
    W

(W=weiß, S=schwarz) angezeigt.

von Heinz (Gast)


Lesenswert?

So weit bin noch nicht gekommen. Hänge noch an der Stelle

Heinz schrieb:
> uint16_t disp_data1 = 0;
>   for (uint8_t j=0; j<=8; j++)
>     {
>     uint16_t bit1 = disp_data & (1<<j);
>     disp_data1 += (bit1 << j);
>     }

Wenn ich es richtig sehe erfolgt eine Bitverschiebung.

Heinz schrieb:
> uint8_t disp_data_h = (disp_data1>>8);
>   uint8_t disp_data_l = (disp_data1&0b11111111);

Unklar ist ... grübel,grübel ...

von leo (Gast)


Lesenswert?

Heinz schrieb:
>> uint8_t disp_data_h = (disp_data1>>8);
>>   uint8_t disp_data_l = (disp_data1&0b11111111);
>
> Unklar ist ... grübel,grübel ...

Ich wuerde raten, mit einem 1-bit Display zu beginnen, dann blinken, ...

leo

von Heinz (Gast)


Lesenswert?

Hallo
Der Text von leo soll wahrscheinlich bedeuten mit einem einfachen 
Display anzufangen und erst einmal die Grundlagen lernen, vieleicht auch 
noch anders gemeint. Ich stimme der Sache aber vollkommen zu. Sag mir 
einfach wie ich beginnen soll, mit welchem Display, welcher Aufbau oder 
Hersteller. Aber  bitte nicht mit 1+1 anfangen. Habe bereits 
verschiedene Displays mit dem I2C Bus zum laufen bekommen und dabei auch 
Libs selber geschrieben.
Kennst du vielleicht auch eine gute Literaturstelle oder Tut dazu. Werde 
die genannten Stellen dazu anschauen.
LG Heinz

von Stefan F. (Gast)


Lesenswert?

Grafikroutinen kann man auch prima auf dem PC als Windows Programm üben. 
Oder im Browser mit Javascript und dem Canvas Objekt.

Wenn man einzelne Pixel malen kann, hat man eine Basis auf der alle 
weiteren Grafiken aufbauen können. Performanceoptimierung würde ich erst 
später angehen. Oft ist die Performance ziemlich egal, so dass man seine 
Freizeit in erquickendere Arbeiten stecken kann. Zb durchdachte 
Benutzerinterface und schöne Bilder.

von Egonwalter M. (heiner1234)


Lesenswert?

Hallo

Stefanus F. schrieb:
> Grafikroutinen kann man auch prima auf dem PC als Windows Programm üben.
> Oder im Browser mit Javascript und dem Canvas Objekt.

damit ist Heinz wohl weniger geholfen ... das muss er dann ja auf "AVR - 
C" portieren, und da wird's wohl wieder ....

@Heinz
Du hast doch schon Grafik für andere Displays benutzt und selbst Libs 
dafür erstellt - gibt es da keine "Synergie-Effekte"?

Fkt denn die reine Textausgabe auf dem Display oder WO GENAU klemmt es?

Und wg links - die hast Du - zumindest in diesem Thread - nicht 
gepostet, nur den Namen - hast Du Dich schon an ihn mit Deinen Problemen 
gewendet?

von Heinz (Gast)


Lesenswert?

Hallo
habe bereits andere Displays in Betrieb genommen. Sind meistens welche 
von EA mit I2C Bus. Leider ergibt sich dabei kein Synergie-Effekt, da 
die Libs sich grundsätzlich unterscheiden.
1
void TFT32_loeschen(void)
2
  {
3
  int8_t e;
4
  e = 0;
5
  int8_t bcc;
6
  bcc = DC1 + 0x03 + ESC + 'D' + 'L' ;
7
  i2c_start(slave_adresse_1);
8
  i2c_write(DC1);    // 0x11
9
  i2c_write(0x03);  // len 03
10
  i2c_write(ESC);    // 0x1b
11
  i2c_write('D');    // D
12
  i2c_write('L');    // L
13
  i2c_write(bcc);
14
  i2c_stop();  
15
  _delay_us(20);
16
  i2c_start(slave_adresse_2);
17
  e = i2c_readAck();
18
  i2c_stop();
19
  itoa( e, Buffer, 10 );  
20
  //lcd_printlc(4,6,Buffer);
21
  _delay_us(20);
22
   }
Habe mal ein Stück zur Ansicht vom TFT Display angehängt. Ist ganz 
anders aufgebaut. Teilweise muss ich bei diesem Display 20 und mehr 
Parameter übergeben.
Die Ausgabe von Text und Bildern mit bmp klappt ohne Probleme.
Habe auch bei der Graphik weiter gemacht. Linie von A nach B (schräg) 
funktioniert. Linie waagerecht auch, Löschen Display, Set Point und 
einige andere auch. Bin auf ein neues Problem gestossen. Es geht dabie 
um diesen Code:
1
void LCD_Plot_Vline(uint8_t x, uint8_t y, uint8_t h)    // x Start w, y start s, h Länge  ori
2
  {
3
  uint8_t yp;
4
  for(yp = y; yp <= y + h - 1; yp++)
5
    {
6
    LCD_Plot_Point(x, yp, 1);       
7
    }
8
  }
Funktion:
x - Angabe Start waagerecht
y - Angabe Start senkrecht
h - Angabe senkrechter Strich
Es wird von y nach y+h gezählt, dabei bleibt x immer gleich, es sollte 
ein senkrechter Strich mit der Länge h erscheinen
Ergebnis:
Es erscheint an der angegebenen Position ein Strich senkrecht aber mit 
Unterbrechung. Es wird scheinbar nur an jedem 8 Stelle des Striches ein 
Punkt dargestellt, sieht aus wie eine Punktlinie mit Unterbrechung.
Idee dazu?
LG Heinz

von spess53 (Gast)


Lesenswert?

Hi

>Leider ergibt sich dabei kein Synergie-Effekt, ...

Wie sollte auch? Du vergleichst ein blankes DOG160 mit einem 
'intelligenten' TFT-Display.

MfG Spess

von Heinz (Gast)


Lesenswert?

Ich vergleiche gar nichts. Die Frage war ob sich Synergie Effekte 
ergeben. Habe das mit Ansicht dieser Zeile den Unterschied dargestellt 
und klar gesagt das es nicht geht.
Sagen wir es dann ganz einfach, vergiss diesen code, er passt überhaupt 
nicht zum XL160, was ich niemals gesagt habe. Bitte die Antwort genau 
lesen

von Yalu X. (yalu) (Moderator)


Lesenswert?

Wenn ich das richtig sehe, entspricht das eDIP160-7 einem DOGXL160-7 mit
eingebauten Text- und Grafikfunktionen, die denen deines TFT-Displays
gleich oder zumindest sehr ähnlich sind. Du kannst ja mal die Befehle in
den Datenblättern vergleichen.

Wenn du mit dem DOG nicht weiterkommst, wäre somit das eDIP eine Option.

von Heinz (Gast)


Lesenswert?

Yalu X. schrieb:
> Wenn ich das richtig sehe, entspricht das eDIP160-7 einem DOGXL160-7 mit
> eingebauten Text- und Grafikfunktionen,

Deine Annahme stimmt nur Teilweise. Auch das Edip hat einen Prozessor 
drin und kann auf den I2C Bus eingestellt werden. Habe leider nicht so 
schnell gefunden welcher Prozessor drin ist. Die Grösse des Display ist 
identisch, ob gleicher Aufbau oder Typ ist noch unklar. Die Ansteuerung 
erfolgt noch meinem Beispiel und ist damit wieder unterschiedlich. Die 
Idee dazu ist aber gut, schade.
LG Heinz

von Johann J. (johannjohanson)


Lesenswert?

Heinz schrieb:
> Idee dazu?

Ja - Du hast das

Beitrag "Re: Zeichnen eines Punktes mit LCD_Plot_Point"

nicht verstanden.

Daher kann dieser Aufruf
1
    LCD_Plot_Point(x, yp, 1);
auch nie zur einer vertikalen Linie führen.

Schau Dir mal hier

https://www.lcd-module.de/deu/pdf/grafik/dogxl160-7.pdf

Seite 6 oben an.

Zeichne mal mit Deinem Aufruf 2 horizontale Linien mit 1 Pixel Abstand 
:-)

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Heinz schrieb:
> Linie von A nach B (schräg)
> funktioniert. Linie waagerecht auch, Löschen Display, Set Point und
> einige andere auch.

Ich habe Dir weiter oben ein Codebeispiel gegeben, welches Kreise und 
Kreisflächen auf Basis von Punkten und Linien zeichnet. Da du Punkte und 
Linien schon hast, hast du die notwendige Basis. Du musst nur den 
Algorithmus für die Kreise kopieren. Es ist doch nur eine einzige C 
Funktion* !

Wie gesagt stammt der Algorithmus von Wikipedia 
(https://de.wikipedia.org/wiki/Bresenham-Algorithmus), dort ist er 
detailliert erklärt (ebenso ein Algorithmus, der schräge Linien 
zeichnet).

*) Genau genommen ist eine C++ Methode, aber sie nutzt nur den 
Sprachumfang von C.

> Es erscheint an der angegebenen Position
> ein Strich senkrecht aber mit Unterbrechung.
> Idee dazu?

Lass das wie in meinem obigen Beispiel auf einem PC (ggf. im Debugger) 
laufen und gebe die LCD Zugriffe in Text_Form auf dem Bildschirm aus. 
Dann siehst du direkt, woran es hapert.

von Johann J. (johannjohanson)


Lesenswert?

Stefanus F. schrieb:
> Da du Punkte und
> Linien schon hast

Das bezweifle ich ...

von Stefan F. (Gast)


Lesenswert?

Johann J. schrieb:
> Stefanus F. schrieb:
>> Da du Punkte und Linien schon hast
>
> Das bezweifle ich ...

Naja, damit muss er auf jeden Fall Anfangen, denn darauf bauen alle 
anderen Figuren auf.

Hardware-optimierte Algorithmen, die nicht auf einzelne Pixel (sondern 
auf Bytes im Bildspeicher) aufsetzen, gibt es natürlich auch. Aber das 
wäre der nächste Optimierungsschritt, von dem ich weiter ob bereits 
abgeraten habe. Erstmal muss man die Grundlagen verstehen und ans Laufen 
bringen.

von Heinz (Gast)


Lesenswert?

Wo finde ich die Grundlagen? Zum Display Typ oder Prozessor Typ? Gibt es 
Tuts dazu?
Die Algorithmen die ihr oben bereits empfohlen habt laufen. Die 
Darstellung von HLinie sind gar nicht so schwer. Warum bezweifelst du 
es?

von Johann J. (johannjohanson)


Lesenswert?

Heinz schrieb:
> Warum bezweifelst du
> es?

Weil Du noch keinen Punkt bzw Pixel "gezielt" setzen kannst. Wenn Du das 
könntest, wäre auch eine vertikale Linie kein Problem.

Zur Verdeutlichung (Yalu hat es ja auch schon geschrieben):

Du kannst einen Punkt bzw. Pixel nur dann gezielt setzen wenn Du bereits 
gesetzte Punkte bzw. Pixel berücksichtigst, da mit einem 
Schreibzugriff immer gleichzeitig mindestens 4 Punkte bzw. Pixel 
vertikal geschrieben werden. Wenn Du die eingangs aufgeführte Funktion 
nutzt sind es 8 Punkte bzw. Pixel.

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

Heinz schrieb:
> Yalu X. schrieb:
>> Wenn ich das richtig sehe, entspricht das eDIP160-7 einem DOGXL160-7 mit
>> eingebauten Text- und Grafikfunktionen,
>
> Deine Annahme stimmt nur Teilweise. Auch das Edip hat einen Prozessor
> drin und kann auf den I2C Bus eingestellt werden.

Eben, und genau auf diesen Prozessor, der die High-Level-Funktionen (wie
bspw. Punkte, Linien und Texte ausgeben) abwickelt, kommt es an. Dein
TFT-Display und das eDIP160-7 haben beide so einen Prozessor, das
DOGXL160-7 aber nicht. Deswegen kostet es beim DOGXL160-7 einige
Anstrengung, um nur ein einzelnes Pixel an den gewünschten
x-y-Koordinaten zu setzen, während das eDIP160-7 einen fertigen Befehl
dafür hat.

> Habe leider nicht so schnell gefunden welcher Prozessor drin ist.

Auf

  https://www.lcd-module.de/datenblaetter.html

unter "Displaykontroller" und dort unter "High-Level-Grafikkontroller"
findest du die Datenblätter dieser Prozessoren. Deren Anschlussbelegung
deutet daruf hin, dass es sich um 8051-kompatible Mikrocontroller
handelt, die wohl von EA mit den Grafikfunktionen programmiert worden
sind.

Die Grafikbefehle, die dieser Prozessor versteht, sind aber auch in den
Datenblättern der jeweiligen Displays beschrieben.

> Die Grösse des Display ist identisch, ob gleicher Aufbau oder Typ ist
> noch unklar. Die Ansteuerung erfolgt noch meinem Beispiel und ist
> damit wieder unterschiedlich. Die Idee dazu ist aber gut, schade.

Diese beiden Sätze verstehe ich nicht. Wenn die Ansteuerung nach deinem
Beispiel (ich nehme an, du meinst damit die Funktion TFT32_loeschen von
oben) erfolgt, dann ist doch alles perfekt. Du kannst damit deine
bisherige (und schon funktionierende) Software weiterbenutzen. Der
einige Apfel, in den du beißen musst, sind die Kosten für ein neues
Display, das diesen High-Level-Grafik-Chip integriert hat.

Vergleiche einfach mal die Datenblätter von deinem TFT-Display (was ist
eigentlich dessen genaue Typbezeichnung?) und dem eDip160-7 und suche
nach Unterschieden, was deren Ansteuerung und deren Grafikbefehlssatz
betrifft. Ich bin sicher, davon gibt es nur wenige bis gar keine.

von Heinz (Gast)


Lesenswert?

Ein Display vom Typ eDIP TFT32 habe ich auch. Zur Darstellung der Texte 
und anderer Funktionen verwende ich das Programm Stück. Dabei ist die 
Programmierung leichter, da ich nur eine Adresse ansprechen muss.
Beim XL160 sind 2x je 4 Adressn vorgegeben. Das ist schon schwieriger 
für mich. Hatte deshalb die vorhandenen Libs dazu genutzt. Da ja beim 
eDIP die Umschaltung der Adresse mit 6 Jumper möglich ist, vermute ich 
das alles ein bischen neuer ist.
Der Befehlssatz unterscheidet sich deutlich. Beim eDIP verwende ich 
viele Funktionen des Herstellers. Habe in meinem Programm ca. 30 Befehle 
nach C "übersetzt" und angewendet.

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.