1.28 inch round tft display flickering

Hi, I have a small problem. I am creating a multigauge with a round 1.28inch display and esp32 and my program is basically finished but I'm having trouble with the display flickering every refresh I can't just put a delay there, because I need the fastest refresh rate possible to accurately display boost pressure. I'm thankful for every help.
here is my program

#include <TFT_eSPI.h> // Knižnica pre TFT display
#include <math.h>    // Pre funkcie ako sin a cos
#include <OneWire.h> // Knižnica pre DS18B20
#include <DallasTemperature.h> // Knižnica pre DS18B20

TFT_eSPI tft = TFT_eSPI(); // Inicializácia TFT displeja

// Pin pre tlak turba
const int analogPinTurbo = 15; // Analogový pin pre tlak turba (MAP senzor)

// DS18B20 senzory pripojené na pin 17
const int oneWireBus = 17; // Dátový pin pre DS18B20 senzory

// Pin pre ovládanie solenoidu
const int solenoidPin = 5; // Vyberte vhodný GPIO pin

// Prahová hodnota pre tlak turba (v baroch)
const float pressureThreshold = 1.5; // Hodnota tlaku, pri ktorej sa aktivuje solenoid

// Napájacie napätie senzora (v voltoch)
const float sensorSupplyVoltage = 5; // Napájacie napätie senzora
const float voltageCalibrationFactor = 1.0 / 1.58; // Kalibračný faktor na kompenzáciu odchýlky

// Napäťový delič: R1 = 1kΩ, R2 = 2kΩ
const float R1 = 2000.0;
const float R2 = 2000.0;

// Napäťové hodnoty a odpovedajúce tlaky z tabuľky
const float voltageTable[] = {0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 1.23, 1.47, 1.7, 1.93, 2.17, 2.4, 2.63, 2.87, 3.1, 3.33, 3.57, 3.8, 4.03, 4.27, 4.5};
const float pressureTable[] = {-1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.1};

// Inicializácia OneWire a DallasTemperature objektov
OneWire oneWire(oneWireBus);
DallasTemperature sensors(&oneWire);

// Uložené predchádzajúce hodnoty na kontrolu zmien
float lastPressure = -1;
float lastTemp1 = -1;
float lastTemp2 = -1;

// Deklarácia funkcie pre interpoláciu
float interpolate(float x, const float* xTable, const float* yTable, int size);
void displayPressure(float pressure);
void displayTemperatures(float temp1, float temp2);
void displayTemperatureBar(bool isTop, float temp);
void displayPressureBar(float pressure); // Nová funkcia na zobrazenie pásika pre tlak
void drawArcBar(TFT_eSPI& tft, int centerX, int centerY, int radius, int thickness, int angleStart, int angleEnd, uint16_t color);
uint16_t getColorFromPressure(float pressure); // Nová funkcia pre získanie farby na základe tlaku
uint16_t getColorFromTemperature(float temp);

void setup() {
  Serial.begin(115200); // Inicializácia sériového portu
  tft.init();
  tft.setRotation(1); // Nastavte rotáciu displeja
  tft.fillScreen(TFT_BLACK); // Vymažte obrazovku

  // Inicializácia pinu pre solenoid
  pinMode(solenoidPin, OUTPUT);
  digitalWrite(solenoidPin, LOW); // Solenoid je na začiatku vypnutý

  // Inicializácia DS18B20 senzorov
  sensors.begin();
}

void loop() {
  // Prečítajte napätie zo snímača a aplikujte napäťový delič
  float rawVoltage = (analogRead(analogPinTurbo) * voltageCalibrationFactor) * (sensorSupplyVoltage / 4095.0); // Pre ESP32 s 12-bitovým ADC
  float measuredVoltage = rawVoltage * ((R1 + R2) / R2); // Úprava napätia po deličovi

  // Previesť napätie na tlak pomocou interpolácie
  float pressure = interpolate(measuredVoltage, voltageTable, pressureTable, sizeof(voltageTable) / sizeof(voltageTable[0]));

  // Diagnostika: vypíš analogovú hodnotu, napätie a tlak turba do sériového portu
  Serial.print("Measured Voltage: ");
  Serial.print(measuredVoltage);
  Serial.print("rawvoltage ");
  Serial.print(rawVoltage);
  Serial.print(" V, Pressure: ");
  Serial.print(pressure);
  Serial.println(" bar");

  // Získanie teplôt zo senzorov DS18B20
  sensors.requestTemperatures(); // Vyžiadajte teploty zo senzorov
  float temp1 = sensors.getTempCByIndex(0); // Získanie teploty prvého senzora
  float temp2 = sensors.getTempCByIndex(1); // Získanie teploty druhého senzora

  // Diagnostika: vypíš hodnoty teplôt do sériového portu
  Serial.print("Temp1: ");
  Serial.print(temp1);
  Serial.print(" C, Temp2: ");
  Serial.println(temp2);

  // Ovládanie solenoidu na základe tlaku
  if (pressure >= pressureThreshold) {
    digitalWrite(solenoidPin, HIGH); // Aktivujte solenoid
  } else {
    digitalWrite(solenoidPin, LOW); // Deaktivujte solenoid
  }

  // Minimalizácia prekresľovania obrazovky
  bool updateRequired = false;
  if (pressure != lastPressure) {
    updateRequired = true;
  }
  if (temp1 != lastTemp1 || temp2 != lastTemp2) {
    updateRequired = true;
  }

  if (updateRequired) {
    // Vymažte len časti obrazovky, kde sa menia údaje
    tft.fillRect(0, 0, tft.width(), tft.height(), TFT_BLACK);

    // Zobrazenie teplôt
    displayTemperatures(temp1, temp2);

    // Zobrazenie tlaku turba
    displayPressure(pressure);

    // Zobrazenie teplôt s farebným pásikom
    displayTemperatureBar(true, temp1);  // Pásik na hornom okraji
    displayTemperatureBar(false, temp2); // Pásik na dolnom okraji

    // Zobrazenie pásika pre tlak
    displayPressureBar(pressure);

    // Uložte aktuálne hodnoty pre ďalšiu kontrolu
    lastPressure = pressure;
    lastTemp1 = temp1;
    lastTemp2 = temp2;
  }
}

float interpolate(float x, const float* xTable, const float* yTable, int size) {
  for (int i = 0; i < size - 1; i++) {
    if (x >= xTable[i] && x <= xTable[i + 1]) {
      // Lineárna interpolácia
      float x1 = xTable[i];
      float x2 = xTable[i + 1];
      float y1 = yTable[i];
      float y2 = yTable[i + 1];
      return y1 + (y2 - y1) * ((x - x1) / (x2 - x1));
    }
  }
  // Mimo rozsahu
  return -1.0; // Vráti neplatnú hodnotu, ak je mimo rozsahu
}

void displayPressure(float pressure) {
  int centerX = tft.width() / 2;
  int centerY = tft.height() / 2;

  // Formátovanie textu tlaku
  String pressureText = String(pressure, 1);
  String pressureUnit = "      bar";

  // Získanie veľkosti textu
  tft.setTextSize(6); // Väčšia veľkosť textu pre hodnotu tlaku
  int16_t textWidth = tft.textWidth(pressureText);
  int16_t textHeight = tft.fontHeight();

  // Nastavenie pozície kurzora na stred textu
  int16_t cursorX = centerX - (textWidth / 2);
  int16_t cursorY = centerY - (textHeight / 2) - 10; // Posuňte hore pre hodnotu

  // Zobrazovanie digitálnej hodnoty tlaku
  tft.setTextColor(TFT_WHITE, TFT_BLACK); // Zmeňte farbu textu na bielu
  tft.setCursor(cursorX, cursorY);
  tft.print(pressureText);

  // Zobrazovanie jednotky tlaku
  tft.setTextSize(2); // Menšia veľkosť textu pre jednotku
  tft.setTextColor(TFT_WHITE, TFT_BLACK); // Zmeňte farbu textu na bielu
  tft.setCursor(cursorX, cursorY + textHeight + 10); // Posuňte dole pre jednotku
  tft.print(pressureUnit);
}

void displayTemperatures(float temp1, float temp2) {
  int centerX = tft.width() / 2;
  int centerY = tft.height() / 2;

  // Určte veľkosť textu pre teploty
  tft.setTextSize(2); // Zmenšená veľkosť textu
  int16_t textWidth1 = tft.textWidth(String(temp1, 1));
  int16_t textWidth2 = tft.textWidth(String(temp2, 1));
  int16_t textHeight = tft.fontHeight();

  // Pozície pre teploty
  int16_t temp1X = centerX - textWidth1 - 50; // Posunutie teploty 1 ďalej doľava od stredu (o 50 pixelov)
  int16_t temp1Y = centerY - textHeight / 2;

  int16_t temp2X = centerX + 70; // Posunutie teploty 2 ďalej doprava od stredu (o 10 pixelov)
  int16_t temp2Y = centerY - textHeight / 2;

  // Zobrazenie označení
  tft.setTextSize(1); // Menšia veľkosť textu pre označenia
  tft.setTextColor(TFT_WHITE, TFT_BLACK);

  tft.setCursor(temp1X, temp1Y - 15); // Pozícia pre označenie nad teplotou 1
  tft.print("IN");

  tft.setCursor(temp2X, temp2Y - 15); // Pozícia pre označenie nad teplotou 2
  tft.print("OUT");

  // Zobrazenie teplôt
  tft.setTextSize(2); // Väčšia veľkosť textu pre hodnoty teplôt
  tft.setCursor(temp1X, temp1Y);
  tft.print(String(temp1, 0)); // Zaokrúhlená hodnota s 0 desatinnými miestami
  tft.setCursor(temp1X, temp1Y + textHeight + 5); // Posunutie dole pre jednotku
  tft.print("C");
  
  tft.setCursor(temp2X, temp2Y);
  tft.print(String(temp2, 0)); // Zaokrúhlená hodnota s 0 desatinnými miestami
  tft.setCursor(temp2X, temp2Y + textHeight + 5); // Posunutie dole pre jednotku
  tft.print("C");
}

void displayTemperatureBar(bool isTop, float temp) {
  int radius = tft.width() / 2 - 10; // Polomer okruhu
  int barThickness = 5; // Hrúbka pásika

  // Prepočítajte pozíciu pásika na základe horného alebo dolného okraja
  int angleStart, angleEnd;
  if (isTop) {
    angleStart = 135; // Začiatok pásika na dolnom okraji
    angleEnd = 225;   // Konec pásika na dolnom okraji
  } else {
    angleStart = 315; // Začiatok pásika na hornom okraji
    angleEnd = 405;   // Konec pásika na hornom okraji
  }

  // Nakreslite pásik ako oblúk s novou hrúbkou
  drawArcBar(tft, tft.width() / 2, tft.height() / 2, radius, barThickness, angleStart, angleEnd, getColorFromTemperature(temp));
}

void displayPressureBar(float pressure) {
  int radius = tft.width() / 2 - 10; // Polomer okruhu
  int barThickness = 10; // Hrúbka pásika

  // Pásik sa zobrazí na vrchu
  int angleStart = 240;
  int angleEnd = 300;

  // Nakreslite pásik ako oblúk s novou hrúbkou
  drawArcBar(tft, tft.width() / 2, tft.height() / 2, radius, barThickness, angleStart, angleEnd, getColorFromPressure(pressure));
}

void drawArcBar(TFT_eSPI& tft, int centerX, int centerY, int radius, int thickness, int angleStart, int angleEnd, uint16_t color) {
  int steps = 50; // Počet krokov pre vykreslenie oblúka
  float angleStep = (angleEnd - angleStart) / (float)steps;

  for (int i = 0; i < steps; i++) {
    float startAngle = angleStart + i * angleStep;
    float endAngle = startAngle + angleStep;

    int x1 = centerX + radius * cos(radians(startAngle));
    int y1 = centerY + radius * sin(radians(startAngle));
    int x2 = centerX + (radius + thickness) * cos(radians(startAngle));
    int y2 = centerY + (radius + thickness) * sin(radians(startAngle));
    int x3 = centerX + (radius + thickness) * cos(radians(endAngle));
    int y3 = centerY + (radius + thickness) * sin(radians(endAngle));
    int x4 = centerX + radius * cos(radians(endAngle));
    int y4 = centerY + radius * sin(radians(endAngle));

    tft.fillTriangle(x1, y1, x2, y2, x3, y3, color);
    tft.fillTriangle(x1, y1, x3, y3, x4, y4, color);
  }
}

uint16_t getColorFromPressure(float pressure) {
  // Definujte farby
  uint16_t blue = tft.color565(0, 0, 255); // Modrá
  uint16_t green = tft.color565(0, 255, 0); // Zelená
  uint16_t red = tft.color565(255, 0, 0); // Červená

  // Farebný gradient od modrej (pre záporné hodnoty) cez zelenú po červenú
  if (pressure < 0) {
    return blue; // Celá modrá farba pre záporné hodnoty
  } else if (pressure < 1.0) {
    // Vypočítať pomer medzi modrou a zelenou
    float ratio = constrain(pressure / 1.0, 0, 1); // Predpokladaná maximálna hodnota tlaku je 1.0 bar
    return tft.color565(0, (int)(255 * ratio), (int)(255 * (1 - ratio))); // Gradient od modrej po zelenú
  } else if (pressure <= 2.0) {
    // Vypočítať pomer medzi zelenou a červenou
    float ratio = constrain((pressure - 1.0) / 1.0, 0, 1); // Predpokladaná maximálna hodnota tlaku je 2.0 bar
    return tft.color565((int)(255 * ratio), (int)(255 * (1 - ratio)), 0); // Gradient od zelenej po červenú
  } else {
    return red; // Celá červená farba pre hodnoty nad 2 bary
  }
}


uint16_t getColorFromTemperature(float temp) {
  // Definujte teplotné rozsahy a farby
  uint16_t green = tft.color565(0, 255, 0); // Zelená
  uint16_t yellow = tft.color565(255, 255, 0); // Žltá
  uint16_t red = tft.color565(255, 0, 0); // Červená

  // Farebný gradient zo zelenej na červenú
  float ratio = constrain(temp / 80.0, 0, 1); // Predpokladaná maximálna teplota je 80°C
  if (ratio < 0.5) {
    return tft.color565(0, 255 * 2 * ratio, 0); // Zelená na žltú
  } else {
    return tft.color565(255 * (ratio - 0.5) * 2, 255, 0); // Žltá na červenú
  }
}

Then don't refresh! Just change what has changed from the time it was displayed.

1 Like

I tried to do that, but all I managed to do was mess up the whole display because everything was out of place.

Then you did not make the changes, ONE AT A TIME and test each change. Slow down and do things methodically!

1 Like

managed to figure it out. it was just one bad line.

1 Like

Not sure why you had a problem. Every field has a stat pos and a length, just pos the cursor to the start pos and ONLY write len bytes that match the field in question. That may mean pre-pending blanks.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.