KiCad PCB EDA Suite
Loading...
Searching...
No Matches
panel_galvanic_corrosion.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
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
24#include <math/util.h> // for KiROUND
25#include <string_utils.h>
26#include <i18n_utility.h> // For _HKI definition in galvanic_corrosion_help.h
27wxString galvanic_corrosion_help =
29
30
31// Return ITU-R BT.709 luminance text colour contrast (white or black) for a given background.
32static wxColour getContrastingTextColour( const wxColour& aBg )
33{
34 int r = aBg.Red();
35 int g = aBg.Green();
36 int b = aBg.Blue();
37
38 // ITU-R BT.709 luminance
39 double luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b;
40
41 return ( luminance < 140.0 ) ? *wxWHITE : *wxBLACK;
42}
43
44CORROSION_TABLE_ENTRY::CORROSION_TABLE_ENTRY( const wxString& aName, const wxString& aSymbol,
45 double aPotential )
46{
47 m_name = aName;
48 m_symbol = aSymbol;
49 m_potential = aPotential;
50}
51
52PANEL_GALVANIC_CORROSION::PANEL_GALVANIC_CORROSION( wxWindow* parent, wxWindowID id,
53 const wxPoint& pos, const wxSize& size,
54 long style, const wxString& name ) :
55 PANEL_GALVANIC_CORROSION_BASE( parent, id, pos, size, style, name )
56{
57 m_entries.clear();
58
59 // Galvanic electrode potentials in volts, relative to the Standard Hydrogen Electrode (SHE).
60 // More negative values indicate anodic (less noble, more likely to corrode) behavior.
61 // More positive values indicate cathodic (more noble, corrosion-resistant) behavior.
62 //
63 // This table initializes m_entries with validated single-potential values drawn from
64 // authoritative engineering sources, including:
65 // - MIL-STD-889D (DoD Standard Practice: Dissimilar Metals)
66 // - NASA-STD-6012 (Materials and Processes for Corrosion Control)
67 // - CRC Handbook of Chemistry and Physics (pure metals, lab conditions)
68 // - ASM Handbook, Volumes 2 and 13C (material behavior and alloy data)
69 // - EN 50310 (electrical bonding and earthing potentials)
70 //
71 // All values assume standard conditions (approximately 25 °C) and aerated seawater exposure.
72 // For passivated metals, passive film stability is assumed. Where applicable, the copper
73 // electrode (Cu) is defined as the zero reference potential.
74 //
75 // Notes on solders:
76 // - Tin-lead solder alloys such as Sn63Pb37 and Sn60Pb40 have potentials similar to tin (~+0.23 V),
77 // but slightly lower due to lead content.
78 // - These alloys remain in use for aerospace, defense, and critical legacy systems
79 // where tin-whisker suppression is essential.
80
81 // Noble, extremely corrosion-resistant; used in aerospace-grade plating
82 // Ref: NASA-STD-6012, CRC Handbook
83 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Rhodium" ), "Rh", -0.60 ) );
84
85 // Noble, cathodic; stable in seawater environments
86 // Ref: MIL-STD-889D, CRC Handbook
87 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Platinum" ), "Pt", -0.57 ) );
88
89 // Noble; used in hybrid microcircuits and plated contacts; Pd black value
90 // Ref: MIL-STD-889D, CRC Handbook, ASM Handbook Vol. 13C
91 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Palladium" ), "Pd", -0.50 ) );
92
93 // Highly noble; stable under most atmospheric and marine exposures
94 // Ref: MIL-STD-889D, CRC Handbook, ASM Handbook Vol. 13C
95 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Gold" ), "Au", -0.44 ) );
96
97 // Molybdenum-stabilized austenitic stainless steel; passivated
98 // Ref: MIL-STD-889D, NASA-STD-6012, ASM Handbook Vol. 13C
99 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Stainless steel 316L" ), "X2CrNiMo17-12-2", -0.35 ) );
100
101 // Nickel–chromium–iron superalloy; oxidation-resistant
102 // Ref: NASA-STD-6012, ASM Handbook Vol. 13C
103 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Inconel" ), "Inconel", -0.35 ) );
104
105 // Soft post-transition metal; tarnishes but forms a protective film
106 // Ref: CRC Handbook, ASM Handbook Vol. 13C
107 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Indium" ), "In", -0.34 ) );
108
109 // Passive titanium; forms stable oxide film; widely corrosion-resistant
110 // Ref: MIL-STD-889D, ASM Handbook Vol. 13C
111 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Titanium, passive" ), "Ti", -0.32 ) );
112
113 // Austenitic stainless steel (18-8); passivated condition
114 // Ref: MIL-STD-889D, ASM Handbook Vol. 13C
115 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Stainless steel 18-9" ), "X8CrNiS18-9", -0.32 ) );
116
117 // Noble metal; resists corrosion despite surface tarnish
118 // Ref: MIL-STD-889D, CRC Handbook, ASM Handbook Vol. 13C
119 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Silver" ), "Ag", -0.22 ) );
120
121 // Elemental liquid metal; seldom structural; included for completeness
122 // Ref: CRC Handbook, ASM Handbook
123 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Mercury" ), "Hg", -0.22 ) );
124
125 // Electroless nickel with palladium and immersion gold finish; used in high-reliability PCBs
126 // Ref: IPC-4556, NASA-STD-8739.3, ASM Handbook Vol. 13C
127 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "ENEPIG (Ni/Pd/Au)" ), "ENEPIG", -0.18 ) );
128
129 // Electroless nickel / immersion gold PCB finish; porosity-dependent
130 // Ref: MIL-STD-889D (Ni base), IPC-4552
131 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "ENIG (Ni/Au)" ), "ENIG", -0.15 ) );
132
133 // Stable passivated nickel surface; common in structural and PCB coatings
134 // Ref: MIL-STD-889D, CRC Handbook
135 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Nickel" ), "Ni", -0.14 ) );
136
137 // Conductive graphite or carbon ink; used in membrane switches and low-cost sensor interfaces
138 // Ref: ASM Handbook Vol. 13C, IPC Application Notes
139 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Carbon (Graphitic)" ), "C", -0.10 ) );
140
141 // Reference metal; zero potential in galvanic series
142 // Ref: MIL-STD-889D, CRC Handbook
143 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Copper" ), "Cu", 0.00 ) );
144
145 // Copper–aluminium bronze alloy; more anodic than pure Cu
146 // Ref: MIL-STD-889D, ASM Handbook Vol. 2
147 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Copper-Aluminium" ), "CuAl10", 0.03 ) );
148
149 // Common 60/40 brass alloy; moderately anodic to copper
150 // Ref: MIL-STD-889D, ASM Handbook Vol. 13C
151 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Brass" ), "CuZn39Pb", 0.08 ) );
152
153 // Used in precision contacts and PCB spring connectors
154 // Ref: MIL-HDBK-5, ASM Handbook Vol. 2
155 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Beryllium copper" ), "CuBe2", 0.15 ) );
156
157 // Tin-silver-copper alloy (SAC305); RoHS-compliant lead-free solder
158 // Ref: IPC J-STD-006C, NASA-STD-8739.3, ASM Soldering Materials
159 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Lead-free Solder" ), "SAC305", 0.15 ) );
160
161 // Tin-phosphor bronze; widely used in contact springs and connector terminations
162 // Ref: MIL-HDBK-5, ASM Handbook Vol. 2
163 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Phosphor bronze" ), "CuSnP", 0.15 ) );
164
165 // Tin-bronze alloy; structurally and electrochemically similar to Sn
166 // Ref: CRC Handbook, ASM Handbook Vol. 2
167 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Bronze" ), "CuSn12", 0.20 ) );
168
169 // Tin-nickel alloy plating; RoHS-compliant alternative to pure tin; mitigates whiskering
170 // Ref: IPC J-STD-006C, ASM Soldering Materials
171 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Tin-Nickel (Sn/Ni)" ), "SnNi", 0.21 ) );
172
173 // Sn63Pb37 eutectic solder; used in aerospace and high-reliability assemblies
174 // Ref: CRC Handbook, IPC J-STD-006C, NASA-STD-8739.3
175 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Solder 63/37 (Eutectic)" ), "Sn63Pb37", 0.21 ) );
176
177 // Sn60Pb40 solder; slightly more anodic due to increased Pb content
178 // Ref: CRC Handbook, IPC J-STD-006C, NASA-STD-8739.3
179 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Solder 60/40 (Leaded)" ), "Sn60Pb40", 0.22 ) );
180
181 // Pure tin; used in solders, plating, and legacy components
182 // Ref: CRC Handbook, IPC J-STD-006C
183 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Tin" ), "Sn", 0.23 ) );
184
185 // Heavy metal; stable potential; often used in radiation shielding
186 // Ref: CRC Handbook, ASM Handbook
187 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Lead" ), "Pb", 0.27 ) );
188
189 // High-strength aluminum-copper alloy (2024-T3 family)
190 // Ref: MIL-STD-889D, ASM Handbook Vol. 2
191 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "2xxx series Al alloy" ), "AlCu4Mg", 0.37 ) );
192
193 // Gray cast iron; nominal potential above mild steel
194 // Ref: MIL-STD-889D, NASA-STD-6012
195 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Cast iron" ), "Fe-C-Si", 0.38 ) );
196
197 // Mild carbon steel in uncoated, aerated seawater conditions
198 // Ref: MIL-STD-889D, EN 50310
199 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Carbon steel" ), "Fe–C", 0.43 ) );
200
201 // Chromated aluminium alloy (e.g., Alodine); used in EMI shield cans and structural enclosures
202 // Ref: MIL-STD-889D, NASA-STD-6012
203 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Aluminium, chromated" ), "Al-Chromate", 0.50 ) );
204
205 // Pure aluminum with passive oxide layer; typical field potential
206 // Ref: MIL-STD-889D, NASA-STD-6012
207 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Aluminium, pure, passive" ), "Al", 0.52 ) );
208
209 // Soft plating metal; used in fasteners and aerospace corrosion protection
210 // Ref: MIL-STD-889D, ASM Handbook Vol. 13C
211 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Cadmium" ), "Cd", 0.53 ) );
212
213 // Unalloyed iron in its active state; more anodic than steels
214 // Ref: CRC Handbook, ASM Handbook
215 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Iron" ), "Fe", 0.535 ) );
216
217 // Passive chromium (trivalent); protective oxide layer assumed
218 // Ref: MIL-STD-889D, CRC Handbook
219 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Chrome, passive" ), "Cr", 0.63 ) );
220
221 // Highly anodic metal; used in sacrificial anode systems
222 // Ref: MIL-STD-889D, ASM Handbook Vol. 13C
223 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Zinc" ), "Zn", 0.83 ) );
224
225 // Mild steel with zinc-plated surface; common in chassis screws and mounting hardware
226 // Ref: MIL-STD-889D, ASM Handbook Vol. 13C
227 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Steel, zinc-plated" ), "Fe-Zn", 0.83 ) );
228
229 // Reactive transition metal; rarely used unalloyed
230 // Ref: CRC Handbook, ASM Handbook
231 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Manganese" ), "Mn", 0.90 ) );
232
233 // Most anodic structural metal in common use; sacrificial anode
234 // Ref: MIL-STD-889D, NASA-STD-6012
235 m_entries.emplace_back( CORROSION_TABLE_ENTRY( _( "Magnesium" ), "Mg", 1.38 ) );
236
237
238 // Resize the table
239
240 m_table->DeleteCols( 0, m_table->GetNumberCols() );
241 m_table->DeleteRows( 0, m_table->GetNumberRows() );
242 m_table->AppendCols( (int) m_entries.size() );
243 m_table->AppendRows( (int) m_entries.size() );
244
245 // show markdown formula explanation in lower help panel
246 wxString msg;
247 ConvertMarkdown2Html( wxGetTranslation( galvanic_corrosion_help ), msg );
248 m_helpText->SetPage( msg );
249
250 m_symbolicStatus = true;
251 m_corFilterValue = 0;
252
253 fillTable();
254}
255
256
258{
259}
260
261
263{
264 // Update the HTML window with the help text
265 m_helpText->ThemeChanged();
266}
267
268
270{
273
274 bool refill_table = m_symbolicStatus != aCfg->m_CorrosionTable.show_symbols;
277 m_radioBtnName->SetValue( !m_symbolicStatus );
278
279 if( refill_table )
280 fillTable();
281}
282
283
285{
286 aCfg->m_CorrosionTable.threshold_voltage = wxString( "" ) << m_corFilterValue;
288}
289
290
291void PANEL_GALVANIC_CORROSION::OnNomenclatureChange( wxCommandEvent& aEvent )
292{
293 if( m_radioBtnSymbol->GetValue() )
294 {
295 m_symbolicStatus = true;
296 }
297 else if( m_radioBtnName->GetValue() )
298 {
299 m_symbolicStatus = false;
300 }
301
302 fillTable();
303}
304
305
306void PANEL_GALVANIC_CORROSION::OnCorFilterChange( wxCommandEvent& aEvent )
307{
309 fillTable();
310}
311
312
314{
315
316 // Fill the table with data
317 int i = 0;
318 wxColour color_ok( 122, 166, 194 );
319 wxColour color_text( 0, 0, 0 );
320 wxString value;
321 wxString label;
322
323 for( const CORROSION_TABLE_ENTRY& entryA : m_entries )
324 {
325 int j = 0;
326
327 if( m_symbolicStatus == true )
328 {
329 if( entryA.m_symbol.size() > 0 )
330 {
331 label = entryA.m_symbol;
332 }
333 else
334 {
335 label = entryA.m_name;
336 }
337 }
338 else
339 {
340 if( entryA.m_name.size() > 0 )
341 {
342 label = entryA.m_name;
343 }
344 else
345 {
346 label = entryA.m_symbol;
347 }
348 }
349
350 m_table->SetRowLabelAlignment( wxALIGN_RIGHT, wxALIGN_CENTER );
351 m_table->SetRowLabelValue( i, label );
352 m_table->SetColLabelAlignment( wxALIGN_LEFT, wxALIGN_CENTER );
353 m_table->SetColLabelValue( i, label );
354 m_table->SetCellAlignment( i, j, wxALIGN_CENTER, wxALIGN_CENTER );
355
356 for( const CORROSION_TABLE_ENTRY& entryB : m_entries )
357 {
358 double diff = entryA.m_potential - entryB.m_potential;
359 int diff_temp = KiROUND( abs( diff * 99 ) );
360
361 value = wxString::Format( "%.0f", diff * 1000 ); // display in mV
362 m_table->SetCellValue( i, j, value );
363
364 wxColour aBg;
365
366 if( abs( diff ) == 0 )
367 {
368 aBg = wxColour( 193, 231, 255 );
369 }
370 else if( ( KiROUND( abs( diff * 1000 ) ) ) > m_corFilterValue )
371 {
372 if( diff > 0 )
373 {
374 aBg = wxColour( 226 - diff_temp, 226 - diff_temp, 246 - diff_temp );
375 }
376 else if( diff < 0 )
377 {
378 aBg = wxColour( 255 - diff_temp, 222 - diff_temp, 199 - diff_temp );
379 }
380 }
381 else
382 {
383 aBg = color_ok;
384 }
385
386 m_table->SetCellBackgroundColour( i, j, aBg );
387 m_table->SetCellTextColour( i, j, getContrastingTextColour( aBg ) );
388 m_table->SetCellAlignment( i, j, wxALIGN_CENTER, wxALIGN_CENTER );
389 m_table->SetReadOnly( i, j, true );
390 j++;
391 }
392
393 i++;
394 }
395
396 m_table->SetColLabelTextOrientation( wxVERTICAL );
397
398 m_table->SetColLabelSize( wxGRID_AUTOSIZE );
399 m_table->SetRowLabelSize( wxGRID_AUTOSIZE );
400 m_table->AutoSizeColumns();
401 m_table->AutoSizeRows();
402
403 Layout();
404}
const char * name
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:995
wxString m_symbol
Chemical symbol (Cu), not translatable.
wxString m_name
Translatable name ( Copper )
double m_potential
potential in volts, relative to copper
CORROSION_TABLE_ENTRY(const wxString &aName, const wxString &aSymbol, double aPotential)
Class PANEL_GALVANIC_CORROSION_BASE.
void OnNomenclatureChange(wxCommandEvent &aEvent) override
PANEL_GALVANIC_CORROSION(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
std::vector< CORROSION_TABLE_ENTRY > m_entries
void ThemeChanged() override
Update UI elements of the panel when the theme changes to ensure the images and fonts/colors are appr...
void OnCorFilterChange(wxCommandEvent &aEvent) override
void LoadSettings(PCB_CALCULATOR_SETTINGS *aCfg) override
Load the settings into the panel.
void SaveSettings(PCB_CALCULATOR_SETTINGS *aCfg) override
Save the settings from the panel.
#define _(s)
Some functions to handle hotkeys in KiCad.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:411
double DoubleFromString(const wxString &TextValue)
void ConvertMarkdown2Html(const wxString &aMarkdownInput, wxString &aHtmlOutput)