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ú
}
}