KiCad PCB EDA Suite
panel_via_size.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 /* All calculations are based on this [1] online calculator:
21  *
22  * References:
23  *
24  * [1]: The CircuitCalculator.com Blog - PCB Via Calculator
25  * http://circuitcalculator.com/wordpress/2006/03/12/pcb-via-calculator/
26  *
27  * [2]: Constructing Your Power Supply - Layout Considerations
28  * https://www.ti.com/seclit/ml/slup230/slup230.pdf
29  *
30  * [3]: Current Carrying Capacity of Vias - Some Conceptual Observations
31  * https://www.ultracad.com/articles/viacurrents.pdf
32  *
33  * [4]: IPC-2221A - Generic Standard on Printed Board Design
34  * http://www.sphere.bc.ca/class/downloads/ipc_2221a-pcb%20standards.pdf
35  *
36  * [5]: Copper - online catalogue source - Goodfellow
37  * http://www.goodfellow.com/E/Copper.html
38  *
39  * [6]: Thermal Conductivity of Metals, Metallic Elements and Alloys
40  * https://www.engineeringtoolbox.com/thermal-conductivity-metals-d_858.html
41  *
42  * [7]: Johnson & Graham, High Speed Digital Design: A Handbook of Black Magic
43  */
44 
45 #include <cmath>
46 #include <wx/choicdlg.h>
47 
48 #include <bitmaps.h>
50 #include <common_data.h>
52 #include <units_scales.h>
53 
54 
55 extern double DoubleFromString( const wxString& TextValue );
56 
57 
58 PANEL_VIA_SIZE::PANEL_VIA_SIZE( wxWindow* parent, wxWindowID id,
59  const wxPoint& pos, const wxSize& size,
60  long style, const wxString& name ) :
61  PANEL_VIA_SIZE_BASE( parent, id, pos, size, style, name )
62 {
63  m_viaResistivityUnits->SetLabel( wxT( "Ω⋅m" ) );
64  m_viaTempUnits->SetLabel( wxT( "°C" ) );
65  m_viaResUnits->SetLabel( wxT( "Ω" ) );
66  m_viaThermalResUnits->SetLabel( wxT( "°C/W" ) );
67  m_viaReactanceUnits->SetLabel( wxT( "Ω" ) );
68 
69  m_viaBitmap->SetBitmap( KiBitmap( BITMAPS::viacalc ) );
70 
71  // Needed on wxWidgets 3.0 to ensure sizers are correctly set
72  GetSizer()->SetSizeHints( this );
73 }
74 
75 
77 {
78 }
79 
80 
82 {
83  m_viaBitmap->SetBitmap( KiBitmap( BITMAPS::viacalc ) );
84 }
85 
86 
87 void PANEL_VIA_SIZE::OnViaEpsilonR_Button( wxCommandEvent& event )
88 {
89  //Shows a list of current relative dielectric constant(Er) and select a value.
90  wxArrayString list = StandardRelativeDielectricConstantList();
91 
92  wxString value = wxGetSingleChoice( wxEmptyString, _("Relative Dielectric Constants"),
93  list).BeforeFirst( ' ' );
94 
95  if( !value.IsEmpty() )
96  m_textCtrlPlatingPermittivity->SetValue( value );
97 }
98 
99 
100 void PANEL_VIA_SIZE::OnViaRho_Button( wxCommandEvent& event )
101 {
102  wxArrayString list = StandardResistivityList();
103 
104  // Shows a list of current Specific resistance list (rho) and select a value
105  wxString value = wxGetSingleChoice( wxEmptyString, _( "Electrical Resistivity in Ohm*m" ),
106  list ).BeforeFirst( ' ' );
107 
108  if( !value.IsEmpty() )
109  m_textCtrlPlatingResistivity->SetValue( value );
110 }
111 
112 
113 void PANEL_VIA_SIZE::onUpdateViaCalcErrorText( wxUpdateUIEvent& event )
114 {
115  // Update the Error message if a via has a external diameter
116  // bigger than the clearance area diameter
117  // (therefore the via is inside a copper zone and some parameters cannot be calculated)
118  double clearanceDia = std::abs( DoubleFromString( m_textCtrlClearanceDia->GetValue() ) );
119  clearanceDia *= m_choiceClearanceDia->GetUnitScale();
120  double padDia = std::abs( DoubleFromString( m_textCtrlViaPadDia->GetValue() ) );
121  padDia *= m_choiceViaPadDia->GetUnitScale();
122 
123  m_staticTextWarning->Show( clearanceDia <= padDia );
124 }
125 
126 
127 void PANEL_VIA_SIZE::OnViaResetButtonClick( wxCommandEvent& event )
128 {
129  #define DEFAULT_UNIT_SEL_MM 0
130  #define DEFAULT_UNIT_SEL_OHM 0
131 
132  m_textCtrlHoleDia->SetValue( wxString::Format( "%g", 0.4 ) );
133  m_choiceHoleDia->SetSelection( DEFAULT_UNIT_SEL_MM );
134  m_textCtrlPlatingThickness->SetValue( wxString::Format( "%g", 0.035 ) );
136  m_textCtrlViaLength->SetValue( wxString::Format( "%g", 1.6 ) );
137  m_choiceViaLength->SetSelection( DEFAULT_UNIT_SEL_MM );
138  m_textCtrlViaPadDia->SetValue( wxString::Format( "%g", 0.6 ) );
139  m_choiceViaPadDia->SetSelection( DEFAULT_UNIT_SEL_MM );
140  m_textCtrlClearanceDia->SetValue( wxString::Format( "%g", 1.0 ) );
141  m_choiceClearanceDia->SetSelection( DEFAULT_UNIT_SEL_MM );
142  m_textCtrlImpedance->SetValue( wxString::Format( "%g", 50.0 ) );
143  m_choiceImpedance->SetSelection( DEFAULT_UNIT_SEL_OHM );
144  m_textCtrlAppliedCurrent->SetValue( wxString::Format( "%g", 1.0 ) );
145  m_textCtrlPlatingResistivity->SetValue( wxString::Format( "%g", 1.72e-8 ) );
146  m_textCtrlPlatingPermittivity->SetValue( wxString::Format( "%g", 4.5 ) );
147  m_textCtrlTemperatureDiff->SetValue( wxString::Format( "%g", 10.0 ) );
148  m_textCtrlRiseTime->SetValue( wxString::Format( "%g", 1.0 ) );
149 }
150 
151 
153 {
154  m_textCtrlHoleDia->SetValue( aCfg->m_ViaSize.hole_diameter );
155  m_choiceHoleDia->SetSelection( aCfg->m_ViaSize.hole_diameter_units );
156 
158  m_choicePlatingThickness->SetSelection( aCfg->m_ViaSize.thickness_units );
159 
160  m_textCtrlViaLength->SetValue( aCfg->m_ViaSize.length );
161  m_choiceViaLength->SetSelection( aCfg->m_ViaSize.length_units );
162 
163  m_textCtrlViaPadDia->SetValue( aCfg->m_ViaSize.pad_diameter );
164  m_choiceViaPadDia->SetSelection( aCfg->m_ViaSize.pad_diameter_units );
165 
168 
171 
175  m_textCtrlTemperatureDiff->SetValue( aCfg->m_ViaSize.temp_rise );
176  m_textCtrlRiseTime->SetValue( aCfg->m_ViaSize.pulse_rise_time );
177 }
178 
179 
181 {
182  aCfg->m_ViaSize.hole_diameter = m_textCtrlHoleDia->GetValue();
183  aCfg->m_ViaSize.hole_diameter_units = m_choiceHoleDia->GetSelection();
184  aCfg->m_ViaSize.thickness = m_textCtrlPlatingThickness->GetValue();
185  aCfg->m_ViaSize.thickness_units = m_choicePlatingThickness->GetSelection();
186  aCfg->m_ViaSize.length = m_textCtrlViaLength->GetValue();
187  aCfg->m_ViaSize.length_units = m_choiceViaLength->GetSelection();
188  aCfg->m_ViaSize.pad_diameter = m_textCtrlViaPadDia->GetValue();
189  aCfg->m_ViaSize.pad_diameter_units = m_choiceViaPadDia->GetSelection();
197  aCfg->m_ViaSize.temp_rise = m_textCtrlTemperatureDiff->GetValue();
198  aCfg->m_ViaSize.pulse_rise_time = m_textCtrlRiseTime->GetValue();
199 }
200 
201 
202 void PANEL_VIA_SIZE::OnViaCalculate( wxCommandEvent& event )
203 {
204  // Load parameters
205  double finishedHoleDia = std::abs( DoubleFromString( m_textCtrlHoleDia->GetValue() ) );
206  double platingThickness = std::abs( DoubleFromString( m_textCtrlPlatingThickness->GetValue() ) );
207  double viaLength = std::abs( DoubleFromString( m_textCtrlViaLength->GetValue() ) );
208  double padDia = std::abs( DoubleFromString( m_textCtrlViaPadDia->GetValue() ) );
209  double clearanceDia = std::abs( DoubleFromString( m_textCtrlClearanceDia->GetValue() ) );
210  double charImpedance = std::abs( DoubleFromString( m_textCtrlImpedance->GetValue() ) );
211  double appliedCurrent = std::abs( DoubleFromString( m_textCtrlAppliedCurrent->GetValue() ) );
212  double platingResistivity = std::abs( DoubleFromString( m_textCtrlPlatingResistivity->GetValue() ) );
213  double relativePermitivity = std::abs( DoubleFromString( m_textCtrlPlatingPermittivity->GetValue() ) );
214  double temperatureDiff = std::abs( DoubleFromString( m_textCtrlTemperatureDiff->GetValue() ) );
215  double pulseRiseTime = std::abs( DoubleFromString( m_textCtrlRiseTime->GetValue() ) );
216 
217  // Normalize units
218  finishedHoleDia *= m_choiceHoleDia->GetUnitScale();
219  platingThickness *= m_choicePlatingThickness->GetUnitScale();
220  viaLength *= m_choiceViaLength->GetUnitScale();
221  padDia *= m_choiceViaPadDia->GetUnitScale();
222  clearanceDia *= m_choiceClearanceDia->GetUnitScale();
223  charImpedance *= m_choiceImpedance->GetUnitScale();
224  // platingResistivity is ok: it is in Ohm*m in tables
225 
226  // Calculate cross-sectional area of the via's cylindrical structure [3]
227  double area = M_PI * (finishedHoleDia + platingThickness) * platingThickness; // m^2
228 
229  double viaResistance = platingResistivity * viaLength / area; // Ohms
230 
231  // Using thermal resistivity value 2.49e-3 meter-Kelvin/Watt, equivalent to
232  // thermal conductivity of 401 Watt/(meter-Kelvin) [5][6]
233  const double thermalResistivity = 2.49e-3; // m K/W
234  double thermalResistance = thermalResistivity * viaLength / area; // deg C/W
235 
236  double voltageDrop = appliedCurrent * viaResistance;
237 
238  double powerLoss = appliedCurrent * voltageDrop;
239 
240  // Estimate current carrying capacity of the via
241  // See comment #17 in [1] for a brief discussion on the formula
242  // This formula from IPC-2221 [4] is also used in the Track Width calculator
243  area /= pow( UNIT_MIL, 2 ); // m^2 to mil^2
244  const double k = 0.048;
245  const double b = 0.44;
246  const double c = 0.725;
247  double estimatedAmpacity = k * pow( temperatureDiff, b ) * pow( area, c );
248 
249  // Equation 7.6 in [7]
250  double capacitance = 55.51 * relativePermitivity * viaLength * padDia;
251  capacitance /= clearanceDia - padDia;
252 
253  // Equation 7.8 in [7]
254  double timeDegradation = 2.2 * capacitance * charImpedance / 2;
255 
256  // Equation 7.9 in [7]
257  double inductance = 200 * viaLength;
258  inductance *= log( 4 * viaLength / finishedHoleDia ) + 1;
259 
260  // Equation 7.11 in [7]
261  double reactance = M_PI * inductance / pulseRiseTime;
262 
263  // Update the display
264  VSDisplayValues( viaResistance, voltageDrop, powerLoss, estimatedAmpacity,
265  thermalResistance, capacitance, timeDegradation, inductance, reactance );
266 }
267 
268 void PANEL_VIA_SIZE::VSDisplayValues( double aViaResistance, double aVoltageDrop, double aPowerLoss,
269  double aEstimatedAmpacity, double aThermalResistance,
270  double aCapacitance, double aTimeDegradation, double aInductance,
271  double aReactance )
272 {
273  wxString msg;
274 
275  msg.Printf( "%g", aViaResistance );
276  m_ViaResistance->SetLabel( msg );
277 
278  msg.Printf( "%g", aVoltageDrop );
279  m_ViaVoltageDrop->SetLabel( msg );
280 
281  msg.Printf( "%g", aPowerLoss );
282  m_ViaPowerLoss->SetLabel( msg );
283 
284  msg.Printf( "%g", aEstimatedAmpacity );
285  m_ViaAmpacity->SetLabel( msg );
286 
287  msg.Printf( "%g", aThermalResistance );
288  m_ViaThermalResistance->SetLabel( msg );
289 
290  msg.Printf( "%g", aCapacitance );
291  m_ViaCapacitance->SetLabel( msg );
292 
293  msg.Printf( "%g", aTimeDegradation );
294  m_RiseTimeOutput->SetLabel( msg );
295 
296  msg.Printf( "%g", aInductance );
297  m_Inductance->SetLabel( msg );
298 
299  msg.Printf( "%g", aReactance );
300  m_Reactance->SetLabel( msg );
301 }
void SaveSettings(PCB_CALCULATOR_SETTINGS *aCfg) override
Save the settings from the panel.
wxStaticText * m_ViaResistance
wxStaticText * m_ViaCapacitance
wxArrayString StandardRelativeDielectricConstantList()
Definition: common_data.cpp:28
wxTextCtrl * m_textCtrlRiseTime
wxStaticText * m_RiseTimeOutput
wxTextCtrl * m_textCtrlTemperatureDiff
PANEL_VIA_SIZE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
wxTextCtrl * m_textCtrlPlatingPermittivity
void LoadSettings(PCB_CALCULATOR_SETTINGS *aCfg) override
Load the settings into the panel.
#define DEFAULT_UNIT_SEL_OHM
wxTextCtrl * m_textCtrlViaPadDia
double DoubleFromString(const wxString &TextValue)
wxTextCtrl * m_textCtrlHoleDia
UNIT_SELECTOR_LEN * m_choiceViaLength
wxTextCtrl * m_textCtrlPlatingResistivity
UNIT_SELECTOR_LEN * m_choiceViaPadDia
wxStaticText * m_staticTextWarning
wxTextCtrl * m_textCtrlViaLength
void OnViaEpsilonR_Button(wxCommandEvent &event) override
Shows a list of current relative dielectric constant(Er) and select a value.
double GetUnitScale() override
Function GetUnitScale.
wxStaticText * m_viaResUnits
wxStaticText * m_viaThermalResUnits
void ThemeChanged() override
Update UI elements of the panel when the theme changes to ensure the images and fonts/colors are appr...
void OnViaRho_Button(wxCommandEvent &event) override
Shows a list of current Specific resistance list (rho) and select a value.
wxStaticText * m_viaTempUnits
wxTextCtrl * m_textCtrlImpedance
UNIT_SELECTOR_LEN * m_choiceHoleDia
wxStaticText * m_viaReactanceUnits
UNIT_SELECTOR_LEN * m_choicePlatingThickness
#define _(s)
wxArrayString StandardResistivityList()
Definition: common_data.cpp:84
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition: bitmap.cpp:105
wxStaticText * m_ViaAmpacity
wxStaticText * m_Inductance
void OnViaResetButtonClick(wxCommandEvent &event) override
Called when the user clicks the reset button; sets the parameters to their default values.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
Class PANEL_VIA_SIZE_BASE.
#define DEFAULT_UNIT_SEL_MM
void VSDisplayValues(double aViaResistance, double aVoltageDrop, double aPowerLoss, double aEstimatedAmpacity, double aThermalResistance, double aCapacitance, double aTimeDegradation, double aInductance, double aReactance)
Display the results of the calculation.
wxStaticText * m_Reactance
const char * name
Definition: DXF_plotter.cpp:56
double GetUnitScale() override
Function GetUnitScale.
void onUpdateViaCalcErrorText(wxUpdateUIEvent &event) override
Update the Error message in via calculation panel.
UNIT_SELECTOR_RESISTOR * m_choiceImpedance
wxTextCtrl * m_textCtrlClearanceDia
wxTextCtrl * m_textCtrlPlatingThickness
wxStaticText * m_ViaPowerLoss
void OnViaCalculate(wxCommandEvent &event) override
Called when the user changes any value in the via calculator.
#define UNIT_MIL
Definition: units_scales.h:35
wxStaticText * m_viaResistivityUnits
wxStaticText * m_ViaVoltageDrop
wxTextCtrl * m_textCtrlAppliedCurrent
wxStaticText * m_ViaThermalResistance
wxStaticBitmap * m_viaBitmap
UNIT_SELECTOR_LEN * m_choiceClearanceDia