#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_FT6206.h>
// TFT Display Pins
#define TFT_CS 10
#define TFT_RST 4
#define TFT_DC 9
// Create TFT Display Object
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
// Create Capacitive Touchscreen Object
Adafruit_FT6206 ts = Adafruit_FT6206();
// Toggle switch state (OFF by default)
bool toggleState = false;
int speedLevel = 0; // 0 (OFF), 25, 50, 75, 100
// Brightness variables
int brightnessLevel = 100; // Default brightness (100%)
// Feature states (WiFi, Bluetooth, GPS)
bool wifiState = true; // WiFi ON by default
bool bluetoothState = true; // Bluetooth ON by default
bool gpsState = true; // GPS ON by default
// Screen states
enum ScreenState {
CONTROL_PAGE,
ABOUT_PAGE
};
ScreenState currentScreen = CONTROL_PAGE; // Start with Control Center page
void setup() {
Serial.begin(115200);
tft.begin();
tft.setRotation(3); // Adjust rotation if needed
tft.fillScreen(ILI9341_BLACK);
if (!ts.begin(40)) { // Sensitivity threshold (default: 40)
Serial.println("FT6236 Not found! Check wiring.");
while (1); // Halt if touchscreen isn't detected
}
Serial.println("Capacitive Touchscreen Initialized.");
drawUI(); // Draw UI elements
}
void loop() {
handleTouch();
}
// Draw the UI elements including the toggle switch
void drawUI() {
tft.fillScreen(ILI9341_BLACK); // Clear the screen
// Top Bar (Date, Time, Battery)
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
tft.setCursor(10, 10);
tft.print("25/03/2025 12:45 PM"); // Dummy Date & Time
// Battery Icon & Percentage
int batteryX = 300, batteryY = 10, batteryWidth = 18, batteryHeight = 8;
tft.drawRect(batteryX, batteryY, batteryWidth, batteryHeight + 1, ILI9341_WHITE);
tft.fillRect(batteryX + batteryWidth, batteryY + 2, 3, 4, ILI9341_WHITE);
tft.fillRect(batteryX + 2, batteryY + 2, 12, 4, ILI9341_WHITE);
tft.setCursor(280, 10);
tft.print("85%"); // Dummy battery percentage
// Draw the appropriate screen based on currentScreen state
if (currentScreen == CONTROL_PAGE) {
drawControlPage();
} else if (currentScreen == ABOUT_PAGE) {
drawAboutPage();
}
}
// Function to draw the Control Center page
void drawControlPage() {
// Control Center Box
tft.drawRoundRect(30, 45, 280, 120, 15, ILI9341_WHITE);
tft.setCursor(30, 35);
tft.print("Control Center");
// Motor Control Box
tft.drawRoundRect(160, 50, 145, 110, 10, ILI9341_WHITE);
tft.setCursor(195, 55);
tft.print("Motor Control");
// Speed Control Buttons
drawSpeedButtons();
// Draw the Toggle Switch in OFF state initially
drawToggleSwitch(toggleState);
// Brightness Control (Bar)
tft.drawRoundRect(50, 180, 250, 40, 15, ILI9341_WHITE);
tft.setCursor(30, 170);
tft.setTextSize(1);
tft.print("Brightness");
drawBrightnessBar();
// Left Side Boxes (WiFi, Bluetooth, GPS, About)
drawFeatureBox(40, 60, "WiFi", wifiState);
drawFeatureBox(95, 60, "Bluetooth", bluetoothState);
drawFeatureBox(40, 110, "GPS", gpsState);
drawFeatureBox(95, 110, "About", false); // About button is always OFF
}
// Function to draw the About page
void drawAboutPage() {
// Heading
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.setCursor(115, 35);
tft.print("About");
// Circular-edged rectangle border
tft.drawRoundRect(30, 60, 260, 175, 20, ILI9341_WHITE);
// Back Button (Top-left corner)
tft.fillRoundRect(10, 30, 45, 30, 10, ILI9341_BLUE);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.setCursor(23, 33);
tft.print("<");
}
// Function to draw a box and place the corresponding symbol
void drawFeatureBox(int x, int y, String label, bool state) {
// Draw the box with blue background if the feature is ON
if (state) {
tft.fillRoundRect(x, y, 50, 35, 5, ILI9341_BLUE);
} else {
tft.fillRoundRect(x, y, 50, 35, 5, ILI9341_BLACK);
}
tft.drawRoundRect(x, y, 50, 35, 5, ILI9341_WHITE);
// Draw the symbol
if (label == "WiFi") drawWiFiSymbol(x + 17, y + 5);
else if (label == "Bluetooth") drawBluetoothSymbol(x + 20, y + 7);
else if (label == "GPS") drawGPSSymbol(x + 17, y + 12);
else if (label == "About") drawAboutSymbol(x + 18, y + 10);
}
// Function to draw toggle switch based on its state
void drawToggleSwitch(bool state) {
int x = 210, y = 140, width = 50, height = 15;
if (state) {
// ON State: Blue background, circle at right
tft.fillRoundRect(x, y, width, height, 12, ILI9341_BLUE);
tft.fillCircle(x + width - 8, y + height / 2, 5, ILI9341_WHITE);
} else {
// OFF State: Clear previous blue background and redraw white border
tft.fillRoundRect(x, y, width, height, 12, ILI9341_BLACK);
tft.drawRoundRect(x, y, width, height, 12, ILI9341_WHITE);
tft.fillCircle(x + 8, y + height / 2, 5, ILI9341_WHITE);
}
// Labels ON and OFF
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
tft.setCursor(185, 144);
tft.print("OFF");
tft.setCursor(270, 144);
tft.print("ON");
}
// Function to draw speed buttons
void drawSpeedButtons() {
int x1 = 175, y1 = 75, w = 50, h = 25;
int speedColors[] = {ILI9341_BLACK, ILI9341_BLACK, ILI9341_BLACK, ILI9341_BLACK};
if (toggleState) {
if (speedLevel == 25) speedColors[0] = ILI9341_BLUE;
else if (speedLevel == 50) speedColors[1] = ILI9341_BLUE;
else if (speedLevel == 75) speedColors[2] = ILI9341_BLUE;
else if (speedLevel == 100) speedColors[3] = ILI9341_BLUE;
}
// Draw buttons
for (int i = 0; i < 4; i++) {
tft.fillRoundRect(x1 + (i % 2) * 65, y1 + (i / 2) * 30, w, h, 10, speedColors[i]);
tft.drawRoundRect(x1 + (i % 2) * 65, y1 + (i / 2) * 30, w, h, 10, ILI9341_WHITE);
}
// Labels
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
tft.setCursor(190, 83); tft.print("25%");
tft.setCursor(255, 83); tft.print("50%");
tft.setCursor(190, 113); tft.print("75%");
tft.setCursor(255, 113); tft.print("100%");
}
// Function to handle touch events
void handleTouch() {
if (!ts.touched()) return; // No touch detected
TS_Point p = ts.getPoint(); // Get touch point
int touchX = p.x;
int touchY = p.y;
// Adjust rotation mapping (depends on display orientation)
int screenX = map(touchY, 320, 0, 0, 320);
int screenY = touchX;
Serial.print("Touch Detected at: X=");
Serial.print(screenX);
Serial.print(", Y=");
Serial.println(screenY);
if (currentScreen == CONTROL_PAGE) {
// Toggle Switch Region: (210,140) width 50, height 15
if (screenX >= 210 && screenX <= 260 && screenY >= 140 && screenY <= 155) {
toggleState = !toggleState; // Toggle the state
drawToggleSwitch(toggleState);
delay(250); // 500ms delay after toggle
if (!toggleState) {
speedLevel = 0; // Ensure speed resets when turned OFF
} else {
speedLevel = 25; // Default speed when turning ON
}
drawSpeedButtons();
Serial.println(toggleState ? "Motor ON" : "Motor OFF");
}
// Speed Button Regions
int newSpeed = -1;
if (screenX >= 175 && screenX <= 225 && screenY >= 75 && screenY <= 100) newSpeed = 25;
else if (screenX >= 240 && screenX <= 290 && screenY >= 75 && screenY <= 100) newSpeed = 50;
else if (screenX >= 175 && screenX <= 225 && screenY >= 105 && screenY <= 130) newSpeed = 75;
else if (screenX >= 240 && screenX <= 290 && screenY >= 105 && screenY <= 130) newSpeed = 100;
if (newSpeed != -1) {
if (!toggleState) {
toggleState = true; // Turn ON if speed button pressed when toggle was OFF
drawToggleSwitch(true);
}
speedLevel = newSpeed;
drawSpeedButtons();
Serial.print("Speed Level: ");
Serial.println(speedLevel);
delay(250);
}
// Brightness Bar Region
handleBrightnessTouch(screenX, screenY);
// Feature Box Regions (WiFi, Bluetooth, GPS, About)
if (screenX >= 40 && screenX <= 90 && screenY >= 60 && screenY <= 95) {
wifiState = !wifiState; // Toggle WiFi state
drawFeatureBox(40, 60, "WiFi", wifiState);
Serial.println(wifiState ? "WiFi ON" : "WiFi OFF");
delay(250);
}
if (screenX >= 95 && screenX <= 145 && screenY >= 60 && screenY <= 95) {
bluetoothState = !bluetoothState; // Toggle Bluetooth state
drawFeatureBox(95, 60, "Bluetooth", bluetoothState);
Serial.println(bluetoothState ? "Bluetooth ON" : "Bluetooth OFF");
delay(250);
}
if (screenX >= 40 && screenX <= 90 && screenY >= 110 && screenY <= 145) {
gpsState = !gpsState; // Toggle GPS state
drawFeatureBox(40, 110, "GPS", gpsState);
Serial.println(gpsState ? "GPS ON" : "GPS OFF");
delay(250);
}
if (screenX >= 95 && screenX <= 145 && screenY >= 110 && screenY <= 145) {
currentScreen = ABOUT_PAGE; // Switch to About page
drawUI();
delay(250);
}
} else if (currentScreen == ABOUT_PAGE) {
// Back Button Region
if (screenX >= 10 && screenX <= 55 && screenY >= 30 && screenY <= 60) {
currentScreen = CONTROL_PAGE; // Switch back to Control Center page
drawUI();
delay(250);
}
}
}
// Function to handle brightness bar touch
void handleBrightnessTouch(int touchX, int touchY) {
int barX = 50, barY = 180, barWidth = 250, barHeight = 40;
// Check if the touch is within the brightness bar area
if (touchX >= barX && touchX <= barX + barWidth && touchY >= barY && touchY <= barY + barHeight) {
// Map the touch position to a brightness level (10% to 100%)
brightnessLevel = map(touchX, barX, barX + barWidth, 10, 100);
// Constrain brightness to 10%-100%
brightnessLevel = constrain(brightnessLevel, 10, 100);
// Update the brightness bar display
drawBrightnessBar();
// Print the brightness level to Serial for debugging
Serial.print("Brightness: ");
Serial.print(brightnessLevel);
Serial.println("%");
delay(250);
}
}
// Function to draw the brightness bar
void drawBrightnessBar() {
int barX = 50, barY = 180, barWidth = 250, barHeight = 40;
// Clear the bar area
tft.fillRoundRect(barX, barY, barWidth, barHeight, 15, ILI9341_BLACK);
tft.drawRoundRect(barX, barY, barWidth, barHeight, 15, ILI9341_WHITE);
// Calculate the filled width based on brightnessLevel
int filledWidth = map(brightnessLevel, 10, 100, 0, barWidth);
// Fill the bar with blue up to the current brightness level
tft.fillRoundRect(barX + 5, barY + 5, filledWidth - 10, barHeight - 10, 12, ILI9341_BLUE);
}
// WiFi Symbol
void drawWiFiSymbol(int x, int y) {
tft.fillCircle(x + 6, y + 15, 2, ILI9341_WHITE); // Small dot
tft.drawLine(x, y + 6, x + 12, y + 6, ILI9341_WHITE); // Arc 1
tft.drawLine(x + 2, y + 10, x + 10, y + 10, ILI9341_WHITE); // Arc 2
}
// Bluetooth Symbol
void drawBluetoothSymbol(int x, int y) {
tft.drawLine(x, y, x + 10, y + 5, ILI9341_WHITE);
tft.drawLine(x, y + 10, x + 10, y + 5, ILI9341_WHITE);
tft.drawLine(x, y + 10, x + 10, y + 15, ILI9341_WHITE);
tft.drawLine(x + 10, y + 15, x, y + 20, ILI9341_WHITE);
tft.drawLine(x , y , x, y + 20, ILI9341_WHITE);
tft.drawLine(x , y + 10 , x - 5, y + 5, ILI9341_WHITE);
tft.drawLine(x , y + 10 , x - 5, y + 15, ILI9341_WHITE);
}
// GPS Symbol
void drawGPSSymbol(int x, int y) {
tft.drawCircle(x + 5, y + 5, 5, ILI9341_WHITE); // Outer circle
tft.fillCircle(x + 5, y + 5, 2, ILI9341_WHITE); // Inner dot
tft.fillTriangle(x + 5, y, x + 2, y + 8, x + 8, y + 8, ILI9341_WHITE); // Pointer
}
// About Symbol
void drawAboutSymbol(int x, int y) {
tft.drawCircle(x + 7, y + 7, 7, ILI9341_WHITE); // Outer circle
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(1);
tft.setCursor(x+5, y+5); tft.print("i");
}