Skip to content. | Skip to navigation

Personal tools

lcu/presvac.cpp

lcu/presvac.cpp

lcu/presvac.cpp

/////////////////////////////////////////////////////////////////////////////
// PRESVAC.CPP
//
//  Last updated: 3/16/2005
//
//  Part of the source code for the Remote M3 Program
//
//  This file contains code for the control of the pressure/vacuum behind
//  the tertiary mirror.
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
// PresVacClockInterrupt - Called on each clock interrupt for pres/vac control
void PresVacClockInterrupt()
// Opens and closes pressure/vacuum valves with millisecond precision
// according to the pulse widths given by the control variables
// VacuumPulseWidth and PressurePulseWidth.
{
  static int vwidth,pwidth;  // Used to store a snapshot of the control variables

  if (PresVacMode == PVMAuto)
  {
    if ((Timer - PulseTime) >= (PulseCycle*CKF))
    {
      vwidth = VacuumPulseWidth;
      pwidth = PressurePulseWidth;
      PulseTime = Timer;
      write_bit(20,(vwidth > 0));
      write_bit(19,(pwidth > 0));
    }
    if (((Timer - PulseTime) >= (vwidth*CKF)) && (vwidth < PulseCycle))
      write_bit(20,0);
    if (((Timer - PulseTime) >= (pwidth*CKF)) && (pwidth < PulseCycle))
      write_bit(19,0);
  }
}

/////////////////////////////////////////////////////////////////////////////
// CPresVac::Init - Initialize pressure/vacuum control, load-cell DGHs
void CPresVac::Init()
{
  // Next variables were extracted from M3.INI
  // Kp, Proportional PID control loop constant (~1-5)
  Kp = 0.8;
  // Ki, Integral PID control loop constant (~0.01-0.1)
  Ki = 0.02;
  // Kd, Derivative PID control loop constant (~1)
  Kd = 1.0;
  // PIl, Pressure Integral Limit (0.0-1.0)
  PIl = 0.5;
  // VIl, Vacuum Integral Limit (0.0-1.0)
  VIl = 0.5;
  // Integral Reset Threshold (~0.3-1.0)
  IntegralThreshold = 1.0;
  // Minimum pulse in msecs for pressure valve
  PressureMinPulseWidth = 10;
  // Minimum pulse in msecs for vacuum valve
  VacuumMinPulseWidth = 10;
  // Cycle time between control variable updates in msecs
  PulseCycle = 200;

  PulseUpdateTime = Timer;
  olderr = 0.0;
  target = 0.0;
  ave = 0;
  P = 0.0;
  I = 0.0;
  D = 0.0;

  // Start reading first DGH
  CurrentDGH = 0;
  // Initialize DGH modules.
  DGHs[0].Init('a');
  DGHs[1].Init('b');
  DGHs[2].Init('c');
}

/////////////////////////////////////////////////////////////////////////////
// CPresVac::Update - Update pressure/vacuum control variables
void CPresVac::Update()
{
  int e;  // Stores error codes

  // Update DGH modules (mirror load cell readings)
  e = DGHs[CurrentDGH].Update();
  if (e == -1)
    return;  // DGH module not finished updating
  // Host will handle display of errors in Log ???.
  // EDS gets saturated too soon otherwise
  // Likewise sending reading here all the time
  /*
  if (e == 0)
  // DGH module read success
  {
    EDSLog.Add(802,"D%cR%+07.3f",'A'+CurrentDGH,DGHs[CurrentDGH].Reading);
    //if (ErrorCount >= 3)
    //  EDSLog.Add(950,"DGH %c Error Messages Resumed",CurrentDGH+'A');
  }
  else
  // DGH module read error
  {
    EDSLog.Add(802,"D%cRE",'A'+CurrentDGH);
    //if (DGHs[CurrentDGH].ErrorCount < 3)
    //  EDSLog.Add(50,"DGH %c Read Error",CurrentDGH+'A');
    //else if (DGHs[CurrentDGH].ErrorCount == 3)
    //  EDSLog.Add(51,"DGH %c Error Messages Suspended",CurrentDGH+'A');
  }
  */
  CurrentDGH++;
  // Continue scanning DGH's
  if (CurrentDGH > 2)
    CurrentDGH = 0;

  if ((Timer - PulseUpdateTime) > (PulseCycle*CKF))
  {
    PulseUpdateTime  = Timer;
    ave = (DGHs[0].Reading + DGHs[1].Reading + DGHs[2].Reading) / 3.0;
    err = target - ave;

    if (PresVacMode == PVMAuto)
    {
      // Calc derivative term
      D = Kd * (err - olderr);
      olderr = err;
      // Calc proportional term
      P = Kp * err;
      // Calc integral term
      I = I + Ki * err;

      if (fabs(err) > IntegralThreshold)
        I = 0.0;
      // Limit I to within +/- VIl/PIl
      if (I > VIl)
        I = VIl;
      if (I < -PIl)
        I = -PIl;
    }
    else
    {
      P = 0.0;
      I = 0.0;
      D = 0.0;
    }

    // Calculate pulse width
    _disable();

    if ((P + I + D) > 0.0)
    {
      PressurePulseWidth = PulseCycle * (P + I + D) + PressureMinPulseWidth;
      VacuumPulseWidth = PressureMinPulseWidth;
    }
    else if ((P + I + D) < 0.0)
    {
      VacuumPulseWidth = -PulseCycle * (P + I + D) + VacuumMinPulseWidth;
      PressurePulseWidth = VacuumMinPulseWidth;
    }
    else
    {
      VacuumPulseWidth = VacuumMinPulseWidth;
      PressurePulseWidth = PressureMinPulseWidth;
    }
    // Limit pulse width to 0..PulseCycle
    if (VacuumPulseWidth > PulseCycle) VacuumPulseWidth = PulseCycle;
    if (PressurePulseWidth > PulseCycle) PressurePulseWidth = PulseCycle;

    _enable();
  }
}

Generated by GNU Enscript 1.6.5.2.
Document Actions