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-2022 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
55extern double DoubleFromString( const wxString& TextValue );
56
57
58PANEL_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
87void 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" ), list )
93 .BeforeFirst( ' ' );
94
95 if( !value.IsEmpty() )
96 m_textCtrlPlatingPermittivity->SetValue( value );
97}
98
99
100void 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
113void 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
127void 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 ) );
142 m_textCtrlImpedance->SetValue( wxString::Format( "%g", 50.0 ) );
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
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
177}
178
179
181{
182 aCfg->m_ViaSize.hole_diameter = m_textCtrlHoleDia->GetValue();
183 aCfg->m_ViaSize.hole_diameter_units = m_choiceHoleDia->GetSelection();
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();
198 aCfg->m_ViaSize.pulse_rise_time = m_textCtrlRiseTime->GetValue();
199}
200
201
202void 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
268void 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}
const char * name
Definition: DXF_plotter.cpp:56
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
Class PANEL_VIA_SIZE_BASE.
wxTextCtrl * m_textCtrlPlatingResistivity
wxTextCtrl * m_textCtrlClearanceDia
wxStaticText * m_RiseTimeOutput
wxTextCtrl * m_textCtrlPlatingThickness
wxStaticText * m_staticTextWarning
UNIT_SELECTOR_LEN * m_choiceClearanceDia
wxStaticText * m_ViaThermalResistance
wxTextCtrl * m_textCtrlViaLength
wxTextCtrl * m_textCtrlAppliedCurrent
wxTextCtrl * m_textCtrlViaPadDia
wxTextCtrl * m_textCtrlRiseTime
wxStaticText * m_ViaAmpacity
wxStaticText * m_viaResUnits
wxTextCtrl * m_textCtrlHoleDia
wxTextCtrl * m_textCtrlImpedance
wxStaticText * m_viaReactanceUnits
UNIT_SELECTOR_LEN * m_choiceViaPadDia
wxStaticText * m_ViaCapacitance
UNIT_SELECTOR_RESISTOR * m_choiceImpedance
wxStaticText * m_ViaResistance
wxTextCtrl * m_textCtrlTemperatureDiff
wxStaticText * m_Inductance
wxStaticText * m_ViaVoltageDrop
wxTextCtrl * m_textCtrlPlatingPermittivity
wxStaticBitmap * m_viaBitmap
wxStaticText * m_viaResistivityUnits
UNIT_SELECTOR_LEN * m_choiceViaLength
UNIT_SELECTOR_LEN * m_choiceHoleDia
wxStaticText * m_viaTempUnits
wxStaticText * m_Reactance
wxStaticText * m_ViaPowerLoss
UNIT_SELECTOR_LEN * m_choicePlatingThickness
wxStaticText * m_viaThermalResUnits
void OnViaResetButtonClick(wxCommandEvent &event) override
Called when the user clicks the reset button; sets the parameters to their default values.
void SaveSettings(PCB_CALCULATOR_SETTINGS *aCfg) override
Save the settings from the panel.
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.
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.
void LoadSettings(PCB_CALCULATOR_SETTINGS *aCfg) override
Load the settings into the panel.
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)
void OnViaEpsilonR_Button(wxCommandEvent &event) override
Shows a list of current relative dielectric constant(Er) and select a value.
void onUpdateViaCalcErrorText(wxUpdateUIEvent &event) override
Update the Error message in via calculation panel.
void OnViaCalculate(wxCommandEvent &event) override
Called when the user changes any value in the via calculator.
double GetUnitScale() override
Function GetUnitScale.
double GetUnitScale() override
Function GetUnitScale.
wxArrayString StandardResistivityList()
Definition: common_data.cpp:84
wxArrayString StandardRelativeDielectricConstantList()
Definition: common_data.cpp:28
#define _(s)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:401
#define DEFAULT_UNIT_SEL_OHM
#define DEFAULT_UNIT_SEL_MM
double DoubleFromString(const wxString &TextValue)
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
#define UNIT_MIL
Definition: units_scales.h:37