TFT Bargraph - Volt ausgeben - AD8318

Hallo zusammen,

ich wende mich mit einer Frage an Euch weil ich in meinem tun etwas auf dem Schlauch stehe und im Moment einfach nicht mehr weiter weis.

Ich habe einen AD8318 an A0 angeschlossen mit dem ich Leistung in kleinen Bereichen messen kann. Hier erhalte ich eine Voltzahl bis Max 2 Volt.

Mein Bargraph funktioniert zwar, hat aber:

a) Keine Begrenzung auf 2 Volt
b) durch den fillRect auf BLACK immer wieder mal ein flickern

Vieleicht könnte mir ja jemand auf die Sprünge helfen wie ich das evtl. besser verfolständigen könnte. Wie das ganze am TFT in kompletten Umfang aussieht poste ich am Ende in einem Bildchen.

Hier der Sketch, abgespeckt auf den Bargrah

#include <SPI.h>                  
#include <ILI9341_due_config.h>   
#include <ILI9341_due.h>          

// TFT LCD Treiber und Pins 
// Anschluss per Hardware SPI .. Pin #11, #12, #13 .. UNO, NANO 
#define ILI9341_DC 9              
#define ILI9341_CS 10            
ILI9341_due tft = ILI9341_due(ILI9341_CS, ILI9341_DC);

int   volt_in;
int   Lastvolt_in = 0;
float A0_volt;
byte  iii;

void setup(){
  tft.begin();                     
  tft.setRotation(1); 
  tft.fillScreen(ILI9341_BLACK);

  analogReference (DEFAULT) ;

  skala();
}

 
void loop() 
{
        volt_vout();
        bargraph();
}

void volt_vout()
{ 
    A0_volt  =  analogRead(A0);
    for(iii=0;iii<=8; iii++)
    A0_volt  =  A0_volt + analogRead(A0);
    A0_volt  =  A0_volt/2048 ;
}    

void bargraph()
{
  volt_in = (76-(A0_volt*45));
  tft.fillRect(10, 102, volt_in ,7, ILI9341_ORANGE);

  if (volt_in < Lastvolt_in)
  {
      tft.fillRect(10, 102, 300 ,7, ILI9341_BLACK);
  }  
  Lastvolt_in = volt_in;
}

void skala()
{
   // Skala und Power BarGraph
   tft.drawFastHLine(10, 98, 301, ILI9341_WHITE);
   tft.drawFastVLine(10, 92, 6, ILI9341_WHITE);
   tft.drawFastVLine(22, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(32, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(42, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(52, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(62, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(72, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(85, 92, 6,ILI9341_WHITE);
   tft.drawFastVLine(98, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(108, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(118, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(128, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(138, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(148, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(160, 92, 6, ILI9341_WHITE);
   tft.drawFastVLine(172, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(182, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(192, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(202, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(212, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(222, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(235, 92, 6, ILI9341_WHITE);
   tft.drawFastVLine(248, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(258, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(268, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(278, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(288, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(298, 95, 3, ILI9341_WHITE);
   tft.drawFastVLine(310, 92, 6, ILI9341_WHITE);
}

Achja, der ein oder andere mag sich fragen was das "volt_in = (76-(A0_volt*45));" soll. Der AD8318 gibt weniger Volt bei mehr Leistung aus. Darum dreh ich das so. Sicher gbt es da auch bessere Lösungen.

Hier noch das Bildchen des Probeaufbaues.

Weniger Flicker kann man erreichen, indem man Ausgaben nur bei Änderungen macht, und dann entweder den Balken verlängert, oder den Hintergrund zum Verkürzen des Balkens.

DrDiettrich:
Weniger Flicker kann man erreichen, indem man Ausgaben nur bei Änderungen macht, und dann entweder den Balken verlängert, oder den Hintergrund zum Verkürzen des Balkens.

Naja den Balken lass ich ja nur neu aufbauen wenn der letzte Wert größer war. Dennoch gibt es da sicher bessere Möglichkeiten. Meine aktuelle Lösung funktioniert halt noch nicht 100%. Darum fragte ich hier. Mit TFT Display inkl. Touch hatte ich bisher nichts gemacht.

Gruß Wolle

"Den Balken neu aufbauen" ist die falsche Denke!

  1. Nur ändern wenn sich der Wert ändert.
  2. Nicht den Balken schwarz übermalen und dann wieder in Farbe, sondern
  3. Nur das ändern was sich ändert

Dann flackert nix

Im Nachhinein erscheinen mir die fillRect() schuld zu sein. Wird da bei Änderungen immer der ganze Balken mit schwarz gefüllt? Und das bis zum nächsten Aufruf?

Füllen ist langsam, ja. Das sollte man wirklich optimieren. Also nicht den kompletten Balken zeichnen sondern immer nur die Differenz zwischen alten und neuem Wert. Als X-Startpunkt den alten Wert + 1 nehmen.
Und bei abnehmenden Werten genauso nur das auf Schwarz setzen was zu viel ist

Hört sich leicht an, aber ich werde mal etwas weiter fummeln .. Vielleicht hat ja noch jemand einen Ansatz für mich. Danke!

Gruß Wolle

Klingt nicht so als hättest du was verstanden.
Vielleicht nochmal anders erklärt:

Du darfst den Balken nie komplett schwarz übermalen.

Wenn der Balken höher soll als er war, malst du nur das Stück höher, um wie viel er nun höher muss, nicht den ganzen Balken übermalen.

Wenn der Balken niedriger soll, malst du nur von der vorigen höchsten Position bis zu der aktuell höchsten Position.

Gemerkt?

(Der Balken der stehenbleibt wird überhaupt nicht gemalt. Und deswegen kann er gar nicht flackern.)

Vor dem ganzen Kram wird verglichen ob der aktuelle Wert sich überhaupt von dem letzten gemerkten Wert unterscheidet. Is der Wert gleich überspringt man das alles.

Genau so geht das richtig.

Nun musst du da ein bischen Köpfchen reinstecken um die genannten Vorgänge zu realisieren.

Lieben Gruß,
Chris

@themanfrommoon

Mir ist schon klar wie du das meinst, aber irgendwie scheitert es an der Umsetzung. Bei einem Vertikalen Balken hatte ich da schon mal ein Beispiel gesehen.

Horizontal, bei fillRect bleiben ja nicht viele Optionen übrig. x,y ( also Startpunkt und Abstand zum oberen Rand sind ja Fix. Bleiben noch Länge und Höhe des Balken, wobei die Höhe mit 7 aus meinem Beispiel ja auch Fix ist. Bleibt also doch nur an der Länge anzusetzen, oder sehe ich da was Falsch .. Ich glaub ich sitz da irgendwie auf der Leitung :slight_smile:

Gruß Wolle

Hi

Du hast ein Rechteck mit zwei bekannten Eckpunkten - Die Sich gegenüber liegen (sonst wird's eher eine Linie ...).
Nun berechnest Du die aktuelle Länge des Balken - die alte Länge hast Du Dir aber gemerkt.
Nun:
Sind die beiden Werte gleich?? -> dann mache nix
Ist der neue Wert kleiner als der Alte?? -> dann zeichne ein Rechteck vom alten Punkt zum Neuen (wobei die zweite Variable, hier wohl y, die Entgegengesetzten sein müssen) 'in Wagenfarbe' - also Hintergrund, damit löschen wir das obere Ende des Balken.
Bei der anderen Richtung gleiches Vorgehen, aber in Balkenfarbe.
Fertig

MfG

Moin Wolle,

nee, is dir nicht klar, und nein Startpunkt ist nicht fix.

Beispiel:

links oben ist Position 0,0
X geht nach rechts positiv
Y geht nach unten positiv
Der Balken soll 7 Pixel hoch sein
Der Balken fängt am linken Rand an
Der Balken fängt am 40 Pixel von oben an
Hintergrundfarbe ist schwarz
Balkenfarbe ist gelb
Der Balken wird folgendermaßen definiert (Startposition X, Startposition Y, Länge X, Länge Y, Farbe)
1V=10Pixel

  1. Wert ist 1,2V
    1,2V in eine Variable schreiben und somit merken.
    Balken zeichnen mit den Koordinaten (0)
    Balken malen mit folgenden Werten (0,40,12,7,gelb)

  2. Wert ist 1,2V
    1,2V mit dem gemerkten Wert vergleichen, kein Unterschied , nix machen

  3. Wert ist 1,7V
    1,7V mit dem gemerkten Wert vergleichen, ist größer als der gemerkte Wert, dann folgendes machen
    Balken zeichnen mit folgenden Werten (13,40,4,7,gelb)
    Warum Start bei x=13? Weil 0-12 schon da sind, aber ab 13 is noch nix da.
    Warum Länge 4? Weil 17-13=4
    Wir haben also nur das gemalt, was anders ist und vorher nicht da war.
    Das was vorher da war kann also nicht blinken
    1,7V in die Variable schreiben und somit merken.

  4. Wert ist 0,8V
    0,8V mit dem gemerkten Wert vergleichen, ist kleiner als der gemerkte Wert, dann folgendes machen
    Balken zeichnen mit folgenden Werten (9,40,8,7,schwarz)
    Warum Start bei x=9? Weil wir nun den Balken da löschen wollen wo wir ihn nicht mehr brauchen, also von 10-17 muss er weg, damit 0-9 noch da bleiben.
    Warum Länge 8? Weil 17-9=8
    Warum schwarz, weil das die Hintergrundfarbe ist und wir so wieder etwas löschen können.
    Wir haben also nur das gelöscht, was wir nicht mehr haben und vorher da war.
    Das was vorher da war kann also auch nicht blinken
    0,8V in die Variable schreiben und somit merken.

Damit hast du alle Fälle erschlagen.
Und nun ist es unmöglich, das da noch was flackert.

Isses nun klar? Besser kann man es wohl nicht mehr erklären.

Viel Erfolg,
Chris

Ich würde der Einfachheit halber nur mit 2 Rechtecken arbeiten.
Eines linksbündig, in Farbe, und eines rechtsbündig, in Hintergrundfarbe.
Wenn sich was ändert, eben nur den einen oder anderen neu zeichnen. Wird der Wert grösser, den linksbündigen Balken, wir der Wert kleiner, den rechtsbündigen.
Weniger Rechnerei, weniger Sketch, gleiches Resultat

Das ist aber deutlich langsamer, weil fill sehr lange dauert.
Meine Beschreibung ist auch nicht viel aufwendiger, aber deutlich schneller, vermutlich deutlich über Faktor 10 schneller, weil bei Änderungen immer nur ein wenig neu gezeichnet werden muss und nicht immer große Flächen.

Möglich ist natürlich beides

Hi

Wenn man IMMER IST und SOLL vergleicht und bei Unterschied EINE Linie neu zeichnet, braucht's nahezu keien Zeit, wird ja eh nur jeweils 7 Pixel 'gemalt' - dafür halt in jedem loop()-Durchlauf - aber halt auch nur, wenn IST ungleich SOLL ist.
Und: Anhand der Abweichung kann man sogar feststellen, in welcher Richtung und somit in welcher Farbe gemalt werden muß.
Danach wird IST um 1 erhöht/erniedrigt und wir warten auf den nächsten loop()-Durchlauf - käme auf einen Versuch an, ob Das wirklich fix geht :wink:

MfG

Das glaubst aber auch nur du, dass sich der Wert immer nur um einen Pixel ändert

Hi

Im nächsten Durchlauf haben wir bereits den 2.ten Pixel 'erschlagen'.
Sofern Du kein delay(100) einfügst, sollten sich auch größere Sprünge smooth abarbeiten lassen.

Ich schrieb, 1 Pixel pro Durchlauf - Das ist etwas Anderes, als Unterschied:1 Pixel.

MfG

Achso war das gemeint. Jetzt hab sogar ich das verstanden. Ja das klappt bestimmt auch gut.

1 Pixel pro loop, da muss man dann schon ordentlich delays einfügen, dass das smooth erscheint. duck und wech

ElEspanol:
1 Pixel pro loop, da muss man dann schon ordentlich delays einfügen, dass das smooth erscheint.

So ein Effekt wird besser im Eingabefilter durchgeführt als in der Ausgabe.

DrDiettrich:
So ein Effekt wird besser im Eingabefilter durchgeführt als in der Ausgabe.

Versteh ich beides nicht?!

Gemeint war doch, dass es einen gemerkten und einen neuen Wert gibt, man die Differenz bildet, und dann die nächsten x Loops jeweils eine Linie hinzufügt oder wegnimmt.
Die neue Messung muss dann natürlich so lange gesperrt werden, bis der Balken den Sollwert erreicht hat.
Da die Loop aber so schnell durchlaufen wird, wird das keine nennenswerte Verzögerung geben.

Ich denke auch, das dass schön smooth aussieht und nichts flackert.

Was das Delay jetzt da soll ist mir schleierhaft.
Ebenso welcher Effekt gemeint ist.

Lieben Gruß,
Chris