#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Servo.h>
// TFT Display pins - using easy-to-find digital pins
#define TFT_CS 10 // Chip Select
#define TFT_RST 9 // Reset
#define TFT_DC 8 // Data/Command
#define TFT_MOSI 11 // SDI on your display
#define TFT_CLK 13 // SCK on your display
#define TFT_MISO 12 // SDO on your display
// Sensor and servo pins
#define TRIG_PIN 4 // Ultrasonic TRIG
#define ECHO_PIN 5 // Ultrasonic ECHO
#define SERVO_PIN 6 // Servo signal
// Display dimensions
#define SCREEN_WIDTH 240
#define SCREEN_HEIGHT 320
// Radar parameters
#define RADAR_CENTER_X 120
#define RADAR_CENTER_Y 280
#define RADAR_RADIUS 100
#define MAX_DISTANCE 200
#define ANGLE_STEP 3
// Colors (16-bit RGB565 format)
#define COLOR_BACKGROUND 0x0020 // Dark green
#define COLOR_GRID 0x0400 // Medium green
#define COLOR_SWEEP 0x07E0 // Bright green
#define COLOR_OBJECT 0xF800 // Red
#define COLOR_TEXT 0x07E0 // Bright green
#define COLOR_TRAIL 0x0200 // Dim green
// Create display using software SPI (easier wiring)
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);
Servo radarServo;
// Radar variables
int currentAngle = 0;
int direction = 1;
int lastSweepAngle = -1;
unsigned long lastScanTime = 0;
const int scanDelay = 120; // Milliseconds between scans
// Object storage
struct RadarObject {
int angle;
int distance;
unsigned long timestamp;
bool active;
};
const int MAX_OBJECTS = 15;
RadarObject objects[MAX_OBJECTS];
int objectCount = 0;
void setup() {
Serial.begin(9600);
Serial.println("Starting TFT Radar System...");
// Initialize TFT display
tft.begin();
tft.setRotation(0); // Portrait mode
tft.fillScreen(COLOR_BACKGROUND);
// Initialize sensor pins
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
// Initialize servo
radarServo.attach(SERVO_PIN);
radarServo.write(0);
delay(1000);
// Draw initial radar screen
drawRadarBase();
drawTitle();
Serial.println("TFT Radar System Ready!");
}
void loop() {
unsigned long currentTime = millis();
if (currentTime - lastScanTime >= scanDelay) {
// Move servo to current angle
radarServo.write(currentAngle);
delay(60); // Wait for servo to reach position
// Measure distance
int distance = measureDistance();
// Clear old sweep line
if (lastSweepAngle >= 0) {
drawSweepLine(lastSweepAngle, COLOR_BACKGROUND);
}
// Add object if detected within range
if (distance > 5 && distance < MAX_DISTANCE) {
addObject(currentAngle, distance);
Serial.print("Object detected at ");
Serial.print(currentAngle);
Serial.print("° - ");
Serial.print(distance);
Serial.println("cm");
}
// Redraw radar components
drawObjects();
drawSweepLine(currentAngle, COLOR_SWEEP);
drawSweepTrail(currentAngle);
updateInfoDisplay(currentAngle, distance);
lastSweepAngle = currentAngle;
// Update angle for next scan
currentAngle += direction * ANGLE_STEP;
if (currentAngle >= 180) {
direction = -1;
currentAngle = 180;
} else if (currentAngle <= 0) {
direction = 1;
currentAngle = 0;
}
lastScanTime = currentTime;
}
// Clean old objects periodically
cleanOldObjects();
}
void drawRadarBase() {
// Clear radar area
tft.fillCircle(RADAR_CENTER_X, RADAR_CENTER_Y, RADAR_RADIUS + 5, COLOR_BACKGROUND);
// Draw concentric circles (distance rings)
for (int i = 1; i <= 4; i++) {
int radius = (RADAR_RADIUS * i) / 4;
drawArc(RADAR_CENTER_X, RADAR_CENTER_Y, radius, 0, 180, COLOR_GRID);
}
// Draw angle lines every 30 degrees
for (int angle = 0; angle <= 180; angle += 30) {
float radian = angle * PI / 180.0;
int x = RADAR_CENTER_X + cos(radian) * RADAR_RADIUS;
int y = RADAR_CENTER_Y - sin(radian) * RADAR_RADIUS;
tft.drawLine(RADAR_CENTER_X, RADAR_CENTER_Y, x, y, COLOR_GRID);
}
// Draw distance labels
tft.setTextColor(COLOR_TEXT);
tft.setTextSize(1);
for (int i = 1; i <= 4; i++) {
int distance = (MAX_DISTANCE * i) / 4;
int radius = (RADAR_RADIUS * i) / 4;
tft.setCursor(RADAR_CENTER_X - 15, RADAR_CENTER_Y - radius - 8);
tft.print(distance);
tft.print("cm");
}
// Draw angle labels
tft.setCursor(RADAR_CENTER_X + RADAR_RADIUS - 15, RADAR_CENTER_Y + 8);
tft.print("0°");
tft.setCursor(RADAR_CENTER_X - 8, RADAR_CENTER_Y - RADAR_RADIUS + 8);
tft.print("90°");
tft.setCursor(RADAR_CENTER_X - RADAR_RADIUS + 5, RADAR_CENTER_Y + 8);
tft.print("180°");
}
void drawArc(int centerX, int centerY, int radius, int startAngle, int endAngle, uint16_t color) {
// Draw arc by plotting points
for (int angle = startAngle; angle <= endAngle; angle += 1) {
float radian = angle * PI / 180.0;
int x = centerX + cos(radian) * radius;
int y = centerY - sin(radian) * radius;
tft.drawPixel(x, y, color);
}
}
void drawSweepLine(int angle, uint16_t color) {
float radian = angle * PI / 180.0;
int x = RADAR_CENTER_X + cos(radian) * RADAR_RADIUS;
int y = RADAR_CENTER_Y - sin(radian) * RADAR_RADIUS;
tft.drawLine(RADAR_CENTER_X, RADAR_CENTER_Y, x, y, color);
}
void drawSweepTrail(int currentAngle) {
// Draw fading trail behind sweep line
for (int i = 1; i <= 8; i++) {
int trailAngle = currentAngle - (direction * i * ANGLE_STEP);
if (trailAngle >= 0 && trailAngle <= 180) {
uint16_t trailColor;
if (i <= 4) {
trailColor = COLOR_TRAIL; // Dim green trail
} else {
trailColor = COLOR_BACKGROUND; // Fade to background
}
drawSweepLine(trailAngle, trailColor);
}
}
}
int measureDistance() {
// Send ultrasonic pulse
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
// Read echo pulse duration
long duration = pulseIn(ECHO_PIN, HIGH, 30000); // 30ms timeout
if (duration == 0) {
return MAX_DISTANCE; // No echo received
}
// Calculate distance in centimeters
int distance = duration * 0.034 / 2;
// Limit to maximum range
if (distance > MAX_DISTANCE) {
return MAX_DISTANCE;
}
return distance;
}
void addObject(int angle, int distance) {
// Find empty slot or replace oldest object
int targetIndex = -1;
unsigned long oldestTime = millis();
for (int i = 0; i < MAX_OBJECTS; i++) {
if (!objects[i].active) {
targetIndex = i;
break;
}
if (objects[i].timestamp < oldestTime) {
oldestTime = objects[i].timestamp;
targetIndex = i;
}
}
if (targetIndex >= 0) {
objects[targetIndex].angle = angle;
objects[targetIndex].distance = distance;
objects[targetIndex].timestamp = millis();
objects[targetIndex].active = true;
if (objectCount < MAX_OBJECTS) objectCount++;
}
}
void drawObjects() {
unsigned long currentTime = millis();
for (int i = 0; i < MAX_OBJECTS; i++) {
if (objects[i].active) {
// Calculate object age for fading effect
unsigned long age = currentTime - objects[i].timestamp;
if (age < 4000) { // Show objects for 4 seconds
float radian = objects[i].angle * PI / 180.0;
int scaledDistance = (objects[i].distance * RADAR_RADIUS) / MAX_DISTANCE;
int x = RADAR_CENTER_X + cos(radian) * scaledDistance;
int y = RADAR_CENTER_Y - sin(radian) * scaledDistance;
// Choose color based on age
uint16_t color = COLOR_OBJECT;
if (age > 2500) {
color = 0x8000; // Dimmer red for older objects
}
// Draw object as filled circle
tft.fillCircle(x, y, 2, color);
// Draw small ring around recent objects
if (age < 1000) {
tft.drawCircle(x, y, 4, color);
}
}
}
}
}
void cleanOldObjects() {
unsigned long currentTime = millis();
for (int i = 0; i < MAX_OBJECTS; i++) {
if (objects[i].active && (currentTime - objects[i].timestamp > 4000)) {
// Clear old object from screen
float radian = objects[i].angle * PI / 180.0;
int scaledDistance = (objects[i].distance * RADAR_RADIUS) / MAX_DISTANCE;
int x = RADAR_CENTER_X + cos(radian) * scaledDistance;
int y = RADAR_CENTER_Y - sin(radian) * scaledDistance;
// Clear the object area
tft.fillCircle(x, y, 6, COLOR_BACKGROUND);
objects[i].active = false;
if (objectCount > 0) objectCount--;
}
}
}
void drawTitle() {
tft.setTextColor(COLOR_TEXT);
tft.setTextSize(2);
tft.setCursor(35, 10);
tft.print("RADAR SCAN");
tft.setTextSize(1);
tft.setCursor(90, 35);
tft.print("SYSTEM");
}
void updateInfoDisplay(int angle, int distance) {
// Clear info area
tft.fillRect(5, 50, 230, 110, COLOR_BACKGROUND);
// Draw info box border
tft.drawRect(5, 50, 230, 110, COLOR_GRID);
tft.setTextColor(COLOR_TEXT);
tft.setTextSize(1);
// Current readings - top row
tft.setCursor(10, 60);
tft.print("Angle: ");
tft.print(angle);
tft.print("°");
tft.setCursor(130, 60);
tft.print("Distance: ");
tft.print(distance);
tft.print("cm");
// Status info - second row
tft.setCursor(10, 80);
tft.print("Objects: ");
tft.print(objectCount);
tft.setCursor(130, 80);
tft.print("Range: ");
tft.print(MAX_DISTANCE);
tft.print("cm");
// Scan direction - third row
tft.setCursor(10, 100);
tft.print("Direction: ");
if (direction == 1) {
tft.print("→ (0 to 180°)");
} else {
tft.print("← (180 to 0°)");
}
// System status - fourth row
tft.setCursor(10, 120);
tft.print("Status: SCANNING");
tft.setCursor(130, 120);
tft.print("Mode: ACTIVE");
// Progress bar
int barWidth = 200;
int barHeight = 6;
int barX = 20;
int barY = 140;
// Draw progress bar background
tft.drawRect(barX - 1, barY - 1, barWidth + 2, barHeight + 2, COLOR_GRID);
tft.fillRect(barX, barY, barWidth, barHeight, COLOR_BACKGROUND);
// Draw current progress
int progress = (angle * barWidth) / 180;
tft.fillRect(barX, barY, progress, barHeight, COLOR_SWEEP);
// Progress percentage
tft.setCursor(10, 155);
tft.print("Progress: ");
tft.print((angle * 100) / 180);
tft.print("%");
}
Comments1
TFT
Pin Connections for TFT Version