Keithley.TempMeter uses ITS90 forms for Platinum resistance thermometer, ver. 2.10.344

This commit is contained in:
Milan Hanajik 2016-08-24 10:49:06 +02:00
parent 581819de9f
commit 1feb3215e5
9 changed files with 284 additions and 54 deletions

View File

@ -18,6 +18,8 @@ namespace TBF.BenchControl
private static readonly int[] Ji;
private static readonly double[] ni;
private static readonly double[] Di;
/// <summary>
/// Constructor
/// </summary>
@ -64,6 +66,24 @@ namespace TBF.BenchControl
0.18228094581404E-23, /// 33
-0.93537087292458E-25, /// 34
};
///
/// Initialize a table to calculate temperature of a platinum thermometer from resistance
///
Di = new double[]
{
439.932854,
472.418020,
37.684494,
7.472018,
2.920828,
0.005184,
-0.963864,
-0.188732,
0.191203,
0.049025,
};
}
/// <summary>
@ -246,5 +266,31 @@ namespace TBF.BenchControl
}
return result;
}
}
/// <summary>
/// Conversion of measured resistance of a platinum thermometer to temperature according to ITS-90
/// </summary>
/// <param name="R">Measured resistance in [°C]</param>
/// <param name="R001C">Calibrated resistance in Ohm at 0.01°C</param>
/// <param name="a7">Calibrated ITS-90 coefficient a7</param>
/// <param name="b7">Calibrated ITS-90 coefficient b7</param>
/// <param name="c7">Calibrated ITS-90 coefficient c7</param>
/// <returns></returns>
public static double PlatinumResistanceTM_ITS90_R2T(double R, double R001C, double a7, double b7, double c7)
{
double w = R / R001C; /// ratio
double r1 = w - 1.0;
double dw = r1 * (a7 + r1 * (b7 + r1 * c7)); /// = a7*r1 + b7*r1^2 + c7*r1^3
double wr = w - dw;
double x = (wr - 2.64) / 1.64;
double sum = 0;
for (int i = Di.Length - 1; i >= 0; i--)
{
sum = sum * x + Di[i];
}
return sum;
}
}
}

View File

@ -36,6 +36,9 @@ namespace TBF.BenchControl.Keithley.Multimeter_2010_RS232
/// Private fields
SerialPort serialPort;
StringBuilder receivedData;
int readAttemptsCount;
IList<int> listOfReadOperations;
IList<int> listOfChannels;
@ -45,9 +48,10 @@ namespace TBF.BenchControl.Keithley.Multimeter_2010_RS232
{
Off,
Start_Reset,
Reset_SwitchCh,
SwitchCh_Read,
Read_SwitchCh,
Reset_SwitchChnl,
SwitchChnl_Read,
Read_Receive,
Receive_SwitchChnl,
}
ScanState scanState;
@ -67,6 +71,9 @@ namespace TBF.BenchControl.Keithley.Multimeter_2010_RS232
multimeterCfg = cfg as MultimeterCfg;
serialPort = null;
receivedData = new StringBuilder();
readAttemptsCount = 0;
Resistance = new double[ChannelTo + 1];
for (int i = 0; i < Resistance.Length; i++) Resistance[i] = 0;
@ -177,6 +184,10 @@ namespace TBF.BenchControl.Keithley.Multimeter_2010_RS232
}
/// <summary>
/// Send an ASCII string, appends <CR><LF> at the end.
/// </summary>
/// <param name="message">ASCII string</param>
public void SendMessage(string message)
{
if (multimeterCfg.DebugLevel == DebugMode.Simulate) return;
@ -188,20 +199,40 @@ namespace TBF.BenchControl.Keithley.Multimeter_2010_RS232
/// <summary>Run this device</summary>
public void RunDeviceBefore()
{
if ((scanState == ScanState.Read_SwitchCh) && (currentChannel >= ChannelFrom) && (currentChannel <= ChannelTo))
receivedData.Append(serialPort.ReadExisting());
if (scanState == ScanState.Read_Receive)
{
string completeStr = serialPort.ReadExisting();
int len = completeStr.Length - 2;
if (len > 0)
if(currentChannel >= ChannelFrom && currentChannel <= ChannelTo)
{
string resStr = completeStr.Substring(0, len);
log.DebugFormat("Received message {0}", resStr);
double res;
if (completeStr.IndexOf("\r\n") == len &&
double.TryParse(resStr, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out res))
int len = receivedData.Length;
if (len >= 2 && receivedData[len - 2] == '\r' && receivedData[len - 1] == '\n')
{
Resistance[currentChannel] = res;
string resStr = receivedData.ToString().Substring(0, len - 2);
log.DebugFormat("Received message {0}", resStr);
/// Check whether there is <CR><LF> at the end of received data and the text before <CR><LF> can be parsed.
double res;
if (Utils.TryParseEDouble(resStr, out res))
{
Resistance[currentChannel] = Math.Abs(res); /// Store the parsed number
log.DebugFormat("Resistance[{0}] = {1}", currentChannel, res);
}
scanState = ScanState.Receive_SwitchChnl;
}
else
{
if (++readAttemptsCount >= 5)
{
scanState = ScanState.Receive_SwitchChnl;
readAttemptsCount = 0;
}
}
}
else
{
scanState = ScanState.Receive_SwitchChnl;
}
}
}
@ -217,11 +248,11 @@ namespace TBF.BenchControl.Keithley.Multimeter_2010_RS232
SendMessage("*RST");
SendMessage("*CLS");
SendMessage(":conf:fres");
scanState = ScanState.Reset_SwitchCh;
scanState = ScanState.Reset_SwitchChnl;
return;
case ScanState.Reset_SwitchCh:
case ScanState.Read_SwitchCh:
case ScanState.Reset_SwitchChnl:
case ScanState.Receive_SwitchChnl:
if (nextChannelIx >= 0 && nextChannelIx < listOfChannels.Count)
{
@ -235,13 +266,15 @@ namespace TBF.BenchControl.Keithley.Multimeter_2010_RS232
nextChannelIx++;
if (nextChannelIx >= listOfChannels.Count) nextChannelIx = 0;
}
scanState = ScanState.SwitchCh_Read;
scanState = ScanState.SwitchChnl_Read;
return;
case ScanState.SwitchCh_Read:
case ScanState.SwitchChnl_Read:
SendMessage(":read?");
scanState = ScanState.Read_SwitchCh;
scanState = ScanState.Read_Receive;
receivedData.Clear();
readAttemptsCount = 0;
return;
default: /// Scanning is off

View File

@ -1,10 +1,8 @@
///
/// Copyright (c) 2016 Sensus Metering Systems
///
using System.IO;
using System.Collections.Generic;
using System;
using System.IO.Ports;
using System.Xml.Serialization;
using TBF.BenchControl.Generic;
namespace TBF.BenchControl.Keithley.Multimeter_2010_RS232

View File

@ -14,26 +14,26 @@ namespace TBF.BenchControl.Keithley.TempMeter
public override string ToString() { return string.Format("ReadTempOp({0},.,{1})", tempMeter.Name, eventDone); }
/// Set by the constructor
TempMeter tempMeter;
Event eventDone;
FloatBox temp;
readonly TempMeter tempMeter;
readonly FloatBox temperature;
readonly Event eventDone;
/// <summary>
/// Events: TempInDone, TempOutDone, TempDivDone or Error
/// </summary>
/// <param name="tempMeter">TempMeter reference</param>
/// <param name="temp">Reference to the variable, value is in degree Celsius</param>
/// <param name="temperature">Reference to the variable, value is in degree Celsius</param>
/// <param name="eventDone">Event to be returned by Run() when completed OK</param>
public ReadTempOp(TempMeter tempMeter, ref FloatBox temp, Event eventDone)
public ReadTempOp(TempMeter tempMeter, ref FloatBox temperature, Event eventDone)
{
if (tempMeter == null) throw new ArgumentNullException("tempMeter");
this.tempMeter = tempMeter;
this.temp = temp;
this.temperature = temperature;
this.eventDone = eventDone;
log.Debug(this.ToString());
}
public ReadTempOp(TempMeter tempMeter, ref FloatBox temp)
: this(tempMeter, ref temp, Event.TempDone)
public ReadTempOp(TempMeter tempMeter, ref FloatBox temperature)
: this(tempMeter, ref temperature, Event.TempDone)
{
}
@ -41,7 +41,7 @@ namespace TBF.BenchControl.Keithley.TempMeter
public void Start()
{
tempMeter.Multimeter.StartReadingMultimeter(tempMeter.Channel);
temp.Val = 0;
temperature.Val = 0;
}
/// <summary>Run this operation</summary>
@ -50,7 +50,7 @@ namespace TBF.BenchControl.Keithley.TempMeter
/// </returns>
public Event Run()
{
temp.Val = tempMeter.ReadTemperature();
temperature.Val = tempMeter.ReadTemperature();
return eventDone;
}

View File

@ -20,6 +20,8 @@ namespace TBF.BenchControl.Keithley.TempMeter
public int Channel { get { return tempMtrCfg.Channel; } } /// 1..5
/// Dictionaries to maintain separate operations for each FloatBox argument
Dictionary<FloatBox, IOperation> operations;
Dictionary<FloatBox, IOperation> operations2;
@ -44,16 +46,23 @@ namespace TBF.BenchControl.Keithley.TempMeter
public float ReadTemperature()
{
double resistance = Multimeter.ReadResistance(Channel);
double resistance = Multimeter.ReadResistance(tempMtrCfg.Channel);
return Resistance2Temperature(resistance);
double temperature = 0;
if (resistance > 0 && resistance < 200)
{
temperature = Formulas.PlatinumResistanceTM_ITS90_R2T(resistance,
tempMtrCfg.R001C,
tempMtrCfg.a7,
tempMtrCfg.b7,
tempMtrCfg.c7);
log.DebugFormat("Ch = {0}, R = {1} Ohm, T = {2} °C", Channel, resistance.ToString("F3"), temperature.ToString("F3"));
}
return (float)temperature;
}
private float Resistance2Temperature(double resistance)
{
return 30.0F + (float)tempMtrCfg.Channel; /// TODO: implement
}
/// <summary>
/// Events: TempDone, Error
/// </summary>
@ -64,10 +73,11 @@ namespace TBF.BenchControl.Keithley.TempMeter
IOperation operation;
if (operations.TryGetValue(temp, out operation))
{
return operation;
return operation; /// Operation already available
}
else
{
/// Create a new operation and store it in the dictionary
operation = new ReadTempOp(this, ref temp);
operations.Add(temp, operation);
return operation;
@ -85,10 +95,11 @@ namespace TBF.BenchControl.Keithley.TempMeter
IOperation operation;
if (operations2.TryGetValue(temp, out operation))
{
return operation;
return operation; /// Operation already available
}
else
{
/// Create a new operation and store it in the dictionary
operation = new ReadTempOp(this, ref temp, tempDone);
operations2.Add(temp, operation);
return operation;

View File

@ -16,7 +16,11 @@ namespace TBF.BenchControl.Keithley.TempMeter
///
/// Serialized parameters
///
public int Channel; /// 1..5
public int Channel; /// 1..5
public double R001C;
public double a7;
public double b7;
public double c7;
/// Private parameterless constructor invoked by all other (public) constructors
TempMeterCfg()
@ -34,10 +38,11 @@ namespace TBF.BenchControl.Keithley.TempMeter
public string ToString(int i)
{
return string.Format("Name={0}, Parent={1}, Channel={2}",
return string.Format("Name={0}, Parent={1}, Channel={2}, R0={3}, a7={4}, b7={5}, c7={6}",
Name,
(string.IsNullOrEmpty(ParentName) ? "-" : ParentName),
Channel);
Channel,
R001C, a7, b7, c7);
}
}
}

View File

@ -38,12 +38,21 @@ namespace TBF.BenchControl.Keithley.TempMeter
this.nameLabel = new System.Windows.Forms.Label();
this.classNameLabel = new System.Windows.Forms.Label();
this.parentNameComboBox = new System.Windows.Forms.ComboBox();
this.r0TextBox = new System.Windows.Forms.TextBox();
this.a7TextBox = new System.Windows.Forms.TextBox();
this.b7TextBox = new System.Windows.Forms.TextBox();
this.c7TextBox = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.its90Label = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// channelTextBox
//
this.channelTextBox.Enabled = false;
this.channelTextBox.Location = new System.Drawing.Point(130, 82);
this.channelTextBox.Location = new System.Drawing.Point(125, 82);
this.channelTextBox.Name = "channelTextBox";
this.channelTextBox.Size = new System.Drawing.Size(46, 20);
this.channelTextBox.TabIndex = 6;
@ -51,7 +60,7 @@ namespace TBF.BenchControl.Keithley.TempMeter
// channelLabel
//
this.channelLabel.AutoSize = true;
this.channelLabel.Location = new System.Drawing.Point(20, 85);
this.channelLabel.Location = new System.Drawing.Point(30, 85);
this.channelLabel.Name = "channelLabel";
this.channelLabel.Size = new System.Drawing.Size(73, 13);
this.channelLabel.TabIndex = 5;
@ -60,7 +69,7 @@ namespace TBF.BenchControl.Keithley.TempMeter
// parentNameLabel
//
this.parentNameLabel.AutoSize = true;
this.parentNameLabel.Location = new System.Drawing.Point(20, 61);
this.parentNameLabel.Location = new System.Drawing.Point(30, 61);
this.parentNameLabel.Name = "parentNameLabel";
this.parentNameLabel.Size = new System.Drawing.Size(69, 13);
this.parentNameLabel.TabIndex = 3;
@ -69,7 +78,7 @@ namespace TBF.BenchControl.Keithley.TempMeter
// nameTextBox
//
this.nameTextBox.Enabled = false;
this.nameTextBox.Location = new System.Drawing.Point(130, 34);
this.nameTextBox.Location = new System.Drawing.Point(125, 34);
this.nameTextBox.Name = "nameTextBox";
this.nameTextBox.Size = new System.Drawing.Size(130, 20);
this.nameTextBox.TabIndex = 2;
@ -77,7 +86,7 @@ namespace TBF.BenchControl.Keithley.TempMeter
// nameLabel
//
this.nameLabel.AutoSize = true;
this.nameLabel.Location = new System.Drawing.Point(20, 37);
this.nameLabel.Location = new System.Drawing.Point(30, 37);
this.nameLabel.Name = "nameLabel";
this.nameLabel.Size = new System.Drawing.Size(35, 13);
this.nameLabel.TabIndex = 1;
@ -86,7 +95,7 @@ namespace TBF.BenchControl.Keithley.TempMeter
// classNameLabel
//
this.classNameLabel.AutoSize = true;
this.classNameLabel.Location = new System.Drawing.Point(127, 10);
this.classNameLabel.Location = new System.Drawing.Point(122, 10);
this.classNameLabel.Name = "classNameLabel";
this.classNameLabel.Size = new System.Drawing.Size(83, 13);
this.classNameLabel.TabIndex = 0;
@ -96,15 +105,101 @@ namespace TBF.BenchControl.Keithley.TempMeter
//
this.parentNameComboBox.Enabled = false;
this.parentNameComboBox.FormattingEnabled = true;
this.parentNameComboBox.Location = new System.Drawing.Point(130, 58);
this.parentNameComboBox.Location = new System.Drawing.Point(125, 58);
this.parentNameComboBox.Name = "parentNameComboBox";
this.parentNameComboBox.Size = new System.Drawing.Size(130, 21);
this.parentNameComboBox.TabIndex = 4;
//
// r0TextBox
//
this.r0TextBox.Enabled = false;
this.r0TextBox.Location = new System.Drawing.Point(125, 137);
this.r0TextBox.Name = "r0TextBox";
this.r0TextBox.Size = new System.Drawing.Size(130, 20);
this.r0TextBox.TabIndex = 7;
//
// a7TextBox
//
this.a7TextBox.Enabled = false;
this.a7TextBox.Location = new System.Drawing.Point(125, 160);
this.a7TextBox.Name = "a7TextBox";
this.a7TextBox.Size = new System.Drawing.Size(130, 20);
this.a7TextBox.TabIndex = 8;
//
// b7TextBox
//
this.b7TextBox.Enabled = false;
this.b7TextBox.Location = new System.Drawing.Point(125, 183);
this.b7TextBox.Name = "b7TextBox";
this.b7TextBox.Size = new System.Drawing.Size(130, 20);
this.b7TextBox.TabIndex = 9;
//
// c7TextBox
//
this.c7TextBox.Enabled = false;
this.c7TextBox.Location = new System.Drawing.Point(125, 206);
this.c7TextBox.Name = "c7TextBox";
this.c7TextBox.Size = new System.Drawing.Size(130, 20);
this.c7TextBox.TabIndex = 10;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(30, 140);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(53, 13);
this.label1.TabIndex = 11;
this.label1.Text = "R(0.01°C)";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(30, 163);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(19, 13);
this.label2.TabIndex = 12;
this.label2.Text = "a7";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(30, 186);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(19, 13);
this.label3.TabIndex = 13;
this.label3.Text = "b7";
//
// its90Label
//
this.its90Label.AutoSize = true;
this.its90Label.Location = new System.Drawing.Point(30, 117);
this.its90Label.Name = "its90Label";
this.its90Label.Size = new System.Drawing.Size(217, 13);
this.its90Label.TabIndex = 14;
this.its90Label.Text = "Calibration coefficients as defined in ITS-90 :";
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(30, 209);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(19, 13);
this.label4.TabIndex = 15;
this.label4.Text = "c7";
//
// TempMeterCfgCtrl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.label4);
this.Controls.Add(this.its90Label);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.c7TextBox);
this.Controls.Add(this.b7TextBox);
this.Controls.Add(this.a7TextBox);
this.Controls.Add(this.r0TextBox);
this.Controls.Add(this.parentNameComboBox);
this.Controls.Add(this.channelTextBox);
this.Controls.Add(this.channelLabel);
@ -129,5 +224,14 @@ namespace TBF.BenchControl.Keithley.TempMeter
private System.Windows.Forms.Label nameLabel;
private System.Windows.Forms.Label classNameLabel;
private System.Windows.Forms.ComboBox parentNameComboBox;
private System.Windows.Forms.TextBox r0TextBox;
private System.Windows.Forms.TextBox a7TextBox;
private System.Windows.Forms.TextBox b7TextBox;
private System.Windows.Forms.TextBox c7TextBox;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label its90Label;
private System.Windows.Forms.Label label4;
}
}

View File

@ -75,6 +75,10 @@ namespace TBF.BenchControl.Keithley.TempMeter
nameTextBox.Text = config.Name;
parentNameComboBox.Text = string.IsNullOrEmpty(config.ParentName) ? "---" : config.ParentName;
channelTextBox.Text = config.Channel.ToString();
r0TextBox.Text = config.R001C.ToString();
a7TextBox.Text = config.a7.ToString();
b7TextBox.Text = config.b7.ToString();
c7TextBox.Text = config.c7.ToString();
}
public void Unlock()
@ -82,6 +86,10 @@ namespace TBF.BenchControl.Keithley.TempMeter
nameTextBox.Enabled = true;
parentNameComboBox.Enabled = true;
channelTextBox.Enabled = true;
r0TextBox.Enabled = true;
a7TextBox.Enabled = true;
b7TextBox.Enabled = true;
c7TextBox.Enabled = true;
}
public CfgUpdateFlags VerifyCfg(ref string message)
@ -99,6 +107,27 @@ namespace TBF.BenchControl.Keithley.TempMeter
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "'Channel' should be in the range 1 .. 5";
}
double ddummy;
if (!Utils.TryParseUDouble(r0TextBox.Text, out ddummy))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "Invalid 'R(0.01°C)'";
}
if (!Utils.TryParseSDouble(a7TextBox.Text, out ddummy))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "Invalid 'a7'";
}
if (!Utils.TryParseSDouble(b7TextBox.Text, out ddummy))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "Invalid 'b7'";
}
if (!Utils.TryParseSDouble(c7TextBox.Text, out ddummy))
{
flags |= CfgUpdateFlags.Error;
message += Environment.NewLine + "Invalid 'c7'";
}
return flags;
}
@ -112,6 +141,10 @@ namespace TBF.BenchControl.Keithley.TempMeter
config.Name = nameTextBox.Text;
config.ParentName = parentNameComboBox.Text.Equals("---") ? string.Empty : parentNameComboBox.Text;
config.Channel = int.Parse(channelTextBox.Text);
config.R001C = Utils.ParseUDouble(r0TextBox.Text);
config.a7 = Utils.ParseSDouble(a7TextBox.Text);
config.b7 = Utils.ParseSDouble(b7TextBox.Text);
config.c7 = Utils.ParseSDouble(c7TextBox.Text);
return flags;
}

View File

@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
// Build Number
// Revision
//
[assembly: AssemblyVersion("2.10.343.1")]
[assembly: AssemblyFileVersion("2.10.343.1")]
[assembly: AssemblyVersion("2.10.344.1")]
[assembly: AssemblyFileVersion("2.10.344.1")]