//Dashboard designed by UPIR
//Code adjusted for it to work without any bitmaps by Arjan Pals
//Entire dashboard drawn in less 20 lines of code! (excluding code within functions oc)
//For now startAngle needs to be smaller then endAngle
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Hello, ESP32!");
u8g2.begin();
}
void loop() {
int calclulatedGear = map(analogRead(4), 0, 4095, 1, 7);
int RPM = map(analogRead(4), 0, 4095, 0, 6500);
int Speed = map(analogRead(4), 0, 4095, 0, 230);
u8g2.sendBuffer();
u8g2.clearBuffer();
//Draw the Gauges first, it influences with already drawn object around it
//drawGauge(centerX,centerY,innerRadius,outerRadius,startAngle,endAngle,currentAngle);
drawGauge(27, 40, 22, 27, 45, 315, map(analogRead(4), 0, 4095, 45, 315));
drawGauge(99, 40, 22, 27, 45, 315, map(analogRead(4), 0, 4095, 45, 315));
drawCricleCustomAngles(99, 40, 27, 285, 315); //Red region for RPM Gauge
u8g2.setFont(u8g2_font_profont10_tr);
printTextAtCenter(27, 62, "KPH");
printTextAtCenter(99, 62, "RPM");
u8g2.setFont(u8g2_font_profont22_tr);
printTextAtCenter(64, 61, String(calclulatedGear));
u8g2.drawFilledEllipse(63, 64, 12, 2, U8G2_DRAW_ALL);
printTextAtCenter(27, 40 + u8g2.getAscent() / 2, String(Speed));
u8g2.setFont(u8g2_font_profont22_tr);
int totalWidth = u8g2.getStrWidth(String((int)round(RPM / 100)*100).substring(0,1).c_str());
u8g2.setFont(u8g2_font_profont17_tr);
totalWidth += u8g2.getStrWidth(String((int)round(RPM / 100)*100).substring(1,String((int)round(RPM / 100)*100).length()).c_str());
u8g2.setFont(u8g2_font_profont22_tr);
u8g2.setCursor(99-totalWidth/2,40+u8g2.getFontAscent()/2);
u8g2.print(String((int)round(RPM / 100)*100).substring(0,1));
u8g2.setFont(u8g2_font_profont17_tr);
u8g2.print(String((int)round(RPM / 100)*100).substring(1,4));
u8g2.drawLine(0, 11, 128, 11);
u8g2.setFont(u8g2_font_profont11_tr);
static unsigned long pMillis = 0;
printTextAtCenter(64, 8, "Gauge Cluster @ " + String(1000 / (millis() - pMillis)) + " Hz");
pMillis = millis();
}
//Entire gauge with dots and needle changes when you enter diffrent parameters
void drawGauge(int centerX, int centerY, int innerRadius, int outerRadius, int minAngle, int maxAngle, int currentAngle)
{
//Always use 'drawCDCustomAngles' first
drawCDCustomAngles(centerX, centerY, innerRadius, outerRadius, minAngle, constrain(currentAngle,minAngle,maxAngle));
drawNeedleCustomAngles(centerX, centerY, innerRadius * 0.8, outerRadius, currentAngle);
drawDottedCircleCustomAngles(centerX, centerY, outerRadius, 20, minAngle, maxAngle);//20 dots
}
void drawCricleCustomAngles(int centerX, int centerY, int radius, int startDeg, int endDeg)
{
for (int currentAngle = startDeg; currentAngle != endDeg; currentAngle++)
{
float pointX = -sin((currentAngle) * PI / 180.0) * radius;
float pointY = cos((currentAngle) * PI / 180.0) * radius;
pointX += centerX;
pointY += centerY;
u8g2.drawPixel(round(pointX), round(pointY));
if (currentAngle == 360)
{
currentAngle = 0;
}
}
}
void drawNeedleCustomAngles(int centerX, int centerY, int innerRadius, int outerRadius, int degree)
{
float needle_x_start = -sin((degree) * PI / 180.0) * innerRadius ;
float needle_y_start = cos((degree) * PI / 180.0) * innerRadius;
needle_x_start += centerX;
needle_y_start += centerY;
float needle_x_end = -sin((degree) * PI / 180.0) * outerRadius ;
float needle_y_end = cos((degree) * PI / 180.0) * outerRadius ;
needle_x_end += centerX;
needle_y_end += centerY;
u8g2.drawLine(needle_x_start, needle_y_start, needle_x_end, needle_y_end);
}
void drawCDCustomAngles(int centerX, int centerY, int innerRadius, int outerRadius, int startDeg, int endDeg)
{
//First draw a disc with a hole in the middle
startDeg += 360;
u8g2.setDrawColor(1);
u8g2.drawDisc(centerX, centerY, outerRadius);
u8g2.setDrawColor(0);
u8g2.drawDisc(centerX, centerY, innerRadius);
//Now draw triangles to remove unwanted disc
bool done = false;
int currentAngle = endDeg;
int secondAngle = 0;
while (done == false)
{
if ((currentAngle + 20) < startDeg)
{
secondAngle = (currentAngle + 20);
}
else
{
secondAngle = startDeg;
done = true;
}
float needle_x_start = -sin((currentAngle) * PI / 180.0) * outerRadius * 1.1;
float needle_y_start = cos((currentAngle) * PI / 180.0) * outerRadius * 1.1;
needle_x_start += centerX;
needle_y_start += centerY;
float needle_x_end = -sin((secondAngle) * PI / 180.0) * outerRadius * 1.1;
float needle_y_end = cos((secondAngle) * PI / 180.0) * outerRadius * 1.1;
needle_x_end += centerX;
needle_y_end += centerY;
u8g2.setDrawColor(0);
u8g2.drawTriangle(needle_x_start, needle_y_start, needle_x_end, needle_y_end, centerX, centerY);
currentAngle = secondAngle;
}
u8g2.setDrawColor(1);
}
void drawDottedCircleCustomAngles(int centerX, int centerY, int radius, int amountOfDots, int startDeg, int endDeg)
{
float angleToAdd = (endDeg - startDeg) / amountOfDots;
for (double currentAngle = startDeg; currentAngle <= endDeg ; currentAngle += angleToAdd)
{
float needle_x_start = -sin((currentAngle) * PI / 180.0) * radius;
float needle_y_start = cos((currentAngle) * PI / 180.0) * radius;
needle_x_start += centerX;
needle_y_start += centerY;
u8g2.drawPixel(round(needle_x_start), round(needle_y_start));
if (currentAngle == 360)
{
currentAngle = 0;
}
}
}
void printTextAtCenter(int x, int y, String textToPrint)
{
u8g2.setCursor(x - u8g2.getStrWidth(textToPrint.c_str()) / 2, y);
u8g2.print(textToPrint);
}