Example #1
0
// internal
void Thermocycler::Loop() {
	digitalWrite(6, (lamp)?HIGH:LOW);
	digitalWrite(5, (!lamp)?HIGH:LOW);
	lamp = !lamp;
  switch (iProgramState) {
  case EStartup:
    if (millis() > STARTUP_DELAY) {
      iProgramState = EStopped;
      	iRestarted = false;
      if (!iRestarted && !ipSerialControl->CommandReceived()) {
        //check for stored program
        SCommand command;
        if (ProgramStore::RetrieveProgram(command, (char*)ipSerialControl->GetBuffer()))
          ProcessCommand(command);
      }
    }
    break;

  case ELidWait:
    if (GetLidTemp() >= iTargetLidTemp - LID_START_TOLERANCE) {
      //lid has warmed, begin program
      iThermalDirection = OFF;
      iPeltierPwm = 0;
      PreprocessProgram();
      iProgramState = ERunning;

      ipProgram->BeginIteration();
      AdvanceToNextStep();

      iProgramStartTimeMs = millis();
    }
    break;

  case ERunning:
    //update program
    if (iProgramState == ERunning) {
      if (iRamping && abs(ipCurrentStep->GetTemp() - GetPlateTemp()) <= CYCLE_START_TOLERANCE && GetRampElapsedTimeMs() > ipCurrentStep->GetRampDurationS() * 1000) {
        //begin step hold
        //eta updates
        if (ipCurrentStep->GetRampDurationS() == 0) {
          //fast ramp
          iElapsedFastRampDegrees += absf(GetPlateTemp() - iRampStartTemp);
          iTotalElapsedFastRampDurationMs += millis() - iRampStartTime;
        }

        if (iRampStartTemp > GetPlateTemp()) {
          iHasCooled = true;
        }
        iRamping = false;
        iCycleStartTime = millis();

      } 
      else if (!iRamping && !ipCurrentStep->IsFinal() && millis() - iCycleStartTime > (unsigned long)ipCurrentStep->GetStepDurationS() * 1000) {
        //begin next step
        AdvanceToNextStep();

        //check for program completion
        if (ipCurrentStep == NULL || ipCurrentStep->IsFinal()) {
          iProgramState = EComplete;        
        }
      }
    }
    break;

  case EComplete:
    if (iRamping && ipCurrentStep != NULL && abs(ipCurrentStep->GetTemp() - GetPlateTemp()) <= CYCLE_START_TOLERANCE)
      iRamping = false;
    break;
  }
  //lid 
  iLidThermistor.ReadTemp();
  ControlLid();

  //plate  
  iPlateThermistor.ReadTemp();
  CalcPlateTarget();
  ControlPeltier();

  //program
  UpdateEta();
  ipDisplay->Update();
  ipSerialControl->Process();

}
Example #2
0
// internal
boolean Thermocycler::Loop() {

  ipCommunicator->Process();
  unsigned long loopElapsedTimeMs = millis() - iPrevLoopStartTimeMs;
  iPrevLoopStartTimeMs = millis();

  switch (iProgramState) {
  case EStartup:
    iTempUpdated = false;
    if (millis() > STARTUP_DELAY) {
      iProgramState = EStopped;
      	iRestarted = false;
      if (!iRestarted && !ipCommunicator->CommandReceived()) {
        //check for stored program
        SCommand command;
        /*
        if (ProgramStore::RetrieveProgram(command, (char*)ipCommunicator->GetBuffer())) {
          ProcessCommand(command);
        }
        */
      }
    }
    break;

  case ELidWait:
    if (GetLidTemp() >= iTargetLidTemp - LID_START_TOLERANCE) {
      //lid has warmed, begin program
      iThermalDirection = OFF;
      iPeltierPwm = 0;
      PreprocessProgram();
      iProgramState = ERunning;

      ipProgram->BeginIteration();
      AdvanceToNextStep();

      iProgramStartTimeMs = millis();
    }
    break;

  case ERunning:
    //update program
    if (!iPaused) {
      if (iRamping) {
        // Increment ramping time
        iRampElapsedTimeMs += loopElapsedTimeMs;
      } else {
        // Increment holding time
        iCycleElapsedTimeMs += loopElapsedTimeMs;
      }
      if (iProgramState == ERunning) {
        if (!ipCurrentStep->IsFinal() && (iNextStepPending || iNextCyclePending)) {
          if (iNextStepPending) {
            iNextStepPending = false;
            AdvanceToNextStep();
          }
          if (iNextCyclePending) {
            iNextCyclePending = false;
            AdvanceToNextCycle();
          }
          //check for program completion
          if (ipCurrentStep == NULL || ipCurrentStep->IsFinal()) {
            iProgramState = EComplete;
          }
        } else if (iRamping && abs(ipCurrentStep->GetTemp() - GetTemp()) <= CYCLE_START_TOLERANCE && GetRampElapsedTimeMs() > ipCurrentStep->GetRampDurationS() * 1000) {
          //begin step hold
          //eta updates
          if (ipCurrentStep->GetRampDurationS() == 0) {
            //fast ramp
            iElapsedFastRampDegrees += absf(GetTemp() - iRampStartTemp);
            iTotalElapsedFastRampDurationMs += iRampElapsedTimeMs;
          }

          if (iRampStartTemp > GetTemp()) {
            iHasCooled = true;
          }
          iRamping = false;
          iCycleElapsedTimeMs = 0;
        }
        else if (!iRamping && !ipCurrentStep->IsFinal() && iCycleElapsedTimeMs > (unsigned long)ipCurrentStep->GetStepDurationS() * 1000) {
          //begin next step
          AdvanceToNextStep();
          //check for program completion
          if (ipCurrentStep == NULL || ipCurrentStep->IsFinal()) {
            iProgramState = EComplete;
          }
        }
      }
      break;

    case EComplete:
      PCR_DEBUG_LINE(ipCurrentStep->GetTemp());
      if (iRamping && ipCurrentStep != NULL && abs(ipCurrentStep->GetTemp() - GetTemp()) <= CYCLE_START_TOLERANCE) {
        iRamping = false;
      }
      break;
    }
  }

  statusBuff[statusIndex].timestamp = millis();
  //Read lid and well temp
  statusBuff[statusIndex].hardwareStatus = HARD_NO_ERROR;
  HardwareStatus result = iPlateThermistor.ReadTemp();
  if (result!=HARD_NO_ERROR) {
      statusBuff[statusIndex].hardwareStatus = result;
  }
  result = iLidThermistor.ReadTemp();
  if (result!=HARD_NO_ERROR) {
      statusBuff[statusIndex].hardwareStatus = result;
  }

  statusBuff[statusIndex].lidTemp = GetLidTemp();
  statusBuff[statusIndex].wellTemp = GetPlateTemp();

  float lidTemp = 0;
  float wellTemp = 0;

  CheckHardware(&lidTemp, &wellTemp);
  PCR_DEBUG("L=");
  PCR_DEBUG(lidTemp);
  PCR_DEBUG(" W=wellTemp");
  PCR_DEBUG_LINE(wellTemp);

  iLidThermistor.setTemp(lidTemp);
  iPlateThermistor.setTemp(wellTemp);

  double estimatedAirTemp = wellTemp * 0.4 + lidTemp * 0.6;
  // Estimated delta to next 1 sec
  double diff = ((wellTemp - iEstimatedSampleTemp)/THETA_WELL + (estimatedAirTemp-iEstimatedSampleTemp)/THETA_LID ) / CAPACITY_TUBE;

  if (!iTempUpdated) {
    iTempUpdated = true;
    iEstimatedSampleTemp = estimatedAirTemp;
  } else if ( 5>diff && diff > -5) {
    iEstimatedSampleTemp += diff;
  }

  CalcPlateTarget();

  // Check error
  //if (iHardwareStatus==HARD_NO_ERROR || true) { //TODO WELL_TEST (dummy line)
  if (iHardwareStatus==HARD_NO_ERROR) { //TODO WELL_TEST
      ControlLid();
      ControlPeltier();
      if (iHardwareStatus!=HARD_NO_ERROR) {
        PCR_DEBUG("ERR=");
        PCR_DEBUG_LINE(iHardwareStatus);
      }
  } else {
      PCR_DEBUG_LINE("ALL OFF");
      iProgramState = EError;
      SetPeltier(OFF, 0);
      SetLidOutput(0);
  }

  //program
  UpdateEta();
 #ifdef USE_LCD
  ipDisplay->Update();
 #endif
  statusIndex = (statusIndex+1) % CyclerStatusBuffSize;
  statusCount++;
  return true;
}
void Thermocycler::Loop()
{
  switch (m_program_state)
  {
    case EStartup:
    if (millis() > STARTUP_DELAY) {
      m_program_state = EStopped;
      
      //if (!m_is_restarted && !m_serial_control->CommandReceived())
      {
        //check for stored program
        //SCommand command;
        //if (ProgramStore::RetrieveProgram(command, (char*)m_serial_control->GetBuffer()))
        //  ProcessCommand(command);
      }
    }
    break;

  case ELidWait:    
    if (GetLidTemp() >= m_target_lid_temp - LID_START_TOLERANCE) {
      //lid has warmed, begin program
      m_thermal_direction = OFF;
      m_peltier_pwm = 0;
      PreprocessProgram();
      m_program_state = ERunning;
      
      m_program->BeginIteration();
      AdvanceToNextStep();
      
      m_program_start_time_ms = millis();
    }
    break;
  
  case ERunning:
    //update program
    if (m_program_state == ERunning) {
      if (m_is_ramping && abs(m_current_step->GetTemp() - GetPlateTemp()) <= CYCLE_START_TOLERANCE && GetRampElapsedTimeMs() > m_current_step->GetRampDurationS() * 1000) {
        //begin step hold
        
        //eta updates
        if (m_current_step->GetRampDurationS() == 0) {
          //fast ramp
          m_elapsed_fast_ramp_degrees += fabs(GetPlateTemp() - m_ramp_start_temp);
          m_total_elapsed_fast_ramp_duration_ms += millis() - m_ramp_start_time;
        }
        
        if (m_ramp_start_temp > GetPlateTemp())
          m_has_cooled = true;
        m_is_ramping = false;
        m_cycle_start_time = millis();
        
      } else if (!m_is_ramping && !m_current_step->IsFinal() && millis() - m_cycle_start_time > (unsigned long)m_current_step->GetStepDurationS() * 1000) {
        //begin next step
        AdvanceToNextStep();
          
        //check for program completion
        if (m_current_step == NULL || m_current_step->IsFinal())
          m_program_state = EComplete;
      }
    }
    break;
    
  case EComplete:
    if (m_is_ramping && m_current_step != NULL && abs(m_current_step->GetTemp() - GetPlateTemp()) <= CYCLE_START_TOLERANCE)
      m_is_ramping = false;
    break;
  case EStopped: //Nothing
  case EError: //Nothing
  case EClear: //Nothing
    break;
  }
  
  //lid 
  m_lid_thermistor.ReadTemp();
  ControlLid();
  
  //plate  
  m_plate_thermistor.ReadTemp();
  CalcPlateTarget();
  ControlPeltier();
  
  //program
  UpdateEta();
  m_display->Update();
  m_serial_control->Process();
}