// This function closes the window and exits the program. It checks // if the threads are in the stopped state, and if not it stops them by // the value of check to -1. It then changes the color of the Stop TC // button to red to notify the user, and again checks to see if the // threads are stopped and aborted. If not, it counts to 10 and aborts // the thread using Thread.Abort() before closing. public void StopThreads_AndCloseOvenProgram() { if (close_program_inprogress) return; close_program_inprogress = true; if (oven_start_check != ComponentCheckStatusEnum.None || temperature_start_check != ComponentCheckStatusEnum.None) { DialogResult dialogResult = MessageBox.Show( "WARNING! This will exit the program and shut down all ongoing processes" + " Are you sure you want to exit?", " Exit Application?", MessageBoxButtons.YesNo); if (dialogResult == DialogResult.No) { abort_oven_program = false; close_program_inprogress = false; return; } } if (temperature_start_check == ComponentCheckStatusEnum.Running && read_check != ComponentCheckStatusEnum.None) { this.StopTC_Button.Text = "Stopping"; this.StopTC_Button.BackColor = Color.Firebrick; } if (oven_start_check == ComponentCheckStatusEnum.Running && oven_check != ComponentCheckStatusEnum.None) { this.StopOvenButton.Text = "Stopping"; this.StopOvenButton.BackColor = Color.Firebrick; } this.Refresh(); Thread.Sleep(1000); if ((temperature_read_thread != null && temperature_read_thread.ThreadState != ThreadState.Stopped) || (oven_control_thread != null && oven_control_thread.ThreadState != ThreadState.Stopped) || (log_thread != null && log_thread.ThreadState != ThreadState.Stopped)) { read_check = ComponentCheckStatusEnum.Aborted; oven_check = ComponentCheckStatusEnum.Aborted; log_check = ComponentCheckStatusEnum.Aborted; oven_cooling_check = ComponentCheckStatusEnum.Aborted; } int counter = 0; while ((temperature_read_thread != null && temperature_read_thread.ThreadState != ThreadState.Stopped && temperature_read_thread.ThreadState != ThreadState.Aborted) || (oven_control_thread != null && oven_control_thread.ThreadState != ThreadState.Stopped && oven_control_thread.ThreadState != ThreadState.Aborted) || (log_thread != null && log_thread.ThreadState != ThreadState.Stopped && log_thread.ThreadState != ThreadState.Aborted)) { counter++; if (counter > 10) { if (temperature_read_thread != null) { temperature_read_thread.Abort(); } if (oven_control_thread != null) { oven_control_thread.Abort(); } if (log_thread != null) { log_thread.Abort(); } } oven_cooling_check = ComponentCheckStatusEnum.Aborted; Thread.Sleep(100); } log_thread = null; this.Close(); }
// Helper function for IsError that gives user the option to respond to the error public static ErrorCodeEnum IsError_WithExitOption(object sender, ErrorInfo error) { if (abort_oven_program) return ErrorCodeEnum.Error; while (application_error_window_open) { Thread.Sleep(20); } if (abort_oven_program) return ErrorCodeEnum.Error; try { USB_TC_Control_Form oven_form = (USB_TC_Control_Form)sender; AbortOvenCode abortcode_del = new AbortOvenCode(oven_form.StopThreads_AndCloseOvenProgram); if (error.Value != 0) { System.Windows.Forms.DialogResult user_resp = DialogResult.None; application_error_window_open = true; user_resp = MessageBox.Show(error.Message + Environment.NewLine + "Click 'Cancel' to exit out of the oven program", "Error", MessageBoxButtons.OKCancel); if (user_resp == DialogResult.Cancel) { abort_oven_program = true; // Set check flags for the three threads (Oven PID // Control, Read Temp, Log Temp) to -1 to end the // threads oven_check = ComponentCheckStatusEnum.Aborted; read_check = ComponentCheckStatusEnum.Aborted; log_check = ComponentCheckStatusEnum.Aborted; // Pause 100 milliseconds Thread.Sleep(100); // Invoke the close/abort program delegate oven_form.BeginInvoke(abortcode_del); } application_error_window_open = false; return ErrorCodeEnum.Error; } } catch(Exception e) { MessageBox.Show( String.Format( "Unexpected Error occurred while processing Oven Application Error." + "{0}Error Message: {1}{0}" + "Error Source: {2}{0}" + "Stack Trace: {3}{0}", Environment.NewLine, e.Message, e.Source, e.StackTrace), " Unexpected Error!"); //Call the single argument error handler IsError(error); } return ErrorCodeEnum.NoError; }
public void DoOvenCooling() { bool high_n2_on = false; //Read Switch N2 to Air and Stop Temperatures Directly from the controls //in case the user has changed them float switch_temperature = 10000; float stop_temperature = 10000; switch_temperature = SwitchTemp_copy; stop_temperature = StopTemp_copy; //Lock CurrentTemperatures array for access by the oven thread. IsLockedCurrentTemp_Array = true; //Check to see if the oven temperature is below the Stop Cooling Temperature bool already_below_stop_temp = true; for (int i = 0; i < MAX_CHANCOUNT - NUM_WALLCOUNT; i++) { if (CurrentTemperatures[i] > stop_temperature) { //Don't need to check any more temperatures //Temperature is too high to switch i = MAX_CHANCOUNT; already_below_stop_temp = false; } else { already_below_stop_temp = true; } } //Unlock the CurrentTemperatures Array IsLockedCurrentTemp_Array = false; CoolingStarted = true; //If the oven temperature is already below the stop cooling temperature //Set flags to end cooling //Else, start the Air or High Pressure N2 if (already_below_stop_temp) { oven_cooling_check = ComponentCheckStatusEnum.None; } else { //start cooling if (CoolMethod_copy == "1") { SetAirRelayChannelOutput(AirChanStatusEnum.HighN2); high_n2_on = true; } else { SetAirRelayChannelOutput(AirChanStatusEnum.Air); high_n2_on = false; } } while (oven_cooling_check == ComponentCheckStatusEnum.Running && oven_check != ComponentCheckStatusEnum.Aborted) { //Read Switch N2 to Air and Stop Temperatures Directly from the controls //in case the user has changed them switch_temperature = SwitchTemp_copy; stop_temperature = StopTemp_copy; IsLockedCurrentTemp_Array = true; if (CoolMethod_copy == "1" && high_n2_on) { bool do_switch = true; for (int i = 0; i < MAX_CHANCOUNT - NUM_WALLCOUNT; i++) { if (CurrentTemperatures[i] > switch_temperature) { //Don't need to check any more temperatures //Temperature is too high to switch i = MAX_CHANCOUNT; do_switch = false; } else { do_switch = true; } } if (do_switch) { SetAirRelayChannelOutput(AirChanStatusEnum.Air); high_n2_on = false; } } else { bool is_cooling_done = true; for (int i = 0; i < MAX_CHANCOUNT - NUM_WALLCOUNT; i++) { if (CurrentTemperatures[i] > stop_temperature) { //Don't need to check any more temperatures //Temperature is too high to switch i = MAX_CHANCOUNT; is_cooling_done = false; } else { is_cooling_done = true; } } if (is_cooling_done) { //Set oven cooling check status to none to end the cooling loop oven_cooling_check = ComponentCheckStatusEnum.None; } } IsLockedCurrentTemp_Array = false; //Sleep for five seconds System.Threading.Thread.Sleep(5000); } SetAirRelayChannelOutput(AirChanStatusEnum.AirOff); OvenRunDone = true; CoolingStarted = false; CoolingStarted_logged = false; HeatingStopped = false; HeatingStopped_logged = false; //Stop reading the temperature read_check = ComponentCheckStatusEnum.None; }
// This function is called when the Start Oven button in the GUI is // clicked. It sets the value of the global variable check to 3, and // changes the Start Oven button color to Green. private void StopOvenButton_Click(object sender, EventArgs e) { UserNameTextBox.ReadOnly = false; UserNameTextBox.BorderStyle = BorderStyle.Fixed3D; OvenNameTextBox.ReadOnly = false; OvenNameTextBox.BorderStyle = BorderStyle.Fixed3D; UserEmailTextBox.ReadOnly = false; UserEmailTextBox.BorderStyle = BorderStyle.Fixed3D; UserPhoneTextBox.ReadOnly = false; UserPhoneTextBox.BorderStyle = BorderStyle.Fixed3D; UserPhoneTextBox.BackColor = Color.White; BatchIDCodeTextBox.ReadOnly = false; BatchIDCodeTextBox.BorderStyle = BorderStyle.Fixed3D; MaxTemperatureNumericUpDown.ReadOnly = false; MaxTemperatureNumericUpDown.BorderStyle = BorderStyle.Fixed3D; HoldTimeAtPeakNumericUpDown.ReadOnly = false; HoldTimeAtPeakNumericUpDown.BorderStyle = BorderStyle.Fixed3D; CoolMethodComboBox.Enabled = true; if (oven_check != ComponentCheckStatusEnum.None) { DialogResult dialogResult = MessageBox.Show( "WARNING! This will stop the oven run process and shut down all coils!" + " Are you sure you want to stop the oven run?", " " + "STOP OVEN WARNING", MessageBoxButtons.YesNo); if (dialogResult == DialogResult.Yes) { oven_check = ComponentCheckStatusEnum.None; StartOvenButton.BackColor = default(Color); if (oven_start_check != ComponentCheckStatusEnum.Running) StopOvenButton.BackColor = Color.GreenYellow; HeatingStopped = true; HeatingStarted = false; HeatingStarted_logged = false; } else return; } return; }
// This function is called when the Stop TC button in the GUI is // clicked. It sets the value of the global variable read_check to 0, // changes the Stop TC button color to Green, and resets the color of // the Read TC button to default, so that the user knows which button // was last clicked. private void StopTCbutton_Click(object sender, EventArgs e) { if (oven_check == ComponentCheckStatusEnum.None) { UserEmailTextBox.Enabled = true; UserPhoneTextBox.Enabled = true; MaxTemperatureNumericUpDown.Enabled = true; HoldTimeAtPeakNumericUpDown.Enabled = true; CoolMethodComboBox.Enabled = true; SwitchToAirTemperatureNumericUpDown.Enabled = true; } read_check = ComponentCheckStatusEnum.None; ReadTC_Button.BackColor = default(Color); for (int i = 0; i < MAX_CHANCOUNT; i++) { this.Controls["Channel" + i.ToString("#0") + "TextBox"].ForeColor = Color.Gray; } if (temperature_start_check != ComponentCheckStatusEnum.None) StopTC_Button.BackColor = Color.GreenYellow; }
private void StartCoolingButton_Click(object sender, EventArgs e) { //End Oven Heating oven_check = ComponentCheckStatusEnum.None; CoolingStarted = true; }
// This function is called when the Start Oven button in the GUI is // clicked. It sets the value of the global variable check to 3, and // changes the Start Oven button color to Green. private void StartOvenButton_Click(object sender, EventArgs e) { UserEmailTextBox.Enabled = true; UserPhoneTextBox.Enabled = true; MaxTemperatureNumericUpDown.Enabled = true; HoldTimeAtPeakNumericUpDown.Enabled = true; CoolMethodComboBox.Enabled = true; SwitchToAirTemperatureNumericUpDown.Enabled = true; if (CheckParameters(ParameterTypeEnum.Oven) != ErrorCodeEnum.NoError) { if (String.IsNullOrWhiteSpace(directory)) SaveLogFileDirectoryTextBox.BackColor = Color.MistyRose; else SaveLogFileDirectoryTextBox.BackColor = Color.White; MessageBox.Show( "Check and complete highlighted oven run" + " parameters!", " ERROR!"); return; } if (String.IsNullOrWhiteSpace(directory)) { SaveLogFileDirectoryTextBox.BackColor = Color.MistyRose; MessageBox.Show( "Please choose a directory to save log " + "file in!", " " + "ERROR!"); return; } else SaveLogFileDirectoryTextBox.BackColor = Color.White; if (IsParametersChanged() || (temperature_start_check == ComponentCheckStatusEnum.Set && oven_start_check == ComponentCheckStatusEnum.None)) { UpdateDirectory(); MessageBox.Show("Please double check all values, just to be " + "sure. Click the Start Oven button when ready.", " Check Values"); CopyParameters(); oven_start_check = ComponentCheckStatusEnum.Set; return; } UserNameTextBox.ReadOnly = true; UserNameTextBox.BorderStyle = BorderStyle.FixedSingle; UserEmailTextBox.ReadOnly = true; UserEmailTextBox.BorderStyle = BorderStyle.FixedSingle; UserPhoneTextBox.ReadOnly = true; UserPhoneTextBox.BorderStyle = BorderStyle.FixedSingle; UserPhoneTextBox.BackColor = Color.White; BatchIDCodeTextBox.ReadOnly = true; BatchIDCodeTextBox.BorderStyle = BorderStyle.FixedSingle; //MaxTemperatureNumericUpDown.ReadOnly = true; //MaxTemperatureNumericUpDown.BorderStyle = BorderStyle.FixedSingle; //HoldTimeAtPeakNumericUpDown.ReadOnly = true; //HoldTimeAtPeakNumericUpDown.BorderStyle = BorderStyle.FixedSingle; OvenNameTextBox.ReadOnly = true; OvenNameTextBox.BorderStyle = BorderStyle.FixedSingle; CoolMethodComboBox.Enabled = false; //SwitchToAirTemperatureNumericUpDown.ReadOnly = true; //SwitchToAirTemperatureNumericUpDown.BorderStyle = BorderStyle.FixedSingle; if (IsParametersChanged()) UpdateDirectory(); if (oven_check != ComponentCheckStatusEnum.Running) { Start_Oven_Time = DateTime.Now; OvenStartTimeTextBox.Text = Start_Oven_Time.ToString("T"); graph_check++; } CopyParameters(); int count = 0; for (int i = 0; i < MAX_CHANCOUNT; i++) { if (((CheckBox)this.Controls["Channel" + i.ToString("#0") + "CheckBox"]).Enabled == true && ((CheckBox)this.Controls["Channel" + i.ToString("#0") + "CheckBox"]).Checked == true) { count++; } } if (count == 0) { not_showing_temp = true; } if (not_showing_temp == true) { ResetThemocoupleInputStatusCheckboxes(); not_showing_temp = false; } // Start thread once the Start Oven button is clicked for the // first time. if (oven_start_check == ComponentCheckStatusEnum.Set) { oven_control_thread = new Thread(new ThreadStart(PID_control)); oven_control_thread.Start(); oven_start_check = ComponentCheckStatusEnum.Running; CopyParameters(); if (temperature_start_check != ComponentCheckStatusEnum.Running) { temperature_read_thread = new Thread(new ThreadStart(ReadTemperature)); temperature_read_thread.Start(); temperature_start_check = ComponentCheckStatusEnum.Running; if (log_check != ComponentCheckStatusEnum.Running) { log_thread = new Thread(new ThreadStart(UpdateLog)); log_check = ComponentCheckStatusEnum.Running; log_state = LogStatusEnum.NotLogged; log_thread.Start(); } read_check = ComponentCheckStatusEnum.Running; ReadTC_Button.BackColor = Color.GreenYellow; StopTC_Button.BackColor = default(Color); } } oven_check = ComponentCheckStatusEnum.Running; StopOvenButton.BackColor = default(Color); StartOvenButton.BackColor = Color.GreenYellow; }
// This function is called when the Read TC button in the GUI is // clicked. It sets the value of the global variable read_check to 1, // changes the Read TC button color to Green, and resets the color of // the Stop TC button to default, so that the user knows which button // was last clicked. private void ReadThermoCouplesbutton_Click(object sender, EventArgs e) { if (!String.IsNullOrWhiteSpace(WarningTextBox.Text)) { if (not_showing_temp == true) ResetThemocoupleInputStatusCheckboxes(); UpdateWarningDisplay("", ErrorCodeEnum.NoError); } if (temperature_start_check == ComponentCheckStatusEnum.None && oven_start_check == ComponentCheckStatusEnum.None) ResetInputControls(); if (CheckParameters(ParameterTypeEnum.ThermoCouples) != ErrorCodeEnum.NoError) { MessageBox.Show( "Check and complete highlighted thermocouple" + " read parameters!", " ERROR!"); return; } UpdateDirectory(); if (String.IsNullOrWhiteSpace(directory)) { SaveLogFileDirectoryTextBox.BackColor = Color.MistyRose; MessageBox.Show( String.Format( "Please choose a directory to save log file in!{0}" + "Also add other (optional) parameters, like the batch " + "code and email address...", Environment.NewLine), " " + "ERROR!"); return; } else { SaveLogFileDirectoryTextBox.BackColor = Color.White; } if (IsParametersChanged()) { UpdateDirectory(); MessageBox.Show( "Please double check all values, just to be " + "sure. Click the Read TC button when ready.", " Check Values"); CopyParameters(); return; } UserNameTextBox.ReadOnly = true; UserNameTextBox.BorderStyle = BorderStyle.FixedSingle; BatchIDCodeTextBox.ReadOnly = true; BatchIDCodeTextBox.BorderStyle = BorderStyle.FixedSingle; OvenNameTextBox.ReadOnly = true; OvenNameTextBox.BorderStyle = BorderStyle.FixedSingle; UserEmailTextBox.Enabled = false; UserPhoneTextBox.Enabled = false; SwitchToAirTemperatureNumericUpDown.Enabled = false; MaxTemperatureNumericUpDown.Enabled = false; HoldTimeAtPeakNumericUpDown.Enabled = false; CoolMethodComboBox.Enabled = false; UserPhoneTextBox.BackColor = Color.White; // Create and start the threads when the Read TC button is clicked // for the first time. Log thread and the temperature read thread // are the two threads started here if (temperature_start_check == ComponentCheckStatusEnum.None) { CopyParameters(); Start_Temp_Time = DateTime.Now; Start_Log_File_Time = Start_Temp_Time; temperature_read_thread = new Thread(new ThreadStart(ReadTemperature)); temperature_read_thread.Start(); temperature_start_check = ComponentCheckStatusEnum.Running; if (log_check != ComponentCheckStatusEnum.Running) { log_thread = new Thread(new ThreadStart(UpdateLog)); log_check = ComponentCheckStatusEnum.Running; log_state = LogStatusEnum.NotLogged; log_thread.Start(); } } if (IsParametersChanged()) UpdateDirectory(); if (read_check != ComponentCheckStatusEnum.Running) Start_Temp_Time = DateTime.Now; read_check = ComponentCheckStatusEnum.Running; warning_time = 20; ReadTC_Button.BackColor = Color.GreenYellow; StopTC_Button.BackColor = default(Color); }
// This function reads and displays the temperature inputs by detecting // the buttons clicked, by detecting the value of the variable "check". // It runs a while loop to keep checking for button presses, and using // Thread.Sleep(), it checks buttons, reads and displays temperatures in // the selected scale at a set frequency (2 Hz). The loop ends when the // value of check is set to -1 by clicking the Exit button. Temperatures // are read using the TInScan function, and an array is passed to the // update_temp() function to display them using a delegate. private void ReadTemperature() { while (read_check != ComponentCheckStatusEnum.Aborted) { int count = 0; float[] TempData = new float[MAX_CHANCOUNT]; float[] TempData_C = new float[MAX_CHANCOUNT]; MccDaq.ErrorInfo RetVal; Update_Temperature update_temp_del = new Update_Temperature(UpdateTemperatureDisplays); Update_Warning update_warning_del = new Update_Warning(UpdateWarningDisplay); Reset_Checkboxes resetcheckboxes_del = new Reset_Checkboxes(ResetThemocoupleInputStatusCheckboxes); for (int i = 0; i < MAX_CHANCOUNT; i++) { if (((CheckBox)this.Controls["Channel" + i.ToString("#0") + "CheckBox"]).Enabled == true && ((CheckBox)this.Controls["Channel" + i.ToString("#0") + "CheckBox"]).Checked == true) { count++; } } if (count == 0) { TempData = new float[MAX_CHANCOUNT] {-9999, -9999, -9999, -9999, -9999, -9999, -9999, -9999}; //Array.Copy(TempData, TempData_C, 8); not_showing_temp = true; //BeginInvoke(update_temp_del, TempData, TempData_C); } else not_showing_temp = false; if (read_check == ComponentCheckStatusEnum.Running && not_showing_temp == false) { for (int i = 0; i < MAX_CHANCOUNT; i++) { if (((CheckBox)this.Controls["Channel" + i.ToString("#0") + "CheckBox"]).Checked == true) // null object reference error, suggests using "new" keyword { RetVal = thermocouple_board.TIn(i, TempScale.Celsius, out TempData_C[i], ThermocoupleOptions.Filter); IsError(this, RetVal, true); } else TempData_C[i] = -9999; while (IsLockedCurrentTemp_Array) { //Nothing - pause till lock lifted } CurrentTemperatures[i] = TempData_C[i]; if (PlateauTemperatureWindow == null) PlateauTemperatureWindow = new List<float[]>(); AddToMaxTemperaturePlateau(ref TempData_C); MaxTempPlateauReached = IsAtSetTemperaturePlateau(); } switch (my_TempScale) { case TempScale.Fahrenheit: for (int i = 0; i < MAX_CHANCOUNT; i++) { if (((CheckBox)this.Controls["Channel" + i.ToString("#0") + "CheckBox"]).Checked == true) { RetVal = thermocouple_board.TIn(i, TempScale.Fahrenheit, out TempData[i], ThermocoupleOptions.Filter); IsError(this, RetVal, true); } else TempData[i] = -9999; } break; case TempScale.Kelvin: for (int i = 0; i < MAX_CHANCOUNT; i++) { if (((CheckBox)this.Controls["Channel" + i.ToString("#0") + "CheckBox"]).Checked == true) { RetVal = thermocouple_board.TIn(i, TempScale.Kelvin, out TempData[i], ThermocoupleOptions.Filter); IsError(this, RetVal, true); } else TempData[i] = -9999; } break; default: for (int i = 0; i < MAX_CHANCOUNT; i++) { if (((CheckBox)this.Controls["Channel" + i.ToString("#0") + "CheckBox"]).Checked == true) { RetVal = thermocouple_board.TIn(i, TempScale.Celsius, out TempData[i], ThermocoupleOptions.Filter); IsError(this, RetVal, true); } else TempData[i] = -9999; } break; } BeginInvoke(update_temp_del, TempData, TempData_C); System.Threading.Thread.Sleep(500); } if ((read_check == ComponentCheckStatusEnum.None && oven_check == ComponentCheckStatusEnum.Running) || (not_showing_temp == true && oven_check == ComponentCheckStatusEnum.Running)) { string temp = String.Format( "WARNING! Temperature readings are no longer live during an oven run!{0}" + "Automatically fixing this in {1} seconds...", Environment.NewLine, ((int)(warning_time / 2)).ToString("0")); BeginInvoke(update_warning_del, temp, 1); Thread.Sleep(500); warning_time--; if (warning_time <= 0) { read_check = ComponentCheckStatusEnum.Running; BeginInvoke(resetcheckboxes_del); not_showing_temp = false; BeginInvoke(update_warning_del, " ", 0); warning_time = 20; } } // Make sure that the text is grayed out when the Stop TC button // is in its clicked state. if (read_check == ComponentCheckStatusEnum.None && oven_check != ComponentCheckStatusEnum.Running) { TempData[0] = 1234; TempData_C[0] = 1234; BeginInvoke(update_temp_del, TempData, TempData_C); Thread.Sleep(500); } } }
// Necessary constructor for the program to load properly. public USB_TC_Control_Form() { Program.splash_screen_form.BeginInvoke( (Action)(() => Program.splash_screen_form.WaitForHideSplashScreen())); InitializeComponent(); StartCoolingButton.Enabled = false; System.Windows.Forms.DialogResult user_resp = System.Windows.Forms.DialogResult.None; do { // Locate the USB-TC and give it a number. // BNum is a TextBox BoardNum = GetBoardNum(DEVICE, UsbThermoCoupleDaqBoardNumberTextBox); if (BoardNum == -1) { user_resp = MessageBox.Show(String.Format("No USB-{0} Thermocouple Input DAQ Device detected! " + "Click 'Cancel' to exit out of the oven program.", DEVICE), "Comm Error", MessageBoxButtons.RetryCancel); // Throw an error message if no USB-TC device is found. It is // recommended to first locate and caliberate the board in // InstaCal before use. // Give user the option to exit from the code in the modal error message window. if (user_resp == System.Windows.Forms.DialogResult.Cancel) { StopThreads_AndCloseOvenProgram(); return; } } else { // Set default value for the button press detection variables. read_check = ComponentCheckStatusEnum.None; oven_check = ComponentCheckStatusEnum.None; log_check = ComponentCheckStatusEnum.None; //Instantiate boards for ThermoCouples and Oven SetupThermoCoupleDAQBoard(); SetupOvenDAQBoard(); } } while (user_resp == System.Windows.Forms.DialogResult.Retry); // Detect number of connected thermocouples DetectThermoCoupleInputs(); Outer_HeatingElementStatusButton.BackColor = ElementOffColor; Inner_HeatingElementStatusButton.BackColor = ElementOffColor; SampleZone_HeatingElementStatusButton.BackColor = ElementOffColor; // Default batch code BatchIDCodeTextBox.Text = "_"; // Default user UserNameTextBox.Text = "User"; // Default email UserEmailTextBox.Text = "*****@*****.**"; // Default phone UserPhoneTextBox.Text = "111-222-3333"; // Default max. temp MaxTemperatureNumericUpDown.Value = 50; // Default hold time HoldTimeAtPeakNumericUpDown.Value = 30; // Default Stop Cooling Temperature StopCoolingTemperatureNumericUpDown.Value = 25; // Default cooling method is Nitrogen CoolMethodComboBox.SelectedIndex = 1; // Setup graph TempertureVsTimeGraph.ChartAreas[0].BackColor = Color.Black; TempertureVsTimeGraph.ChartAreas[0].AxisX.MajorGrid.LineColor = Color.DarkSlateGray; TempertureVsTimeGraph.ChartAreas[0].AxisY.MajorGrid.LineColor = Color.DarkSlateGray; TempertureVsTimeGraph.ChartAreas[0].AxisX.Minimum = 0; TempertureVsTimeGraph.ChartAreas[0].AxisY.Minimum = 0; TempertureVsTimeGraph.Series[ Enum.GetName(typeof(TemperatureVsTimeDataSeriesEnum), TemperatureVsTimeDataSeriesEnum.TrayOuter_Edge)].Points.AddXY(0, 0); TempertureVsTimeGraph.Series[ Enum.GetName(typeof(TemperatureVsTimeDataSeriesEnum), TemperatureVsTimeDataSeriesEnum.TraySampleZone_Edge)].Points.AddXY(0, 0); TempertureVsTimeGraph.Series[ Enum.GetName(typeof(TemperatureVsTimeDataSeriesEnum), TemperatureVsTimeDataSeriesEnum.TrayInner_Edge)].Points.AddXY(0, 0); TempertureVsTimeGraph.Series[ Enum.GetName(typeof(TemperatureVsTimeDataSeriesEnum), TemperatureVsTimeDataSeriesEnum.TrayOuter_Center)].Points.AddXY(0, 0); TempertureVsTimeGraph.Series[ Enum.GetName(typeof(TemperatureVsTimeDataSeriesEnum), TemperatureVsTimeDataSeriesEnum.TraySampleZone_Center)].Points.AddXY(0, 0); TempertureVsTimeGraph.Series[ Enum.GetName(typeof(TemperatureVsTimeDataSeriesEnum), TemperatureVsTimeDataSeriesEnum.TrayInner_Center)].Points.AddXY(0, 0); TempertureVsTimeGraph.Series[ Enum.GetName(typeof(TemperatureVsTimeDataSeriesEnum), TemperatureVsTimeDataSeriesEnum.Inner)].Points.AddXY(0, 0); TempertureVsTimeGraph.Series[ Enum.GetName(typeof(TemperatureVsTimeDataSeriesEnum), TemperatureVsTimeDataSeriesEnum.Outer)].Points.AddXY(0, 0); }
// This function implements PID control in the oven, by using three // USB-TC output channels. It calls the functions channel_out() to // control the heater coils according to the known setup. private void PID_control() { int count = 0; oven_pid_settings = Program.pid_settings_form.ProgramPidSettings; set_point_temperature = MaxTemp_copy; double[] CurrentTemp_EachZone = new double[3] { 0, 0, 0 }; double[] PreviousTemp_EachZone = new double[3] { 0, 0, 0 }; int heat_increment_time_in_milliseconds = (int)((oven_pid_settings.cycle_time_in_seconds / 110) * 1000); //Heat per each zone int[] heat_EachZone = new int[3] { 0, 0, 0 }; //rate correction per each zone double[] rate_correction_EachZone = new double[3] { 0, 0, 0 }; bool fill_n2_check = false; bool n2_running_check = false; bool outer_coil_on = false; bool inner_coil_on = false; bool sample_zone_coil_on = false; SetOvenChannelOutput(OvenChanEnum.AllOff); // start with all oven channels off SetAirRelayChannelOutput(AirChanStatusEnum.AirOff); //Start with air switched off if (CoolMethod_copy == "1" && n2_running_check == false) { // Flow high pressure nitrogen for 10 seconds to fill // the oven cavity with nitrogen if (fill_n2_check == false) { count = 0; SetAirRelayChannelOutput(AirChanStatusEnum.HighN2); while (count <= 10) { Thread.Sleep(1000); count++; } fill_n2_check = true; SetAirRelayChannelOutput(AirChanStatusEnum.AirOff); } // Low pressure N2 trickle begins SetAirRelayChannelOutput(AirChanStatusEnum.LowN2); n2_running_check = true; bool low_n2_adjusted = false; while (!low_n2_adjusted) { MessageBox.Show( "Please change the Low N2 Gauge Level (by twisting the Gauge now) until " + "the black indicator bead is beween the two black arrows. ", "Set Gauge Level", MessageBoxButtons.OK); DialogResult result = MessageBox.Show( "Is the Low N2 Gauge set to the correct level?", "Verify Gauge Level", MessageBoxButtons.YesNo); if (result == System.Windows.Forms.DialogResult.Yes) { low_n2_adjusted = true; } } } EnableStartOvenButton start_oven_button_del = new EnableStartOvenButton(EnableStartCoolingButton); StartCoolingButton.BeginInvoke(start_oven_button_del); HeatingStarted = true; while (oven_check == ComponentCheckStatusEnum.Running) { Heat_Time = DateTime.Now; DateTime start_heat_increment; DateTime end_heat_increment; for (int i = 1; i <= 100; i++) { start_heat_increment = DateTime.Now; if (heat_EachZone[0] > 0) { if (!outer_coil_on) { SetOvenChannelOutput(OvenChanEnum.Outer, OvenHeatOnOffEnum.On); outer_coil_on = true; } } else { SetOvenChannelOutput(OvenChanEnum.Outer, OvenHeatOnOffEnum.Off); outer_coil_on = false; } if (heat_EachZone[1] > 0) { if (!sample_zone_coil_on) { SetOvenChannelOutput(OvenChanEnum.SampleZone, OvenHeatOnOffEnum.On); sample_zone_coil_on = true; } } else { SetOvenChannelOutput(OvenChanEnum.SampleZone, OvenHeatOnOffEnum.Off); sample_zone_coil_on = false; } if (heat_EachZone[2] > 0) { if (!inner_coil_on) { SetOvenChannelOutput(OvenChanEnum.Inner, OvenHeatOnOffEnum.On); inner_coil_on = true; } } else { SetOvenChannelOutput(OvenChanEnum.Inner, OvenHeatOnOffEnum.Off); inner_coil_on = false; } for (int j = 0; j < 3; j++) { heat_EachZone[j]--; } end_heat_increment = DateTime.Now; TimeSpan heat_increment_duration = (end_heat_increment - start_heat_increment); if (heat_increment_duration.TotalMilliseconds < heat_increment_time_in_milliseconds) { System.Threading.Thread.Sleep((int)(heat_increment_time_in_milliseconds - heat_increment_duration.TotalMilliseconds)); } //If Set Temp Reached and Start Set Temp Hold Time not set //Set Start Set Temp Hold Time if (MaxTempPlateauReached && !MaxTemp_StartTime_Set) { MaxTemp_StartTime = DateTime.Now; MaxTemp_StartTime_Set = true; } //If Set Temp Reached, then wait Hold Time till start cool down //Use MaxTemp_StartTime to determine the curent duration of the Hold Peak Time if (MaxTempPlateauReached) { TimeSpan peak_duration = DateTime.Now - MaxTemp_StartTime; double hold_time_minutes = HoldTime_copy.TotalMinutes; HoldTimeRemaining_copy = (hold_time_minutes - peak_duration.TotalMinutes).ToString("#0.0#"); HoldTimeRemainingTextBox.BeginInvoke((Action)(() => HoldTimeRemainingTextBox.Text = HoldTimeRemaining_copy)); if (peak_duration.TotalMinutes > hold_time_minutes) { oven_check = ComponentCheckStatusEnum.None; } } } //turn off oven heat outside of heating cycle SetOvenChannelOutput(OvenChanEnum.OvenOff); inner_coil_on = false; outer_coil_on = false; sample_zone_coil_on = false; /////////////////////////////////////////////////////////////// //Set interlock for PID cycle reading temperature IsLockedCurrentTemp_Array = true; //Select Max Temperature on the Outer Zone of the Sample tray CurrentTemp_EachZone[0] = Math.Max(CurrentTemperatures[0], CurrentTemperatures[5]); //Select Max Temperature at Sample Tray in Sample Zone CurrentTemp_EachZone[1] = Math.Max(CurrentTemperatures[1], CurrentTemperatures[4]); //Select Max Temperature at Sample Tray in Inner Zone CurrentTemp_EachZone[2] = Math.Max(CurrentTemperatures[2], CurrentTemperatures[3]); IsLockedCurrentTemp_Array = false; for (int i = 0; i < 3; i++) { //Make sure a Previous Temp of Zero is never used //this will throw off the rate correction parameter if (PreviousTemp_EachZone[i] == 0) PreviousTemp_EachZone[i] = CurrentTemp_EachZone[i]; //Calculate the rate correction - D in PID rate_correction_EachZone[i] = (PreviousTemp_EachZone[i] - CurrentTemp_EachZone[i]) * 100 * oven_pid_settings.rate_EachZone[i]; //Calculate the heat duty cycle % parameter from P, I, & D heat_EachZone[i] = (int)((100 / oven_pid_settings.proportional_band_EachZone[i]) * (set_point_temperature - CurrentTemp_EachZone[i]) + oven_pid_settings.offset_EachZone[i] + rate_correction_EachZone[i]); //Anti-windup - prevent I from incrementing unless we're heating //and at set-point if (heat_EachZone[i] < 100 && heat_EachZone[i] > 0 && rate_correction_EachZone[i] == 0) oven_pid_settings.offset_EachZone[i] += (set_point_temperature - CurrentTemp_EachZone[i]) * oven_pid_settings.reset_EachZone[i]; //Store current temp to previous temp for next cycle's calculation of the //Rate Correction (D) component. PreviousTemp_EachZone[i] = CurrentTemp_EachZone[i]; } } oven_start_check = ComponentCheckStatusEnum.None; //turn off oven heat outside of heating cycle SetOvenChannelOutput(OvenChanEnum.OvenOff); inner_coil_on = false; outer_coil_on = false; sample_zone_coil_on = false; HeatingStopped = true; MaxTempPlateauReached = false; MaxTemp_StartTime_Set = false; HeatingStarted = false; HeatingStarted_logged = false; MaxTempReached_logged = false; //If not thread aborting, start cooling if (oven_control_thread.ThreadState == ThreadState.AbortRequested || oven_control_thread.ThreadState == ThreadState.Aborted) return; if (oven_check == ComponentCheckStatusEnum.Aborted) return; oven_cooling_check = ComponentCheckStatusEnum.Running; DoOvenCooling(); }
// This function updates the temperature log text file. It returns if // the number of channels is invalid. Otherwise, it uses a while loop to // output temperature readings to a .txt file in the same directory as // the program folder. It shows an error if there is an open channel. public void UpdateLog() { string subject = ""; string body = ""; string separator = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; while (log_check == ComponentCheckStatusEnum.Running && log_thread.ThreadState != ThreadState.AbortRequested) { if (log_state == LogStatusEnum.NotLogged) { log_state = LogStatusEnum.Logged; string[] text1 = {"Temperature and events log file.", " ", "Created on " + Start_Log_File_Time.ToString(format), " ", "Temperature read approx. every 5 " + "seconds in degrees Celsius.", " ", " "}; System.IO.File.WriteAllLines(directory, text1); string text2 = "Time\t"; for (int i = 0; i < MAX_CHANCOUNT; i++) { text2 += String.Format("Channel{0}", i) + "\t"; } using (StreamWriter sw = File.AppendText(directory)) { sw.WriteLine(text2); sw.WriteLine(" "); } } if (HeatingStarted && !HeatingStarted_logged) { string temp = DateTime.Now.ToString("T") + "\t\t" + "HEATING STARTED!"; using (StreamWriter sw = File.AppendText(directory)) { sw.WriteLine(" "); sw.WriteLine(separator); sw.WriteLine(" "); sw.WriteLine(temp); sw.WriteLine("\t\t\tUser: "******"\t\t\tBatch code: " + BatchCode_copy); sw.WriteLine("\t\t\tMax. Temperature: " + MaxTemp_copy); sw.WriteLine("\t\t\tHold Time: " + HoldTime_copy); sw.WriteLine("\t\t\tCooling method: " + CoolMethod_copy); sw.WriteLine(" "); sw.WriteLine(separator); sw.WriteLine(" "); } subject = "Heating has started on " + OvenName_copy + " oven!"; body = User_copy + ",\n\n" + subject + "\n\nParameters are: \nBatch Code: " + BatchCode_copy + "\nMax.Temp: " + MaxTemp_copy + "\nHold Time: " + HoldTime_copy + "\nCooling Method: " + CoolMethod_copy + "\nTime: " + OvenStartTime_copy + "\n"; SendEmail(subject, body); HeatingStarted_logged = true; } else if (HeatingStopped && !HeatingStopped_logged) { string temp = DateTime.Now.ToString("T") + "\t\t" + "HEATING STOPPED!"; using (StreamWriter sw = File.AppendText(directory)) { sw.WriteLine(" "); sw.WriteLine(separator); sw.WriteLine(" "); sw.WriteLine(temp); sw.WriteLine(" "); sw.WriteLine(separator); sw.WriteLine(" "); } subject = "Heating has stopped on " + OvenName_copy + " oven!"; body = User_copy + ",\n\n" + subject; SendEmail(subject, body); HeatingStopped_logged = true; } else if (MaxTempPlateauReached && !MaxTempReached_logged) { string temp = DateTime.Now.ToString("T") + "\t\t" + "MAX. TEMP REACHED!"; using (StreamWriter sw = File.AppendText(directory)) { sw.WriteLine(" "); sw.WriteLine(separator); sw.WriteLine(" "); sw.WriteLine(temp); sw.WriteLine(" "); sw.WriteLine(separator); sw.WriteLine(" "); } subject = "Max. temp reached on " + OvenName_copy + " oven!"; body = User_copy + ",\n\n" + subject; SendEmail(subject, body); MaxTempReached_logged = true; } else if (CoolingStarted && !CoolingStarted_logged) { string temp = DateTime.Now.ToString("T") + "\t\t" + "COOLING STARTED!"; using (StreamWriter sw = File.AppendText(directory)) { sw.WriteLine(" "); sw.WriteLine(separator); sw.WriteLine(" "); sw.WriteLine(temp); sw.WriteLine(" "); sw.WriteLine(separator); sw.WriteLine(" "); } subject = "Cooling has started on " + OvenName_copy + " oven!"; body = User_copy + ",\n\n" + subject; SendEmail(subject, body); CoolingStarted_logged = true; } else if (IsCriticalApplicationError && !IsCriticalApplicationError_logged) { string temp = DateTime.Now.ToString("T") + "\t\t" + "CRITICAL ERROR!"; using (StreamWriter sw = File.AppendText(directory)) { sw.WriteLine(" "); sw.WriteLine(separator); sw.WriteLine(" "); sw.WriteLine(temp); sw.WriteLine(" "); sw.WriteLine(separator); sw.WriteLine(" "); } subject = "Critical error on " + OvenName_copy + " oven!"; body = User_copy + ",\n\n" + subject + "\n" + CriticalErrorMessage; SendEmail(subject, body); IsCriticalApplicationError_logged = true; } else if (OvenRunDone && !OvenRunDone_logged) { string temp = DateTime.Now.ToString("T") + "\t\t" + "OVEN RUN COMPLETE!"; using (StreamWriter sw = File.AppendText(directory)) { sw.WriteLine(" "); sw.WriteLine(separator); sw.WriteLine(" "); sw.WriteLine(temp); sw.WriteLine("\t\t\tUser: "******"\t\t\tBatch code: " + BatchCode_copy); sw.WriteLine("\t\t\tMax. Temperature: " + MaxTemp_copy); sw.WriteLine("\t\t\tHold Time: " + HoldTime_copy); sw.WriteLine("\t\t\tCooling method: " + CoolMethod_copy); sw.WriteLine(" "); sw.WriteLine(separator); sw.WriteLine(" "); } subject = "Oven run completed on " + OvenName_copy + " oven!"; body = User_copy + ",\n\n" + subject + "\n"; SendEmail(subject, body); //Stop Logging -- Oven run is done log_check = ComponentCheckStatusEnum.None; } string text3 = DateTime.Now.ToString("T") + "\t"; for (int i = 0; i < MAX_CHANCOUNT; i++) { text3 += CurrentTemperatures[i].ToString() + "\t"; } using (StreamWriter sw = File.AppendText(directory)) { sw.WriteLine(text3); } Thread.Sleep(4800); } OvenRunDone = false; OvenRunDone_logged = false; }