KiCad PCB EDA Suite
Loading...
Searching...
No Matches
track_width_calculations.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 The 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
21
22#include <cmath>
23
24namespace
25{
35struct BA_COEFFICIENTS
36{
37 double K;
38 double a;
39 double b;
40 double c;
41};
42
43
44constexpr BA_COEFFICIENTS EXTERNAL_COEFFS{ 215.3, 2.0, -1.15, -1.0 };
45
46constexpr BA_COEFFICIENTS INTERNAL_HALF_OZ_COEFFS{ 120.0, 2.0, -1.10, -1.52 };
47constexpr BA_COEFFICIENTS INTERNAL_1OZ_COEFFS{ 200.0, 1.9, -1.10, -1.52 };
48constexpr BA_COEFFICIENTS INTERNAL_2OZ_COEFFS{ 300.0, 2.0, -1.15, -1.52 };
49constexpr BA_COEFFICIENTS INTERNAL_3OZ_COEFFS{ 262.5, 1.9, -1.15, -1.52 };
50
51// Nominal copper weight thicknesses in mils (1 oz/ft^2 is about 1.378 mil).
52constexpr double HALF_OZ_MILS = 0.689;
53constexpr double ONE_OZ_MILS = 1.378;
54constexpr double TWO_OZ_MILS = 2.756;
55constexpr double THREE_OZ_MILS = 4.134;
56
57
58const BA_COEFFICIENTS& coefficients( bool aUseInternalLayer, double aThicknessMils )
59{
60 if( !aUseInternalLayer )
61 return EXTERNAL_COEFFS;
62
63 if( aThicknessMils < ( HALF_OZ_MILS + ONE_OZ_MILS ) / 2.0 )
64 return INTERNAL_HALF_OZ_COEFFS;
65
66 if( aThicknessMils < ( ONE_OZ_MILS + TWO_OZ_MILS ) / 2.0 )
67 return INTERNAL_1OZ_COEFFS;
68
69 if( aThicknessMils < ( TWO_OZ_MILS + THREE_OZ_MILS ) / 2.0 )
70 return INTERNAL_2OZ_COEFFS;
71
72 return INTERNAL_3OZ_COEFFS;
73}
74} // namespace
75
76
77double TRACK_WIDTH_CALCULATIONS::CurrentFromWidth( double aWidthMils, double aThicknessMils,
78 double aDeltaT_C, bool aUseInternalLayer )
79{
80 const BA_COEFFICIENTS& k = coefficients( aUseInternalLayer, aThicknessMils );
81
82 // dT = K * I^a * W^b * Th^c -> I = ( dT / ( K * W^b * Th^c ) )^(1/a)
83 double denom = k.K * std::pow( aWidthMils, k.b ) * std::pow( aThicknessMils, k.c );
84
85 return std::pow( aDeltaT_C / denom, 1.0 / k.a );
86}
87
88
89double TRACK_WIDTH_CALCULATIONS::WidthFromCurrent( double aCurrentA, double aThicknessMils,
90 double aDeltaT_C, bool aUseInternalLayer )
91{
92 const BA_COEFFICIENTS& k = coefficients( aUseInternalLayer, aThicknessMils );
93
94 // dT = K * I^a * W^b * Th^c -> W = ( dT / ( K * I^a * Th^c ) )^(1/b)
95 double denom = k.K * std::pow( aCurrentA, k.a ) * std::pow( aThicknessMils, k.c );
96
97 return std::pow( aDeltaT_C / denom, 1.0 / k.b );
98}
double CurrentFromWidth(double aWidthMils, double aThicknessMils, double aDeltaT_C, bool aUseInternalLayer)
Compute the maximum current a track can carry for a given temperature rise.
double WidthFromCurrent(double aCurrentA, double aThicknessMils, double aDeltaT_C, bool aUseInternalLayer)
Compute the track width required to carry a given current for a given temperature rise.