#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Define OLED display parameters
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// Define IR sensor pin
const int irSensorPin = 9;

// Define pump control pin
const int pumpPin = 6;

// Define buzzer pin
const int buzzerPin = 7;

// Define battery monitoring pin
const int batteryPin = A0;

// Define voltage divider resistors
const float R1 = 100000.0; // 100kΩ
const float R2 = 10000.0;  // 10kΩ

// Battery voltage range
const float batteryMinVoltage = 3.0; // Minimum battery voltage
const float batteryMaxVoltage = 4.2; // Maximum battery voltage

unsigned long pumpStartTime = 0;
unsigned long cooldownStartTime = 0;
bool isPumping = false;
bool inCooldown = false;

void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  // Initialize OLED display
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  display.display();
  delay(2000);
  display.clearDisplay();

  // Initialize IR sensor pin
  pinMode(irSensorPin, INPUT);

  // Initialize pump control pin
  pinMode(pumpPin, OUTPUT);
  digitalWrite(pumpPin, LOW);  // Ensure pump is off initially

  // Initialize buzzer pin
  pinMode(buzzerPin, OUTPUT);
  digitalWrite(buzzerPin, LOW);  // Ensure buzzer is off initially
}

float readBatteryVoltage() {
  int analogValue = analogRead(batteryPin);
  float voltage = analogValue * (5.0 / 1023.0);  // Convert ADC value to voltage
  voltage = voltage * (R1 + R2) / R2;            // Apply voltage divider formula
  return voltage;
}

int batteryPercentage(float voltage) {
  if (voltage >= batteryMaxVoltage) {
    return 100;
  } else if (voltage <= batteryMinVoltage) {
    return 0;
  } else {
    return (voltage - batteryMinVoltage) / (batteryMaxVoltage - batteryMinVoltage) * 100;
  }
}

void drawBatteryBar(int percentage) {
  int barWidth = 30;
  int barHeight = 5;
  int barX = SCREEN_WIDTH - barWidth - 2;
  int barY = 2;
  int filledWidth = (percentage / 100.0) * barWidth;

  display.drawRect(barX, barY, barWidth, barHeight, SSD1306_WHITE);
  display.fillRect(barX + 1, barY + 1, filledWidth - 2, barHeight - 2, SSD1306_WHITE);
}

void loop() {
  // Read IR sensor value
  int irValue = digitalRead(irSensorPin);

  // Read battery voltage
  float batteryVoltage = readBatteryVoltage();
  int batteryPercent = batteryPercentage(batteryVoltage);

  // Display sensor status and battery voltage on OLED
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print("IR Sensor: ");
  display.print(irValue);
  display.setCursor(0, 10);
  display.print("Battery: ");
  display.print(batteryVoltage, 2);
  display.print("V");

  drawBatteryBar(batteryPercent);

  unsigned long currentTime = millis();

  if (isPumping) {
    // Pumping in progress
    unsigned long elapsedTime = (currentTime - pumpStartTime) / 1000;  // seconds
    int countdown = 20 - elapsedTime;
    display.setCursor(0, 20);
    display.print("Dispensing in: ");
    display.print(countdown);
    display.print("s");

    display.setCursor(0, 40);
    display.print("Working");

    // Activate buzzer
    digitalWrite(buzzerPin, HIGH);

    if (elapsedTime >= 20) {
      // Stop pumping after 20 seconds
      digitalWrite(pumpPin, LOW);
      digitalWrite(buzzerPin, LOW);  // Deactivate buzzer
      isPumping = false;
      inCooldown = true;
      cooldownStartTime = currentTime;
    }
  } else if (inCooldown) {
    // Cooldown period
    unsigned long elapsedCooldownTime = (currentTime - cooldownStartTime) / 1000;  // seconds
    int cooldownCountdown = 60 - elapsedCooldownTime;
    display.setCursor(0, 20);
    display.print("Cooldown: ");
    display.print(cooldownCountdown);
    display.print("s");

    display.setCursor(0, 40);
    display.print("Hand Sanitizer");

    display.setCursor(0, 50);
    display.print("NIVAN TECH");

    if (elapsedCooldownTime >= 60) {
      // End cooldown period
      inCooldown = false;
    }
  } else if (irValue == HIGH) {
    // Start pumping if hand is detected and not in cooldown
    digitalWrite(pumpPin, HIGH);
    pumpStartTime = currentTime;
    isPumping = true;
  } else {
    // Default message when ready for next detection
    display.setCursor(0, 20);
    display.print("Hand Sanitizer");

    display.setCursor(0, 50);
    display.print("NIVAN TECH");
  }

  display.display();
  delay(100);  // Short delay before next measurement
}
Loading
ssd1306