diff --git a/TBF/Properties/AssemblyInfo.cs b/TBF/Properties/AssemblyInfo.cs index b26b82e55..5e23762d7 100644 --- a/TBF/Properties/AssemblyInfo.cs +++ b/TBF/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ using System.Runtime.InteropServices; // Build Number // Revision // -[assembly: AssemblyVersion("3.1.1636.0")] -[assembly: AssemblyFileVersion("3.1.1636.0")] +[assembly: AssemblyVersion("3.1.1638.0")] +[assembly: AssemblyFileVersion("3.1.1638.0")] diff --git a/TBF/Rig/Modbus/Common/Modbus.cs b/TBF/Rig/Modbus/Common/Modbus.cs index cd58e5560..9b555ba5a 100644 --- a/TBF/Rig/Modbus/Common/Modbus.cs +++ b/TBF/Rig/Modbus/Common/Modbus.cs @@ -199,6 +199,31 @@ namespace TBF.Rig.Modbus.Common { for (int candidateLen = MinTelegramLen; candidateLen <= dataToProcess.Length; candidateLen++) { + if (candidateLen == 28 && + dataToProcess[0] == '\r' && + dataToProcess[1] == '\n' && + dataToProcess[3] == 28 && + dataToProcess[5] == 2) + { + int sum = 0; + for (int i = 0; i < 27; i++) sum += dataToProcess[i]; + /// + if (dataToProcess[27] == (sum & 0xFF)) + { + /// Split data in dataToProcess buffer into the verified telegram and newly created dataToProcess + byte[] receivedTelegram = dataToProcess.Take(candidateLen).ToArray(); + dataToProcess = dataToProcess.Skip(candidateLen).ToArray(); + + /// Enqueue + receivedTelegrams[0].Enqueue(receivedTelegram); + + string s = string.Format("{0} - {1} queue size={2}", Name, Telegram.LogTelegram("Received message ", receivedTelegram), receivedTelegrams[0].Count); + Debug.WriteLine(s); + log.Debug(s); + break; /// Quit for loop + } + } + if (Telegram.VerifyTelegramCRC(dataToProcess, candidateLen)) { /// A valid telegram found in dataToProcess buffer diff --git a/TBF/Rig/Modbus/TempMeter/Groch/TempMeter.cs b/TBF/Rig/Modbus/TempMeter/Groch/TempMeter.cs index aa47b61e3..974a575e8 100644 --- a/TBF/Rig/Modbus/TempMeter/Groch/TempMeter.cs +++ b/TBF/Rig/Modbus/TempMeter/Groch/TempMeter.cs @@ -22,7 +22,7 @@ namespace TBF.Rig.Modbus.TempMeter.Groch readonly TempMeterCfg tempMtrCfg; /// - int Idx0 { get { return tempMtrCfg.Idx0; } } /// 0..15 + int Channel { get { return tempMtrCfg.Channel; } } /// 0 .. 7 (7 = TempMeterCfg.ChannelsCount-1) double A1 { get { return tempMtrCfg.A1; } } double A2 { get { return tempMtrCfg.A2; } } double A3 { get { return tempMtrCfg.A3; } } @@ -36,6 +36,8 @@ namespace TBF.Rig.Modbus.TempMeter.Groch readonly Common.Modbus modbus; + static int[] tempRaw = new int[TempMeterCfg.ChannelsCount]; + public bool MsrmntAvailable { get { return true; } } public double MeasuredVal { get { return ReadTemperature(); } } public string AltString { get { return "Invalid format"; } } @@ -90,13 +92,17 @@ namespace TBF.Rig.Modbus.TempMeter.Groch public void Initialize() { } public void RunDeviceBefore() { - if (tempMtrCfg.DebugLevel == Config.Entities.DebugMode.Simulate || + if (Channel != 0 || + tempMtrCfg.DebugLevel == Config.Entities.DebugMode.Simulate || tempMtrCfg.DebugLevel == Config.Entities.DebugMode.FailureDuringOperation) { return; } - if (modbus.ReceivedTelegrams[GrochAddress].Count > 0) + /// + /// Only TempMeter with Channel == 0 communicates via the parent Modbus component + /// + if (modbus.ReceivedTelegrams[0].Count > 0) { byte[] telegram = modbus.ReceivedTelegrams[GrochAddress].Dequeue(); if (telegram.Length == 28) @@ -112,28 +118,39 @@ namespace TBF.Rig.Modbus.TempMeter.Groch telegram[26] == 3 && telegram[27] == checksum) { - /// Swap byte order - int t1 = telegram[10] + 256 * telegram[11]; - int t2 = telegram[12] + 256 * telegram[13]; - int t3 = telegram[14] + 256 * telegram[15]; - int t4 = telegram[16] + 256 * telegram[17]; - int t5 = telegram[18] + 256 * telegram[19]; - int t6 = telegram[20] + 256 * telegram[21]; - int t7 = telegram[22] + 256 * telegram[23]; - int t8 = telegram[24] + 256 * telegram[25]; + if (TempMeterCfg.ChannelsCount > 0) tempRaw[0] = telegram[10] + 256 * telegram[11]; + if (TempMeterCfg.ChannelsCount > 1) tempRaw[1] = telegram[12] + 256 * telegram[13]; + if (TempMeterCfg.ChannelsCount > 2) tempRaw[2] = telegram[14] + 256 * telegram[15]; + if (TempMeterCfg.ChannelsCount > 3) tempRaw[3] = telegram[16] + 256 * telegram[17]; + if (TempMeterCfg.ChannelsCount > 4) tempRaw[4] = telegram[18] + 256 * telegram[19]; + if (TempMeterCfg.ChannelsCount > 5) tempRaw[5] = telegram[20] + 256 * telegram[21]; + if (TempMeterCfg.ChannelsCount > 6) tempRaw[6] = telegram[22] + 256 * telegram[23]; + if (TempMeterCfg.ChannelsCount > 7) tempRaw[7] = telegram[24] + 256 * telegram[25]; - //receivedTemp = System.BitConverter.ToSingle(telegram, 3); - //log.WarnFormat("Temperature: {0}={1}°C", Name, receivedTemp.ToString("F1")); + if (TempMeterCfg.ChannelsCount > 7) + { + log.WarnFormat("Raw temperature values: {0} {1} {2} {3} {4} {5} {6} {7}", + tempRaw[0], tempRaw[1], tempRaw[2], tempRaw[3], tempRaw[4], tempRaw[5], tempRaw[6], tempRaw[7]); + } } } } } public void RunDeviceAfter() { - if ((StateMachine.Time % Constants.ModbusPollPeriod) == (GrochAddress % Constants.ModbusPollPeriod)) /// Each 'ModbusDevices' seconds + if (Channel != 0 || + tempMtrCfg.DebugLevel == Config.Entities.DebugMode.Simulate || + tempMtrCfg.DebugLevel == Config.Entities.DebugMode.FailureDuringOperation) { - byte[] message = new byte[] { 0x20, 0x20, 0x20, 0x20, 0x10, 2, 1, 3, 6, 0x16 }; - modbus.SendMessageGroch(message); + return; + } + + /// + /// Only TempMeter with Channel == 0 communicates via the parent Modbus component + /// + if ((StateMachine.Time % Constants.ModbusPollPeriod) == Constants.ModbusPollPeriod) /// Each 'ModbusDevices' seconds + { + modbus.SendMessageGroch(new byte[] { 0x20, 0x20, 0x20, 0x20, 0x10, 2, 1, 3, 6, 0x16 }); } } public void StopDevice() { } @@ -143,7 +160,9 @@ namespace TBF.Rig.Modbus.TempMeter.Groch { if (Cfg.DebugLevel == Config.Entities.DebugMode.Normal) { - return 0; // Config.Formulas.CorrectedValue((double)ControlBoard.Temperature(Idx0), Corrections); + double raw = Convert.ToDouble(tempRaw[Channel]); + double tempWOCorrection = (((A5 * raw + A4) * raw + A3) * raw + A2) * raw + A1; + return Config.Formulas.CorrectedValue(tempWOCorrection, Corrections); } else if (Cfg.DebugLevel == Config.Entities.DebugMode.Simulate) { diff --git a/TBF/Rig/Modbus/TempMeter/Groch/TempMeterCfg.cs b/TBF/Rig/Modbus/TempMeter/Groch/TempMeterCfg.cs index a0528e8ae..37f7e19c2 100644 --- a/TBF/Rig/Modbus/TempMeter/Groch/TempMeterCfg.cs +++ b/TBF/Rig/Modbus/TempMeter/Groch/TempMeterCfg.cs @@ -24,20 +24,23 @@ namespace TBF.Rig.Modbus.TempMeter.Groch return new Configs.ParamsProvider.ComponentCfgCtrl(this, parents); } + public const int ChannelsCount = 8; + /// /// Serialized parameters /// - public int Idx0; /// 0 (0..15) - public double A1; /// 1 - public double A2; /// 2 - public double A3; /// 3 - public double A4; /// 4 - public double A5; /// 5 - public double DefaultTemp; /// 6 - public string MsrdFormat { get; set; } /// 7 - public Config.Unit MsrdUnit { get; set; } /// 8 - public double MsrdValLimLo { get; set; } /// 9 - public double MsrdValLimHi { get; set; } /// 10 + public int Address; /// 0 0 .. 255 + public int Channel; /// 1 0 .. 7 (7 = TempMeterCfg.ChannelsCount-1) + public double A1; /// 2 + public double A2; /// 3 + public double A3; /// 4 + public double A4; /// 5 + public double A5; /// 6 + public double DefaultTemp; /// 7 + public string MsrdFormat { get; set; } /// 8 + public Config.Unit MsrdUnit { get; set; } /// 9 + public double MsrdValLimLo { get; set; } /// 10 + public double MsrdValLimHi { get; set; } /// 11 /// Calibration info serialized parameters displayed in Metrology tab page public string CalibCertificateNr { get; set; } @@ -82,7 +85,8 @@ namespace TBF.Rig.Modbus.TempMeter.Groch public void InitializeAll() { - Idx0 = 0; + Address = 3; + Channel = 0; A1 = 0; A2 = 0; A3 = 0; @@ -99,17 +103,18 @@ namespace TBF.Rig.Modbus.TempMeter.Groch string[] paramNames = new string[] { - "0-based index", /// 0 - "A1", /// 1 - "A2", /// 2 - "A3", /// 3 - "A4", /// 4 - "A5", /// 5 - "Default temperature", /// 6 - "Display format", /// 7 - "Unit of temperature", /// 8 - "Temperature limit Lo", /// 9 - "Temperature limit Hi", /// 10 + "Address (0 .. 255)", /// 0 + "Channel (0 .. 7)", /// 1 + "A1", /// 2 + "A2", /// 3 + "A3", /// 4 + "A4", /// 5 + "A5", /// 6 + "Default temperature", /// 7 + "Display format", /// 8 + "Unit of temperature", /// 9 + "Temperature limit Lo", /// 10 + "Temperature limit Hi", /// 11 }; public string ParamName(int i) { return paramNames[i]; } public int ParamsCount() { return paramNames.Length; } @@ -120,7 +125,7 @@ namespace TBF.Rig.Modbus.TempMeter.Groch { case 0: var values = new List(); - for (int j = 0; j < 16; j++) values.Add(j.ToString()); + for (int j = 0; j < ChannelsCount; j++) values.Add(j.ToString()); return values; case 8: return new string[] { "°C", "°F", "K" }; @@ -133,21 +138,22 @@ namespace TBF.Rig.Modbus.TempMeter.Groch { switch (i) { - case 0: return Idx0.ToString(); - case 1: return A1.ToString(); - case 2: return A2.ToString(); - case 3: return A3.ToString(); - case 4: return A4.ToString(); - case 5: return A5.ToString(); - case 6: return DefaultTemp.ToString(); - case 7: return MsrdFormat; - case 8: return (MsrdUnit == Unit.K) ? "K" : (MsrdUnit == Unit.F) ? "°F" : "°C"; - case 9: return MsrdValLimLo.ToString(); - case 10: return MsrdValLimHi.ToString(); + case 0: return Address.ToString(); + case 1: return Channel.ToString(); + case 2: return A1.ToString(); + case 3: return A2.ToString(); + case 4: return A3.ToString(); + case 5: return A4.ToString(); + case 6: return A5.ToString(); + case 7: return DefaultTemp.ToString(); + case 8: return MsrdFormat; + case 9: return (MsrdUnit == Unit.K) ? "K" : (MsrdUnit == Unit.F) ? "°F" : "°C"; + case 10: return MsrdValLimLo.ToString(); + case 11: return MsrdValLimHi.ToString(); default: - return string.Format("Name={0}, Parent={1}, Idx0={2}, A1={3}, A2={4}, A3={5}, A4={6}, A5={7}, Default={8}", + return string.Format("Name={0}, Parent={1} Address={2} Channel={3} A1={4} A2={5} A3={6} A4={7} A5={8} Default={9}", Name, (string.IsNullOrEmpty(ParentName) ? "-" : ParentName), - Idx0, A1, A2, A3, A4, A5, DefaultTemp); + Address, Channel, A1, A2, A3, A4, A5, DefaultTemp); } } @@ -155,19 +161,20 @@ namespace TBF.Rig.Modbus.TempMeter.Groch { switch (i) { - case 0: Idx0 = int.Parse(str); return CfgUpdateFlags.RestartRqrd; - case 1: A1 = TBF.Utils.ParseEDouble(str); return CfgUpdateFlags.RestartRqrd; - case 2: A2 = TBF.Utils.ParseEDouble(str); return CfgUpdateFlags.RestartRqrd; - case 3: A3 = TBF.Utils.ParseEDouble(str); return CfgUpdateFlags.RestartRqrd; - case 4: A4 = TBF.Utils.ParseEDouble(str); return CfgUpdateFlags.RestartRqrd; - case 5: A5 = TBF.Utils.ParseEDouble(str); return CfgUpdateFlags.RestartRqrd; - case 6: DefaultTemp = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd; - case 7: MsrdFormat = str; return CfgUpdateFlags.RestartRqrd; - case 8: MsrdUnit = (str == "°K" || str == "K") ? Unit.K - : (str == "°F" || str == "F") ? Unit.F - : Unit.C; return CfgUpdateFlags.RestartRqrd; - case 9: MsrdValLimLo = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd; - case 10: MsrdValLimHi = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd; + case 0: Address = int.Parse(str); return CfgUpdateFlags.RestartRqrd; + case 1: Channel = int.Parse(str); return CfgUpdateFlags.RestartRqrd; + case 2: A1 = TBF.Utils.ParseEDouble(str); return CfgUpdateFlags.RestartRqrd; + case 3: A2 = TBF.Utils.ParseEDouble(str); return CfgUpdateFlags.RestartRqrd; + case 4: A3 = TBF.Utils.ParseEDouble(str); return CfgUpdateFlags.RestartRqrd; + case 5: A4 = TBF.Utils.ParseEDouble(str); return CfgUpdateFlags.RestartRqrd; + case 6: A5 = TBF.Utils.ParseEDouble(str); return CfgUpdateFlags.RestartRqrd; + case 7: DefaultTemp = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd; + case 8: MsrdFormat = str; return CfgUpdateFlags.RestartRqrd; + case 9: MsrdUnit = (str == "°K" || str == "K") ? Unit.K + : (str == "°F" || str == "F") ? Unit.F + : Unit.C; return CfgUpdateFlags.RestartRqrd; + case 10: MsrdValLimLo = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd; + case 11: MsrdValLimHi = TBF.Utils.ParseSDouble(str); return CfgUpdateFlags.RestartRqrd; default: return CfgUpdateFlags.None; } } @@ -181,22 +188,25 @@ namespace TBF.Rig.Modbus.TempMeter.Groch switch (i) { case 0: - if (int.TryParse(str, out idummy) && idummy >= 0 && idummy <= 15) return true; + if (int.TryParse(str, out idummy) && idummy >= 0 && idummy <= 255) return true; break; case 1: + if (int.TryParse(str, out idummy) && idummy >= 0 && idummy < ChannelsCount) return true; + break; case 2: case 3: case 4: case 5: + case 6: if (TBF.Utils.TryParseEDouble(str, out dummy)) return true; break; - case 6: - case 9: + case 7: case 10: + case 11: if (TBF.Utils.TryParseSDouble(str, out dummy)) return true; break; - case 7: return true; - case 8: + case 8: return true; + case 9: if (str == "K" || str == "°K" || str == "°F" || str == "F" || str == "°C" || str == "C") return true; break; default: @@ -226,7 +236,8 @@ namespace TBF.Rig.Modbus.TempMeter.Groch prms.MsrdY = this.MsrdY; prms.MsrdOrient = this.MsrdOrient; - prms.Idx0 = this.Idx0; + prms.Address = this.Address; + prms.Channel = this.Channel; prms.A1 = this.A1; prms.A2 = this.A2; prms.A3 = this.A3; diff --git a/TBF/UI/Bench/Components/ComponentsManagerDlg.cs b/TBF/UI/Bench/Components/ComponentsManagerDlg.cs index b6e1b85ac..fb7175d8e 100644 --- a/TBF/UI/Bench/Components/ComponentsManagerDlg.cs +++ b/TBF/UI/Bench/Components/ComponentsManagerDlg.cs @@ -746,7 +746,7 @@ namespace TBF.UI.Bench.Components else if (cfg is Rig.Modbus.TempMeter.Groch.TempMeterCfg) { (cfg as IChildComponentCfg).ParentName = "CB"; - (cfg as Rig.Modbus.TempMeter.Groch.TempMeterCfg).Idx0 = zeroBasedIdx; + (cfg as Rig.Modbus.TempMeter.Groch.TempMeterCfg).Channel = zeroBasedIdx; return true; } else if (cfg is Rig.Modbus.PressureMeter.Meret.PressureMeterCfg)