/*
Arduino Mega Peristaltic Pump Control (Standalone B/C)
- 3 pumps run simultaneously based on keypad input volumes
- 2 additional relays (4 & 5) toggled anytime by B/C, independent of A
- Each B/C key press toggles its relay state
- D key stops all operations immediately
- Keypad: digits to input volumes and '#' to confirm per pump
- A key starts pumps sequence
- LCD1602 I2C (SDA->20, SCL->21) displays status
*/
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
// I2C LCD setup
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Keypad setup
const byte ROWS = 4, COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte rowPins[ROWS] = {2, 3, 4, 5};
byte colPins[COLS] = {6, 7, A0, A1};
Keypad keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
// Relay pins
#define RELAY1_PIN 8
#define RELAY2_PIN 9
#define RELAY3_PIN 10
#define RELAY4_PIN 11 // B toggle
#define RELAY5_PIN 12 // C toggle
// States and timers
unsigned int volumes[3]; // ml per pump
unsigned long durations[3]; // ms per pump
bool r4State = false;
bool r5State = false;
bool readyToStart = false;
int inputPump = 0;
void setup() {
Wire.begin();
lcd.init(); lcd.backlight();
// Configure relay outputs
pinMode(RELAY1_PIN, OUTPUT);
pinMode(RELAY2_PIN, OUTPUT);
pinMode(RELAY3_PIN, OUTPUT);
pinMode(RELAY4_PIN, OUTPUT);
pinMode(RELAY5_PIN, OUTPUT);
stopAll();
// Initial prompt
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Peris.Pump Setup");
delay(1000);
promptPumpInput();
}
void loop() {
char key = keypad.getKey();
if (key) {
// Always handle B/C/D immediately
if (key == 'B') {
r4State = !r4State;
digitalWrite(RELAY4_PIN, r4State ? HIGH : LOW);
updateStatus();
return;
}
if (key == 'C') {
r5State = !r5State;
digitalWrite(RELAY5_PIN, r5State ? HIGH : LOW);
updateStatus();
return;
}
if (key == 'D') {
stopAll();
lcd.clear(); lcd.setCursor(0,0);
lcd.print("Emergency Stop");
delay(1000);
readyToStart = false;
promptPumpInput();
return;
}
// Handle input or start
if (!readyToStart) {
handleVolumeInput(key);
} else {
if (key == 'A') {
runSimultaneous();
readyToStart = false;
promptPumpInput();
}
}
}
}
// Prompt volumes
void promptPumpInput() {
inputPump = 0;
for (int i = 0; i < 3; i++) volumes[i] = 0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("P1 ml: ");
lcd.setCursor(0,1);
}
// Process numeric volume entry
void handleVolumeInput(char key) {
if (isdigit(key)) {
volumes[inputPump] = volumes[inputPump] * 10 + (key - '0');
lcd.setCursor(0,1);
lcd.print(volumes[inputPump]);
}
else if (key == '#') {
durations[inputPump] = volumes[inputPump] * 600UL;
inputPump++;
if (inputPump < 3) {
lcd.clear(); lcd.setCursor(0,0);
lcd.print("P"); lcd.print(inputPump+1); lcd.print(" ml: ");
lcd.setCursor(0,1);
} else {
readyToStart = true;
lcd.clear(); lcd.setCursor(0,0);
lcd.print("A:START B:R4");
lcd.setCursor(0,1);
lcd.print("C:R5 D:STOP");
}
}
}
// Run pumps together
void runSimultaneous() {
// Activate pumps
digitalWrite(RELAY1_PIN, HIGH);
digitalWrite(RELAY2_PIN, HIGH);
digitalWrite(RELAY3_PIN, HIGH);
unsigned long startT = millis();
unsigned long maxDur = max(durations[0], max(durations[1], durations[2]));
bool stopFlag = false;
while (millis() - startT < maxDur) {
// Display each pump remaining sequentially
for (int i = 0; i < 3; i++) {
unsigned long elapsed = millis() - startT;
int remMl = (durations[i] > elapsed) ? (durations[i] - elapsed) / 600UL : 0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("P"); lcd.print(i+1);
lcd.print(" Rem:"); lcd.print(remMl); lcd.print("ml");
updateStatus();
delay(200);
}
}
// Deactivate pumps
digitalWrite(RELAY1_PIN, LOW);
digitalWrite(RELAY2_PIN, LOW);
digitalWrite(RELAY3_PIN, LOW);
lcd.clear(); lcd.setCursor(0,0);
lcd.print("Process Done");
delay(2000);
}
// Update LCD with relay statuses
void updateStatus() {
lcd.setCursor(0,1);
lcd.print("R4:"); lcd.print(r4State?"On ":"Off");
lcd.print(" R5:"); lcd.print(r5State?"On ":"Off");
}
// Stop all relays
void stopAll() {
digitalWrite(RELAY1_PIN, LOW);
digitalWrite(RELAY2_PIN, LOW);
digitalWrite(RELAY3_PIN, LOW);
digitalWrite(RELAY4_PIN, LOW);
digitalWrite(RELAY5_PIN, LOW);
r4State = false;
r5State = false;
}