Habe das Ganze mal in eine Klasse überführt:
Klasse (fehlerhaft, siehe unten unter [Edit])
#pragma once
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#define TFT_DC 9
#define TFT_CS 10
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
constexpr float pi = 3.1415926;
class PointerClass {
private:
int centerX = 0;
int centerY = 0;
int radius = 10;
int oldX = 0;
int oldY = 0;
float oldAngle = 0;
boolean doErase = false;
public:
void setXYR(int cX, int cY, int rad);
void draw(float newAngle, uint16_t color);
};
class BarClass {
private:
int startX = 0;
int startY = 0;
int width = 10;
int oldLength = 0;
byte direction = 0;
public:
void setXYWD(int x, int y, int w, byte dir);
void draw(int length, uint16_t color);
};
void PointerClass::setXYR(int cX, int cY, int rad) {
centerX = cX;
centerY = cY;
radius = rad;
}
void PointerClass::draw(float newAngle, uint16_t color) {
if (doErase) {
tft.drawLine(centerX, centerY, centerX + oldX, centerY + oldY, ILI9341_BLACK);
}
int newX = int(cos(newAngle * pi / 180) * radius);
int newY = int(sin(newAngle * pi / 180) * radius);
tft.drawLine(centerX, centerY, centerX + newX, centerY + newY, color);
oldX = newX;
oldY = newY;
doErase = true;
}
void BarClass::setXYWD(int x, int y, int w, byte dir) {
startX = x;
startY = y;
width = w;
direction = dir;
}
void BarClass::draw(int length, uint16_t color) {
int delta = length - oldLength;
if (delta == 0) {
return;
}
if (delta > 0) {
// Longer
switch (direction) {
case 0:
tft.fillRect(startX, startY + oldLength, width, length - oldLength, color);
break;
case 1:
tft.fillRect(startX + oldLength, startY, length - oldLength, width, color);
break;
case 2:
tft.fillRect(startX, startY - oldLength, width, length - oldLength, color);
break;
case 3:
tft.fillRect(startX - oldLength, startY, length - oldLength, width, color);
break;
}
} else {
// Shorter
switch (direction) {
case 0:
tft.fillRect(startX, startY + length, width, oldLength, ILI9341_BLACK);
break;
case 1:
tft.fillRect(startX + length, startY, oldLength, width, ILI9341_BLACK);
break;
case 2:
tft.fillRect(startX, startY - length, width, oldLength - length, ILI9341_BLACK);
break;
case 3:
tft.fillRect(startX - length, startY, oldLength - length, width, ILI9341_BLACK);
break;
}
}
oldLength = length;
}
Beispielanwendung
/*
Forum: https://forum.arduino.cc/t/adafruit-320x240-mit-teensy-4-0-flickering/1350338
Wokwi: https://wokwi.com/projects/422046098566960129
ec2021
Draw Bars/Pointers with minimum erasure effort
*/
#include "GraphicClass.h"
constexpr float Radius = 100.0;
unsigned long lastTime = 0;
int Angle = 180;
int AngleDx = 10;
int value = 1;
int delta = 1;
PointerClass pointerA, pointerB, pointerC, pointerD;
BarClass barA, barB, barC, barD;
void setup() {
Serial.begin(115200);
Serial.println("Graphics Example");
tft.begin();
pointerA.setXYR(120, 160, 80);
pointerB.setXYR(120, 160, 60);
pointerC.setXYR(120, 160, 50);
pointerD.setXYR(120, 160, 40);
barA.setXYWD(200, 20, 40, 0);
barB.setXYWD( 40, 260, 30, 1);
barC.setXYWD( 20, 120, 20, 2);
barD.setXYWD(160, 300, 10, 3);
clearScreen();
}
void loop(void) {
if (millis() - lastTime > 100) {
lastTime = millis();
handlePointers();
handleBars();
}
}
void clearScreen() {
tft.fillScreen(ILI9341_BLACK);
}
void handlePointers() {
pointerA.draw(Angle, ILI9341_YELLOW);
pointerB.draw(90 - Angle, ILI9341_GREEN);
pointerC.draw(Angle + 45, ILI9341_YELLOW);
pointerD.draw(180 - Angle, ILI9341_GREEN);
Angle += AngleDx;
if ((Angle < 0) || (Angle > 180)) {
AngleDx = -AngleDx;
}
}
void handleBars() {
barA.draw(value * 10, ILI9341_MAGENTA);
barB.draw(value * 10, ILI9341_RED);
barC.draw(value * 10, ILI9341_BLUE);
barD.draw(value * 10, ILI9341_GREEN);
value += delta;
if (value > 10 || value < 2) {
delta = -delta;
}
}
Position, Breite und Richtung der Balken werden so gesetzt
barA.setXYWD(200, 20, 40, 0);
Länge und Farbe des Balkens werden so beeinflusst:
barA.draw(value * 10, ILI9341_MAGENTA);
Mittelpunkt (Drehpunkt) und Länge des Zeigers
pointerA.setXYR(120, 160, 80);
Zeichnen mit Richtung (Winkel in Grad 0..360) und Farbe:
pointerA.draw(Angle, ILI9341_YELLOW);
Die Umsetzung ist nicht ganz "sauber" umgesetzt, aber wer Lust hat, kann gerne die Klasse in .h und .cpp Dateien aufteilen ... 
Einschränkungen:
- Basiert auf den Adafruit Libraries
- Vor Wechsel der Farbe im "laufenden Betrieb" sollte man einmal den Balken mit der Länge 0 zeichnen, da ansonsten beim "Verlängern" ein zweifarbiger Balken dargestellt wird. Könnte man in der Klasse abfangen, indem man prüft, ob ein Farbwechsel stattgefunden hat.
Viel Spass damit!
ec2021
[Edit]: Ich habe leider noch einen Fehler in der ursprünglich geposteten Klasse gefunden, daher hier eine korrigierte Version:
Klasse (korrigiert)
#pragma once
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#define TFT_DC 9
#define TFT_CS 10
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
constexpr float pi = 3.1415926;
class PointerClass {
private:
int centerX = 0;
int centerY = 0;
int radius = 10;
int oldX = 0;
int oldY = 0;
float oldAngle = 0;
boolean doErase = false;
public:
void setXYR(int cX, int cY, int rad);
void draw(float newAngle, uint16_t color);
};
class BarClass {
private:
int startX = 0;
int startY = 0;
int width = 10;
int oldLength = 0;
byte direction = 0;
public:
void setXYWD(int x, int y, int w, byte dir);
void draw(int length, uint16_t color);
};
void PointerClass::setXYR(int cX, int cY, int rad) {
centerX = cX;
centerY = cY;
radius = rad;
}
void PointerClass::draw(float newAngle, uint16_t color) {
if (doErase) {
tft.drawLine(centerX, centerY, centerX + oldX, centerY + oldY, ILI9341_BLACK);
}
int newX = int(cos(newAngle * pi / 180) * radius);
int newY = int(sin(newAngle * pi / 180) * radius);
tft.drawLine(centerX, centerY, centerX + newX, centerY + newY, color);
oldX = newX;
oldY = newY;
doErase = true;
}
void BarClass::setXYWD(int x, int y, int w, byte dir) {
startX = x;
startY = y;
width = w;
direction = dir;
}
void BarClass::draw(int length, uint16_t color) {
int delta = length - oldLength;
if (delta == 0) {
return;
}
if (delta > 0) {
// Longer
switch (direction) {
case 0:
tft.fillRect(startX, startY + oldLength, width, length - oldLength, color);
break;
case 1:
tft.fillRect(startX + oldLength, startY, length - oldLength, width, color);
break;
case 2:
tft.fillRect(startX, startY - oldLength, width, length - oldLength, color);
break;
case 3:
tft.fillRect(startX - oldLength, startY, length - oldLength, width, color);
break;
}
} else {
// Shorter
switch (direction) {
case 0:
tft.fillRect(startX, startY + length, width, oldLength - length, ILI9341_BLACK);
break;
case 1:
tft.fillRect(startX + length, startY, oldLength - length, width, ILI9341_BLACK);
break;
case 2:
tft.fillRect(startX, startY - length, width, oldLength - length, ILI9341_BLACK);
break;
case 3:
tft.fillRect(startX - length, startY, oldLength - length, width, ILI9341_BLACK);
break;
}
}
oldLength = length;
}
/*
(- length) was missing in BarClass::draw -> // Shorter -> case 0 and case 1
case 0:
tft.fillRect(startX, startY + length, width, oldLength, ILI9341_BLACK);
break;
case 1:
tft.fillRect(startX + length, startY, oldLength, width, ILI9341_BLACK);
*/
Die Fehlerbehebung ist im Code dokumentiert.