#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_NeoPixel.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
LiquidCrystal_I2C lcd(0x27, 16, 2);
#define PIR_PIN 13
#define TRIG_PIN 12
#define ECHO_PIN 14
#define BUZZER_A 25
#define NEO_A 26
#define BUZZER_B 33
#define NEO_B 27
#define NUM_LEDS 16
Adafruit_NeoPixel ringA(NUM_LEDS, NEO_A, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel ringB(NUM_LEDS, NEO_B, NEO_GRB + NEO_KHZ800);
int virtualDistance = 180;
bool enemyApproaching = true;
unsigned long prevAutoMillis = 0;
const long enemySpeedInterval = 250;
unsigned long prevBuzzerMillis = 0;
bool buzzerToggle = false;
void setup() {
Serial.begin(115200);
pinMode(PIR_PIN, INPUT);
ledcAttach(BUZZER_A, 1200, 8);
ledcAttach(BUZZER_B, 1200, 8);
if(!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println("OLED Link Error"); }
lcd.init();
lcd.backlight();
ringA.begin(); ringA.show();
ringB.begin(); ringB.show();
lcd.setCursor(0, 0); lcd.print("GRID INITIALIZED");
lcd.setCursor(0, 1); lcd.print("RADAR VISUAL OK ");
delay(1500);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - prevAutoMillis >= enemySpeedInterval) {
prevAutoMillis = currentMillis;
if (enemyApproaching) {
virtualDistance -= 5;
if (virtualDistance <= 15) enemyApproaching = false;
} else {
virtualDistance += 5;
if (virtualDistance >= 180) enemyApproaching = true;
}
}
oled.clearDisplay();
drawFuturisticRadarUI(virtualDistance);
setRingColor(ringA, 0, 255, 0);
setRingColor(ringB, 0, 255, 0);
if (virtualDistance < 150) {
if (virtualDistance > 80 && virtualDistance <= 150) {
ledcWrite(BUZZER_B, 0);
setRingColor(ringA, 255, 100, 0);
lcd.setCursor(0, 0); lcd.print("ALERT: SECTOR A ");
lcd.setCursor(0, 1); lcd.print("ENEMY: " + String(virtualDistance) + "cm ");
if (currentMillis - prevBuzzerMillis >= 250) {
prevBuzzerMillis = currentMillis;
buzzerToggle = !buzzerToggle;
}
if(buzzerToggle) {
ledcWrite(BUZZER_A, 128);
} else {
ledcWrite(BUZZER_A, 0);
}
}
else if (virtualDistance <= 80) {
setRingColor(ringA, 255, 0, 0);
setRingColor(ringB, 255, 0, 0);
lcd.setCursor(0, 0); lcd.print("🚨 BREACH: ZONE B");
lcd.setCursor(0, 1); lcd.print("CTRL ROOM IMPACT");
ledcWrite(BUZZER_A, 128);
ledcWrite(BUZZER_B, 128);
}
} else {
ledcWrite(BUZZER_A, 0);
ledcWrite(BUZZER_B, 0);
lcd.setCursor(0, 0); lcd.print("GRID ONLINE: ");
lcd.setCursor(0, 1); lcd.print("SYSTEM SECURE ");
}
oled.display();
}
void drawFuturisticRadarUI(int distance) {
// Radar Semicircle Arcs
oled.drawCircle(64, 63, 60, WHITE);
oled.drawCircle(64, 63, 38, WHITE);
// Center Control Room Core Circle (Radius 14)
oled.drawCircle(64, 63, 14, WHITE);
oled.drawLine(4, 63, 124, 63, WHITE);
oled.setTextSize(1);
oled.setTextColor(WHITE);
// 📍 EXACT TARGET ALIGNMENT: Sectors are positioned right above the central Control Room Circle Line!
oled.setCursor(24, 44); oled.print("Sec A"); // Left side just above the core arc boundary
oled.setCursor(76, 44); oled.print("Sec B"); // Right side just above the core arc boundary
// Control Room core mark centered inside its circle
oled.setCursor(53, 52); oled.print("CTRL");
if (distance < 150) {
int mappedRadius = map(constrain(distance, 10, 150), 10, 150, 10, 58);
oled.fillCircle(64, 63 - mappedRadius, 3, WHITE);
oled.drawCircle(64, 63 - mappedRadius, 6, WHITE);
oled.setCursor(2, 4); oled.print(String(distance) + "cm");
} else {
oled.setCursor(2, 4); oled.print("SCAN");
}
}
void setRingColor(Adafruit_NeoPixel &targetRing, uint8_t r, uint8_t g, uint8_t b) {
for(int i=0; i<NUM_LEDS; i++) {
targetRing.setPixelColor(i, targetRing.Color(r, g, b));
}
targetRing.show();
}
Loading
esp32-devkit-c-v4
esp32-devkit-c-v4
Loading
ssd1306
ssd1306