#include <TFT_eSPI.h>
#include <XPT2046_Touchscreen.h>
// Define TFT pins
#define TFT_CS 15
#define TFT_RST -1 // Set TFT_RST to -1 if not used
#define TFT_DC 2
#define TFT_MOSI 13
#define TFT_SCLK 14
#define TFT_MISO 12
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
// Constants for the display
#define DISPLAY_WIDTH 240
#define DISPLAY_HEIGHT 320
#define MAX_SPEED 100
#define WHEEL_CIRCUMFERENCE_CM 200 // 2m circumference wheel
// Touch screen calibration values (you need to calibrate these values)
#define TS_MINX 150
#define TS_MINY 130
#define TS_MAXX 3800
#define TS_MAXY 4000
// Pin definitions for the touch screen
#define TOUCH_CS 33
#define HALL_SENSOR_PIN 22
// Create TouchScreen object
XPT2046_Touchscreen ts(TOUCH_CS);
// Variables
volatile unsigned long lastMillis = 0;
volatile float distanceTraveled = 0;
float maxSpeed = 0;
volatile float currentSpeed = 0;
volatile bool resetButtonPressed = false;
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define PARROT 0x67E6
#define SKY 0xDF3E
#define PINK 0xE5BF
float i = 0;
int randomvalue = -90;
int returnx = 0;
float angle, x, y;
bool down;
int lotx = 50, loty = 120;
void IRAM_ATTR hallSensorISR() {
unsigned long currentMillis = millis();
if (currentMillis - lastMillis >= 300) {
float elapsedSeconds = (currentMillis - lastMillis) / 1000.0;
float wheelCircumferenceKm = WHEEL_CIRCUMFERENCE_CM / 100000.0; // Convert cm to km
distanceTraveled += (wheelCircumferenceKm / elapsedSeconds) * (currentSpeed / MAX_SPEED);
currentSpeed = (WHEEL_CIRCUMFERENCE_CM / 100000.0) / elapsedSeconds * 3.6; // km/h
lastMillis = currentMillis;
}
}
void setup() {
Serial.begin(115200);
// Initialize TFT display
tft.begin();
tft.setRotation(1); // Landscape orientation
// Initialize touch screen
ts.begin();
// Attach interrupt to hall sensor pin
attachInterrupt(digitalPinToInterrupt(HALL_SENSOR_PIN), hallSensorISR, RISING);
// Draw initial screen
drawScreen();
}
void loop() {
// Check for touch events
TS_Point touch = ts.getPoint();
if (touch.z > 0 && touch.z < 1000) { // Touch detected
int16_t x = map(touch.x, TS_MINX, TS_MAXX, 0, tft.width());
int16_t y = map(touch.y, TS_MINY, TS_MAXY, 0, tft.height());
if (x >= 150 && x <= 250 && y >= 110 && y <= 150) { // Reset button pressed
resetButtonPressed = true;
}
}
// Check for reset button press
if (resetButtonPressed) {
resetButtonPressed = false;
distanceTraveled = 0;
maxSpeed = 0;
}
if (currentSpeed > maxSpeed) {
maxSpeed = currentSpeed;
tft.setTextSize(3);
tft.setTextColor(RED);
tft.setCursor(200, 150);
tft.printf("%.1f", maxSpeed);
}
// Update display
updateDisplay();
}
void drawScreen() {
tft.fillScreen(BLACK);
// Draw circular speed gauge
int centerX = 70;
int centerY = 100;
int radius = 70;
for (i = -130; i <= -90; i = i + 0.1)
{
float angle = (i / 57.2958) - 1.57;
float x = centerX + cos(angle) * radius;
float y = centerY + sin(angle) * radius;
tft.drawLine(centerX, centerY, x, y, RED);
}
for (i = -90; i <= 0; i = i + 0.1)
{
float angle = (i / 57.2958) - 1.57;
float x = centerX + cos(angle) * radius;
float y = centerX + sin(angle) * radius;
tft.drawLine(centerX, centerY, x, y + 30, BLUE);
}
for (i = 0; i <= 90; i = i + 0.1)
{
float angle = (i / 57.2958) - 1.57;
float x = centerX + cos(angle) * radius;
float y = centerY + sin(angle) * radius;
tft.drawLine(centerX, centerY, x, y, GREEN);
}
// tft.fillCircle(160,240,150,YELLOW);
tft.fillCircle(centerX, centerY, radius - 8, BLACK);
i = randomvalue;
tft.drawLine(centerX, centerY, 15, 130, RED);
tft.drawLine(centerX, centerY, 10, 120, RED);
tft.drawLine(centerX, centerY, 7, 110, RED);
tft.drawLine(centerX, centerY, 7, 85, BLUE);
tft.drawLine(centerX, centerY, 15, 75, BLUE);
tft.drawLine(centerX, centerY, 20, 66, BLUE);
tft.drawLine(centerX, centerY, 30, 45, BLUE);
tft.drawLine(centerX, centerY, 45, 40, BLUE);
tft.drawLine(centerX, centerY, 55, 35, BLUE);
tft.drawLine(centerX, centerY, 85, 35, GREEN);
tft.drawLine(centerX, centerY, 95, 40, GREEN);
tft.drawLine(centerX, centerY, 110, 50, GREEN);
tft.drawLine(centerX, centerY, 120, 66, GREEN);
tft.drawLine(centerX, centerY, 125, 75, GREEN);
tft.drawLine(centerX, centerY, 133, 85, GREEN);
tft.fillCircle(centerX, centerY, radius - 15, BLACK);
tft.drawLine(centerX, centerY, 20, 142, RED);
tft.drawLine(centerX, centerY, 7, 100, BLUE);
tft.drawLine(centerX, centerY, 20, 58, BLUE);
tft.drawLine(centerX, centerY, 70, 30, GREEN);
tft.drawLine(centerX, centerY, 120, 58, GREEN);
tft.drawLine(centerX, centerY, 135, 100, GREEN);
tft.fillCircle(centerX, centerY, radius - 20, BLACK);
tft.setTextSize(1);
tft.setTextColor(WHITE);
tft.setCursor(35, 130);
tft.print("0");
tft.setCursor(25, 100);
tft.print("20");
tft.setCursor(30, 65);
tft.print("40");
tft.setCursor(65, 50);
tft.print("60");
tft.setCursor(100, 62);
tft.print("80");
tft.setCursor(100, 95);
tft.print("100");
tft.fillCircle(centerX, centerY, 10, MAGENTA);
// Draw reset button
tft.fillRect(150, 90, 100, 40, TFT_BLUE);
tft.setTextSize(3);
tft.setTextColor(CYAN);
tft.setCursor(160, 100);
tft.print("RESET");
// Draw indicator line
tft.drawLine(centerX, centerY, 50, 120, GREEN);
tft.drawLine(centerX, centerY + 1, 50, 120, GREEN);
tft.drawLine(centerX, centerY + 2, 50, 120, GREEN);
tft.drawLine(centerX, centerY + 3, 50, 120, GREEN);
tft.drawLine(centerX, centerY + 4, 50, 120, GREEN);
tft.drawLine(centerX, centerY - 1, 50, 120, GREEN);
tft.drawLine(centerX, centerY - 2, 50, 120, GREEN);
tft.drawLine(centerX, centerY - 3, 50, 120, GREEN);
tft.drawLine(centerX, centerY - 4, 50, 120, GREEN);
// Display current speed
tft.setTextSize(5);
tft.setTextColor(GREEN);
tft.setCursor(40, 180);
tft.printf("%.1f", currentSpeed);
tft.setTextSize(3);
tft.setTextColor(GREEN);
tft.setCursor(150, 190);
tft.printf("km/h");
// Display distance traveled
tft.setTextSize(2);
tft.setTextColor(CYAN);
tft.setCursor(150, 10);
tft.printf("Distance");
tft.setTextSize(3);
tft.setTextColor(CYAN);
tft.setCursor(150, 35);
tft.printf("%.2fKM", distanceTraveled);
tft.setTextSize(2);
tft.setTextColor(CYAN);
tft.setCursor(205, 40);
tft.printf("KM");
// Display max speed
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor(150, 150);
tft.print("Max:");
tft.setTextSize(3);
tft.setTextColor(RED);
tft.setCursor(200, 150);
tft.printf("%.1f", maxSpeed);
tft.setTextSize(2);
tft.setTextColor(RED);
tft.setCursor(255, 150);
tft.print("km/h");
}
void updateDisplay() {
int centerX = 70;
int centerY = 100;
//Draw indicator Line
int tatx;
if (currentSpeed <= 20)
tatx= map(currentSpeed, 0, 100, 50, 42);
else
tatx= map(currentSpeed, 0, 100, 42, 100);
int taty;
if (currentSpeed <= 60)
taty = map(currentSpeed, 0, 60, 120, 70);
else
taty = map(currentSpeed, 60, 100, 70, 100);
while (lotx != tatx || loty != taty)
{
if (tatx > lotx)
{
lotx++;
}
else if (tatx < lotx)
{
lotx--;
}
if (taty > loty)
{
loty++;
}
else if (taty < loty)
{
loty--;
}
tft.fillCircle(centerX, centerY, 35, BLACK);
tft.fillCircle(centerX, centerY, 10, MAGENTA);
tft.drawLine(centerX, centerY, lotx, loty, GREEN);
tft.drawLine(centerX, centerY + 1, lotx, loty, GREEN);
tft.drawLine(centerX, centerY + 2, lotx, loty, GREEN);
tft.drawLine(centerX, centerY + 3, lotx, loty, GREEN);
tft.drawLine(centerX, centerY + 4, lotx, loty, GREEN);
tft.drawLine(centerX, centerY - 1, lotx, loty, GREEN);
tft.drawLine(centerX, centerY - 2, lotx, loty, GREEN);
tft.drawLine(centerX, centerY - 3, lotx, loty, GREEN);
tft.drawLine(centerX, centerY - 4, lotx, loty, GREEN);
tft.fillCircle(centerX, centerY, 8, YELLOW);
}
// Display current speed
tft.setTextSize(5);
tft.setTextColor(GREEN);
tft.setCursor(40, 180);
tft.printf("%.1f", currentSpeed);
//update distance
tft.setTextSize(3);
tft.setTextColor(CYAN);
tft.setCursor(150, 35);
tft.printf("%.2fKM", distanceTraveled);
}