mikrocontroller.net

Forum: Projekte & Code HD44780 Hochauflösender Bargraf auf Text-LCD (Beispiel AVR-GCC)


Autor: Dominik (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
animiert durch eine Diskussion zum Thema CGRam, und als Dankeschön, hier 
mal ein CodeSchnipsel mit etwas anderem Ansatz.

Vorwort:
Obwohl mittlerweile grafische und farbige Displays den Text-LCDs den 
Rang ablaufen haben diese durchaus noch eine Daseinsberechtigung durch 
Ihre einfache Ansteuerung und Anschaffung. Mit etwas Geduld hat man ja 
heute innerhalb von 4 Wochen für einen guten Euro ein 16x2 Modell im 
Briefkasten.
Und für kleinere µC-Projekte muss es ja nicht immer Grafik sein... aber 
ganz ohne ist irgendwie auch doof... daher haben alle HD44780 und 
kompatible einen Speicherbereich für 8 eigenen Zeichen (5*8), die man 
beliebig belegen kann, und - da es sich um Ram handelt - auch beliebig 
oft.
Beim "Standardansatz" werden nun diese Zeichen vorbelegt und der Bargraf 
daraus zusammengesetzt.
Das bedeutet man benötigt mindestens 6 Zeichen für einen horizontalen 
und mindestens 9 Zeichen für einen vertikalen Bargraf. Hier kann man 
sich zur Not dann z.B. mit Leerzeichen und Vollzeichen(0xFF) behelfen 
wenn man nicht genügend freie eigene Zeichen zur Verfügung hat, was 
jedoch die Designs wiederum stark einschränkt.
Die Auflösung dieser Bargrafen liegt dann auch in einem überschaubaren 
Bereich:
Horizontal: Spalten*5 (z.B. 16x5=80 Werte)
Vertikal:   Zeilen*8 (z.B. 4x8=32 Werte)

Erweiterte Herangehensweise:
Die eigenen Zeichen werden erst dann belegt oder geändert, wenn der 
anzuzeigende Wert bekannt ist.
Dieser Ansatz erlaubt eine dtl. höhere Auflösung und benötigt weniger 
eigene Zeichen pro Bargraf (hier 3) auch verfügt der Bargraf über einen 
Rand, um dem User zu vermitteln wo dieser endet. Ob horizontal oder 
Vertikal ist hierbei wurscht, das folgende Beispiel ist horizontal, was 
bei den meisten Displays wohl mehr Sinn macht.
(Mit leichter Anpassung im Code wären bis zu 6 solcher Bargrafen in 
horizontal oder vertikal gleichzeitig auf einem LCD möglich, in der 
vorliegenden Variante sind 2 gleichzeitig erlaubt, was für die meisten 
LCDs ausreichen sollte.)
Das Bild im Anhang zeigt die Anwendung beispielhaft auf einem 20x4 LCD, 
die Auflösung beträgt hier 400 Werte. Verzichtet man auf den Rand wären 
800 möglich (bei 20 Spalten). Dargestellt wird dies durch den letzten 
Balken, der -wertabhängig- nur anteilig eingeblendet wird. Benötigt man 
diese Auflösung nicht, hat man mit dem Ansatz zumindest eigene Zeichen 
gespart:

Code kann frei verwendet oder angepasst werden,
von der Anwendung sind 3 Funktionen bereitzustellen:
void LCD_setCGRamAddress(uint8_t address);
void LCD_goto(column, row); //DDRAM
LCD_writeCharacter(uin8_t data); //unsigned char


Viel Spaß damit...
#define BAR_LINE_0       0b00000000
#define BAR_LINE_5       0b00011111
#define BAR_LINES      4      //3 or 4 allowed
#define BAR_PIXEL_PER_CHAR   (BAR_LINES*5ul)

void LCD_drawBarGraphHorizontal(uint8_t column, uint8_t row, uint8_t width, uint16_t value, uint16_t maxValue, uint8_t uCharOffset)
{
  uint16_t scaledValue=((uint32_t) value)*(((uint32_t) (width)))*BAR_PIXEL_PER_CHAR/((uint32_t) maxValue);
  uint8_t scaledValueCharPosition=scaledValue/BAR_PIXEL_PER_CHAR;
  uint8_t scaledValueRemainder=scaledValue%BAR_PIXEL_PER_CHAR;

  LCD_setCGRamAddress(uCharOffset*8);
  //Full Element  UDF 0
  LCD_writeCharacter(BAR_LINE_5);
  LCD_writeCharacter(BAR_LINE_0);
  LCD_writeCharacter(BAR_LINE_5);
  LCD_writeCharacter(BAR_LINE_5);
  LCD_writeCharacter(BAR_LINE_5);
  if(BAR_LINES==3)
  {
    LCD_writeCharacter(BAR_LINE_0);
    LCD_writeCharacter(BAR_LINE_5);
    LCD_writeCharacter(BAR_LINE_0);
  }
  else
  {
    LCD_writeCharacter(BAR_LINE_5);
    LCD_writeCharacter(BAR_LINE_0);
    LCD_writeCharacter(BAR_LINE_5);
  }
  //Scaled Element UDF 1
  LCD_writeCharacter(BAR_LINE_5);
  LCD_writeCharacter(BAR_LINE_0);

  uint8_t line;
  for(int8_t lineId=(BAR_LINES-1); lineId>=0; lineId--)
  {
    line=BAR_LINE_0;
    for(uint8_t digit=0; digit<5; digit++)
    {
      if(scaledValueRemainder>((digit*BAR_LINES)+lineId))
      {
        line|=(0b00010000>>digit);
      }
    }
    LCD_writeCharacter(line);
  }
  if(BAR_LINES==3)
  {
    LCD_writeCharacter(BAR_LINE_0);
    LCD_writeCharacter(BAR_LINE_5);
    LCD_writeCharacter(BAR_LINE_0);
  }
  else
  {
    LCD_writeCharacter(BAR_LINE_0);
    LCD_writeCharacter(BAR_LINE_5);
  }
  //Empty Element UDF 2
  LCD_writeCharacter(BAR_LINE_5);
  LCD_writeCharacter(BAR_LINE_0);
  LCD_writeCharacter(BAR_LINE_0);
  LCD_writeCharacter(BAR_LINE_0);
  LCD_writeCharacter(BAR_LINE_0);
  LCD_writeCharacter(BAR_LINE_0);
  if(BAR_LINES==3)
  {
    LCD_writeCharacter(BAR_LINE_5);
    LCD_writeCharacter(BAR_LINE_0);
  }
  else
  {

    LCD_writeCharacter(BAR_LINE_0);
    LCD_writeCharacter(BAR_LINE_5);
  }

  LCD_goto(column, row);
  for(uint8_t charPosition=0; charPosition<width; charPosition++)
  {
    if(charPosition<scaledValueCharPosition)
      LCD_writeCharacter(0);
    else if(charPosition==scaledValueCharPosition)
      LCD_writeCharacter(1);
    else
      LCD_writeCharacter(2);
  }  
}

P.S.: Char 0 und 2 kann man natürlich auch in eine Init-Funktion 
auslagern, falls das restliche Programm diese Zeichen nicht nutzt, damit 
fallen dann wesentlich weniger LCD-Schreibzyklen an.

Autor: Tom (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nette Idee. Für jeden weiteren Bargraf wird ein weiteres Zeichen fällig 
und trotzdem hat man noch ein paar Zeichen frei :-)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.