{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.core.display import display, HTML\n", "display(HTML(\"\"))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import pandas as pd\n", "import numpy as np\n", "import math\n", "import scipy\n", "\n", "from __future__ import print_function\n", "from ipywidgets import interact, interactive, fixed, interact_manual\n", "import ipywidgets as widgets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Read in Measurements" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "two_k_sampling_trafo = pd.read_csv(r'2000OhmSamplingTrafoSupply.csv')\n", "one_k_sampling_trafo = pd.read_csv(r'1000OhmSamplingTrafoSupply.csv')\n", "temperature_measurement = pd.read_csv(r'TempSamplingTrafoSupply.csv')\n", "constant_sampling = pd.read_csv(r'1000OhmSampling.csv')\n", "shielded_df = pd.read_csv(r'ContactPT1000HeatgunCooldown.csv')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Calculation Function for $\\vartheta(R_{PT1000})$\n", "$\\vartheta(R_{PT1000}) = \\frac{-\\alpha R_0 + \\sqrt{\\alpha^2R_0^2 - 4\\beta R_0 \\left(R_0 - R_{PT1000}\\right)}}{2\\beta R_0}$\n", "\n", "with\n", "* $\\alpha = 3.9083 \\cdot 10^{-3}$\n", "* $\\beta = -5.7750 \\cdot 10^{-7}$\n", "* $R_0 = 1000~\\Omega$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "R_zero = 1000.0\n", "A = 3.9083E-3\n", "B = -5.7750E-7\n", "\n", "def calc_temp(resistance):\n", " temp = (-R_zero * A + np.sqrt(R_zero*R_zero * A * A - 4* R_zero * B * (R_zero - resistance)))/(2*R_zero*B)\n", " return temp" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Description of ADC Value" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(constant_sampling['adc_results.pa2_raw'].describe())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "--------------------\n", "# Calculate Temperature from Resistance Value" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def calculate_temp_for_df(data_frame, resistance_col_name='ext_lf_corr', temp_col_name='temp_calculated'):\n", " data_frame[temp_col_name] = data_frame.apply(lambda row: calc_temp(row[resistance_col_name]) , axis=1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "df_list = [one_k_sampling_trafo, two_k_sampling_trafo, temperature_measurement, constant_sampling, shielded_df]\n", "for df in df_list:\n", " calculate_temp_for_df(df)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Histograms -- Starting from Index 100 (Uncalibrated)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, axes = plt.subplots(nrows=3, ncols=3, figsize=(28,20))\n", "plot_data = [(one_k_sampling_trafo, '1 kOhm Sampling Transformer powered', 0), (two_k_sampling_trafo, '2 kOhm Sampling Transformer powered' , 0), (constant_sampling, '1 kOhm Sampling', 100)]\n", "signal_list = [('adc_results.pa2_raw', 20), ('ext_lf_corr', 20), ('temp_calculated', 20)]\n", "\n", "for (data_df, title, start_idx), ax_rows in zip(plot_data, axes):\n", " for ax,sig in zip(ax_rows, signal_list):\n", " n, bins, patches = ax.hist(data_df[sig[0]][start_idx:], sig[1], density=1, color='navy')\n", " mu = np.mean(data_df[sig[0]][start_idx:])\n", " sigma = np.std(data_df[sig[0]][start_idx:])\n", " y = ((1 / (np.sqrt(2 * np.pi) * sigma)) * np.exp(-0.5 * (1 / sigma * (bins - mu))**2))\n", " ax.plot(bins, y, color='darkorange')\n", " ax.set_title(title)\n", " ax.set_ylabel(sig[0] + ' probability (normalized)')\n", " ax.set_xlabel(sig[0])\n", " # Plot sigma and mu lines\n", " ax.axvline(x=mu-sigma, ls='--', color='magenta')\n", " ax.axvline(x=mu+sigma, ls='--', color='magenta')\n", " ax.axvline(x=mu, ls='--', color='lawngreen')\n", " \n", " #Plot textbox\n", " textstr = '\\n'.join((\n", " r'$\\mu=%.2f$' % (mu, ),\n", " r'$\\sigma=%.2f$' % (sigma, )))\n", " props = dict(boxstyle='round', facecolor='wheat', alpha=0.5)\n", " ax.text(0.05, 0.95, textstr, transform=ax.transAxes, fontsize=14,\n", " verticalalignment='top', bbox=props)\n", "\n", " \n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Startup of Moving Average Filter with $\\alpha' = 0.005$\n", "\n", "Filter difference equation: $y[n] = (1-\\alpha')y[n-1] + \\alpha'x[n]$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(nrows=2, ncols=1, figsize=(28,6), sharex=True)\n", "data = constant_sampling['ext_lf_corr'][:20]\n", "ax[0].plot(constant_sampling['Time'][:20], data)\n", "ax[1].plot(constant_sampling['Time'][:20], constant_sampling['temp_calculated'][:20])\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Temperature Plotting\n", "\n", "Noise is visible as soon as the temperature sensor is touched or connected to ground in an improper way." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "idx_count = len(temperature_measurement.index)\n", "@interact(low=(0,idx_count -1,10), high=(0, idx_count-1, 10))\n", "def plot_temp(low=0, high=idx_count-1):\n", " fig, ax = plt.subplots(nrows=3, ncols=1, figsize=(28,9*3), sharex=True)\n", " ax[0].plot(temperature_measurement['Time'][low:high], temperature_measurement['adc_results.pa2_raw'][low:high])\n", " ax[1].plot(temperature_measurement['Time'][low:high], temperature_measurement['ext_lf_corr'][low:high])\n", " ax[2].plot(temperature_measurement['Time'][low:high], temperature_measurement['temp_calculated'][low:high])\n", " titles = ['Raw ADC Results', 'Low Pass Filtered Resistance Reading', 'Calculated Low Frequency Temperature']\n", " for i, title in zip(range(0,3), titles):\n", " ax[i].grid()\n", " ax[i].set_title(title)\n", " plt.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Temperature Plotting With Proper Grounding of Circuit and the Cable Shield" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Derivateve of temp\n", "shielded_df['temp_gradient'] = shielded_df['temp_calculated'].diff() / shielded_df['Time'].diff()\n", "\n", "# Low pass filter gradient with moving average\n", "shielded_df['temp_gradient_lf'] = 0.0\n", "shielded_df['temp_gradient_lf_2'] = 0.0\n", "last_grad_lf = 0.0\n", "\n", "alpha = 0.005\n", "delta_alpha = 0.00\n", "zeta = 20\n", "\n", "for index, row in shielded_df.iterrows():\n", " if index == 0:\n", " pass\n", " else:\n", " current_gradient = row['temp_gradient']\n", " if last_grad_lf != 0.0:\n", " alpha_corr = abs(current_gradient) / zeta * delta_alpha\n", " else:\n", " alpha_corr = 0\n", " last_grad_lf = last_grad_lf * (1-(alpha+alpha_corr)) + (alpha+alpha_corr) * current_gradient\n", " shielded_df.at[index, 'temp_gradient_lf'] = last_grad_lf\n", " \n", "# Derivateve of grad is grad2\n", "shielded_df['temp_gradient_lf_2'] = shielded_df['temp_gradient_lf'].diff() / shielded_df['Time'].diff()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Full curve" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(figsize=(28,9))\n", "tau = 25\n", "tau2 = 0\n", "ax.plot(shielded_df['Time'], shielded_df['temp_calculated'], label='Uncalibrated Temperature')\n", "ax.plot(shielded_df['Time'], shielded_df['temp_calculated']+shielded_df['temp_gradient_lf']*tau + shielded_df['temp_gradient_lf_2']*tau2, label=r'PT1 corrected with $\\tau = %f$' % tau)\n", "ax.grid()\n", "ax.legend()\n", "ax.set_title('Temperature measurement with proper ground connection')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Temperature Gradient Noise vs Moving Average\n", "### Time Domain" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(figsize=(28,8))\n", "tau = 30\n", "ax.plot(shielded_df['Time'], shielded_df['temp_gradient'], label=r\"$\\dot{\\vartheta} = \\frac{\\partial\\vartheta}{\\partial t}$\")\n", "ax.plot(shielded_df['Time'], shielded_df['temp_gradient_lf'], label=r'$\\tilde{\\dot{\\vartheta}}$')\n", "ax.legend()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cooldown to Room Temperature in Detail" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig, ax = plt.subplots(figsize=(28,9))\n", "start_time = -320\n", "filtered_cooldown = shielded_df[shielded_df['Time'] > start_time]\n", "ax.plot(filtered_cooldown['Time'], filtered_cooldown['temp_calculated'], label='Measured Cooldown')\n", "ax.plot(filtered_cooldown['Time'], filtered_cooldown['temp_calculated']+filtered_cooldown['temp_gradient_lf']*tau, label='Calculated Exterior Temperature')\n", "ax.grid()\n", "ax.set_title('Cooldown without airflow | Convection has to be taken into account') \n", "plt.show()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.1" } }, "nbformat": 4, "nbformat_minor": 2 }