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