Program stopper efter nogle timers kørsel
Hej alleHvem kan knække dette problem?
Til noget laboratorieudstyr på min arbejdsplads (Århus Universitet) er jeg ved at skrive et styringsprogram. Udstyret skal bruges til at analyserer hydrauliske data i jord.
Mit problem at programmet "låser" efter nogle timers kørsel.
Timeren i klassen PressureTransducer holder op med at køre.
At genstarte Visual Studio hjælper ikke.
Programmets første linier kører, men timeren kommer aldrig igang igen.
Computeren skal simpelhen genstartes.
Kan det være min program, der er en fejl i, eller er det noget med en driver eller andet ??
Da programmet skal køre i 1 - 2 måneder er det temmelig katastrofalt.
Jeg vil derfor være yderst taknemmelig for ethvert indput!
200 point er det maksimale, jeg kan give. Jeg gav gerne 2000 point om det var muligt.
Har nogen en god ide ?
Nærmere beskrivelse og programmet er listet nedenfor.
Opklarende spørgsmål besvares naturligvis.
/Michael
/* Styringsprogrammets formål INDTIL VIDERE er at styre trykket i en kontainer.
* To ventiler en forbundet til hhv atmosfæren og tryk (kompressor) styrer dette ved enten at være eller lukkede.
* Er ventilen til atmosfæretrykket åben og ventilen til tryk lukket falder trykket i beholderen.
* Er ventilen til atmosfæretrykket lukket og ventilen til tryk åben falder trykket i beholderen.
* Er ventilen til atmosfæretrykket lukket og ventilen til tryk lukket er trykket i beholderen uændret.
* Ventilerne kan styres gennem en USB til RS485 converter, der igen er koblet til et relæsystem, ved sende en tekststring for "luk" og en anden for "åben".
* Trykket i beholderen måles af to tryktransducere: en fra 0-300 mBar (adresse 101) og en fra 0-3000 mBar (adresse 102)
* Er trykket højere en 300 bruges den store tryktransducer. Er det lavere en 300 bruges den lille.
* Trykket fås ved at sende en streng til den RS485-adresse, hvor den pågældende tryktransducer er koblet på.
* Svaret kontrolleres med en CRC-modbus og godkendes kun hvis checksummen er korrekt.
* Der findes en ekstra ventil som åbner op til tryktransduceren, når disse skal bruges.
* Trykket i beholderen plottes i en zedgraph i formen "modul".
*
* Klassen pressureController henter et tryk fra Airpressure.cs.
* AirPressure henter, via SerielPressureTransducer, trykket fra begge de to tryktransducere og beslutter, hvilken værdi der skal bruges.
* Er trykket større en 300 mbar er det den store tryktransducers værdi. Er trykket mindre end 300 mbar er det den lille.
* SerialPressuretransducer.cs skriver direkte til comporten og modtager svar, som fyres op til AirPressure.
* PressureController åbner og lukker ventiler via SerielValve. Ventil status visualiseres i formen vha. ValveAlarmView.
*/
------------------------------------------------------
MODUL
------------------------------------------------------
using System;
using System.IO;
using System.IO.Ports;
using System.Windows.Forms;
using ZedGraph;
namespace Hysterese
{
public partial class Modul : Form
{
AirPressure AirPressure;
PressureController Pcontrol;
SerialPressureTransmitter pt;
ZedGraphClass zgc;
SerialPort port;
public Modul()
{
InitializeComponent();
this.BringToFront();
this.TopMost = true;
this.ShowInTaskbar = false;
//
//serialport
port = new SerialPort("COM4", 9600, Parity.None, 8, StopBits.One);
port.Open();
pt = new SerialPressureTransmitter(port);
AirPressure = new AirPressure(port,pt);
AirPressure.DataAvailable+=new EventHandler<DataAvailableEventArgs>(AirPressure_DataAvailable);
//startup presssure
listBox_Pressure.SelectedIndex = 0;
//make ready for plotting pressure
zgc = new ZedGraphClass(zg_pressure);
zgc.CreateGraph("Hysteresis","time","cm");
//be able to se when then valves is open or when the valves are closed
ValveAlarmView ValveAlarmView = new ValveAlarmView(checkBox_pressure, checkBox_Air, checkBox_Transmitter);
//startup pressurecontroller
int pF_value = Convert.ToInt32(listBox_Pressure.SelectedItem.ToString());
Pcontrol = new PressureController(port, pF_value,ValveAlarmView,AirPressure);
//get a message when pressure is okay (Pcontrol_PressureOK)
Pcontrol.PressureOK += new EventHandler<PressureOkEventArgs>(Pcontrol_PressureOK);
Start();
}
public void Start()
{
this.Visible = true;
//startPressureController
Pcontrol.Start();
}
//Be able to recieve data from pressurecontroller and to plot it
private void pressureDataReady(object sender, DataAvailableEventArgs e)
{//water pressure from pt
timer1.Stop();
zgc.AddPoint(DateTime.Now.Ticks, e.Data);
}
private void Pcontrol_PressureOK(object sender, PressureOkEventArgs e)
{
//pressure ok, then ask for pF and stop recieve data from Airpressure
MessageBox.Show("pressureOK");
}
private void AirPressure_DataAvailable(object sender, DataAvailableEventArgs e)
{
zgc.AddPoint(DateTime.Now.Ticks, e.Data);
}
private void Modul_FormClosing(object sender, FormClosingEventArgs e)
{
if (port.IsOpen)
port.Close();
}
private void Btn_close_Click(object sender, EventArgs e)
{
if (port.IsOpen)
port.Close();
Application.Exit();
}
}
}
------------------------------------------------------
PressureController
------------------------------------------------------
using System;
using System.Timers;
using System.IO;
using System.IO.Ports;
namespace Hysterese
{
public class PressureController
{
private double pSetPoint;
private Timer timer;
private AirPressure AirPressure;
public event EventHandler<PressureOkEventArgs> PressureOK;
public event EventHandler<DataAvailableEventArgs> AirDataAvailable;
private SerielValve Valve;
public PressureController(SerialPort port, double pressureSetPoint, ValveAlarmView ValveAlarmView, AirPressure AirPressure)
{
timer = new Timer(500);
timer.Elapsed += new ElapsedEventHandler(TimerElapsed);
this.AirPressure = AirPressure;
//hook op på airpressure
AirPressure.DataAvailable += SerAirPressure_DataAvailable;
// set pressurepoint
pSetPoint = pressureSetPoint;
Valve = new SerielValve(port, ValveAdresses.valvePreAdr(0), ValveAdresses.valveAtmAdr(0) , ValveAdresses.valveTransAdr(0),ValveAlarmView);
}
public double SetPoint
{
get { return pSetPoint; }
set { pSetPoint = value; }
}
public void Start()
{
Valve.OpenValveTrans();
timer.Start();
}
public void Stop()
{
Valve.CloseValveTrans();
timer.Stop();
}
public void TimerElapsed(object sender, ElapsedEventArgs e)
{
AirPressure.SendTransducerCommands();//get answar in SerPressure_DataAvailable
}
private void PressureAjust(double pressure)
{
double lower = pSetPoint - pSetPoint * 0.01 / 100;
double upper = pSetPoint + pSetPoint * 0.01 / 100;
//pressure to low
if (pressure < lower)
{
Valve.OpenValvePressure();
Valve.CloseValveAtm();
}
//pressure to heigh
if (pressure > upper)
{
Valve.OpenValveAtm();
Valve.CloseValvePressure();
//Console.Beep(1000, 50);
}
//pressure ok close all walves at stop timer
if (pressure < upper & pressure>lower)
{
Valve.CloseValveAtm();
Valve.CloseValvePressure();
Valve.CloseValveTrans();
//timer.Enabled = false;
//OnPressureOk(true);
}
}
void SerAirPressure_DataAvailable(object sender, DataAvailableEventArgs e)
{
//Is send from Airpressure.OnDataAvaiable
//send to module
OnAirDataAvaiable(e.Data);
//ajust pressure
PressureAjust(e.Data);
}
void OnPressureOk(bool data)
{//watched from Modul
PressureOkEventArgs e = new PressureOkEventArgs() { Data = data };
EventHandler<PressureOkEventArgs> d = PressureOK;
if (d != null)
d(this, e);
}
void OnAirDataAvaiable(double data)
{//watched of Modul
DataAvailableEventArgs e = new DataAvailableEventArgs() { Data = data };
EventHandler<DataAvailableEventArgs> d = AirDataAvailable;
if (d != null)
d(this, e);
}
}
}
------------------------------------------------------
AirPressure
------------------------------------------------------
using System;
using System.IO.Ports;
using System.Collections.Generic;
using System.IO;
using System.Timers;
namespace Hysterese
{
public class AirPressure
{
SerialPort port;
SerialPressureTransmitter pt;
private List<double> dataList;
System.Timers.Timer aTimer;
int transducerAdr;
double pressure3000;
double pressure300;
public event EventHandler<DataAvailableEventArgs> DataAvailable;
public AirPressure(SerialPort port,SerialPressureTransmitter pt)
{
dataList=new List<double>();
this.pt = pt;
pt.AirDataAvailable += pressureDataReady;
aTimer = new System.Timers.Timer(100);
aTimer.Elapsed += new System.Timers.ElapsedEventHandler(OnTimedEvent);
try
{
this.port = port;
}
catch (Exception ex)
{
ExceptionLogger.Instance.logExceptionToFile(ex);;
}
}
public void SendTransducerCommands()
{
transducerAdr = 102;//first 3000
aTimer.Start();
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
pt.ReadPort(transducerAdr);//first 3000 then 300
}
private void pressureDataReady(object sender, DataAvailableEventArgs e)
{
if (transducerAdr == 102)
{
pressure3000 = e.Data;
transducerAdr = 101;
}
else//adr then 101
{
aTimer.Stop();
pressure300 = e.Data;
EvalData(pressure300,pressure3000);
}
}
private void EvalData(double pressure300, double pressure3000)
{
if (pressure300 < 300)
OnDataAvaiable(pressure300);//if pressure <300 then use low transducer
else
OnDataAvaiable(pressure3000);//if pressure >300 then use heigh transducer
}
void OnDataAvaiable(double data)
{//wached from pressurecontroller
DataAvailableEventArgs e = new DataAvailableEventArgs() { Data = data };
EventHandler<DataAvailableEventArgs> d = DataAvailable;
if (d != null)
d(this, e);
}
}
}
------------------------------------------------------
SerialPressureTransmitter
------------------------------------------------------
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Windows.Forms;
namespace Hysterese
{
public class SerialPressureTransmitter
{
SerialPort port;
private List<int> byteList;
private List<byte> hexList;
private string hex_string;
private bool found;
int transducerAdr;
private CRC_Modbus Modbus;
public event EventHandler<DataAvailableEventArgs> AirDataAvailable;
public SerialPressureTransmitter(SerialPort port)
{
this.port=port;
ConnectToPort();
Modbus = new CRC_Modbus();
hexList = new List<byte>();
byteList = new List<int>();
}
public void ConnectToPort()
{
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
}
public void DisConnectToPort()
{
port.DataReceived -= new SerialDataReceivedEventHandler(port_DataReceived);
}
public void InitTransmitter(int transducerAdr)
{
if (transducerAdr == 100)
port.Write(new byte[] { 0x64, 0x30, 0x64, 0x2B }, 0, 4);//init
if (transducerAdr == 101)
port.Write(new byte[] { 0x65, 0x30, 0xFA, 0x2A }, 0, 4);//init
if (transducerAdr == 102)
port.Write(new byte[] { 0x66, 0x30, 0x04, 0x2A }, 0, 4);//init 66 30 04 2A
}
public void ReadPort(int transducerAdr)
{
try
{
this.transducerAdr = transducerAdr;
if (transducerAdr == 100)
port.Write(new byte[] { 0x64, 0x4A, 0x01, 0xBF, 0xC6 }, 0, 5); // ADR CMD CH CHH CHL
if (transducerAdr == 101)
port.Write(new byte[] { 0x65, 0x4A, 0x01, 0x7F, 0x97 }, 0, 5);//65 64 02 DE CA
if (transducerAdr == 102)
port.Write(new byte[] { 0x66, 0x4A, 0x01, 0x7F, 0x67 }, 0, 5);
}
catch (Exception ex)
{
ExceptionLogger.Instance.logExceptionToFile(ex);
}
}
public void zero()
{
if(transducerAdr==100)
port.Write(new byte[] { 0x64, 0x5F, 0x00, 0xEF, 0x09 }, 0, 5);
if(transducerAdr==101)
port.Write(new byte[] { 0x65, 0x5F, 0x00, 0x2F, 0x58 }, 0, 5);
if(transducerAdr==102)
port.Write(new byte[] { 0x66, 0x5F, 0x00, 0x2F, 0xA8 }, 0, 5);
}
private bool ChksumChecker(List<int> byteList)
{
int ModbusChksum = Modbus.crc16(hexList.ToArray(), 7);
string ModbusChksum_str = Convert.ToInt32(ModbusChksum).ToString("X");//convert to hex
string hex7 = Convert.ToInt32(byteList[7]).ToString("X");//get the values from reading in order to calc chksum
string hex8 = Convert.ToInt32(byteList[8]).ToString("X");
if (hex7.Length == 1)
hex7 = "0" + hex7;//length to 2
if (hex8.Length == 1)
hex8 = "0" + hex8;//length to 2
string KellerCheckSum_str = Convert.ToInt32(byteList[8]).ToString("X") + Convert.ToInt32(byteList[7]).ToString("X");//remove??
KellerCheckSum_str = hex8 + hex7;
if (ModbusChksum_str == KellerCheckSum_str) found = true;
return found;
}
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int b=0;
try
{
b = port.ReadByte();
}
catch (Exception ex)
{
ExceptionLogger.Instance.logExceptionToFile(ex);
}
byteList.Add(b);
hexList.Add(Convert.ToByte(b));
if (byteList.Count > 8)
{
if (byteList[0] == transducerAdr & byteList[1] == 74)
{//if address and command is alright
found = ChksumChecker(byteList);
if (found)
{
string hex4 = Convert.ToInt32(byteList[4]).ToString("X");
string hex5 = Convert.ToInt32(byteList[5]).ToString("X");
hex_string = stringExtend(hex4) + stringExtend(hex5);
int Pa_int = int.Parse(hex_string, System.Globalization.NumberStyles.HexNumber);
if (Pa_int > 60000) Pa_int = Pa_int - 65535;//if negative pressure
double ws_m = Convert.ToDouble(Convert.ToDouble(Pa_int)) * 0.0102;
if (transducerAdr == 101 | transducerAdr == 102 )
OnAirDataAvaiable(ws_m);
}
}
//keep bytelist shorter than 10
while (byteList.Count > 9)
byteList.RemoveAt(0);
while (hexList.Count > 9)
hexList.RemoveAt(0);
}
}
private string stringExtend(string str)
{
if (str.Length == 1)
str = "0" + str;
return str;
}
void OnAirDataAvaiable(double data)
{//watched of Modul
DataAvailableEventArgs e = new DataAvailableEventArgs() { Data = data };
EventHandler<DataAvailableEventArgs> d = AirDataAvailable;
if (d != null)
d(this, e);
}
}
}
------------------------------------------------------
CRC_Modbus
------------------------------------------------------
using System;
namespace Hysterese
{
/// <summary>
/// Summary description for CRC_Modbus.
/// </summary>
public class CRC_Modbus
{
public byte[] crc_table=new byte[512];
public CRC_Modbus()
{
crc_table[0] = 0x0;
crc_table[1] = 0xC1;
crc_table[2] = 0x81;
crc_table[3] = 0x40;
crc_table[4] = 0x1;
crc_table[5] = 0xC0;
crc_table[6] = 0x80;
crc_table[7] = 0x41;
crc_table[8] = 0x1;
crc_table[9] = 0xC0;
crc_table[10] = 0x80;
crc_table[11] = 0x41;
crc_table[12] = 0x0;
crc_table[13] = 0xC1;
crc_table[14] = 0x81;
crc_table[15] = 0x40;
crc_table[16] = 0x1;
crc_table[17] = 0xC0;
crc_table[18] = 0x80;
crc_table[19] = 0x41;
crc_table[20] = 0x0;
crc_table[21] = 0xC1;
crc_table[22] = 0x81;
crc_table[23] = 0x40;
crc_table[24] = 0x0;
crc_table[25] = 0xC1;
crc_table[26] = 0x81;
crc_table[27] = 0x40;
crc_table[28] = 0x1;
crc_table[29] = 0xC0;
crc_table[30] = 0x80;
crc_table[31] = 0x41;
crc_table[32] = 0x1;
crc_table[33] = 0xC0;
crc_table[34] = 0x80;
crc_table[35] = 0x41;
crc_table[36] = 0x0;
crc_table[37] = 0xC1;
crc_table[38] = 0x81;
crc_table[39] = 0x40;
crc_table[40] = 0x0;
crc_table[41] = 0xC1;
crc_table[42] = 0x81;
crc_table[43] = 0x40;
crc_table[44] = 0x1;
crc_table[45] = 0xC0;
crc_table[46] = 0x80;
crc_table[47] = 0x41;
crc_table[48] = 0x0;
crc_table[49] = 0xC1;
crc_table[50] = 0x81;
crc_table[51] = 0x40;
crc_table[52] = 0x1;
crc_table[53] = 0xC0;
crc_table[54] = 0x80;
crc_table[55] = 0x41;
crc_table[56] = 0x1;
crc_table[57] = 0xC0;
crc_table[58] = 0x80;
crc_table[59] = 0x41;
crc_table[60] = 0x0;
crc_table[61] = 0xC1;
crc_table[62] = 0x81;
crc_table[63] = 0x40;
crc_table[64] = 0x1;
crc_table[65] = 0xC0;
crc_table[66] = 0x80;
crc_table[67] = 0x41;
crc_table[68] = 0x0;
crc_table[69] = 0xC1;
crc_table[70] = 0x81;
crc_table[71] = 0x40;
crc_table[72] = 0x0;
crc_table[73] = 0xC1;
crc_table[74] = 0x81;
crc_table[75] = 0x40;
crc_table[76] = 0x1;
crc_table[77] = 0xC0;
crc_table[78] = 0x80;
crc_table[79] = 0x41;
crc_table[80] = 0x0;
crc_table[81] = 0xC1;
crc_table[82] = 0x81;
crc_table[83] = 0x40;
crc_table[84] = 0x1;
crc_table[85] = 0xC0;
crc_table[86] = 0x80;
crc_table[87] = 0x41;
crc_table[88] = 0x1;
crc_table[89] = 0xC0;
crc_table[90] = 0x80;
crc_table[91] = 0x41;
crc_table[92] = 0x0;
crc_table[93] = 0xC1;
crc_table[94] = 0x81;
crc_table[95] = 0x40;
crc_table[96] = 0x0;
crc_table[97] = 0xC1;
crc_table[98] = 0x81;
crc_table[99] = 0x40;
crc_table[100] = 0x1;
crc_table[101] = 0xC0;
crc_table[102] = 0x80;
crc_table[103] = 0x41;
crc_table[104] = 0x1;
crc_table[105] = 0xC0;
crc_table[106] = 0x80;
crc_table[107] = 0x41;
crc_table[108] = 0x0;
crc_table[109] = 0xC1;
crc_table[110] = 0x81;
crc_table[111] = 0x40;
crc_table[112] = 0x1;
crc_table[113] = 0xC0;
crc_table[114] = 0x80;
crc_table[115] = 0x41;
crc_table[116] = 0x0;
crc_table[117] = 0xC1;
crc_table[118] = 0x81;
crc_table[119] = 0x40;
crc_table[120] = 0x0;
crc_table[121] = 0xC1;
crc_table[122] = 0x81;
crc_table[123] = 0x40;
crc_table[124] = 0x1;
crc_table[125] = 0xC0;
crc_table[126] = 0x80;
crc_table[127] = 0x41;
crc_table[128] = 0x1;
crc_table[129] = 0xC0;
crc_table[130] = 0x80;
crc_table[131] = 0x41;
crc_table[132] = 0x0;
crc_table[133] = 0xC1;
crc_table[134] = 0x81;
crc_table[135] = 0x40;
crc_table[136] = 0x0;
crc_table[137] = 0xC1;
crc_table[138] = 0x81;
crc_table[139] = 0x40;
crc_table[140] = 0x1;
crc_table[141] = 0xC0;
crc_table[142] = 0x80;
crc_table[143] = 0x41;
crc_table[144] = 0x0;
crc_table[145] = 0xC1;
crc_table[146] = 0x81;
crc_table[147] = 0x40;
crc_table[148] = 0x1;
crc_table[149] = 0xC0;
crc_table[150] = 0x80;
crc_table[151] = 0x41;
crc_table[152] = 0x1;
crc_table[153] = 0xC0;
crc_table[154] = 0x80;
crc_table[155] = 0x41;
crc_table[156] = 0x0;
crc_table[157] = 0xC1;
crc_table[158] = 0x81;
crc_table[159] = 0x40;
crc_table[160] = 0x0;
crc_table[161] = 0xC1;
crc_table[162] = 0x81;
crc_table[163] = 0x40;
crc_table[164] = 0x1;
crc_table[165] = 0xC0;
crc_table[166] = 0x80;
crc_table[167] = 0x41;
crc_table[168] = 0x1;
crc_table[169] = 0xC0;
crc_table[170] = 0x80;
crc_table[171] = 0x41;
crc_table[172] = 0x0;
crc_table[173] = 0xC1;
crc_table[174] = 0x81;
crc_table[175] = 0x40;
crc_table[176] = 0x1;
crc_table[177] = 0xC0;
crc_table[178] = 0x80;
crc_table[179] = 0x41;
crc_table[180] = 0x0;
crc_table[181] = 0xC1;
crc_table[182] = 0x81;
crc_table[183] = 0x40;
crc_table[184] = 0x0;
crc_table[185] = 0xC1;
crc_table[186] = 0x81;
crc_table[187] = 0x40;
crc_table[188] = 0x1;
crc_table[189] = 0xC0;
crc_table[190] = 0x80;
crc_table[191] = 0x41;
crc_table[192] = 0x0;
crc_table[193] = 0xC1;
crc_table[194] = 0x81;
crc_table[195] = 0x40;
crc_table[196] = 0x1;
crc_table[197] = 0xC0;
crc_table[198] = 0x80;
crc_table[199] = 0x41;
crc_table[200] = 0x1;
crc_table[201] = 0xC0;
crc_table[202] = 0x80;
crc_table[203] = 0x41;
crc_table[204] = 0x0;
crc_table[205] = 0xC1;
crc_table[206] = 0x81;
crc_table[207] = 0x40;
crc_table[208] = 0x1;
crc_table[209] = 0xC0;
crc_table[210] = 0x80;
crc_table[211] = 0x41;
crc_table[212] = 0x0;
crc_table[213] = 0xC1;
crc_table[214] = 0x81;
crc_table[215] = 0x40;
crc_table[216] = 0x0;
crc_table[217] = 0xC1;
crc_table[218] = 0x81;
crc_table[219] = 0x40;
crc_table[220] = 0x1;
crc_table[221] = 0xC0;
crc_table[222] = 0x80;
crc_table[223] = 0x41;
crc_table[224] = 0x1;
crc_table[225] = 0xC0;
crc_table[226] = 0x80;
crc_table[227] = 0x41;
crc_table[228] = 0x0;
crc_table[229] = 0xC1;
crc_table[230] = 0x81;
crc_table[231] = 0x40;
crc_table[232] = 0x0;
crc_table[233] = 0xC1;
crc_table[234] = 0x81;
crc_table[235] = 0x40;
crc_table[236] = 0x1;
crc_table[237] = 0xC0;
crc_table[238] = 0x80;
crc_table[239] = 0x41;
crc_table[240] = 0x0;
crc_table[241] = 0xC1;
crc_table[242] = 0x81;
crc_table[243] = 0x40;
crc_table[244] = 0x1;
crc_table[245] = 0xC0;
crc_table[246] = 0x80;
crc_table[247] = 0x41;
crc_table[248] = 0x1;
crc_table[249] = 0xC0;
crc_table[250] = 0x80;
crc_table[251] = 0x41;
crc_table[252] = 0x0;
crc_table[253] = 0xC1;
crc_table[254] = 0x81;
crc_table[255] = 0x40;
crc_table[256] = 0x0;
crc_table[257] = 0xC0;
crc_table[258] = 0xC1;
crc_table[259] = 0x1;
crc_table[260] = 0xC3;
crc_table[261] = 0x3;
crc_table[262] = 0x2;
crc_table[263] = 0xC2;
crc_table[264] = 0xC6;
crc_table[265] = 0x6;
crc_table[266] = 0x7;
crc_table[267] = 0xC7;
crc_table[268] = 0x5;
crc_table[269] = 0xC5;
crc_table[270] = 0xC4;
crc_table[271] = 0x4;
crc_table[272] = 0xCC;
crc_table[273] = 0xC;
crc_table[274] = 0xD;
crc_table[275] = 0xCD;
crc_table[276] = 0xF;
crc_table[277] = 0xCF;
crc_table[278] = 0xCE;
crc_table[279] = 0xE;
crc_table[280] = 0xA;
crc_table[281] = 0xCA;
crc_table[282] = 0xCB;
crc_table[283] = 0xB;
crc_table[284] = 0xC9;
crc_table[285] = 0x9;
crc_table[286] = 0x8;
crc_table[287] = 0xC8;
crc_table[288] = 0xD8;
crc_table[289] = 0x18;
crc_table[290] = 0x19;
crc_table[291] = 0xD9;
crc_table[292] = 0x1B;
crc_table[293] = 0xDB;
crc_table[294] = 0xDA;
crc_table[295] = 0x1A;
crc_table[296] = 0x1E;
crc_table[297] = 0xDE;
crc_table[298] = 0xDF;
crc_table[299] = 0x1F;
crc_table[300] = 0xDD;
crc_table[301] = 0x1D;
crc_table[302] = 0x1C;
crc_table[303] = 0xDC;
crc_table[304] = 0x14;
crc_table[305] = 0xD4;
crc_table[306] = 0xD5;
crc_table[307] = 0x15;
crc_table[308] = 0xD7;
crc_table[309] = 0x17;
crc_table[310] = 0x16;
crc_table[311] = 0xD6;
crc_table[312] = 0xD2;
crc_table[313] = 0x12;
crc_table[314] = 0x13;
crc_table[315] = 0xD3;
crc_table[316] = 0x11;
crc_table[317] = 0xD1;
crc_table[318] = 0xD0;
crc_table[319] = 0x10;
crc_table[320] = 0xF0;
crc_table[321] = 0x30;
crc_table[322] = 0x31;
crc_table[323] = 0xF1;
crc_table[324] = 0x33;
crc_table[325] = 0xF3;
crc_table[326] = 0xF2;
crc_table[327] = 0x32;
crc_table[328] = 0x36;
crc_table[329] = 0xF6;
crc_table[330] = 0xF7;
crc_table[331] = 0x37;
crc_table[332] = 0xF5;
crc_table[333] = 0x35;
crc_table[334] = 0x34;
crc_table[335] = 0xF4;
crc_table[336] = 0x3C;
crc_table[337] = 0xFC;
crc_table[338] = 0xFD;
crc_table[339] = 0x3D;
crc_table[340] = 0xFF;
crc_table[341] = 0x3F;
crc_table[342] = 0x3E;
crc_table[343] = 0xFE;
crc_table[344] = 0xFA;
crc_table[345] = 0x3A;
crc_table[346] = 0x3B;
crc_table[347] = 0xFB;
crc_table[348] = 0x39;
crc_table[349] = 0xF9;
crc_table[350] = 0xF8;
crc_table[351] = 0x38;
crc_table[352] = 0x28;
crc_table[353] = 0xE8;
crc_table[354] = 0xE9;
crc_table[355] = 0x29;
crc_table[356] = 0xEB;
crc_table[357] = 0x2B;
crc_table[358] = 0x2A;
crc_table[359] = 0xEA;
crc_table[360] = 0xEE;
crc_table[361] = 0x2E;
crc_table[362] = 0x2F;
crc_table[363] = 0xEF;
crc_table[364] = 0x2D;
crc_table[365] = 0xED;
crc_table[366] = 0xEC;
crc_table[367] = 0x2C;
crc_table[368] = 0xE4;
crc_table[369] = 0x24;
crc_table[370] = 0x25;
crc_table[371] = 0xE5;
crc_table[372] = 0x27;
crc_table[373] = 0xE7;
crc_table[374] = 0xE6;
crc_table[375] = 0x26;
crc_table[376] = 0x22;
crc_table[377] = 0xE2;
crc_table[378] = 0xE3;
crc_table[379] = 0x23;
crc_table[380] = 0xE1;
crc_table[381] = 0x21;
crc_table[382] = 0x20;
crc_table[383] = 0xE0;
crc_table[384] = 0xA0;
crc_table[385] = 0x60;
crc_table[386] = 0x61;
crc_table[387] = 0xA1;
crc_table[388] = 0x63;
crc_table[389] = 0xA3;
crc_table[390] = 0xA2;
crc_table[391] = 0x62;
crc_table[392] = 0x66;
crc_table[393] = 0xA6;
crc_table[394] = 0xA7;
crc_table[395] = 0x67;
crc_table[396] = 0xA5;
crc_table[397] = 0x65;
crc_table[398] = 0x64;
crc_table[399] = 0xA4;
crc_table[400] = 0x6C;
crc_table[401] = 0xAC;
crc_table[402] = 0xAD;
crc_table[403] = 0x6D;
crc_table[404] = 0xAF;
crc_table[405] = 0x6F;
crc_table[406] = 0x6E;
crc_table[407] = 0xAE;
crc_table[408] = 0xAA;
crc_table[409] = 0x6A;
crc_table[410] = 0x6B;
crc_table[411] = 0xAB;
crc_table[412] = 0x69;
crc_table[413] = 0xA9;
crc_table[414] = 0xA8;
crc_table[415] = 0x68;
crc_table[416] = 0x78;
crc_table[417] = 0xB8;
crc_table[418] = 0xB9;
crc_table[419] = 0x79;
crc_table[420] = 0xBB;
crc_table[421] = 0x7B;
crc_table[422] = 0x7A;
crc_table[423] = 0xBA;
crc_table[424] = 0xBE;
crc_table[425] = 0x7E;
crc_table[426] = 0x7F;
crc_table[427] = 0xBF;
crc_table[428] = 0x7D;
crc_table[429] = 0xBD;
crc_table[430] = 0xBC;
crc_table[431] = 0x7C;
crc_table[432] = 0xB4;
crc_table[433] = 0x74;
crc_table[434] = 0x75;
crc_table[435] = 0xB5;
crc_table[436] = 0x77;
crc_table[437] = 0xB7;
crc_table[438] = 0xB6;
crc_table[439] = 0x76;
crc_table[440] = 0x72;
crc_table[441] = 0xB2;
crc_table[442] = 0xB3;
crc_table[443] = 0x73;
crc_table[444] = 0xB1;
crc_table[445] = 0x71;
crc_table[446] = 0x70;
crc_table[447] = 0xB0;
crc_table[448] = 0x50;
crc_table[449] = 0x90;
crc_table[450] = 0x91;
crc_table[451] = 0x51;
crc_table[452] = 0x93;
crc_table[453] = 0x53;
crc_table[454] = 0x52;
crc_table[455] = 0x92;
crc_table[456] = 0x96;
crc_table[457] = 0x56;
crc_table[458] = 0x57;
crc_table[459] = 0x97;
crc_table[460] = 0x55;
crc_table[461] = 0x95;
crc_table[462] = 0x94;
crc_table[463] = 0x54;
crc_table[464] = 0x9C;
crc_table[465] = 0x5C;
crc_table[466] = 0x5D;
crc_table[467] = 0x9D;
crc_table[468] = 0x5F;
crc_table[469] = 0x9F;
crc_table[470] = 0x9E;
crc_table[471] = 0x5E;
crc_table[472] = 0x5A;
crc_table[473] = 0x9A;
crc_table[474] = 0x9B;
crc_table[475] = 0x5B;
crc_table[476] = 0x99;
crc_table[477] = 0x59;
crc_table[478] = 0x58;
crc_table[479] = 0x98;
crc_table[480] = 0x88;
crc_table[481] = 0x48;
crc_table[482] = 0x49;
crc_table[483] = 0x89;
crc_table[484] = 0x4B;
crc_table[485] = 0x8B;
crc_table[486] = 0x8A;
crc_table[487] = 0x4A;
crc_table[488] = 0x4E;
crc_table[489] = 0x8E;
crc_table[490] = 0x8F;
crc_table[491] = 0x4F;
crc_table[492] = 0x8D;
crc_table[493] = 0x4D;
crc_table[494] = 0x4C;
crc_table[495] = 0x8C;
crc_table[496] = 0x44;
crc_table[497] = 0x84;
crc_table[498] = 0x85;
crc_table[499] = 0x45;
crc_table[500] = 0x87;
crc_table[501] = 0x47;
crc_table[502] = 0x46;
crc_table[503] = 0x86;
crc_table[504] = 0x82;
crc_table[505] = 0x42;
crc_table[506] = 0x43;
crc_table[507] = 0x83;
crc_table[508] = 0x41;
crc_table[509] = 0x81;
crc_table[510] = 0x80;
crc_table[511] = 0x40;
}
public int crc16(byte[] modbusframe,int Length)
{
int i;
int index;
int crc_Low = 0xFF;
int crc_High = 0xFF;
for (i = 0; i<Length; i++)
{
index = crc_High ^ (char)modbusframe[i];
crc_High = crc_Low ^ crc_table[index];
crc_Low = (byte)crc_table[index + 256];
}
return crc_High*256+crc_Low;
}
}
}
------------------------------------------------------
SerielValve
------------------------------------------------------
using System;
using System.IO.Ports;
using System.Windows.Forms;
namespace Hysterese
{
public class SerielValve
{
private SerialPort port;
private ValveAlarmView ValveAlarmView;
private string valvePreAdr;
private string valveAtmAdr;
private string valveTransAdr;
private bool valvePre;
private bool valveAtm;
private bool valveTrans;
public SerielValve(SerialPort port, string valvePreAdr, string valveAtmAdr, string valveTransAdr, ValveAlarmView ValveAlarmView)
{
this.port = port;
this.ValveAlarmView = ValveAlarmView;
this.valvePreAdr = valvePreAdr;
this.valveAtmAdr = valveAtmAdr;
this.valveTransAdr = valveTransAdr;
CloseAllValves();
}
public bool ValvePre {
get { return valvePre; }
set { valvePre = value;
}
}
public bool ValveAtm
{
get { return valveAtm; }
set {
valveAtm = value;
}
}
public bool ValveTrans
{
get { return valveTrans; }
set { valveTrans = value;
}
}
public void OpenValvePressure()
{
try
{
//if (!ValvePre)
{
string command = "#" + valvePreAdr + "01\r>\r"; //"#021001\r>\r";
port.Write(command);
ValvePre = true;
ValveAlarmView.SetAlarmPre(true);
}
}
catch (Exception ex)
{
ExceptionLogger.Instance.logExceptionToFile(ex);;
ValveAlarmView.SetAlarmPre(true);
}
}
public void CloseValvePressure()
{
try
{
//Console.Beep(5000, 50);
// if (ValvePre)
{
string command = "#" + valvePreAdr + "00\r>\r"; //"#021001\r>\r";
port.Write(command);
ValvePre = false;
ValveAlarmView.SetAlarmPre(false);
}
}
catch (Exception ex)
{
ExceptionLogger.Instance.logExceptionToFile(ex); ;
}
}
public void OpenValveAtm()
{
try
{
// if (!ValveAtm)
{
string command = "#" + valveAtmAdr + "01\r>\r"; //"#021001\r>\r";
port.Write(command);
ValveAtm = true;
ValveAlarmView.SetAlarmAtm(true);
}
}
catch (Exception ex)
{
ExceptionLogger.Instance.logExceptionToFile(ex);;
ValveAlarmView.SetAlarmAtm(true);
}
}
public void CloseValveAtm()
{
try
{
// if (ValveAtm)
{
string command = "#" + valveAtmAdr + "00\r>\r"; //"#021001\r>\r";
port.Write(command);
ValveAtm = false;
ValveAlarmView.SetAlarmAtm(false);
}
}
catch (Exception ex)
{
ExceptionLogger.Instance.logExceptionToFile(ex);;
}
}
public void CloseValveTrans()
{
try
{
// if (ValvePre)
{
string command = "#" + valveTransAdr + "00\r>\r"; //"#021001\r>\r";
port.Write(command);
ValveTrans = false;
ValveAlarmView.SetAlarmTrans(false);
}
}
catch (Exception ex)
{
ExceptionLogger.Instance.logExceptionToFile(ex); ;
}
}
public void OpenValveTrans()
{
try
{
// if (!ValveTrans)
{
string command = "#" + valveTransAdr + "01\r>\r"; //"#021001\r>\r";
port.Write(command);
ValveTrans = true;
ValveAlarmView.SetAlarmTrans(true);
}
}
catch (Exception ex)
{
ExceptionLogger.Instance.logExceptionToFile(ex);
ValveAlarmView.SetAlarmAtm(true);
}
}
public void CloseAllValves()
{
string command = "#" + valvePreAdr + "00\r>\r"; //"#021001\r>\r";
port.Write(command);
command = "#" + valveAtmAdr + "00\r>\r"; //"#021001\r>\r";
port.Write(command);
command = "#" + valveTrans + "00\r>\r"; //"#021001\r>\r";
port.Write(command);
}
}
}
------------------------------------------------------
ValveAlarmView
------------------------------------------------------
using System;
using System.Windows.Forms;
namespace Hysterese
{
public class ValveAlarmView
{
CheckBox checkBoxPre;
CheckBox checkBoxAtm;
CheckBox checkBoxTrans;
private delegate void CheckboxDelegate(bool alarm);
public ValveAlarmView(CheckBox checkBoxPressure, CheckBox checkBoxAtm, CheckBox checkBoxTrans)
{
this.checkBoxPre = checkBoxPressure;
this.checkBoxAtm = checkBoxAtm;
this.checkBoxTrans = checkBoxTrans;
}
public void SetAlarmPre(bool alarm)
{
if (checkBoxPre.InvokeRequired)
checkBoxPre.Invoke(new CheckboxDelegate(SetAlarmPre), alarm);
else
checkBoxPre.Checked = alarm;
}
public void SetAlarmAtm(bool alarm)
{
if (checkBoxAtm.InvokeRequired)
checkBoxAtm.Invoke(new CheckboxDelegate(SetAlarmAtm), alarm);
else
checkBoxAtm.Checked = alarm;
}
public void SetAlarmTrans(bool alarm)
{
if (checkBoxTrans.InvokeRequired)
checkBoxTrans.Invoke(new CheckboxDelegate(SetAlarmTrans), alarm);
else
checkBoxTrans.Checked = alarm;
}
}
}
------------------------------------------------------
ZedGraphClass
------------------------------------------------------
using System;
using ZedGraph;
using System.Data;
using System.Windows.Forms;
using System.Drawing;
namespace Hysterese
{
public class ZedGraphClass
{
ZedGraphControl zgc;
PointPairList list;
private static int listLength=500;
public ZedGraphClass(ZedGraphControl zgc)
{
this.zgc = zgc;
}
public ZedGraphControl zedGraphControl
{
get { return zgc; }
}
public void CreateGraph(string title, string X_axesText, string y_axesText)
{
GraphPane myPane = zgc.GraphPane;
myPane.Title.Text = title;
myPane.XAxis.Title.Text = X_axesText;
myPane.YAxis.Title.Text = y_axesText;
list = new PointPairList();
LineItem myCurve = myPane.AddCurve("Pressure reservoir", list, Color.Blue, SymbolType.Circle);
myCurve.Symbol.Fill = new Fill(Color.White);
myPane.Chart.Fill = new Fill(Color.White, Color.LightGoldenrodYellow, 45F);
myPane.Fill = new Fill(Color.White, Color.FromArgb(220, 220, 255), 45F);
}
public void AddPoint(double x, double y)
{
list.Add(x, y);
if (list.Count > listLength)
list.RemoveAt(0);
zgc.AxisChange();
zgc.Invalidate();
}
public void CreateChart2Axes(string title, string X_axesText, string y_axesText, string y2_axesText)
{
GraphPane myPane = zgc.GraphPane;
// Set the titles and axis labels
myPane.Title.Text = title;
myPane.XAxis.Title.Text = X_axesText;
myPane.YAxis.Title.Text = y_axesText;
myPane.Y2Axis.Title.Text = y2_axesText;
// Make up some data points based on the Sine function
PointPairList waterList = new PointPairList();
PointPairList airList = new PointPairList();
for (int i = 0; i < 36; i++)
{
double x = (double)i * 5.0;
double y = Math.Sin((double)i * Math.PI / 15.0) * 16.0;
double y2 = y * 13.5;
waterList.Add(x, y);
airList.Add(x, y2);
}
// Generate a red curve with diamond symbols, and "Alpha" in the legend
LineItem myCurve = myPane.AddCurve("Air", waterList, Color.Red, SymbolType.Diamond);
// Fill the symbols with white
myCurve.Symbol.Fill = new Fill(Color.White);
// Generate a blue curve with circle symbols, and "Beta" in the legend
myCurve = myPane.AddCurve("water", airList, Color.Blue, SymbolType.Circle);
// Fill the symbols with white
myCurve.Symbol.Fill = new Fill(Color.White);
// Associate this curve with the Y2 axis
myCurve.IsY2Axis = true;
// Show the x axis grid
myPane.XAxis.MajorGrid.IsVisible = true;
// Make the Y axis scale red
myPane.YAxis.Scale.FontSpec.FontColor = Color.Red;
myPane.YAxis.Title.FontSpec.FontColor = Color.Red;
// turn off the opposite tics so the Y tics don't show up on the Y2 axis
myPane.YAxis.MajorTic.IsOpposite = false;
myPane.YAxis.MinorTic.IsOpposite = false;
// Don't display the Y zero line
myPane.YAxis.MajorGrid.IsZeroLine = false;
// Align the Y axis labels so they are flush to the axis
myPane.YAxis.Scale.Align = AlignP.Inside;
// Enable the Y2 axis display
myPane.Y2Axis.IsVisible = true;
// Make the Y2 axis scale blue
myPane.Y2Axis.Scale.FontSpec.FontColor = Color.Blue;
myPane.Y2Axis.Title.FontSpec.FontColor = Color.Blue;
// turn off the opposite tics so the Y2 tics don't show up on the Y axis
myPane.Y2Axis.MajorTic.IsOpposite = false;
myPane.Y2Axis.MinorTic.IsOpposite = false;
// Display the Y2 axis grid lines
myPane.Y2Axis.MajorGrid.IsVisible = true;
// Align the Y2 axis labels so they are flush to the axis
myPane.Y2Axis.Scale.Align = AlignP.Inside;
// Fill the axis background with a gradient
myPane.Chart.Fill = new Fill(Color.White, Color.LightGray, 45.0f);
// Calculate the Axis Scale Ranges
zgc.AxisChange();
}
}
}
------------------------------------------------------
ZedGraphClass
------------------------------------------------------