GFX­can­sas einsetzen


Lese­zeit: 5 Minu­ten

Lösung

Zie­le des Projekts

  • Ein­füh­rung in das Kon­zept GFX­can­vas der Biblio­thek Adafruit GFX Library
  • Anzei­ge der ana­lo­gen Daten eines Poten­tio­me­ters als Text und als ver­än­der­ba­rer Balken

Ver­wen­de­te Hardware

Das Pro­gramm im Film

Anschluss des Potentiometers

Benö­tig­te Bibliothek

Soll ein schnell wech­seln­der Text oder ein sich ver­än­dern­des gra­fi­sches Ele­ment an der glei­chen Posi­ti­on dar­ge­stellt wer­den, gibt es zwei Probleme:

  • der geän­der­te Text ist län­ger oder kür­zer als der vor­he­ri­ge, dadurch über­lap­pen sich die Buch­sta­ben
    das neue gra­fi­sche Ele­ment unter­schei­det sich in der Grö­ße vom bisherigen
  • weil der Bild­schirm immer gelöscht und wie­der neu auf­ge­baut wird, ver­ur­sacht das neue Ele­ment ein Fla­ckern des TFTs

Das ers­te Pro­blem lässt sich lösen indem der bis­he­ri­ge Text oder das gra­fi­sche Ele­ment durch ein aus­ge­füll­tes Recht­eck "gelöscht" wird. Das ver­hin­dert aller­dings nicht das Fla­ckern des TFTs.

Die durch die Instal­la­ti­on der Biblio­thek Adafruit ILI9341 zusätz­lich instal­lier­te Biblio­thek Adafruit GFX Libra­ry ent­hält die Funk­ti­on GFX­can­vas. Sie legt ein Bild der dar­zu­stel­len­den Daten im Spei­cher an, auf Anfor­de­rung wird die­ses Bild auf dem TFT dargestellt.

Im Film wird der blau dar­ge­stell­te Bereich mit GFX­can­vas erzeugt, im roten Bereich wird der Text zunächst durch ein rotes Recht­eck "gelöscht" und anschlie­ßend neu geschrie­ben. Als Text wird die mit ⇒mil­lis() gemes­se­ne Zeit, die seit dem Start des Pro­gramms ver­gan­gen ist, dar­ge­stellt.
Man kann den Unter­schied gut erkennen.

Jedes Objekt vom Typ GFXcanvas1 benö­tigt pro ein Bit pro Pixel. Wie im Bei­spiel eines Bereichs mit 240×150 Pixeln sind das 36.000 Bits, das ent­spricht 4.500 Bytes oder 4,5 kilo­Bytes. Der Spei­cher­platz eines Ardui­no UNO R3 reicht hier­für nicht aus.

Du musst die // vor den Pins des ver­wen­de­ten Mikro­con­trol­lers entfernen.

// Display mit 240x320 Pixeln
#include "Adafruit_ILI9341.h"

// Wemos D1 Mini
// #define TFT_CS       D8
// #define TFT_RST      D1
// #define TFT_DC       D2

// ESP32-WROOM
// #define TFT_CS        5
// #define TFT_RST       4 
// #define TFT_DC        2

// Objekt der Bibliothek erstellen
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

// 1-Bit Canvas definieren
GFXcanvas1 Bereich(240, 150);

void setup() 
{
  // TFT starten
  tft.begin();

  // wenn die Farben invertiert sind
  // weiß = schwarz, schwarz = weiss ...
  // // entfernen
  // tft.invertDisplay(1); 

  // schwarzer Hintergrund
  tft.fillScreen(0x0000);
  
  // Text darf nicht über den Rand fließen
  Bereich.setTextWrap(false);
  tft.setTextWrap(false);
}

void loop() 
{
  // Canvas erstellen
  Bereich.fillScreen(0x0000);    
  Bereich.setCursor(1, 40); 
  Bereich.setTextSize(3);  
  Bereich.print("Millisekunden:");
  Bereich.setCursor(1, 80); 
  Bereich.print(millis());  

  // Canvas als Bild anzeigen
  /* 
    Farben
    0x0000 = schwarz
    0xFFFF = weiß
    0x000F = blau
    0xF800 = rot
  */
  tft.drawBitmap(0, 0, Bereich.getBuffer(), Bereich.width(), Bereich.height(), 0xFFFF, 0x000F);

  // Bereich für den Text "löschen"
  tft.fillRect(1, 180, tft.width(), 100, 0xF800);
  tft.setCursor(1, 200);
  tft.setTextSize(3);
  tft.print("Millisekunden:");
  tft.setCursor(1, 240);

  tft.println(millis());
}

Kon­fi­gu­ra­ti­on der Mikrocontroller

Ana­lo­ger Pin

Schlie­ße das Poten­tio­me­ter an einem ana­lo­gen Pin an:

Das Pro­gramm TFT 240×320 Pixel

Du musst beim ver­wen­de­ten Mikro­con­trol­ler die // ent­fer­nen und den Wert für ADC­max anpas­sen:
ESP32-Wroom: 4096, ESP8266: 1024

#include "Adafruit_ILI9341.h"

// Schriftarten einbinden
#include "Fonts/FreeSans24pt7b.h"
#include "Fonts/FreeSans12pt7b.h"

// Wemos D1 Mini
// #define TFT_CS D8
// #define TFT_RST D1
// #define TFT_DC D2

// ESP32-WROOM
// #define TFT_CS 5
// #define TFT_RST 4 
// #define TFT_DC 2

// Farben
#define SCHWARZ    0x0000
#define WEISS      0xFFFF 

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

// GFXcanvas-Objekt erstellen: Höhe 170 Pixel, Breite 320 Pixel
GFXcanvas1 Bereich(170, 320);

// analogen Pin anpassen
int Poti = A0;

// maximalen Wert des ADC anpassen
// ESP32: 4096, ESP8266: 1024
int ADCMax = 1024;

/*
  Abstand der Markierung von der Mitte des TFTs
  der ADC liefert keine linear verlaufenden Werte
  der Abstand kann angepasst werden
*/
int AbstandMarkierung = 40;

void setup()
{
  // TFT starten
  tft.begin();

  // Rotation anpassen
  tft.setRotation(2);

  // schwarzer Hintergrund
  tft.fillScreen(SCHWARZ);
  Serial.begin(9600);
}

void loop()
{
  Bereich.fillScreen(SCHWARZ);

  // analogen Wert lesen
  int WertPoti = analogRead(Poti);

  Serial.println(WertPoti);

  // analogen Wert anzeigen
  Bereich.setFont(&FreeSans24pt7b); 
  Bereich.setCursor(10, 50);  
  Bereich.print(WertPoti);

  // analogen Wert auf die Höhe des TFTs übertragen
  int BalkenPoti = map(WertPoti, 0, ADCMax, 0, 320);

  /*
    bei gedrehtem Bildschirm wird der Balken von oben nach unten angezeigt
    zuerest maximalen Wert weiß füllen
    anschließend vom maximalen Wert den gemessenen Wert abziehen
    und schwarz füllen
  */
  Bereich.fillRect(120, 1, 50, 320, WEISS);
  Bereich.fillRect(120, 1, 50, 320 - BalkenPoti, SCHWARZ);

  Bereich.setCursor(70, tft.width() / 2 - AbstandMarkierung);
  Bereich.setFont(&FreeSans12pt7b); 

  // je nach Wert ADCMax Zahlen anzeigen
  if (ADCMax == 4096) Bereich.print("3000");
  else  Bereich.print("750");
  Bereich.drawLine(tft.height() / 2, tft.width() / 2 - AbstandMarkierung, 50, tft.width() / 2 - AbstandMarkierung, WEISS);

  Bereich.setCursor(70, tft.width() / 2 + 40);
  if (ADCMax == 4096) Bereich.print("2000");
  else Bereich.print("500");
  Bereich.drawLine(tft.height() / 2, tft.width() / 2 + AbstandMarkierung, 50, tft.width() / 2 + AbstandMarkierung, WEISS);

  Bereich.setCursor(70, tft.width() / 2 + AbstandMarkierung * 3);
  if (ADCMax == 4096) Bereich.print("1000");
  else Bereich.print("250");
  Bereich.drawLine(tft.height() / 2, tft.width() / 2 + AbstandMarkierung * 3, 50, tft.width() / 2 + AbstandMarkierung * 3, WEISS);

  // GFXcanvas anzeigen
  tft.drawBitmap(0, 0, Bereich.getBuffer(), Bereich.width(), Bereich.height(), WEISS, SCHWARZ);
}

Pro­gramm für TFT 160×128 Pixel

Du musst beim ver­wen­de­ten Mikro­con­trol­ler die // ent­fer­nen und den Wert für ADC­max anpas­sen:
ESP32-Wroom: 4096, ESP8266: 1024

#include "Adafruit_ST7735.h"

// Schriftarten einbinden
#include "Fonts/FreeSans9pt7b.h"
#include "Fonts/FreeSans12pt7b.h"

// Wemos D1 Mini
// #define TFT_CS D8
// #define TFT_RST D1
// #define TFT_DC D2

// ESP32-WROOM
// #define TFT_CS 5
// #define TFT_RST 4 
// #define TFT_DC 2

// Farben
#define SCHWARZ    0x0000
#define WEISS      0xFFFF 

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

// GFXcanvas-Objekt erstellen: Höhe 128 Pixel, Breite 160 Pixel
GFXcanvas1 Bereich(128, 160);

// analogen Pin anpassen
int Poti = A0;

// maximalen Wert des ADC anpassen
// ESP32: 4096, ESP8266: 1024
int ADCMax = 4096;

/*
  Abstand der Markierung von der Mitte des TFTs
  der ADC liefert keine lienear verlaufenden Werte
  der Abstand kann angepasst werden
*/
int AbstandMarkierung = 20;

void setup()
{
  // TFT starten
  tft.initR(INITR_BLACKTAB);

  // Rotation anpassen
  tft.setRotation(0);

  // schwarzer Hintergrund
  tft.fillScreen(SCHWARZ);
}

void loop()
{
  Bereich.fillScreen(SCHWARZ);

  // analogen Wert lesen
  int WertPoti = analogRead(Poti);

  // analogen Wert anzeigen
  Bereich.setFont(&FreeSans12pt7b); 
  Bereich.setCursor(10, 20);  
  Bereich.print(WertPoti);

  // analogen Wert auf die Höhe des TFTs übertragen
  int BalkenPoti = map(WertPoti, 0, ADCMax, 0, 160);

  /*
    bei gedrehtem Bildschirm wird der Balken von oben nach unten angezeigt
    zuerest maximalen Wert weiß füllen
    anschließend vom maximalen Wert den gemessenen Wert abziehen
    und schwarz füllen
  */
  Bereich.fillRect(80, 1, 30, 160, WEISS);
  Bereich.fillRect(80, 1, 30, 160 - BalkenPoti, SCHWARZ);

  Bereich.setCursor(30, tft.width() / 2 - AbstandMarkierung);
  Bereich.setFont(&FreeSans9pt7b); 

  // je nach Wert ADCMax Zahlen anzeigen
  if (ADCMax == 4096) Bereich.print("3000");
  else Bereich.print("750");
  Bereich.drawLine(tft.height() / 2, tft.width() / 2 - AbstandMarkierung, 50, tft.width() / 2 - AbstandMarkierung, WEISS);

  Bereich.setCursor(30, tft.width() / 2 + AbstandMarkierung);

  if (ADCMax == 4096) Bereich.print("2000");
  else Bereich.print("500");
  Bereich.drawLine(tft.height() / 2, tft.width() / 2 + AbstandMarkierung, 50, tft.width() / 2 + AbstandMarkierung, WEISS);

  Bereich.setCursor(30, tft.width() / 2 + AbstandMarkierung * 3);

  if (ADCMax == 4096) Bereich.print("1000");
  else Bereich.print("250");
  Bereich.drawLine(tft.height() / 2, tft.width() / 2 + AbstandMarkierung * 3, 50, tft.width() / 2 + AbstandMarkierung * 3, WEISS);

  // GFXcanvas anzeigen
  tft.drawBitmap(0, 0, Bereich.getBuffer(), Bereich.width(), Bereich.height(), WEISS, SCHWARZ);
}

Letzte Aktualisierung: März 22, 2025 @ 10:14