KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_fusing_current.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KICAD, a free EDA CAD application.
3 *
4 * Copyright (C) 1992-2021 Kicad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 3
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20// See equation 9b in this paper:
21// https://adam-research.de/pdfs/TRM_WhitePaper10_AdiabaticWire.pdf
22
23// See equation 8
24//https://scholar.google.com/scholar?hl=en&as_sdt=0%2C5&q=Fusing+of+wires+by+electrical+current&btnG=
25#define ABS_ZERO ( -273.15 )
26
29#include <string_utils.h>
30
32
33#include <i18n_utility.h> // For _HKI definition
34wxString fusing_current_help =
35#include "fusing_current_help.h"
36
37
38PANEL_FUSING_CURRENT::PANEL_FUSING_CURRENT( wxWindow * parent, wxWindowID id,
39 const wxPoint& pos, const wxSize& size,
40 long style, const wxString& name ) :
41PANEL_FUSING_CURRENT_BASE( parent, id, pos, size, style, name )
42{
43 m_ambientUnit->SetLabel( wxT( "°C" ) );
44 m_meltingUnit->SetLabel( wxT( "°C" ) );
45
46 // Set some defaults
47 m_ambientValue->SetValue( wxString::Format( wxT( "%i" ), 25 ) );
48 m_meltingValue->SetValue( wxString::Format( wxT( "%i" ), 1084 ) ); // Value for copper
49 m_meltingValue->SetEditable( false ); // For now, this panel only works for copper.
50 m_widthValue->SetValue( wxString::Format( wxT( "%f" ), 0.1 ) );
51 m_thicknessValue->SetValue( wxString::Format( wxT( "%f" ), 0.035 ) );
52 m_currentValue->SetValue( wxString::Format( wxT( "%f" ), 10.0 ) );
53 m_timeValue->SetValue( wxString::Format( wxT( "%f" ), 0.01 ) );
54
55 // show markdown formula explanation in lower help panel
56 wxString msg;
57 ConvertMarkdown2Html( wxGetTranslation( fusing_current_help ), msg );
58 m_htmlHelp->SetPage( msg );
59
60 // Needed on wxWidgets 3.0 to ensure sizers are correctly set
61 GetSizer()->SetSizeHints( this );
62}
63
64
66{
67}
68
69
71{
72 // Update the HTML window with the help text
74}
75
76
77void PANEL_FUSING_CURRENT::m_onCalculateClick( wxCommandEvent& event )
78{
79 double Tm, Ta, I, W, T, time;
80 bool valid_Tm, valid_Ta, valid_I, valid_W, valid_T, valid_time;
81
82 valid_Tm = m_meltingValue->GetValue().ToDouble( &Tm );
83 valid_Ta = m_ambientValue->GetValue().ToDouble( &Ta );
84 valid_I = m_currentValue->GetValue().ToDouble( &I );
85 valid_W = m_widthValue->GetValue().ToDouble( &W );
86 valid_T = m_thicknessValue->GetValue().ToDouble( &T );
87 valid_time = m_timeValue->GetValue().ToDouble( &time );
88
89 double scalingT, scalingW;
90
91 scalingT = m_thicknessUnit->GetUnitScale();
92 scalingW = m_widthUnit->GetUnitScale();
93 T *= scalingT;
94 W *= scalingW;
95
96 valid_Tm &= std::isfinite( Tm );
97 valid_Ta &= std::isfinite( Ta );
98 valid_I &= std::isfinite( I );
99 valid_W &= std::isfinite( W );
100 valid_T &= std::isfinite( T );
101 valid_time &= std::isfinite( time );
102
103 if( valid_Tm && valid_Ta )
104 {
105 valid_Tm &= ( Tm > Ta );
106 valid_Ta &= ( Tm > Ta ) && ( Ta > ABS_ZERO );
107 }
108
109 valid_I &= ( I > 0 );
110 valid_W &= ( W > 0 );
111 valid_T &= ( T > 0 );
112 valid_time &= ( time > 0 );
113
114 double A = W * T;
115
116 // The energy required for copper to change phase ( fusion ) is 13.05 kJ / mol.
117 // Copper molar mass is 0.06355 kg/mol
118 // => The copper energy required for the phase change is 205.35 kJ / kg
119
120 double latentHeat = 205350.0;
121
122 // The change in enthalpy is deltaH = deltaU + delta P * deltaV
123 // with U the internal energy, P the pressure and V the volume
124 // But for constant pressure, the change in enthalpy is simply the thermal energy
125
126 // Copper specific heat energy is 0.385 kJ / kg / K.
127 // The change in heat energy is then 0.385 kJ / kg per degree.
128
129 double cp = 385; // Heat capacity in J / kg / K
130 double deltaEnthalpy = ( Tm - Ta ) * cp;
131 double density = 8940; // Density of copper to kilogram per cubic meter;
132 double volumicEnergy = density * ( deltaEnthalpy + latentHeat );
133
134 // Equation (3) is equivalent to :
135 // VolumicEnergy * Volume = R * I^2 * t
136 // If we consider the resistivity of copper instead of its resistance:
137 // VolumicEnergy * Volume = resistivity * length / Area * I^2 * t
138 // For a unit length:
139 // VolumicEnergy * Area = resistivity / Area * I^2 * t
140 // We can rewrite it as:
141 // VolumicEnergy * ( Area / I )^2 / resistivity = t
142 // coeff * ( Area / I ) ^2 = t with coeff = VolumicEnergy / resistivity
143
144 // Copper resistivity at 20C ( 293K ) is 1.72e-8 ohm m
145 // Copper temperature coefficient is 0.00393 per degree
146
147 double Ra = ( ( Ta - ABS_ZERO - 293 ) * 0.00393 + 1 ) * 1.72e-8;
148 double Rm = ( ( Tm - ABS_ZERO - 293 ) * 0.00393 + 1 ) * 1.72e-8;
149
150 // Let's consider the average resistivity
151 double R = ( Rm + Ra ) / 2;
152 double coeff = volumicEnergy / R;
153
154 bool valid = valid_I && valid_W && valid_T && valid_Ta && valid_Tm && valid_time;
155
156 if( m_widthRadio->GetValue() )
157 {
158 if( valid )
159 {
160 A = I / sqrt( coeff / time );
161 W = A / T;
162 m_widthValue->SetValue( wxString::Format( wxT( "%f" ), W / scalingW ) );
163 }
164 else
165 {
166 m_widthValue->SetValue( _( "Error" ) );
167 }
168 }
169 else if( m_thicknessRadio->GetValue() )
170 {
171 if( valid )
172 {
173 A = I / sqrt( coeff / time );
174 T = A / W;
175 m_thicknessValue->SetValue( wxString::Format( wxT( "%f" ), T / scalingT ) );
176 }
177 else
178 {
179 m_thicknessValue->SetValue( _( "Error" ) );
180 }
181 }
182 else if( m_currentRadio->GetValue() )
183 {
184 if( valid )
185 {
186 I = A * sqrt( coeff / time );
187 m_currentValue->SetValue( wxString::Format( wxT( "%f" ), I ) );
188 }
189 else
190 {
191 m_currentValue->SetValue( _( "Error" ) );
192 }
193 }
194 else if( m_timeRadio->GetValue() )
195 {
196 if( valid )
197 {
198 time = coeff * A * A / I / I;
199 m_timeValue->SetValue( wxString::Format( wxT( "%f" ), time ) );
200 }
201 else
202 {
203 m_timeValue->SetValue( _( "Error" ) );
204 }
205 }
206 else
207 {
208 // What happened ??? an extra radio button ?
209 }
210
211 // Now let's check the validity domain using the formula from the paper.
212 // https://adam-research.de/pdfs/TRM_WhitePaper10_AdiabaticWire.pdf
213 // We approximate the track with a circle having the same area.
214
215 double r = sqrt( A / M_PI ); // radius in m;
216 double epsilon = 5.67e-8; // Stefan-Boltzmann constant in W / ( m^2 K^4 )
217 double sigma = 0.5; // Surface radiative emissivity ( no unit )
218 // sigma is according to paper, between polished and oxidized
219
220 double tmKelvin = Tm - ABS_ZERO;
221 double frad = 0.5 * ( tmKelvin + 293 ) * ( tmKelvin + 293 ) * ( tmKelvin + 293 );
222
223 double tau = cp * density * r / ( epsilon * sigma * frad * 2 );
224
225 if( 2 * time < tau )
226 {
227 m_comment->SetLabel( "" );
228 }
229 else
230 {
231 m_comment->SetLabel( _( "Current calculation is underestimated due to long fusing time."
232 ) );
233 }
234}
const char * name
Definition: DXF_plotter.cpp:57
void ThemeChanged()
Definition: html_window.cpp:75
Class PANEL_FUSING_CURRENT_BASE.
UNIT_SELECTOR_THICKNESS * m_thicknessUnit
void ThemeChanged() override
Update UI elements of the panel when the theme changes to ensure the images and fonts/colors are appr...
void m_onCalculateClick(wxCommandEvent &event) override
PANEL_FUSING_CURRENT(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
double GetUnitScale() override
Function GetUnitScale.
double GetUnitScale() override
Function GetUnitScale.
#define _(s)
Some functions to handle hotkeys in KiCad.
#define I(x, y, z)
Definition: md5_hash.cpp:18
#define ABS_ZERO
const double epsilon
void ConvertMarkdown2Html(const wxString &aMarkdownInput, wxString &aHtmlOutput)