[gelöst] Anzeige TFT flimmerfrei - Nachtrag - Netzteil ist fertig

Hallo,
ich habe für mein Netzteil eine kleine Anzeige mit INA 219 und 3,2" TFT gebastelt.
Gibt es noch einen Trick, wie man das Anzeigeflimmern unterbinden kann ?
Anbei ein Video dazu.

#include <INA219.h>
#include <SPI.h>
#include <Wire.h>

#include <Adafruit_GFX.h>       // include Adafruit graphics library
#include <Adafruit_ILI9341.h>   // include Adafruit ILI9341 TFT library
#include <Fonts/FreeSerif24pt7b.h>
#include <Fonts/Seven_Segment30pt7b.h>
 
#define TFT_CS    14     // TFT CS  pin is connected to arduino pin 14
#define TFT_RST   13      // TFT RST pin is connected to arduino pin 13
#define TFT_DC    12   // TFT DC  pin is connected to arduino pin 12

// initialize ILI9341 TFT library
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

#define TFT_GREY 0x5AEB // New colour
#define TFT_Yellow 0xFFE0  
#define TFT_AQUA 0x0000
#define TFT_GOLD 0xA508
#define TFT_SILVER 0xA510

  float value1; 
  float old_value1 ;
  float value2; 
  float old_value2 ; 
  float value3; 
  float old_value3 ;
  float shuntvoltage = 0.0;
  float busvoltage = 0.0;
  float current = 0.0;
  float power = 0.0;

INA219 ina;
   
void setup(void)
{
   // Default INA219 address is 0x40
  ina.begin();
  tft.begin();

  tft.setRotation(1);
  tft.fillScreen(ILI9341_BLACK);
  tft.drawRect(0, 0, 320, 80, ILI9341_WHITE );
  tft.drawRect(2, 2, 316, 76,ILI9341_WHITE );
  tft.drawRect(0, 80, 320, 80,ILI9341_WHITE );
  tft.drawRect(2, 82, 316, 76, ILI9341_WHITE );
  tft.drawRect(0, 160, 320, 80, ILI9341_WHITE );
  tft.drawRect(2, 162, 316, 76,ILI9341_WHITE );
  tft.setTextColor( ILI9341_YELLOW); 
  tft.setFont(&FreeSerif24pt7b);
  tft.setTextSize(1); 
  tft.setCursor(10, 50 );
  tft.print("Volt:"); 
  tft.setCursor(10, 130 );
  tft.print("Amp.:"); 
  tft.setCursor(10, 210 );
  tft.print("Pow.:"); 
 
  
 
  // Configure INA219
  ina.configure(INA219_RANGE_16V, INA219_GAIN_320MV, INA219_BUS_RES_12BIT, INA219_SHUNT_RES_12BIT_1S);

  // Calibrate INA219. Rshunt = 0.1 ohm
  ina.calibrate(0.10, 2);

}

void loop(void)
{

 busvoltage = ina.readBusVoltage();
 current = ina.readShuntCurrent();
 power = ina.readBusPower();


value1 = (busvoltage *1.025);
value2 = (current * 1.11);  
value3 = (power * 1.105);  

old_value1 = busvoltage;
old_value2 = current;
old_value3 = power;

  if(value1 != old_value1)
{
      tft.fillRect(160,15,115,50,ILI9341_BLACK);
      tft.setTextColor(ILI9341_GREEN);
     tft.setFont(&Seven_Segment30pt7b);
     tft.setTextSize(1); 
     tft.setCursor(170, 60 );
     tft.print(value1,2); 

 }    
 

 if(value2 != old_value2) 
 
    tft.fillRect(160,95,115,50,ILI9341_BLACK);
    tft.setTextColor( ILI9341_RED);
    tft.setFont(&Seven_Segment30pt7b);
    tft.setTextSize(1); 
    tft.setCursor(170, 140 );
    tft.print(value2,2); 

   
}

  if(value3 != old_value3) 
{  
   
   tft.fillRect(160,175,115,50,ILI9341_BLACK);
   tft.setTextColor(ILI9341_BLUE,ILI9341_BLACK);
   tft.setFont(&Seven_Segment30pt7b);
     tft.setTextSize(1); 
   tft.setCursor(170,220);
   tft.print(value3,2); 

}

}

Ich danke für jegliche Hilfe - viele Grüße Maik.

Anzeige TFT.mpg (1.32 MB)

Deine Berechnung für den Anzeigewert ist fehlerhaft, dadurch wird die Anzeige ständig aktualisiert.

Hm, und und was ist falsch ?
Ich hab keine Idee ....

Z.B. busvoltage ist ja nicht der endgültige Wert.

value1 = (busvoltage *1.025);
value2 = (current * 1.11);  
value3 = (power * 1.105);  

old_value1 = busvoltage;

  if(value1 != old_value1)

Bei value2 und value3 überträgst du es nicht in old.

Hallo
Probier das aus [UNGETESTET]

#include <INA219.h>
#include <SPI.h>
#include <Wire.h>

#include <Adafruit_GFX.h>       // include Adafruit graphics library
#include <Adafruit_ILI9341.h>   // include Adafruit ILI9341 TFT library
#include <Fonts/FreeSerif24pt7b.h>
#include <Fonts/Seven_Segment30pt7b.h>

#define TFT_CS    14     // TFT CS  pin is connected to arduino pin 8
#define TFT_RST   13      // TFT RST pin is connected to arduino pin 9
#define TFT_DC    12   // TFT DC  pin is connected to arduino pin 10

// initialize ILI9341 TFT library
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

#define TFT_GREY 0x5AEB // New colour
#define TFT_Yellow 0xFFE0
#define TFT_AQUA 0x0000
#define TFT_GOLD 0xA508
#define TFT_SILVER 0xA510

/*
  A few colour codes:

  code  color

  #define ILI9341_BLACK 0x0000       ///<   0,   0,   0
  #define ILI9341_NAVY 0x000F        ///<   0,   0, 123
  #define ILI9341_DARKGREEN 0x03E0   ///<   0, 125,   0
  #define ILI9341_DARKCYAN 0x03EF    ///<   0, 125, 123
  #define ILI9341_MAROON 0x7800      ///< 123,   0,   0
  #define ILI9341_PURPLE 0x780F      ///< 123,   0, 123
  #define ILI9341_OLIVE 0x7BE0       ///< 123, 125,   0
  #define ILI9341_LIGHTGREY 0xC618   ///< 198, 195, 198
  #define ILI9341_DARKGREY 0x7BEF    ///< 123, 125, 123
  #define ILI9341_BLUE 0x001F        ///<   0,   0, 255
  #define ILI9341_GREEN 0x07E0       ///<   0, 255,   0
  #define ILI9341_CYAN 0x07FF        ///<   0, 255, 255
  #define ILI9341_RED 0xF800         ///< 255,   0,   0
  #define ILI9341_MAGENTA 0xF81F     ///< 255,   0, 255
  #define ILI9341_YELLOW 0xFFE0      ///< 255, 255,   0
  #define ILI9341_WHITE 0xFFFF       ///< 255, 255, 255
  #define ILI9341_ORANGE 0xFD20      ///< 255, 165,   0
  #define ILI9341_GREENYELLOW 0xAFE5 ///< 173, 255,  41
  #define ILI9341_PINK 0xFC18        ///< 255, 130, 198

*/
float value1;
float old_value1 ;
float value2;
float old_value2 ;
float value3;
float old_value3 ;
float shuntvoltage = 0.0;
float busvoltage = 0.0;
float current = 0.0;
float power = 0.0;

INA219 ina;

void setup(void)
{
  // Default INA219 address is 0x40
  ina.begin();
  tft.begin();
  tft.setRotation(1);
  tft.fillScreen(ILI9341_BLACK);
  tft.drawRect(0, 0, 320, 80, ILI9341_WHITE );
  tft.drawRect(2, 2, 316, 76, ILI9341_WHITE );
  tft.drawRect(0, 80, 320, 80, ILI9341_WHITE );
  tft.drawRect(2, 82, 316, 76, ILI9341_WHITE );
  tft.drawRect(0, 160, 320, 80, ILI9341_WHITE );
  tft.drawRect(2, 162, 316, 76, ILI9341_WHITE );
  tft.setTextColor( ILI9341_YELLOW);
  tft.setFont(&FreeSerif24pt7b);
  tft.setTextSize(1); // For double sized fonts
  tft.setCursor(10, 50 );
  tft.print("Volt:"); // show the new value busvoltage
  tft.setCursor(10, 130 );
  tft.print("Amp.:"); // show the new value current
  tft.setCursor(10, 210 );
  tft.print("Pow.:"); // show the new value power
  // Configure INA219
  ina.configure(INA219_RANGE_16V, INA219_GAIN_320MV, INA219_BUS_RES_12BIT, INA219_SHUNT_RES_12BIT_1S);
  // Calibrate INA219. Rshunt = 0.1 ohm
  ina.calibrate(0.10, 2);
}

void loop(void)
{
  busvoltage = ina.readBusVoltage();
  current = ina.readShuntCurrent();
  power = ina.readBusPower();
  value1 = (busvoltage * 1.025);
  value2 = (current * 1.11);
  value3 = (power * 1.105);
  if (value1 != old_value1)
  {
    old_value1 = value1;
    tft.fillRect(160, 15, 115, 50, ILI9341_BLACK);
    tft.setTextColor(ILI9341_GREEN);
    tft.setFont(&Seven_Segment30pt7b);
    tft.setTextSize(1); // For normal sized fonts
    tft.setCursor(170, 60 );
    tft.print(value1, 2); // show the new value busvoltage
  }
  if (value2 != old_value2)
  {
    old_value2=value2;
    tft.fillRect(160, 95, 115, 50, ILI9341_BLACK);
    tft.setTextColor( ILI9341_RED);
    tft.setFont(&Seven_Segment30pt7b);
    tft.setTextSize(1); // For normal sized fonts
    tft.setCursor(170, 140 );
    tft.print(value2, 2); // show the new value current
  }
  if (value3 != old_value3)
  {
    old_value3=value3;
    tft.fillRect(160, 175, 115, 50, ILI9341_BLACK);
    tft.setTextColor(ILI9341_BLUE, ILI9341_BLACK);
    tft.setFont(&Seven_Segment30pt7b);
    tft.setTextSize(1); // For normal sized fonts
    tft.setCursor(170, 220);
    tft.print(value3, 2); // show the value new power
  }
}
old_value1 = busvoltage;
old_value2 = current;
old_value3 = power;

meinst Du das ?
Keine Besserung - im Gegenteil jetzt werden keine Werte mehr angezeigt.
Wenn ich nur :

old_value1 = busvoltage;

einsetze werden wieder die Werte angezeigt

maik_s:
Ich hab keine Idee ....

In dem Fall empfiehlt sich, den Inhalt von kritischen (d.h. in Bedingungen verwendeten) Variablen an den Stellen wo sie verändert oder benutzt werden auf der seriellen Schnittstelle auszugeben. Dann kann man schön sehen, ob der Inhalt und der Ablauf der Erwartungshaltung entspricht.

Das ist - kann ich aus eigener Erfahrung sagen - gelegentlich bis häufig nicht der Fall.
Es hilft aber dabei, selbst Fehler zu finden und beheben zu können, was ein ziemlich gutes Gefühl ist.

maik_s:

old_value1 = busvoltage;

old_value2 = current;
old_value3 = power;




meinst Du das ?
Keine Besserung - im Gegenteil jetzt werden keine Werte mehr angezeigt.
Wenn ich nur :


old_value1 = busvoltage;



einsetze werden wieder die Werte angezeigt

Sieh dir doch mal deinen Sketch ganz genau an und versuche den zu verstehen.
Dein Problem ist,du hast keinerlei Kommentare im Sketch und damit findest du deine eigenen Fehler nicht raus.

paulpaulson : ich hab es probiert - gleiche Darstellung wie in mein Video

maik_s:
paulpaulson : ich hab es probiert - gleiche Darstellung wie in mein Video

dann brummen die Meßwerte, aus welchen Gründen auch immer.
Bau mal zum Testen ein delay von 100msec in die Loop ein

Ich habe zum testen ein delay von 1 sec. gesetzt - die Werte sind stabil.
Jetzt habe ich aber alle sec. ein Flackern - auch nicht schön.
Ideal wäre es, wenn nur bei Änderung der Werte das Display kurz flackert und nicht ständig.
Ich muss mal weiter überlegen ...

maik_s:
Ich habe zum testen ein delay von 1 sec. gesetzt - die Werte sind stabil.
Jetzt habe ich aber alle sec. ein Flackern - auch nicht schön.
Ideal wäre es, wenn nur bei Änderung der Werte das Display kurz flackert und nicht ständig.
Ich muss mal weiter überlegen ...

Hallo
du arbeitest mit dem Datentyp FLOAT. Dieser Datentype rauscht grundsätzlich im LSB.
Skaliere die Messwerte zu einem INT, z.b. mit dem Faktor 1000, arbeite mit diesem INT im Vergleich und rechne diesen Faktor vor der Darstellung wieder raus.

Wenn du den Text durch ein Rechteck löscht und dann neuen Text darüber schreibst hast du natürlich flimmern. Egal wie das zeitlich löst. So viele Pixel zu zeichnen braucht einfach seine Zeit. Vielleicht sehe ich das auch falsch, aber so sieht der Code für mich aus.

Der Trick besteht darin den Text auf eine konstante Breite zu formatieren und nur das was man nicht mehr braucht durch Leerzeichen zu überschreiben. Dann werden Zeichen direkt überschrieben. Ohne den unnötigen Zwischenschritt

Ich glaube bei der Adafruit Library gibt es einen Trick wie das auch durch richtiges Setzen der Text- und Hintergrundfarbe unterstützt wird

Man kann sich auch den alten Text merken und den mit der Hintergrundfarbe ausgeben. Das dürfte der schnellste Weg sein und natürlich nur wenn sich wirklich was geändert hat (also nicht die float-Fluktuation).

Gruß Tommy

Diese wunderbare und durch nichts zu ersetzende Forensofware meinte jetzt mehr als 10 mal ich müsste das irgendwie verändern, oder da hat schon jemand was geschrieben oder sonst irgend nen Quark.

Da die Anhänge jetzt wohl durchgegangen sind und keiner weiter dazwischengegrätscht hat und auch die unnützte Zeichensperre erledigt ist, noch zwei edits, die ich eintrage:

maik_s:
Gibt es noch einen Trick, wie man das Anzeigeflimmern unterbinden kann ?

Dein Code endet mit:

}

}

Mein Gedanke: Da ist was faul!
Und siehe da: JA!
In Deinem Code ist in Zeile 134 Schluß!

Und warum? Weil Du Deinen Code nicht formatiert hast!
[edit]_code_original - als .txt angehangen[/edit]
So sieht Dein Code formatiert aus:
[edit]_code_original_formatiert als .txt angehangen[/edit]

Und so sieht Dein Code mit der Braces an der Stelle aus, wo ICH meine das sie hin gehört:

#include <INA219.h>
#include <SPI.h>
#include <Wire.h>

#include <Adafruit_GFX.h>       // include Adafruit graphics library
#include <Adafruit_ILI9341.h>   // include Adafruit ILI9341 TFT library
#include <Fonts/FreeSerif24pt7b.h>
#include <Fonts/Seven_Segment30pt7b.h>

#define TFT_CS    14     // TFT CS  pin is connected to arduino pin 8
#define TFT_RST   13      // TFT RST pin is connected to arduino pin 9
#define TFT_DC    12   // TFT DC  pin is connected to arduino pin 10

// initialize ILI9341 TFT library
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);

#define TFT_GREY 0x5AEB // New colour
#define TFT_Yellow 0xFFE0
#define TFT_AQUA 0x0000
#define TFT_GOLD 0xA508
#define TFT_SILVER 0xA510

/*
  A few colour codes:

  code  color

  #define ILI9341_BLACK 0x0000       ///<   0,   0,   0
  #define ILI9341_NAVY 0x000F        ///<   0,   0, 123
  #define ILI9341_DARKGREEN 0x03E0   ///<   0, 125,   0
  #define ILI9341_DARKCYAN 0x03EF    ///<   0, 125, 123
  #define ILI9341_MAROON 0x7800      ///< 123,   0,   0
  #define ILI9341_PURPLE 0x780F      ///< 123,   0, 123
  #define ILI9341_OLIVE 0x7BE0       ///< 123, 125,   0
  #define ILI9341_LIGHTGREY 0xC618   ///< 198, 195, 198
  #define ILI9341_DARKGREY 0x7BEF    ///< 123, 125, 123
  #define ILI9341_BLUE 0x001F        ///<   0,   0, 255
  #define ILI9341_GREEN 0x07E0       ///<   0, 255,   0
  #define ILI9341_CYAN 0x07FF        ///<   0, 255, 255
  #define ILI9341_RED 0xF800         ///< 255,   0,   0
  #define ILI9341_MAGENTA 0xF81F     ///< 255,   0, 255
  #define ILI9341_YELLOW 0xFFE0      ///< 255, 255,   0
  #define ILI9341_WHITE 0xFFFF       ///< 255, 255, 255
  #define ILI9341_ORANGE 0xFD20      ///< 255, 165,   0
  #define ILI9341_GREENYELLOW 0xAFE5 ///< 173, 255,  41
  #define ILI9341_PINK 0xFC18        ///< 255, 130, 198

*/
float value1;
float old_value1 ;
float value2;
float old_value2 ;
float value3;
float old_value3 ;
float shuntvoltage = 0.0;
float busvoltage = 0.0;
float current = 0.0;
float power = 0.0;

INA219 ina;

void setup(void)
{
  // Default INA219 address is 0x40
  ina.begin();
  tft.begin();
  tft.setRotation(1);
  tft.fillScreen(ILI9341_BLACK);
  tft.drawRect(0, 0, 320, 80, ILI9341_WHITE );
  tft.drawRect(2, 2, 316, 76, ILI9341_WHITE );
  tft.drawRect(0, 80, 320, 80, ILI9341_WHITE );
  tft.drawRect(2, 82, 316, 76, ILI9341_WHITE );
  tft.drawRect(0, 160, 320, 80, ILI9341_WHITE );
  tft.drawRect(2, 162, 316, 76, ILI9341_WHITE );
  tft.setTextColor( ILI9341_YELLOW);
  tft.setFont(&FreeSerif24pt7b);
  tft.setTextSize(1); // For double sized fonts
  tft.setCursor(10, 50 );
  tft.print("Volt:"); // show the new value busvoltage
  tft.setCursor(10, 130 );
  tft.print("Amp.:"); // show the new value current
  tft.setCursor(10, 210 );
  tft.print("Pow.:"); // show the new value power



  // Configure INA219
  ina.configure(INA219_RANGE_16V, INA219_GAIN_320MV, INA219_BUS_RES_12BIT, INA219_SHUNT_RES_12BIT_1S);

  // Calibrate INA219. Rshunt = 0.1 ohm
  ina.calibrate(0.10, 2);

}

void loop(void)
{

  busvoltage = ina.readBusVoltage();
  current = ina.readShuntCurrent();
  power = ina.readBusPower();


  value1 = (busvoltage * 1.025);
  value2 = (current * 1.11);
  value3 = (power * 1.105);

  old_value1 = busvoltage;
  old_value2 = current;
  old_value3 = power;

  if (value1 != old_value1)
  {
    tft.fillRect(160, 15, 115, 50, ILI9341_BLACK);
    tft.setTextColor(ILI9341_GREEN);
    tft.setFont(&Seven_Segment30pt7b);
    tft.setTextSize(1); // For normal sized fonts
    tft.setCursor(170, 60 );
    tft.print(value1, 2); // show the new value busvoltage

  }


  if (value2 != old_value2)
  {
    tft.fillRect(160, 95, 115, 50, ILI9341_BLACK);
    tft.setTextColor( ILI9341_RED);
    tft.setFont(&Seven_Segment30pt7b);
    tft.setTextSize(1); // For normal sized fonts
    tft.setCursor(170, 140 );
    tft.print(value2, 2); // show the new value current


  }

  if (value3 != old_value3)
  {

    tft.fillRect(160, 175, 115, 50, ILI9341_BLACK);
    tft.setTextColor(ILI9341_BLUE, ILI9341_BLACK);
    tft.setFont(&Seven_Segment30pt7b);
    tft.setTextSize(1); // For normal sized fonts
    tft.setCursor(170, 220);
    tft.print(value3, 2); // show the value new power

  }

}

rauskopieren. testen.
Is nen Versuch wert.

_code_original.txt (4.12 KB)

_code_original_formatiert.txt (4.11 KB)

maik_s:
Danke für das Formatieren !

Bitte!

Ändert aber nichts am Ergebniss - Flackern weiterhin vorhanden.
Ich habe die Anzeige der Werte aus der Loop ausgelagert - nach ca.
1 Sekunde Refresh wird die Anzeige aktualisiert.
Flackern ist jetzt nicht mehr so "nervig" aber immer noch vorhanden auch wenn der Wert sich nicht ändert
bzw. stabil bleibt.

Spiel Dir folgenden Code ein.
Lese, was auf dem SerMon rauskommt.

float var = 1.00101;

void setup() {
  Serial.begin(115200);
  Serial.println(F("Start"));
  Serial.print("übergebender Wert von var ist mit einer Genauuigkeit von 5 Stellen nach dem Komma: ");
  Serial.println(var, 5);
  Serial.print(F("die erste tft-Ausgabe von var ist: "));
  Serial.println(var);
  var += 0.001;
  Serial.print(F("zweite tft-Ausgabe nach Addition von 0.001 ist: "));
  Serial.println(var);
  Serial.print(F("Wenn die Ausgabe auf 3 Nachkomma erweitert wird, ist var aber: "));
  Serial.println(var, 3);
  Serial.println("(TFT) Print macht da ne Abkürzung....");
  Serial.println("Das muss man wissen, wenn man mit float rechnet");
}

void loop() {

  while (1);
}

Hinweis: Nicht verrückt machen lassen, von dem F!

Warum machst du es nicht so, wie in Post 13 vorgeschlagen ?
Den aktuellen Text merken und bei Änderung mit schwarzem Text überschreiben.
Das funktioniert flackerfrei.

...weil er erstmal das mit den float verstehen muss.

So wie er da mit den Werten hantiert, bekommt er bei jedem Durchlauf einen (wenn auch nur geringfügig) anderen Messwert und dann schlägt der Vergleich mit den old_value immer fehl --> Display wird neu geschrieben.

Ansonsten hast Du ja recht.
Noch schöner wäre fixed-width Font und eine Lib, die Vorder- und Hintergrundpixel schreiben kann. Dann muss man bei gegebener Zeichenanzahl wirklich nur drüberbraten.

wno158:
...weil er erstmal das mit den float verstehen muss.

Ja, das stimmt auch.

Allerdings schon durch das geänderte Überschreiben flackert es deutlich geringer.

HotSystems:
Allerdings schon durch das geänderte Überschreiben flackert es deutlich geringer.

Das ist aber nicht Sinn der Übung. Ich kann nicht darauf warten, das alle XX Sekunden ein Wert ausgegeben wird, sondern ich will wissen, welcher Wert derzeit anliegt.
Sonst könnte man auch delay() regelmässig einsetzen :wink: