/*
  Arduino Forum
  Topics:       Reading Sensor. Do condition with Solenoid and Pump
  Sub-Category: Programming Questions
  Category:     Using Arduino
  Link:         https://forum.arduino.cc/t/reading-sensor-do-condition-with-solenoid-and-pump/1142214/10
*/


/*
  This program is designed to manage pressure-related systems and alarms.
  It reads input from a pressure sensor, scales it to a percentage, and checks for low and high pressure conditions with a deadband.
  Based on these conditions, it activates the pump or valve with specified delays.
  It also updates the alarm status for low and high pressure conditions and the common trip status based on input.
  The engineering unit can be set from 0 to EU_MAX.

  Pressure: 0.0-100.0%
  Low Setpoint (SP): 20.0%
  High Setpoint (SP): 80.0%
  Deadband: 3.0%
*/

// Pin definitions
#define commonTripPin     4  // Pin for common trip
#define hiAlarmPin        5  // Pin for high pressure alarm
#define loAlarmPin        6  // Pin for low pressure alarm
#define normalPin         7  // Pin for normal status indicator

#define pumpOutputPin     2  // Pin for pump output
#define valveOutputPin    3  // Pin for valve output
#define pressureInputPin  A0 // Pin for pressure sensor input

// Constants
#define EU_MAX        100.0F  // Maximum pressure value
#define SETPOINT_HIGH 80.0F   // High setpoint value
#define SETPOINT_LOW  20.0F   // Low setpoint value
#define DEADBAND      3.0F    // Deadband value
#define PUMP_DELAY    3000UL  // Delay for pump activation
#define VALVE_DELAY   5000UL  // Delay for valve activation

// Global variables
int rawValue;        // Raw input value from pressure sensor
float pressure;      // Scaled pressure value
bool lowPressure;    // Flag for low pressure condition
bool highPressure;   // Flag for high pressure condition
bool commonAlarm;    // Flag for common alarm condition

// Calculating deadband value based on the maximum pressure value and the percentage deadband
const float deadband = EU_MAX * DEADBAND * 0.01;

bool pumpState;      // State of the pump
bool valveState;     // State of the valve

bool input;          // Input status for timer
bool done;           // Completion status for timer
unsigned long delayTime;  // Delay time for pump or valve activation
unsigned long startTime;  // Start time for the timer

// Setup function
void setup() {
  // Serial.begin(115200); // Initialize serial communication if needed

  // Set pin modes
  pinMode(normalPin, OUTPUT);       // Set normal pin as output
  pinMode(loAlarmPin, OUTPUT);      // Set low alarm pin as output
  pinMode(hiAlarmPin, OUTPUT);      // Set high alarm pin as output
  pinMode(commonTripPin, OUTPUT);   // Set common trip pin as output

  pinMode(valveOutputPin, OUTPUT);  // Set valve output pin as output
  pinMode(pumpOutputPin, OUTPUT);   // Set pump output pin as output
}

// Main loop
void loop() {
  AnalogCondition();  // Check analog condition
  OutputCondition();  // Update output condition
  AlarmStatus();      // Update alarm status
}

// Function to check analog condition
void AnalogCondition() {
  // Read raw input value from pressure sensor
  rawValue = analogRead(pressureInputPin);
  // Scale analog input to percentage
  pressure = rawValue * 100.0F / 1023.0F;

  // Check for low and high pressure conditions with deadband
  lowPressure = (lowPressure | pressure <= SETPOINT_LOW) & !(pressure >= SETPOINT_LOW + deadband);      // Determine low pressure condition with deadband
  highPressure = (highPressure | pressure >= SETPOINT_HIGH) & !(pressure <= SETPOINT_HIGH - deadband);  // Determine high pressure condition with deadband
  commonAlarm = lowPressure | highPressure; // Set common alarm condition
}

// Function to update output condition
void OutputCondition() {
  // Set delay time based on the type of alarm
  if (commonAlarm) {
    delayTime = lowPressure ? PUMP_DELAY : VALVE_DELAY;
  }

  TimerOn(commonAlarm);                   // Start timer if common alarm is active
  bool pumpStart = lowPressure & done;    // Check if pump should start
  bool valveStart = highPressure & done;  // Check if valve should start

  // Update pump and valve states based on conditions
  pumpState = (pumpState | pumpStart) & !valveStart;    // Update pump state
  valveState = (valveState | valveStart) & !pumpStart;  // Update valve state

  // Update pump and valve outputs
  digitalWrite(pumpOutputPin, pumpState & !highPressure);   // Set pump output based on conditions
  digitalWrite(valveOutputPin, valveState & !lowPressure);  // Set valve output based on conditions
}

// Function to update alarm status
// This function updates the status of different alarms based on pressure conditions and common trip input.
void AlarmStatus() {
  digitalWrite(normalPin, !commonAlarm);    // Update normal status based on common alarm
  digitalWrite(loAlarmPin, lowPressure);    // Update low alarm status based on low pressure condition
  digitalWrite(hiAlarmPin, highPressure);   // Update high alarm status based on high pressure condition
  digitalWrite(commonTripPin, input);       // Update common trip status based on input
}

// Function to handle timer
// Parameters:
// - enable: boolean value to start or stop the timer
// Returns:
// - boolean value indicating if the timer duration has elapsed
bool TimerOn(bool enable) {
  if (enable) {
    if (!done) {
      if (!input) startTime = millis();  // Start timer if not already started
      if (millis() - startTime >= delayTime) done = true;  // Check if timer duration has elapsed
    }
  } else {
    done = false;   // Reset timer
  }
  input = enable;   // Update input status
  return done;      // Return timer status
}
|
80.0%
HIGH
|
77.0%
HIGH-DB
|
20.0%
LOW
|
23.0%
LOW+DB
|
0
|
1023
|
0.0%
|
100.0%
PUMP
VALVE