#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_STAT 18 // Corrected to Pin 18 as per your instruction
#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;
const int MIN_ALCOHOL_LEVEL = 1000;
const int STEP_DELAY = 1000; // Real-world NEMA 17 pulse timing
bool cycleComplete = false;
void setup() {
pinMode(PIN_STEP, OUTPUT);
pinMode(PIN_DIR, OUTPUT);
pinMode(PIN_BUZZER, OUTPUT);
pinMode(PIN_IR_STAT, OUTPUT);
pinMode(PIN_LED_R, OUTPUT);
pinMode(PIN_LED_G, OUTPUT);
pinMode(PIN_LED_B, OUTPUT);
digitalWrite(PIN_IR_STAT, LOW);
setRGB(0, 0, 0);
// Required for Servo response on ESP32
ESP32PWM::allocateTimer(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("READY TO START");
delay(2000);
}
void loop() {
if (!cycleComplete) {
for (int station = 1; station <= 3; station++) {
// 1. MOVEMENT: Green LED ON, Status LED 18 OFF
handleMovement(station, true);
// 2. ARRIVAL: Status LED 18 ON, Single Beep
digitalWrite(PIN_IR_STAT, HIGH);
beepArrival();
// 3. PROCESSING: Red/Blue LEDs, Servo Action, 30s Total
handleProcessing(station);
}
// RETURN HOME (Back to Station 1)
handleMovement(1, false);
// FINAL SHUTDOWN
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Cycle successful");
setRGB(0, 0, 0);
digitalWrite(PIN_IR_STAT, LOW);
cycleComplete = true;
}
}
// ==========================================
// TRANSITION: Stepper Rotation (10 Seconds)
// ==========================================
void handleMovement(int station, bool forward) {
lcd.clear();
setRGB(0, 255, 0); // Green LED ON for movement
digitalWrite(PIN_IR_STAT, LOW); // Status LED OFF during travel
lcd.setCursor(0, 0);
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(STEP_DELAY);
digitalWrite(PIN_STEP, LOW);
delayMicroseconds(STEP_DELAY);
}
}
// ==========================================
// TRANSITION: Station Processing (30 Seconds)
// ==========================================
void handleProcessing(int station) {
// Presentation data
float temp = (station == 1) ? 22.5 : (station == 2) ? 23.1 : 62.0;
// --- STAGE 1: Immersion (15s) ---
setRGB(255, 0, 0); // Red LED ON
liftServo.write(90); // Servo DOWN
updateDisplay(station, "Immersion", temp);
monitorAndDelay(15000);
// --- STAGE 2: Lifting (8s) ---
setRGB(0, 0, 255); // Blue LED ON
liftServo.write(0); // Servo UP
updateDisplay(station, "Lifting ", temp);
monitorAndDelay(8000);
// --- STAGE 3: Purging (7s) ---
// Blue LED stays ON (represents blower fan carryover mitigation)
updateDisplay(station, "Purging ", temp);
monitorAndDelay(7000);
}
// ==========================================
// HELPERS: Display & Safety
// ==========================================
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);
// Beep and display alarm if concentration drops
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);
}
digitalWrite(PIN_BUZZER, LOW);
}
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(200);
digitalWrite(PIN_BUZZER, LOW);
}