/*************************************************
With thanks to Volos
https://www.youtube.com/watch?v=cBtsLxZ13hQ
Updated for ESP32 Core V3.0.0 June 2025
*************************************************/
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite sprite = TFT_eSprite(&tft);
//............INPUT PINS............switches and buttons
#define THROTTLE 43
#define BRIGHTNESS 14
//......................................colors
#define backColor 0x0026
#define gaugeColor 0x055D
#define dataColor 0x0311
#define purple 0xEA16
#define needleColor 0xF811
//............................dont edit this
int cx=75;
int cy=75;
int r=72;
int ir=70;
int n=0;
int angle=0;
float x2[360]; //outer points of RPM gaouges
float y2[360];
float px2[360]; //ineer point of RPM gaouges
float py2[360];
float lx2[360]; //text of RPM gaouges
float ly2[360];
float nx2[360]; //needle low of RPM gaouges
float ny2[360];
double rad=0.01745;
unsigned short color1;
unsigned short color2;
float sA;
float rA;
int blinkPeriod=500;
unsigned long currentTimeL=0;
unsigned long currentTimeR=0;
int brightnesses[5]={40,80,120,150,240};
int selectedBrightness=3;
int deb1=0;
int deb2=0;
int debB=0;
//........................................................colors
unsigned short blockColor[4]={0x0312,0x0290,0x01EC,0x016A};
unsigned short dirColor[2]={0x0312,TFT_ORANGE};
unsigned short lightColor[3]={0x01EC,0x0FA8,0xB79F};
// .........important variables
float rpmAngle=5; //.....RPM variable 0-9
float sweepAngle=5; //.....RPM variable 0-9
void setup() {
pinMode(THROTTLE,INPUT_PULLUP);
tft.init();
tft.setRotation(1);
tft.fillScreen(backColor);
sprite.createSprite(320,150);
sprite.setSwapBytes(true);
sprite.setTextDatum(4);
sprite.setTextColor(TFT_WHITE,backColor);
sprite.setTextDatum(4);
ledcAttach(0, 10000, 8);
// ledcAttachPin(38, 0);
ledcWrite(0, brightnesses[selectedBrightness]); //brightnes of screen
int a=120;
for(int i=0;i<360;i++)
{
x2[i]=((r-10)*cos(rad*a))+320-cx;
y2[i]=((r-10)*sin(rad*a))+cy;
px2[i]=((r-14)*cos(rad*a))+320-cx;
py2[i]=((r-14)*sin(rad*a))+cy;
lx2[i]=((r-24)*cos(rad*a))+320-cx;
ly2[i]=((r-24)*sin(rad*a))+cy;
nx2[i]=((r-36)*cos(rad*a))+320-cx;
ny2[i]=((r-36)*sin(rad*a))+cy;
a++;
if(a==360)
a=0;
}
}
void draw()
{
sprite.fillSprite(backColor);
sprite.fillSmoothCircle(320-cx, cy, r+2, backColor);
for(int i=0;i<5;i++)
{
if(i<=2)
sprite.fillRect(230+(7*i),70,5,5,TFT_WHITE); /// fuel rect
else
sprite.drawRect(230+(7*i),70,5,5,TFT_WHITE); //empty fuel rect
}
sprite.fillSmoothRoundRect(240,84,9,16,2,TFT_WHITE,blockColor[1]);
sprite.fillSmoothRoundRect(251,86,2,14,2,TFT_WHITE,blockColor[1]);
sprite.fillSmoothRoundRect(241,86,7,5,1,blockColor[1],TFT_WHITE);
sprite.drawLine(238,99,251,99,TFT_WHITE); //pumpimage
sprite.drawSmoothArc(320-cx, cy, r, ir, 30, 330, gaugeColor, backColor);
sprite.drawSmoothArc(320-cx, cy, r-5, r-6, 30, 330, TFT_WHITE, backColor);
sprite.drawSmoothArc(320-cx, cy, r-38, ir-37, 10, 350, gaugeColor, backColor);
//.....................................................draw GAUGES
for(int i=0;i<19;i++){
if(i<20) {color1=gaugeColor; color2=TFT_WHITE;} else {color1=purple; color2=purple;}
if(i%2==0) {
sprite.drawWedgeLine(x2[i*16],y2[i*16],px2[i*16],py2[i*16],2,1,color1);
sprite.setTextColor(color2,backColor);
sprite.drawString(String(i/2),lx2[i*16],ly2[i*16]);
}else
sprite.drawWedgeLine(x2[i*16],y2[i*16],px2[i*16],py2[i*16],1,1,color2);
}
// ........................................needles draw
rA=2*rpmAngle*1.6;
sprite.drawWedgeLine(px2[(int)rA],py2[(int)rA],nx2[(int)rA],ny2[(int)rA],2,2,needleColor);
//.....................................drawing TEXT
sprite.setTextColor(TFT_ORANGE,backColor);
sprite.drawString("x1000",320-cx,136);
sprite.drawString("RPM",320-cx,126);
//..............................................push Sprite to screen
sprite.pushSprite(0,10);
}
/*///////////////////////////////////////////////////////////////////////////
void sweep()
{
sprite.fillSprite(backColor);
sprite.fillSmoothCircle(320-cx, cy, r+2, backColor);
for(int i=0;i<5;i++)
{
if(i<=2)
sprite.fillRect(230+(7*i),70,5,5,TFT_WHITE); /// fuel rect
else
sprite.drawRect(230+(7*i),70,5,5,TFT_WHITE); //empty fuel rect
}
sprite.fillSmoothRoundRect(240,84,9,16,2,TFT_WHITE,blockColor[1]);
sprite.fillSmoothRoundRect(251,86,2,14,2,TFT_WHITE,blockColor[1]);
sprite.fillSmoothRoundRect(241,86,7,5,1,blockColor[1],TFT_WHITE);
sprite.drawLine(238,99,251,99,TFT_WHITE); //pumpimage
sprite.drawSmoothArc(320-cx, cy, r, ir, 30, 330, gaugeColor, backColor);
sprite.drawSmoothArc(320-cx, cy, r-5, r-6, 30, 330, TFT_WHITE, backColor);
sprite.drawSmoothArc(320-cx, cy, r-38, ir-37, 10, 350, gaugeColor, backColor);
//.....................................................draw GAUGES
for(int i=0;i<19;i++){
if(i<20) {color1=gaugeColor; color2=TFT_WHITE;} else {color1=purple; color2=purple;}
if(i%2==0) {
sprite.drawWedgeLine(x2[i*16],y2[i*16],px2[i*16],py2[i*16],2,1,color1);
sprite.setTextColor(color2,backColor);
sprite.drawString(String(i/2),lx2[i*16],ly2[i*16]);
}else
sprite.drawWedgeLine(x2[i*16],y2[i*16],px2[i*16],py2[i*16],1,1,color2);
}
//.....................................drawing TEXT
sprite.setTextColor(TFT_ORANGE,backColor);
sprite.drawString("x1000",320-cx,136);
sprite.drawString("RPM",320-cx,126);
//..............................................push Sprite to screen
sprite.pushSprite(0,10);
// ........................................needles draw
for(sweepAngle=0;sweepAngle<270;sweepAngle++){
rA=2*sweepAngle*1.6;
sprite.drawWedgeLine(px2[(int)rA],py2[(int)rA],nx2[(int)rA],ny2[(int)rA],2,2,needleColor);
}
}
sweep();
//////////////////////////////////////////////////////////////////////////*/
//int blinking=1;
void loop() {
if(digitalRead(BRIGHTNESS)==0)
{
if(debB==0)
{
debB=1;
selectedBrightness++;
if(selectedBrightness==5) selectedBrightness=0;
ledcWrite(0, brightnesses[selectedBrightness]); //brightnes of screen
}
}else debB=0;
draw();
if(digitalRead(THROTTLE)==0 && rpmAngle<75)
{rpmAngle=rpmAngle+1;}
if(digitalRead(THROTTLE)==1 && rpmAngle>0)
{ if(rpmAngle>=3)
rpmAngle=rpmAngle-3;
else
rpmAngle=0;
}
}
Loading
ili9341-cap-touch
ili9341-cap-touch