KiCad PCB EDA Suite
pcb_calculator/via.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-2019 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/wx.h>
47 
48 #include <kiface_i.h>
49 #include <pcb_calculator.h>
51 #include <UnitSelector.h>
52 #include <units_scales.h>
53 
54 #include <common_data.h>
55 
56 extern double DoubleFromString( const wxString& TextValue );
57 
62 void PCB_CALCULATOR_FRAME::OnViaEpsilonR_Button( wxCommandEvent& event )
63 {
64  wxArrayString list = StandardRelativeDielectricConstantList();
65 
66  wxString value = wxGetSingleChoice( wxEmptyString,
67  _("Relative Dielectric Constants"), list).BeforeFirst( ' ' );
68  if( ! value.IsEmpty() )
69  m_textCtrlPlatingPermittivity->SetValue( value );
70 }
71 
76 void PCB_CALCULATOR_FRAME::OnViaRho_Button( wxCommandEvent& event )
77 {
78  wxArrayString list = StandardResistivityList();
79 
80  wxString value = wxGetSingleChoice( wxEmptyString,
81  _("Electrical Resistivity in Ohm*m"), list).BeforeFirst( ' ' );
82  if( ! value.IsEmpty() )
83  m_textCtrlPlatingResistivity->SetValue( value );
84 }
85 
86 
87 void PCB_CALCULATOR_FRAME::onUpdateViaCalcErrorText( wxUpdateUIEvent& event )
88 {
89  // Update the Error message if a via has a external diameter
90  // bigger than the clearance area diameter
91  // (therefore the via is inside a copper zone and some parameters cannot be calculated)
92  double clearanceDia = std::abs( DoubleFromString( m_textCtrlClearanceDia->GetValue() ) );
93  clearanceDia *= m_choiceClearanceDia->GetUnitScale();
94  double padDia = std::abs( DoubleFromString( m_textCtrlViaPadDia->GetValue() ) );
95  padDia *= m_choiceViaPadDia->GetUnitScale();
96 
97  m_staticTextWarning->Show( clearanceDia <= padDia );
98 }
99 
100 
101 void PCB_CALCULATOR_FRAME::OnViaResetButtonClick( wxCommandEvent& event )
102 {
103  #define DEFAULT_UNIT_SEL_MM 0
104 
105  m_textCtrlHoleDia->SetValue( wxT( "0.4" ) );
106  m_choiceHoleDia->SetSelection( DEFAULT_UNIT_SEL_MM );
107  m_textCtrlPlatingThickness->SetValue( wxT( "0.035" ) );
109  m_textCtrlViaLength->SetValue( wxT( "1.6" ) );
110  m_choiceViaLength->SetSelection( DEFAULT_UNIT_SEL_MM );
111  m_textCtrlViaPadDia->SetValue( wxT( "0.6" ) );
112  m_choiceViaPadDia->SetSelection( DEFAULT_UNIT_SEL_MM );
113  m_textCtrlClearanceDia->SetValue( wxT( "1.0" ) );
114  m_choiceClearanceDia->SetSelection( DEFAULT_UNIT_SEL_MM );
115  m_textCtrlImpedance->SetValue( wxT( "50" ) );
116  m_choiceImpedance->SetSelection( DEFAULT_UNIT_SEL_MM );
117  m_textCtrlAppliedCurrent->SetValue( wxT( "1" ) );
118  m_textCtrlPlatingResistivity->SetValue( wxT( "1.72e-8" ) );
119  m_textCtrlPlatingPermittivity->SetValue( wxT( "4.5" ) );
120  m_textCtrlTemperatureDiff->SetValue( wxT( "10" ) );
121  m_textCtrlRiseTime->SetValue( wxT( "1" ) );
122 }
123 
124 
126 {
127  auto cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( Kiface().KifaceSettings() );
128 
129  m_textCtrlHoleDia->SetValue( cfg->m_ViaSize.hole_diameter );
130  m_choiceHoleDia->SetSelection( cfg->m_ViaSize.hole_diameter_units );
131 
132  m_textCtrlPlatingThickness->SetValue( cfg->m_ViaSize.thickness );
133  m_choicePlatingThickness->SetSelection( cfg->m_ViaSize.thickness_units );
134 
135  m_textCtrlViaLength->SetValue( cfg->m_ViaSize.length );
136  m_choiceViaLength->SetSelection( cfg->m_ViaSize.length_units );
137 
138  m_textCtrlViaPadDia->SetValue( cfg->m_ViaSize.pad_diameter );
139  m_choiceViaPadDia->SetSelection( cfg->m_ViaSize.pad_diameter_units );
140 
141  m_textCtrlClearanceDia->SetValue( cfg->m_ViaSize.clearance_diameter );
142  m_choiceClearanceDia->SetSelection( cfg->m_ViaSize.clearance_diameter_units );
143 
144  m_textCtrlImpedance->SetValue( cfg->m_ViaSize.characteristic_impedance );
145  m_choiceImpedance->SetSelection( cfg->m_ViaSize.characteristic_impedance_units );
146 
147  m_textCtrlAppliedCurrent->SetValue( cfg->m_ViaSize.applied_current );
148  m_textCtrlPlatingResistivity->SetValue( cfg->m_ViaSize.plating_resistivity );
149  m_textCtrlPlatingPermittivity->SetValue( cfg->m_ViaSize.permittivity );
150  m_textCtrlTemperatureDiff->SetValue( cfg->m_ViaSize.temp_rise );
151  m_textCtrlRiseTime->SetValue( cfg->m_ViaSize.pulse_rise_time );
152 }
153 
155 {
156  auto cfg = static_cast<PCB_CALCULATOR_SETTINGS*>( Kiface().KifaceSettings() );
157 
158  cfg->m_ViaSize.hole_diameter = m_textCtrlHoleDia->GetValue();
159  cfg->m_ViaSize.hole_diameter_units = m_choiceHoleDia->GetSelection();
160  cfg->m_ViaSize.thickness = m_textCtrlPlatingThickness->GetValue();
161  cfg->m_ViaSize.thickness_units = m_choicePlatingThickness->GetSelection();
162  cfg->m_ViaSize.length = m_textCtrlViaLength->GetValue();
163  cfg->m_ViaSize.length_units = m_choiceViaLength->GetSelection();
164  cfg->m_ViaSize.pad_diameter = m_textCtrlViaPadDia->GetValue();
165  cfg->m_ViaSize.pad_diameter_units = m_choiceViaPadDia->GetSelection();
166  cfg->m_ViaSize.clearance_diameter = m_textCtrlClearanceDia->GetValue();
167  cfg->m_ViaSize.clearance_diameter_units = m_choiceClearanceDia->GetSelection();
168  cfg->m_ViaSize.characteristic_impedance = m_textCtrlImpedance->GetValue();
169  cfg->m_ViaSize.characteristic_impedance_units = m_choiceImpedance->GetSelection();
170  cfg->m_ViaSize.applied_current = m_textCtrlAppliedCurrent->GetValue();
171  cfg->m_ViaSize.plating_resistivity = m_textCtrlPlatingResistivity->GetValue();
172  cfg->m_ViaSize.permittivity = m_textCtrlPlatingPermittivity->GetValue();
173  cfg->m_ViaSize.temp_rise = m_textCtrlTemperatureDiff->GetValue();
174  cfg->m_ViaSize.pulse_rise_time = m_textCtrlRiseTime->GetValue();
175 }
176 
177 void PCB_CALCULATOR_FRAME::OnViaCalculate( wxCommandEvent& event )
178 {
179  // Load parameters
180  double finishedHoleDia = std::abs( DoubleFromString( m_textCtrlHoleDia->GetValue() ) );
181  double platingThickness = std::abs( DoubleFromString( m_textCtrlPlatingThickness->GetValue() ) );
182  double viaLength = std::abs( DoubleFromString( m_textCtrlViaLength->GetValue() ) );
183  double padDia = std::abs( DoubleFromString( m_textCtrlViaPadDia->GetValue() ) );
184  double clearanceDia = std::abs( DoubleFromString( m_textCtrlClearanceDia->GetValue() ) );
185  double charImpedance = std::abs( DoubleFromString( m_textCtrlImpedance->GetValue() ) );
186  double appliedCurrent = std::abs( DoubleFromString( m_textCtrlAppliedCurrent->GetValue() ) );
187  double platingResistivity = std::abs( DoubleFromString( m_textCtrlPlatingResistivity->GetValue() ) );
188  double relativePermitivity = std::abs( DoubleFromString( m_textCtrlPlatingPermittivity->GetValue() ) );
189  double temperatureDiff = std::abs( DoubleFromString( m_textCtrlTemperatureDiff->GetValue() ) );
190  double pulseRiseTime = std::abs( DoubleFromString( m_textCtrlRiseTime->GetValue() ) );
191 
192  // Normalize units
193  finishedHoleDia *= m_choiceHoleDia->GetUnitScale();
194  platingThickness *= m_choicePlatingThickness->GetUnitScale();
195  viaLength *= m_choiceViaLength->GetUnitScale();
196  padDia *= m_choiceViaPadDia->GetUnitScale();
197  clearanceDia *= m_choiceClearanceDia->GetUnitScale();
198  charImpedance *= m_choiceImpedance->GetUnitScale();
199  // platingResistivity is ok: it is in Ohm*m in tables
200 
201  // Calculate cross-sectional area of the via's cylindrical structure [3]
202  double area = M_PI * (finishedHoleDia + platingThickness) * platingThickness; // m^2
203 
204  double viaResistance = platingResistivity * viaLength / area; // Ohms
205 
206  // Using thermal resistivity value 2.49e-3 meter-Kelvin/Watt, equivalent to
207  // thermal conductivity of 401 Watt/(meter-Kelvin) [5][6]
208  const double thermalResistivity = 2.49e-3; // m K/W
209  double thermalResistance = thermalResistivity * viaLength / area; // deg C/W
210 
211  double voltageDrop = appliedCurrent * viaResistance;
212 
213  double powerLoss = appliedCurrent * voltageDrop;
214 
215  // Estimate current carrying capacity of the via
216  // See comment #17 in [1] for a brief discussion on the formula
217  // This formula from IPC-2221 [4] is also used in the Track Width calculator
218  area /= pow( UNIT_MIL, 2 ); // m^2 to mil^2
219  const double k = 0.048;
220  const double b = 0.44;
221  const double c = 0.725;
222  double estimatedAmpacity = k * pow( temperatureDiff, b ) * pow( area, c );
223 
224  // Equation 7.6 in [7]
225  double capacitance = 55.51 * relativePermitivity * viaLength * padDia;
226  capacitance /= clearanceDia - padDia;
227 
228  // Equation 7.8 in [7]
229  double timeDegradation = 2.2 * capacitance * charImpedance / 2;
230 
231  // Equation 7.9 in [7]
232  double inductance = 200 * viaLength;
233  inductance *= log( 4 * viaLength / finishedHoleDia ) + 1;
234 
235  // Equation 7.11 in [7]
236  double reactance = M_PI * inductance / pulseRiseTime;
237 
238  // Update the display
239  VSDisplayValues( viaResistance, voltageDrop, powerLoss, estimatedAmpacity,
240  thermalResistance, capacitance, timeDegradation, inductance, reactance );
241 }
242 
243 void PCB_CALCULATOR_FRAME::VSDisplayValues( double aViaResistance, double aVoltageDrop,
244  double aPowerLoss, double aEstimatedAmpacity, double aThermalResistance,
245  double aCapacitance, double aTimeDegradation, double aInductance, double aReactance )
246 {
247  wxString msg;
248 
249  msg.Printf( "%g", aViaResistance );
250  m_ViaResistance->SetLabel( msg );
251 
252  msg.Printf( "%g", aVoltageDrop );
253  m_ViaVoltageDrop->SetLabel( msg );
254 
255  msg.Printf( "%g", aPowerLoss );
256  m_ViaPowerLoss->SetLabel( msg );
257 
258  msg.Printf( "%g", aEstimatedAmpacity );
259  m_ViaAmpacity->SetLabel( msg );
260 
261  msg.Printf( "%g", aThermalResistance );
262  m_ViaThermalResistance->SetLabel( msg );
263 
264  msg.Printf( "%g", aCapacitance );
265  m_ViaCapacitance->SetLabel( msg );
266 
267  msg.Printf( "%g", aTimeDegradation );
268  m_RiseTimeOutput->SetLabel( msg );
269 
270  msg.Printf( "%g", aInductance );
271  m_Inductance->SetLabel( msg );
272 
273  msg.Printf( "%g", aReactance );
274  m_Reactance->SetLabel( msg );
275 }
void VS_WriteConfig()
Function VS_WriteConfig Write Via Size prameters in config.
void VSDisplayValues(double aViaResistance, double aVoltageDrop, double aPowerLoss, double aEstimatedAmpacity, double aThermalResistance, double aCapacitance, double aTimeDegradation, double aInductance, double aReactance)
Function VSDisplayValues Displays the results of the calculation.
wxArrayString StandardRelativeDielectricConstantList()
Definition: common_data.cpp:28
void VS_Init()
Function VS_Init Read config and init dialog widgets values.
#define DEFAULT_UNIT_SEL_MM
virtual double GetUnitScale() override
Function GetUnitScale.
void OnViaCalculate(wxCommandEvent &event) override
Function OnViaCalculate Called when the user changes any value in the via calcultor.
void OnViaRho_Button(wxCommandEvent &event) override
Function OnViaRho_Button.
KIFACE_I & Kiface()
Global KIFACE_I "get" accessor.
wxArrayString StandardResistivityList()
Definition: common_data.cpp:84
UNIT_SELECTOR_LEN * m_choiceClearanceDia
UNIT_SELECTOR_LEN * m_choicePlatingThickness
void OnViaResetButtonClick(wxCommandEvent &event) override
Function OnViaResetButtonClick Called when the user clicks the reset button.
void OnViaEpsilonR_Button(wxCommandEvent &event) override
Function OnViaEpsilonR_Button.
UNIT_SELECTOR_RESISTOR * m_choiceImpedance
double DoubleFromString(const wxString &TextValue)
#define _(s)
Definition: 3d_actions.cpp:33
virtual double GetUnitScale() override
Function GetUnitScale.
void onUpdateViaCalcErrorText(wxUpdateUIEvent &event) override
Update the Error message in Via calculation panel.
#define UNIT_MIL
Definition: units_scales.h:35
a wxChoiceBox to select units in Pcb_Calculator