#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ESP32Servo.h>
// --- PIN DEFINITIONS ---
#define PIN_STEP 27
#define PIN_DIR 26
#define PIN_SERVO 32
#define PIN_BUZZER 25
#define PIN_POT 34
#define PIN_IR_LED 18 // Visual reference for IR Sensor activity
#define PIN_LED_R 14
#define PIN_LED_G 12
#define PIN_LED_B 13
// --- SYSTEM OBJECTS ---
LiquidCrystal_I2C lcd(0x27, 20, 4);
Servo liftServo;
// --- THRESHOLDS & VARIABLES ---
const int MIN_ALCOHOL_LEVEL = 1000;
bool cycleComplete = false;
void setup() {
pinMode(PIN_STEP, OUTPUT);
pinMode(PIN_DIR, OUTPUT);
pinMode(PIN_BUZZER, OUTPUT);
pinMode(PIN_IR_LED, OUTPUT); // The IR status light
pinMode(PIN_LED_R, OUTPUT);
pinMode(PIN_LED_G, OUTPUT);
pinMode(PIN_LED_B, OUTPUT);
digitalWrite(PIN_BUZZER, LOW);
digitalWrite(PIN_IR_LED, LOW);
setRGB(0, 0, 0);
liftServo.setPeriodHertz(50);
liftServo.attach(PIN_SERVO, 500, 2400);
liftServo.write(0);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("TISSUE PROCESSOR");
lcd.setCursor(0, 1);
lcd.print("IR SENSOR ACTIVE");
delay(2000);
}
void loop() {
if (!cycleComplete) {
// 3-Station Sequence
for (int station = 1; station <= 3; station++) {
handleMovement(station, true);
beepArrival();
handleProcessing(station);
}
// Return to Start
handleMovement(1, false);
// Final State
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("CYCLE SUCCESSFUL");
lcd.setCursor(0, 1);
lcd.print("SYSTEM AT HOME");
setRGB(0, 0, 0);
digitalWrite(PIN_IR_LED, LOW);
cycleComplete = true;
}
}
// ==========================================
// MOVEMENT: IR Status LED is ON here
// ==========================================
void handleMovement(int station, bool forward) {
lcd.clear();
setRGB(0, 255, 0); // Green for Stepper Moving
digitalWrite(PIN_IR_LED, HIGH); // IR Sensor LED ON (Searching)
if (forward) {
lcd.print("Moving to station ");
lcd.print(station);
digitalWrite(PIN_DIR, HIGH);
} else {
lcd.print("Returning Home...");
digitalWrite(PIN_DIR, LOW);
}
unsigned long startMove = millis();
while (millis() - startMove < 10000) {
digitalWrite(PIN_STEP, HIGH);
delayMicroseconds(1000);
digitalWrite(PIN_STEP, LOW);
delayMicroseconds(1000);
}
digitalWrite(PIN_IR_LED, LOW); // IR Sensor LED OFF (Arrived)
}
// ==========================================
// PROCESSING: IR Status LED is OFF here
// ==========================================
void handleProcessing(int station) {
float currentTemp = (station == 1) ? 22.5 : (station == 2) ? 23.1 : 62.0;
// --- STAGE: IMMERSION (15s) ---
setRGB(255, 0, 0); // Red LED
liftServo.write(90);
updateDisplay(station, "Immersion", currentTemp);
monitorAndDelay(15000);
// --- STAGE: LIFTING (8s) ---
setRGB(0, 0, 255); // Blue LED
liftServo.write(0);
updateDisplay(station, "Lifting ", currentTemp);
monitorAndDelay(8000);
// --- STAGE: PURGING (7s) ---
updateDisplay(station, "Purging ", currentTemp);
monitorAndDelay(7000);
}
// ==========================================
// HELPERS
// ==========================================
void updateDisplay(int st, String stage, float temp) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("STATION: "); lcd.print(st);
lcd.setCursor(0, 1);
lcd.print("STAGE: "); lcd.print(stage);
lcd.setCursor(0, 2);
lcd.print("TEMP: "); lcd.print(temp, 1); lcd.print(" C");
}
void monitorAndDelay(unsigned long waitTime) {
unsigned long startTime = millis();
while (millis() - startTime < waitTime) {
int alc = analogRead(PIN_POT);
if (alc < MIN_ALCOHOL_LEVEL) {
digitalWrite(PIN_BUZZER, HIGH);
lcd.setCursor(0, 3);
lcd.print("!! LOW ALCOHOL !! ");
} else {
digitalWrite(PIN_BUZZER, LOW);
lcd.setCursor(0, 3);
lcd.print(" ");
}
delay(100);
}
}
void setRGB(int r, int g, int b) {
analogWrite(PIN_LED_R, r);
analogWrite(PIN_LED_G, g);
analogWrite(PIN_LED_B, b);
}
void beepArrival() {
digitalWrite(PIN_BUZZER, HIGH);
delay(150);
digitalWrite(PIN_BUZZER, LOW);
}