#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int potPin = A0;
const int armBTNPin = 7;
int knobValue;
bool armed = false;
int armBTNState;
int alignPercentage = 0;
int alignTargetX = random(10, 117);
int alignCounter = 0;
int loadingBarWidth = 0;
unsigned long timerStart = 0; // Start time in milliseconds
float timerLength; // Timer length in seconds
float timerElapsed;
float timerRemaining;
bool isTimerRunning = false; // Separate timer system
void setup() {
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
pinMode(potPin, INPUT);
pinMode(armBTNPin, INPUT_PULLUP);
}
void defuse() {
armed = false;
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print("Defuse" + String('\n') + "Complete");
display.setTextSize(1);
display.setCursor(95, 54);
display.print(timerRemaining);
display.setTextSize(1);
display.setCursor(0, 35);
display.print("Press ARM to continue");
display.display();
}
void arm() {
delay(2000);
while(digitalRead(armBTNPin) != 0) {
knobValue = analogRead(potPin);
timerLength = 60 * map(knobValue, 0, 1023, 1, 20);
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0,0);
display.print("Timer Length:" + String('\n') + (timerLength / 60) + "min" + String('\n') + "Press ARM to confirm ...");
display.display();
}
alignCounter = 0;
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(3);
display.setCursor(10,10);
display.print("ARMED");
display.display();
delay(5000);
display.clearDisplay();
armed = true;
// Start the timer
timerStart = millis();
isTimerRunning = true;
}
void armedStuff() {
// Read potentiometer value
knobValue = analogRead(potPin);
knobValue = map(knobValue, 0, 1023, 10, 117);
// Map percentage to loading bar width
loadingBarWidth = map(alignPercentage, 0, 100, 0, 127);
// Timer Logic (Separate from alignment)
if (isTimerRunning) {
timerElapsed = (millis() - timerStart) / 1000.0; // Calculate elapsed time in seconds
timerRemaining = timerLength - timerElapsed; // Calculate remaining time
// Stop the timer if it reaches 0
if (timerRemaining <= 0) {
timerRemaining = 0;
isTimerRunning = false;
}
}
// Update display
display.clearDisplay();
// Display the alignment target and selected position
display.drawLine(alignTargetX, 0, alignTargetX, 5, WHITE); // Target indicator
display.drawRect(alignTargetX - 1, 0, 3, 4, WHITE);
display.drawRect(alignTargetX - 2, 0, 5, 2, WHITE);
display.drawLine(alignTargetX, 32, alignTargetX, 37, WHITE);
display.drawRect(alignTargetX - 1, 34, 3, 4, WHITE);
display.drawRect(alignTargetX - 2, 36, 5, 2, WHITE);
display.drawLine(knobValue, 5, knobValue, 32, WHITE); // Knob position
// Display loading bar for alignment percentage
display.fillRect(0, 40, loadingBarWidth, 10, WHITE); // Loading bar
display.drawRect(0, 39, 127, 12, WHITE); // Loading bar outline
// Show the alignment percentage
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(3, 54);
display.print(String(alignPercentage) + "%");
// Display the Align Counter
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(25, 54);
display.print("Counter:" + String(alignCounter) + "/5");
// Display the separate timer countdown
display.setCursor(95, 54);
display.print(timerRemaining, 2); // Display the remaining time with 2 decimal places
display.display();
// Alignment logic (Separate from the timer)
if (knobValue == alignTargetX) {
alignPercentage += 2;
} else {
alignPercentage -= 2;
if (alignPercentage < 0) {
alignPercentage = 0;
}
}
// Reset the alignment and percentage once 100% is reached
if (alignPercentage >= 100) {
alignTargetX = random(10, 117); // Randomize target position
alignPercentage = 0;
alignCounter += 1;
if (alignCounter >= 5) {
defuse();
}
}
delay(50);
}
void loop() {
if(armed) {
armedStuff();
} else if(int(digitalRead(armBTNPin)) == 0) {
arm();
}
}