Arduino Controlled PSE Pump Code

From W220 S-Class Encyclopedia
Jump to navigation Jump to search

This is the code for the Arduino Controlled PSE Pump.

/*
 Code for controlling the Mercedes W220 PSE with an Arduino
*/
 
 // Assign Remote Control Pins
static const int RemA = 10; //A
static const int RemB = 11; //B
static const int RemC = 12; //C
static const int RemD = 13; //D

// Assign PSE Pressure Sensor Pin
static const int PPin = A0;

// Assign Trunk Lid Switch Pin
static const int TPin = A1;
int TrunkPrevState;

// Assign Relay Pins
static const int RelMotor =  2;
static const int RelPos =  3;
static const int RelNeg =  4;
static const int RelFLDr =  5;
static const int RelDrs =  6;
static const int RelTrunk =  8;
static const int RelHR =  9;
static const int RelTrunkSol =  7;

// Double Click Variables
int ButtonAState;
unsigned long timePress = 0;
unsigned long timePressLimit = 0;
int clicks = 0;

// Long Press Variables
long buttonTimer = 0;
long longPressTime = 1000;
boolean buttonActive = false;
boolean longPressActive = false;

// Assign Arduino Auto Shutdown Relay Pin
static const int SPin = A2;

// Timer Variable for Auto Shutdown
unsigned long time;
unsigned long timeout = 14400000; //4 hours

//--------------------------------------------------------------------------------------------------------

void setup() {

  // Define pin modes
  pinMode(PPin, INPUT);
  pinMode(TPin, INPUT_PULLUP);
  pinMode(SPin, OUTPUT);

  pinMode(RelMotor, OUTPUT);
  pinMode(RelPos, OUTPUT);
  pinMode(RelNeg, OUTPUT);
  pinMode(RelFLDr, OUTPUT);
  pinMode(RelDrs, OUTPUT);
  pinMode(RelTrunk, OUTPUT);
  pinMode(RelHR, OUTPUT);
  pinMode(RelTrunkSol, OUTPUT);

  pinMode(RemA, INPUT);
  pinMode(RemB, INPUT);
  pinMode(RemC, INPUT);
  pinMode(RemD, INPUT);

  // Making sure all relays are OFF
  digitalWrite(RelMotor, HIGH);
  digitalWrite(RelPos, HIGH);
  digitalWrite(RelNeg, HIGH);
  digitalWrite(RelFLDr, HIGH);
  digitalWrite(RelDrs, HIGH);
  digitalWrite(RelTrunk, HIGH);
  digitalWrite(RelHR, HIGH);
  digitalWrite(RelTrunkSol, HIGH);
  digitalWrite(SPin, HIGH);

  // Read trunk's current state
  TrunkPrevState = digitalRead(TPin);
}

//--------------------------------------------------------------------------------------------------------

void loop() {

// Auto Shutdown Timer--------------------------------------------------------------
  time = millis(); // Time elapsed since Arduino started
  if (time > timeout && digitalRead(TPin) == HIGH)
  {
    //Turn off Arduino if trunk is and was closed. Else add 30 seconds to the timer.
    if (TrunkPrevState == HIGH && digitalRead(TPin) == HIGH)
    {
      digitalWrite(SPin, LOW);
    }
    else
    {
      timeout = timeout + 30000;
    }
  }

// Button A pressed --------------------------------------------------------------
  if (digitalRead(RemA) == HIGH) 
  {
    LockAll();
  }

// Button B pressed once or twice-------------------------------------------------
// Credit - The_Little_Cousin : https://forum.arduino.cc/index.php?topic=425587.msg2932300#msg2932300
  if (digitalRead(RemB) == HIGH) {
    delay(100);
    if (digitalRead(RemB) == LOW) {
      if (clicks == 0) {
        timePress = millis();
        timePressLimit = timePress + 1000;
        clicks = 1;
      }
      else if (clicks == 1 && millis() < timePressLimit) {
        //Double press action
        UnlockAll();

        //Set variables back to 0
        timePress = 0;
        timePressLimit = 0;
        clicks = 0;
      }
    }
  }
  //Single press
  if (clicks == 1 && timePressLimit != 0 && millis() > timePressLimit)
  {
    timePress = 0;
    timePressLimit = 0;
    clicks = 0;

    //Single press action
    UnlockDriver();
  }



// Button C long-pressed --------------------------------------------------------------
// Credit xn1ch1 : https://www.instructables.com/id/Arduino-Dual-Function-Button-Long-PressShort-Press/
  if (digitalRead(RemC) == HIGH)
  {
    if (buttonActive == false) {
      buttonActive = true;
      buttonTimer = millis();
    }
    if ((millis() - buttonTimer > longPressTime) && (longPressActive == false)) {
      longPressActive = true;
      //Long-press action - Unlock the trunk
      UnlockTrunk();
    }
  } 
  else {
    if (buttonActive == true) {
      if (longPressActive == true) {
        longPressActive = false;
      } else {
        //Short-press action - Nothing
      }
      buttonActive = false;
    }
  }


// Button D pressed --------------------------------------------------------------
  if (digitalRead(RemD) == HIGH)
  {
    DropHeadRest();
  }



// Trunk lid closed -----------------------------------------------------------------
// When the trunk state changes from open(LOW) to closed (HIGH)
  if (TrunkPrevState == LOW && digitalRead(TPin) == HIGH)
  {
    LockTrunk();
  }

  // Store current trunk state
  TrunkPrevState = digitalRead(TPin);

}



//--------------------------------------------------------------------------------------------------------

void LockAll()

/*
  Lock car with +ve pressure, which pulls the Door Lock Button down, then returns to atmospheric press
*/
{
  // Doors are locked in 2 steps since there's not enough pressure. Possibly due to a small leak.
  //+ve Pressure
    digitalWrite(RelPos, LOW);
    digitalWrite(RelNeg, HIGH);
  //Driver Door
    digitalWrite(RelFLDr, LOW);
      MotorRun(3);
    digitalWrite(RelFLDr, HIGH);
  //Remaining Doors
    digitalWrite(RelDrs, LOW);
      MotorRun(5);
    digitalWrite(RelDrs, HIGH);
  //Release Pressure
    digitalWrite(RelPos, HIGH);
    digitalWrite(RelNeg, HIGH);
  delay (100);
}

//--------------------------------------------------------------------------------------------------------

void UnlockAll()
/*
  Unlock car with -ve pressure , which moves Door Lock Button up, then returns to atmospheric pressure.
*/
{
  // Doors are locked in 2 steps since there's not enough pressure. Possibly due to a small leak.
  //-ve Pressure
    digitalWrite(RelPos, HIGH);
    digitalWrite(RelNeg, LOW);
  //Passenger Doors
    digitalWrite(RelDrs, LOW);
      MotorRun(6);
    digitalWrite(RelDrs, HIGH);
  //Driver Door
   digitalWrite(RelFLDr, LOW);
      MotorRun(3);
    digitalWrite(RelFLDr, HIGH);
  //Release Pressure
    digitalWrite(RelPos, HIGH);
    digitalWrite(RelNeg, HIGH);
  delay (100);
}

//--------------------------------------------------------------------------------------------------------

void UnlockDriver()
/*
  Unlock car with -ve pressure , which moves Driver Door Lock Button up, then returns to atmospheric pressure.
*/
{
  //-ve Pressure
    digitalWrite(RelPos, HIGH);
    digitalWrite(RelNeg, LOW);
  //Driver Door
   digitalWrite(RelFLDr, LOW);
      MotorRun(3);
    digitalWrite(RelFLDr, HIGH);
  //Release Pressure
    digitalWrite(RelPos, HIGH);
    digitalWrite(RelNeg, HIGH);
  delay (100);
}

//--------------------------------------------------------------------------------------------------------

void DropHeadRest()
/*
  Drop rear headrests with -ve pressure.
*/
{
  //-ve Pressure
    digitalWrite(RelPos, HIGH);
    digitalWrite(RelNeg, LOW);
  //Rear Seat Head Restraints
    digitalWrite(RelHR, LOW);
      MotorRun(3);
    digitalWrite(RelHR, HIGH);
  //Release Pressure
    digitalWrite(RelPos, HIGH);
    digitalWrite(RelNeg, HIGH);
  delay (100);
}


//--------------------------------------------------------------------------------------------------------

void LockTrunk()
/*
   Manually close Boot/Trunk by pulling down on RTG Handle until latch goes click,
   1) +ve pressure, Boot/Trunk Catch Actuator pulls boot closed,
   2) –ve pressure, retracts the Retractable Trunklid Grip (RTG) Handle,
   3) Returns to atmospheric pressure.
*/
{
  // Open PSE Trunk HECK valve
    digitalWrite(RelTrunk, LOW);
  //+ve Pressure
    digitalWrite(RelPos, LOW);
    digitalWrite(RelNeg, HIGH);
  //Trunk Catch Actuator pulls boot closed
    MotorRun(7);
  //-ve Pressure
    digitalWrite(RelPos, HIGH);
    digitalWrite(RelNeg, LOW);
  // Retract RTG Handle
    MotorRun(4);
  // Close PSE Trunk HECK valve
    digitalWrite(RelTrunk, HIGH);
  //Release Pressure
    digitalWrite(RelPos, HIGH);
    digitalWrite(RelNeg, HIGH);
  delay (100);
}


//--------------------------------------------------------------------------------------------------------

void UnlockTrunk()
/*
   Open Boot/Trunk with trunk latch solenoid and +ve pressure, which
   extends RTG Handle, and unlocks Boot/Trunk latch, releasing lid 
   which fully opens, then returns to atmospheric pressure.
*/
{
  //+ve Pressure
    digitalWrite(RelPos, LOW);
    digitalWrite(RelNeg, HIGH);
  // Open PSE Trunk HECK valve
    digitalWrite(RelTrunk, LOW);
  // Open Solenoid Valve in trunk lock
    digitalWrite(RelTrunkSol, LOW);
  // Open Boot/Trunk latch
    MotorRun(1.5);
  // Close Solenoid Valve in trunk lock
    digitalWrite(RelTrunkSol, HIGH);
  // Extend RTG Handle
    MotorRun(4);
  // Close PSE Trunk HECK valve
    digitalWrite(RelTrunk, HIGH);
  //Release Pressure
    digitalWrite(RelPos, HIGH);
    digitalWrite(RelNeg, HIGH);
  delay (100);
}


//--------------------------------------------------------------------------------------------------------

void MotorRun(float t)
/* Turns on motor relay for t seconds
   Checks PPin for pressure extremes every 100ms and turns off motor if out of bounds.
*/
{
  int pressure;
  delay (100);
  
  //Start the motor
  digitalWrite(RelMotor, LOW);

  for (int i = 0; i <= (t * 10); i++) // t is converted from sec to multiples of 100ms (delay below)
  {
    pressure = analogRead(PPin);
    if (i > 10)  // Only check after 1 sec has passed to ignore spikes at startup
    {
      if (pressure < 80 || pressure > 640)
      {
        // Immediately stop motor and exit function
        digitalWrite(RelMotor, HIGH);
        delay (100);
        return;
      }
      else
      {
        delay (100); //Wait and recheck
      }
    }
  }
  // Stop the motor after t secs have passed
  digitalWrite(RelMotor, HIGH);
  delay (100);
}

//--------------------------------------------------------------------------------------------------------