Form1.Cs

290 views

Published on

Control and monitoring program for automated HLM

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
290
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Form1.Cs

  1. 1. // Basic autopilot for heart-lung machine, monitor reservoir level and controlroller pump// used with a softshell reservoir and Omega load cell and meter, Stockert CAPSroller pump// and Omega digital-to-analog converter// Kenneth Wilkerson 2008 Midwestern Universityusing System;using System.Globalization;using System.IO;using System.Collections;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Runtime.InteropServices;using SpeechLib;using System.Media;namespace hlmautopilot{ public partial class Form1 : Form { public Form1() { InitializeComponent(); serialPort1.Open(); //setup request to load cell meter weightreq[0] = *; weightreq[1] = X; weightreq[2] = 0; weightreq[3] = 1; weightreq[4] = r; weightreq[5] = 0; //setup initial values minreslevel = (double)minreslvlctl.Value; lowreslevel = (double)lowreslvlctl.Value; maxflowrate = (double)flowctl.Value; maxrpm = (int)((maxflowrate * 1000) / strokevolume); pumpon = false; curreslevel = 0; waterbtn.Checked = true; density = waterdensity; recordon = false; nfi = new CultureInfo("en-US", false).NumberFormat; nfi.NumberDecimalDigits = 1; greenuparrow = new Bitmap(@"greenuparrow.bmp", false); reddownarrow = new Bitmap(@"reddownarrow.bmp", false); lvlchangerate.Minimum = 0; lvlchangerate.Maximum = (int)(maxflowrate * 1000); lvlchangerate.Value = 0; minpercentflow = (int)pctflowctl.Value; //Create voice object voice = new SpVoice(); } //Start monitoring reservoir event private void monstart_click(object sender, EventArgs e) { monstopbtn.Enabled = true;
  2. 2. monstartbtn.Enabled = false; timer1.Enabled = true; monitortime = 0.0; reslevels = new Queue(); } //Stop monitoring reservoir event private void monstop_click(object sender, EventArgs e) { monstartbtn.Enabled = true; monstopbtn.Enabled = false; timer1.Enabled = false; curreslvl.Text = ""; } //Start roller pump event private void pumpstart_click(object sender, EventArgs e) { int rc = 0; ushort numcards; //rc = omega.pioda.PIODA_DriverInit(); if (rc != omega.pioda.PIODA_NoError) { throw new System.ApplicationException("DriverInit failed"); } unsafe { // rc = omega.pioda.PIODA_SearchCard(&numcards,omega.pioda.PIO_DA); if (rc != omega.pioda.PIODA_NoError) { throw new System.ApplicationException("SearchCard failed"); } } pumpstartbtn.Enabled = false; pumpstopbtn.Enabled = true; pumpon = true; pumpstate = pumpstates.FullFlow; oldpumpstate = pumpstates.FullFlow; } //Stop roller pump event private void pumpstop_click(object sender, EventArgs e) { omega.pioda.PIODA_Voltage(0, 0, 0.0F); omega.pioda.PIODA_Voltage(0, 1, 0.0F); omega.pioda.PIODA_Voltage(0, 2, 0.0F); omega.pioda.PIODA_Voltage(0, 3, 0.0F); omega.pioda.PIODA_DriverClose(); pumpstartbtn.Enabled = true; pumpstopbtn.Enabled = false; pumpon = false; } //Process timer event private void timer_tick(object sender, EventArgs e) { char[] buf = new char[15]; int nread; char chrread; double pctflow; int changerate;
  3. 3. //Increment times elapsedtime += timer1.Interval / 1000.0; monitortime += timer1.Interval / 1000.0; //Send request to load cell meter and process response serialPort1.Write(weightreq, 0, 5); nread = 0; chrread = 0; while ((chrread != n) && (nread < 15)) { chrread = (char)serialPort1.ReadChar(); buf[nread] = chrread; nread++; } weight = parseweightrsp(buf); curreslevel = (weight * 1000) / density; reslevels.Enqueue(curreslevel); curreslvl.Text = curreslevel.ToString("F"); //Keep five seconds of weight responses if (monitortime < 5.0) { } else if (monitortime >= 5.0) { previousreslevel = (double)reslevels.Dequeue(); if (curreslevel - previousreslevel > 25.0) {//res level rising leveltrend.Image = (Image)greenuparrow; changerate = (int)((curreslevel - previousreslevel) / 5) *60; if (changerate > (int)(maxflowrate * 1000)) { changerate = (int)(maxflowrate * 1000); } lvlchangerate.Value = changerate; } else if (previousreslevel - curreslevel > 25.0) {//res level falling leveltrend.Image = (Image)reddownarrow; changerate = (int)((previousreslevel - curreslevel) / 5) *60; if (changerate > (int)(maxflowrate * 1000)) { changerate = (int)(maxflowrate * 1000); } lvlchangerate.Value = changerate; } else {//res level steady leveltrend.Image = null; lvlchangerate.Value = 0; } } if (pumpon == true) { oldpumpstate = pumpstate;// save current pump state pctflow = manageflow(); //Set status colors based on amount of flow from pump if (pctflow == 100.0)// full flow {
  4. 4. pumpstate = pumpstates.FullFlow; curreslvl.BackColor = Color.LightGreen; curflow.BackColor = Color.LightGreen; } else if (pctflow == 0.0)// no flow { pumpstate = pumpstates.Stopped; curreslvl.BackColor = Color.Red; curflow.BackColor = Color.Red; } else //partial flow { pumpstate = pumpstates.PartialFlow; curreslvl.BackColor = Color.Yellow; curflow.BackColor = Color.Yellow; } setrpm(maxrpm, pctflow);// set pumps rpm for this amount of flow curflowrate = maxflowrate * (pctflow / 100.0); curflow.Text = Convert.ToString(curflowrate); // If state of pump is changing, make announcement if (oldpumpstate == pumpstates.FullFlow) { if (pumpstate == pumpstates.PartialFlow) { SystemSounds.Exclamation.Play(); voice.Speak("warning reservoir low, slowing pump",SpFlags); } else if (pumpstate == pumpstates.Stopped) { SystemSounds.Exclamation.Play(); voice.Speak("warning, reservoir critical, stoppingpump", SpFlags); } } else if (oldpumpstate == pumpstates.PartialFlow) { if (pumpstate == pumpstates.FullFlow) { SystemSounds.Exclamation.Play(); voice.Speak("resuming full flow", SpFlags); } else if (pumpstate == pumpstates.Stopped) { SystemSounds.Exclamation.Play(); voice.Speak("warning, reservoir critical, stoppingpump", SpFlags); } } else if (oldpumpstate == pumpstates.Stopped) { if (pumpstate == pumpstates.FullFlow) { SystemSounds.Exclamation.Play(); voice.Speak("resuming full flow", SpFlags); } else if (pumpstate == pumpstates.PartialFlow) { SystemSounds.Exclamation.Play(); voice.Speak("restarting pump, partial flow", SpFlags); } }
  5. 5. if (recordon)// record res level and flow rate { logfile.Write(elapsedtime); logfile.Write(","); logfile.Write(curreslvl.Text); logfile.Write(","); logfile.WriteLine(curflow.Text); } } else // pump off { curreslvl.BackColor = Color.White; curflow.BackColor = Color.White; } } // Parse response from load cell meter private double parseweightrsp(char[] rsp) { char[] buf = new char[6]; double weight; int i; String swght; for (i = 0; i < 5; i++) { buf[i] = rsp[i + 3]; } buf[5] = 0; swght = new String(buf); weight = Double.Parse(swght); return weight; } //determine proper pump flow rate based on max flow rate, current,minimum and low // reservoir levels private double manageflow() { double pctflow = 0.0; if (curreslevel > lowreslevel)// current above low { pctflow = 100.0; } else if ((curreslevel <= lowreslevel) && (curreslevel >minreslevel)) {// current between low and minimum switch (pumpstate) { case pumpstates.FullFlow://pump slowing case pumpstates.PartialFlow: pctflow = minpercentflow + (int)((100.0 -minpercentflow) * ((curreslevel - minreslevel) / (lowreslevel -minreslevel))); break; case pumpstates.Stopped:// resuming from stopped if (curreslevel > lowreslevel) {
  6. 6. pctflow = 100.0; } else if (curreslevel >= minreslevel + 75) { pctflow = minpercentflow + (int)((100.0 -minpercentflow) * ((curreslevel - minreslevel) / (lowreslevel -minreslevel))); } else { pctflow = 0.0; } break; } } else // current level at or below minimum level { pctflow = 0.0; } return pctflow; } // change in minimum res level event private void minres_click(object sender, EventArgs e) { minreslevel = (double)minreslvlctl.Value; } //change in low res level event private void lowres_click(object sender, EventArgs e) { lowreslevel = (double)lowreslvlctl.Value; } //change in maximum flow event private void maxflow_click(object sender, EventArgs e) { maxflowrate = (double)flowctl.Value; maxrpm = (int)((maxflowrate * 1000) / strokevolume); lvlchangerate.Maximum = (int)(maxflowrate * 1000); } //Stop recording evengt private void rcrdstop_click(object sender, EventArgs e) { logfile.Close(); recordon = false; recordstartbtn.Enabled = true; recordstopbtn.Enabled = false; } //Start recording event private void rcrdstart_click(object sender, EventArgs e) { SaveFileDialog saveFileDialog1 = new SaveFileDialog(); saveFileDialog1.Title = "Save log data"; saveFileDialog1.Filter = "Text files (*.txt)|*.txt"; saveFileDialog1.ShowDialog(); if (saveFileDialog1.FileName != "") { logdata = saveFileDialog1.OpenFile();
  7. 7. logfile = new StreamWriter(logdata); } recordon = true; elapsedtime = 0.0; recordstopbtn.Enabled = true; recordstartbtn.Enabled = false; logfile.WriteLine("Max flow rate,Min percent flow,Min res level,lowres level"); logfile.Write(flowctl.Value); logfile.Write(","); logfile.Write(pctflowctl.Value); logfile.Write(","); logfile.Write(minreslvlctl.Value); logfile.Write(","); logfile.WriteLine(lowreslvlctl.Value); logfile.WriteLine("Elapsed Time, Volume, Flowrate"); } //Set fluid to water event private void waterbtn_click(object sender, EventArgs e) { density = waterdensity; } //Set fluid to blood event private void bloodbtn_click(object sender, EventArgs e) { density = blooddensity; } // set minimum amount of flow relative to max flow before // stop pump private void minpctflow_click(object sender, EventArgs e) { minpercentflow = (int)pctflowctl.Value; } //set pump rpm based on max rpm and percent flow private int setrpm(int maxrpm, double pctflow) { int rc = 0; float currpm; if ((maxrpm >= 0) && (maxrpm <= 175)) { if (pctflow > 0.0) { currpm = (float)(maxrpm * pctflow / 100.0); // rc = omega.pioda.PIODA_CalVoltage(0, 0, channel0_base +0); if (rc != omega.pioda.PIODA_NoError) { throw new System.ApplicationException("set voltagechannel 0 failed"); } // rc = omega.pioda.PIODA_CalVoltage(0, 1, channel1_base +(channel1_vrpm * currpm)); if (rc != omega.pioda.PIODA_NoError) { throw new System.ApplicationException("set voltagechannel 1 failed"); }
  8. 8. // rc = omega.pioda.PIODA_CalVoltage(0, 2, channel2_base +(channel2_vrpm * currpm)); if (rc != omega.pioda.PIODA_NoError) { throw new System.ApplicationException("set voltagechannel 2 failed"); } // rc = omega.pioda.PIODA_CalVoltage(0, 3, channel3_base +(channel3_vrpm * currpm)); if (rc != omega.pioda.PIODA_NoError) { throw new System.ApplicationException("set voltagechannel 3 failed"); } } else // Stop pump { // rc = omega.pioda.PIODA_CalVoltage(0, 0, 0.0F); if (rc != omega.pioda.PIODA_NoError) { throw new System.ApplicationException("set voltagechannel 0 failed"); } // rc = omega.pioda.PIODA_CalVoltage(0, 1, 0.0F); if (rc != omega.pioda.PIODA_NoError) { throw new System.ApplicationException("set voltagechannel 1 failed"); } // rc = omega.pioda.PIODA_CalVoltage(0, 2, 0.0F); if (rc != omega.pioda.PIODA_NoError) { throw new System.ApplicationException("set voltagechannel 2 failed"); } // rc = omega.pioda.PIODA_CalVoltage(0, 3, 0.0F); if (rc != omega.pioda.PIODA_NoError) { throw new System.ApplicationException("set voltagechannel 3 failed"); } } return 0; } else { return -1; } } enum pumpstates { Stopped, PartialFlow, FullFlow }; pumpstates pumpstate, oldpumpstate; const float channel0_base = 0.0739F; //Yellow const float channel1_base = 0.0739F; //Gray const float channel2_base = 0.1148F; // Blue const float channel3_base = 0.0792F; //Brown const float channel0_vrpm = 0.0097F; //Yellow const float channel1_vrpm = 0.0097F; //Gray const float channel2_vrpm = 0.0557F; // Blue const float channel3_vrpm = 0.0239F; //Brown const float strokevolume = 46.0F; const float waterdensity = 0.99823F; // tap water 20 C const float blooddensity = 1.06F; float density = 1.0F;
  9. 9. double weight; char[] weightreq = new char[6]; //"*X01"; double minreslevel; double lowreslevel; Double curreslevel; double previousreslevel; double maxflowrate; int maxrpm; Boolean pumpon; double curflowrate; StreamWriter logfile; Stream logdata; double elapsedtime; Boolean recordon; NumberFormatInfo nfi; double monitortime; Queue reslevels; Bitmap greenuparrow, reddownarrow; SpVoice voice; SpeechVoiceSpeakFlags SpFlags = SpeechVoiceSpeakFlags.SVSFlagsAsync; int minpercentflow; }}namespace omega{ class pioda { // return co public const int PIODA_NoError = 0; // ID public const int PIO_DA = 0x800400; // Driver functions [DllImport("PIODA.DLL")] static public extern ushort PIODA_DriverInit(); [DllImport("PIODA.DLL")] static public extern void PIODA_DriverClose(); [DllImport("PIODA.DLL")] static public unsafe extern ushort PIODA_SearchCard (ushort* wBoards, int dwPIOCardID); // DA functions [DllImport("PIODA.DLL")] static public extern ushort PIODA_Voltage (ushort wBoardNo, ushort wChannel, float fValue); [DllImport("PIODA.DLL")] static public extern ushort PIODA_Current (ushort wBoardNo, ushort wChannel, float fValue); [DllImport("PIODA.DLL")] static public extern ushort PIODA_CalVoltage (ushort wBoardNo, ushort wChannel, float fValue); [DllImport("PIODA.DLL")] static public extern ushort PIODA_CalCurrent (ushort wBoardNo, ushort wChannel, float fValue); }}

×