Forum: Mikrocontroller und Digitale Elektronik 128x64 GLCD mit U8glib


von Dominic S. (dominic_s78)


Lesenswert?

hallo zusammen,
habe nun vor nach start der MCU auf dem display zwei Logos anzuzeigen.
Der display hat die bezeichnung hj12864zw vom controllertyp ST7920
Ein Logo klappt ohne probleme,
doch wenn ich ein zweites hinterherschicke überlagert sich das.


Ich benutze einen arduino.
Kann mir jemand sagen wie das mit u8glib funktioniert, so etwas wie 
clear lcd vermisse ich hier nämlich.

Hier der code:
1
#include "U8glib.h"
2
#include "logos.h" 
3
/* inhalt von logos.h:
4
#define logo1_breite 128
5
#define logo1_hoehe 64
6
static unsigned char logo1[] U8G_PROGMEM = {
7
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; (gekürzt, die ersten zeilen bleiben leer)
8
*/
9
U8GLIB_ST7920_128X64 u8g(8, 9, 255, U8G_PIN_NONE); //E, R-W, 255=VDD, N.C
10
int blPin = 10;//VDD des Backlights an pin 10
11
int blValue = 255;//Helligkeit von 0-255
12
13
void drawLogo1(void) {
14
  // graphic commands to redraw the complete screen should be placed here  
15
  u8g.drawXBMP( 0, 0, logo1_breite, logo1_hoehe, logo1);
16
}
17
18
void setup(void) {
19
      analogWrite(blPin, blValue); 
20
     
21
  
22
}
23
24
void loop(void) {
25
  // picture loop
26
27
28
  u8g.firstPage();  
29
  do {
30
    drawLogo1();
31
              
32
  } while( u8g.nextPage() );
33
  
34
  // rebuild the picture after some delay
35
  delay(500);
36
}


Ich möchte sagen wir mal nach 2 sekunden das logo 2 einblenden
befehl wäre in meinem fall für das logo 2 einzeln:
1
void drawLogo2(void) {
2
  // graphic commands to redraw the complete screen should be placed here  
3
  u8g.drawXBMP( 0, 0, logo2_breite, logo2_hoehe, logo2);
4
}
5
6
//aufruf mit  drawLogo2();

von Oliver (Gast)


Lesenswert?

Hi

Die einfache Lösung wäre diese hier:

void loop(void) {
  // picture loop


  u8g.firstPage();
  do {
    drawLogo1();
  } while( u8g.nextPage() );

  delay(2000);

  u8g.firstPage();
  do {
    drawLogo2();
  } while( u8g.nextPage() );

  // rebuild the picture after some delay
  delay(500);
}


Die etwas komplexere Lösung benutzt einen Zustandsautomaten.
Zustand 1: Logo 1 darstellen.
Zustand 2: Logo 2.
Zustand 3: Etwas anderes machen.

Die draw routine würde dann entsprechend dem aktuellen Zustand die 
eigentliche Zeichen-Procedur aufrufen. Etwa so:

void draw(void)
{
  switch(state)
  {
    case 1: drawLogo1(); break;
    case 2: drawLogo2(); break;
    case 3: /* etwas anderes zeichen */ break;
  }
}

Die loop procedure sieht dann so aus:
void loop(void) {

  // picture loop
  u8g.firstPage();
  do {
    draw();
  } while( u8g.nextPage() );

  // ändere state je nach abgelaufener zeit
  change_state();

  // rebuild the picture after some delay
  delay(500);
}

Die Konstruktion so eines Zustandsautomaten (led_process) habe ich hier 
beschrieben:
http://code.google.com/p/m2tklib/wiki/t05

Der Bildschirm wird übrigens gelöscht, sobald man u8g.firstPage() 
aufruft.
Deshalb ist auch kein "clear-screen" notwendig. Ich gebe auch gerne zu, 
dass das Konzept von u8glib nicht ganz einfach zu versehen ist, aber 
dafür werden auch Displays unterstützt bei denen man den Graphikspeicher 
nicht zurücklesen kann und das, ohne einen komplettes Abbild des 
Graphikspeichers im Controller halten zu müssen.

Fragen auch gerne direkt an mich (siehe sourcecode).

Oliver

von Dominic S. (dominic_s78)


Lesenswert?

Danke Oliver,

mein problem war in der Tat der U8g Firstpage befehl.. der löscht den 
inhalt und kommt einem clear lcd gleich.

Danke für deine Lösungen.
Besonders die zweite ist interessant.. ich denke da zum beispiel an 
menüs oder der gleichen.

Jetzt werden schonmal zwei klar differenzierte Bilder ohne überlagerung 
angezeigt.Das ist doch das was ich wollte

von Sascha K. (kuschelganxta)


Lesenswert?

Hi,

als kurze Anmerkung zu dem Thema picture loop und Bildschirmaufbau:
Ich habe verschiedene "Screens", die ihre eigene draw()-Funktion haben. 
Dann gibt es eine Funktion Picture_Loop, die im Body einen 
Function-Pointer auf die aktuelle draw-Funktion aufruft.

So kann man den aktuellen Bildschirm individuell festlegen und der 
Aufbau bleibt übersichtlich.

Ebenso kann man unnötige Refreshes - die einen Arduino schon recht lange 
beanspruchen (digitalWrite...) - mit einer einfachen bool'schen Variable 
unterdrücken. Bei meinem DG16080 setze ich die Variable z.B. auf true 
wenn der Touchscreen gedrückt wurde.

Beispiel:
1
bool update_screen = true;
2
(void *draw)() = &logo1;
3
4
void logo1() {
5
  u8g. ...
6
}
7
8
9
void logo2() {
10
  u8g. ...
11
}
12
13
void Picture_loop() {
14
  if (! update_screen) return;
15
  u8g.firstPage();  
16
  do {
17
    draw();
18
              
19
  } while( u8g.nextPage() );
20
  update_screen = false;
21
}

Der Code ist aus dem Kopf also muss er nicht direkt sauber compilen ;-)

Grüße
Sascha

von Susanne (Gast)


Lesenswert?

habe ein ST7920 auf einem ATmega 32 zum Laufen gebracht, aber wie kann 
ich werte ( z.B. aus dem AD-Wandler) wiedergeben?

von U8glib (Gast)


Lesenswert?

Auf dem Arduino einfach mit dem "print" Befehl. Auf dem AVR müsste die 
Zahl erst mittels sprintf in einen String konvertiert werden.

Oliver

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.