void Thermocycler::PrepareStep() { //update eta calc params if (ipPreviousStep == NULL || ipPreviousStep->GetTemp() != ipCurrentStep->GetTemp()) { iRamping = true; iRampElapsedTimeMs = 0; iRampStartTemp = GetPlateTemp(); } else { iCycleElapsedTimeMs = 0; //next step starts immediately } // Switch cycle to display ProgramComponent *pComp = ipProgram->GetComponent(ipProgram->GetCurrentComponentIndex()); if (pComp->GetType() == ProgramComponent::ECycle) { ipDisplayCycle = (Cycle*) pComp; } CalcPlateTarget(); SetPlateControlStrategy(); }
//private void Thermocycler::AdvanceToNextStep() { m_previous_step = m_current_step; m_current_step = m_program->GetNextStep(); if (m_current_step == NULL) return; //update eta calc params if (m_previous_step == NULL || m_previous_step->GetTemp() != m_current_step->GetTemp()) { m_is_ramping = true; m_ramp_start_time = millis(); m_ramp_start_temp = GetPlateTemp(); } else { m_cycle_start_time = millis(); //next step starts immediately } CalcPlateTarget(); SetPlateControlStrategy(); }
//private void Thermocycler::AdvanceToNextStep() { ipPreviousStep = ipCurrentStep; ipCurrentStep = ipProgram->GetNextStep(); if (ipCurrentStep == NULL) return; //update eta calc params if (ipPreviousStep == NULL || ipPreviousStep->GetTemp() != ipCurrentStep->GetTemp()) { iRamping = true; iRampStartTime = millis(); iRampStartTemp = GetPlateTemp(); } else { iCycleStartTime = millis(); //next step starts immediately } CalcPlateTarget(); SetPlateControlStrategy(); }
// 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; }
// 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(); }
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(); }