Make ppt on solder join from bdc

Asking for Preferences

What does "BDC" refer to here? I want to pull the right source content for the solder joint presentation.

Reading File
Reading File
Running Command

ls -la /tmp/workspace/ 2>/dev/null || mkdir -p /tmp/workspace

Browsing Directory

~/attachments

Writing File

~/solder_joint_ppt/build_ppt.py

from pptx import Presentation
from pptx.util import Inches, Pt, Emu
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE

# ---------- Palette ----------
NAVY = RGBColor(0x0B, 0x2B, 0x4A)
BLUE = RGBColor(0x1F, 0x6F, 0xB2)
LIGHT_BLUE = RGBColor(0xE8, 0xF1, 0xF8)
ORANGE = RGBColor(0xE8, 0x7A, 0x1E)
GREY = RGBColor(0x4A, 0x4A, 0x4A)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
RED = RGBColor(0xC0, 0x39, 0x2B)
GREEN = RGBColor(0x27, 0xAE, 0x60)

prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
SW, SH = prs.slide_width, prs.slide_height
blank = prs.slide_layouts[6]


def add_slide():
    return prs.slides.add_slide(blank)


def rect(slide, x, y, w, h, color, line=False):
    shp = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, x, y, w, h)
    shp.fill.solid()
    shp.fill.fore_color.rgb = color
    if line:
        shp.line.color.rgb = color
        shp.line.width = Pt(0.5)
    else:
        shp.line.fill.background()
    shp.shadow.inherit = False
    return shp


def textbox(slide, x, y, w, h, text, size=18, color=GREY, bold=False, align=PP_ALIGN.LEFT,
            font="Calibri", italic=False, anchor=MSO_ANCHOR.TOP, wrap=True, line_spacing=1.0):
    tb = slide.shapes.add_textbox(x, y, w, h)
    tf = tb.text_frame
    tf.word_wrap = wrap
    tf.vertical_anchor = anchor
    tf.margin_left = 0
    tf.margin_right = 0
    tf.margin_top = 0
    tf.margin_bottom = 0
    lines = text.split("\n")
    for i, line in enumerate(lines):
        p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
        p.text = line
        p.alignment = align
        p.line_spacing = line_spacing
        for r in p.runs:
            r.font.size = Pt(size)
            r.font.color.rgb = color
            r.font.bold = bold
            r.font.italic = italic
            r.font.name = font
    return tb


def bullets(slide, x, y, w, h, items, size=16, color=GREY, bold_first=False, font="Calibri",
            space_after=8, bullet_color=BLUE, line_spacing=1.05):
    tb = slide.shapes.add_textbox(x, y, w, h)
    tf = tb.text_frame
    tf.word_wrap = True
    tf.margin_left = 0
    tf.margin_right = 0
    tf.margin_top = 0
    tf.margin_bottom = 0
    for i, item in enumerate(items):
        if isinstance(item, tuple):
            txt, lvl = item
        else:
            txt, lvl = item, 0
        p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
        p.space_after = Pt(space_after)
        p.line_spacing = line_spacing
        prefix = "•  " if lvl == 0 else "-  "
        p.text = prefix + txt
        p.level = 0
        r = p.runs[0]
        r.font.size = Pt(size - (2 if lvl else 0))
        r.font.color.rgb = color
        r.font.name = font
        if lvl:
            tb2 = None
    return tb


def footer(slide, num, total=13, title="Solder Joints"):
    rect(slide, 0, SH - Inches(0.35), SW, Inches(0.35), NAVY)
    textbox(slide, Inches(0.4), SH - Inches(0.33), Inches(6), Inches(0.3), title,
            size=10, color=WHITE, font="Calibri")
    textbox(slide, SW - Inches(1.2), SH - Inches(0.33), Inches(0.8), Inches(0.3),
            f"{num}/{total}", size=10, color=WHITE, align=PP_ALIGN.RIGHT)


def header(slide, kicker, title_text, title_color=NAVY):
    rect(slide, 0, 0, SW, Inches(1.15), NAVY)
    rect(slide, 0, Inches(1.15), SW, Inches(0.06), ORANGE)
    textbox(slide, Inches(0.55), Inches(0.15), Inches(11), Inches(0.35), kicker.upper(),
            size=13, color=ORANGE, bold=True, font="Calibri")
    textbox(slide, Inches(0.55), Inches(0.5), Inches(12), Inches(0.6), title_text,
            size=30, color=WHITE, bold=True, font="Calibri")


TOTAL = 13

# ============================================================
# SLIDE 1 - TITLE
# ============================================================
s = add_slide()
rect(s, 0, 0, SW, SH, NAVY)
rect(s, 0, Inches(5.0), SW, Inches(0.08), ORANGE)
textbox(s, Inches(0.9), Inches(2.5), Inches(11.5), Inches(0.5), "SOLDER JOINTS",
        size=20, color=ORANGE, bold=True, font="Calibri")
textbox(s, Inches(0.9), Inches(3.0), Inches(11.5), Inches(1.4),
        "Formation, Types, Quality Criteria & Inspection",
        size(44) if False else 40, color=WHITE, bold=True, font="Calibri")
textbox(s, Inches(0.9), Inches(5.3), Inches(11), Inches(0.5),
        "A Technical Overview for Electronics Assembly", size=18, color=RGBColor(0xC9,0xD9,0xEA), font="Calibri", italic=True)
textbox(s, Inches(0.9), Inches(6.8), Inches(6), Inches(0.4), "Reference: IPC-A-610 Acceptability Standards",
        size=13, color=RGBColor(0x9A,0xB6,0xD1))

prs.save("/tmp/workspace/solder_joint_ppt/Solder_Joints.pptx")
print("draft saved slide 1")
Running Command

mkdir -p /tmp/workspace/solder_joint_ppt

Quick answer

I wasn't able to finish generating the PowerPoint file in this session, and I still need clarification on one thing before I build it: what does "BDC" refer to?
Since I couldn't confirm this, I proceeded on the assumption that you want a general technical presentation on solder joints in electronics/PCB assembly (formation, types, IPC-A-610 acceptance criteria, common defects, inspection methods). If that's not what you meant — for example if "BDC" refers to a specific document/file you have, a "BLDC" motor context, or something else — let me know and I'll redo it with the correct source material.
To finish this properly, please tell me:
  1. What "BDC" means in your request (a file you have, a specific standard, a motor/connector context, etc.), and
  2. Whether the general solder-joint-in-electronics angle (types, formation, IPC-A-610 defects/inspection) is the right scope, or if you want something narrower (e.g., just defect types, just inspection criteria, or joints in a specific application like BLDC motor windings).
Once you confirm, I'll build out the full slide deck (title, solder joint fundamentals, types of joints, formation process, IPC-A-610 classifications, common defects with visuals, inspection methods, best practices, summary) and share the downloadable .pptx file.

Where is my ppt

Writing File

~/solder_joint_ppt/build_ppt.py

from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE

NAVY = RGBColor(0x0B, 0x2B, 0x4A)
BLUE = RGBColor(0x1F, 0x6F, 0xB2)
LIGHT_BLUE = RGBColor(0xE8, 0xF1, 0xF8)
ORANGE = RGBColor(0xE8, 0x7A, 0x1E)
GREY = RGBColor(0x4A, 0x4A, 0x4A)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
RED = RGBColor(0xC0, 0x39, 0x2B)
GREEN = RGBColor(0x27, 0xAE, 0x60)
LIGHT_GREY = RGBColor(0xF2, 0xF4, 0xF6)

prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
SW, SH = prs.slide_width, prs.slide_height
blank = prs.slide_layouts[6]
TOTAL = 12


def add_slide():
    return prs.slides.add_slide(blank)


def rect(slide, x, y, w, h, color, line_color=None):
    shp = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, x, y, w, h)
    shp.fill.solid()
    shp.fill.fore_color.rgb = color
    if line_color:
        shp.line.color.rgb = line_color
        shp.line.width = Pt(1)
    else:
        shp.line.fill.background()
    shp.shadow.inherit = False
    return shp


def textbox(slide, x, y, w, h, text, size=18, color=GREY, bold=False, align=PP_ALIGN.LEFT,
            font="Calibri", italic=False, anchor=MSO_ANCHOR.TOP, wrap=True, line_spacing=1.0):
    tb = slide.shapes.add_textbox(x, y, w, h)
    tf = tb.text_frame
    tf.word_wrap = wrap
    tf.vertical_anchor = anchor
    tf.margin_left = 0
    tf.margin_right = 0
    tf.margin_top = 0
    tf.margin_bottom = 0
    lines = text.split("\n")
    for i, line in enumerate(lines):
        p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
        p.text = line
        p.alignment = align
        p.line_spacing = line_spacing
        for r in p.runs:
            r.font.size = Pt(size)
            r.font.color.rgb = color
            r.font.bold = bold
            r.font.italic = italic
            r.font.name = font
    return tb


def bullets(slide, x, y, w, h, items, size=16, color=GREY, font="Calibri",
            space_after=8, line_spacing=1.05):
    tb = slide.shapes.add_textbox(x, y, w, h)
    tf = tb.text_frame
    tf.word_wrap = True
    tf.margin_left = 0
    tf.margin_right = 0
    tf.margin_top = 0
    tf.margin_bottom = 0
    for i, item in enumerate(items):
        if isinstance(item, tuple):
            txt, lvl = item
        else:
            txt, lvl = item, 0
        p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
        p.space_after = Pt(space_after)
        p.line_spacing = line_spacing
        prefix = "•  " if lvl == 0 else "-  "
        p.text = ("     " * lvl) + prefix + txt
        r = p.runs[0]
        r.font.size = Pt(size - (2 if lvl else 0))
        r.font.color.rgb = color
        r.font.name = font
        r.font.bold = (lvl == 0 and False)
    return tb


def footer(slide, num, title="Solder Joints"):
    rect(slide, 0, SH - Inches(0.35), SW, Inches(0.35), NAVY)
    textbox(slide, Inches(0.4), SH - Inches(0.33), Inches(6), Inches(0.3), title,
            size=10, color=WHITE, font="Calibri")
    textbox(slide, SW - Inches(1.2), SH - Inches(0.33), Inches(0.8), Inches(0.3),
            f"{num}/{TOTAL}", size=10, color=WHITE, align=PP_ALIGN.RIGHT)


def header(slide, kicker, title_text):
    rect(slide, 0, 0, SW, Inches(1.15), NAVY)
    rect(slide, 0, Inches(1.15), SW, Inches(0.06), ORANGE)
    textbox(slide, Inches(0.55), Inches(0.15), Inches(11), Inches(0.35), kicker.upper(),
            size=13, color=ORANGE, bold=True, font="Calibri")
    textbox(slide, Inches(0.55), Inches(0.5), Inches(12), Inches(0.6), title_text,
            size=28, color=WHITE, bold=True, font="Calibri")


def card(slide, x, y, w, h, title, body_lines, title_color=BLUE, num=None):
    rect(slide, x, y, w, h, LIGHT_GREY)
    rect(slide, x, y, Inches(0.08), h, title_color)
    ty = y + Inches(0.15)
    if num:
        textbox(slide, x + Inches(0.25), ty, w - Inches(0.4), Inches(0.4), num,
                size=22, color=title_color, bold=True)
        ty += Inches(0.42)
    textbox(slide, x + Inches(0.25), ty, w - Inches(0.4), Inches(0.4), title,
            size=16, color=NAVY, bold=True)
    bullets(slide, x + Inches(0.25), ty + Inches(0.42), w - Inches(0.45), h - Inches(0.9),
            body_lines, size=12.5, color=GREY, space_after=3)


# ============================================================
# SLIDE 1 - TITLE
# ============================================================
s = add_slide()
rect(s, 0, 0, SW, SH, NAVY)
rect(s, 0, Inches(5.0), SW, Inches(0.08), ORANGE)
textbox(s, Inches(0.9), Inches(2.4), Inches(11.5), Inches(0.5), "SOLDER JOINTS",
        size=20, color=ORANGE, bold=True, font="Calibri")
textbox(s, Inches(0.9), Inches(2.9), Inches(11.5), Inches(1.4),
        "Formation, Types, Quality Criteria\n& Inspection", size=40, color=WHITE, bold=True, font="Calibri")
textbox(s, Inches(0.9), Inches(4.6), Inches(11), Inches(0.5),
        "A Technical Overview for Electronics Assembly", size=18, color=RGBColor(0xC9, 0xD9, 0xEA),
        font="Calibri", italic=True)
textbox(s, Inches(0.9), Inches(6.8), Inches(8), Inches(0.4),
        "Reference: IPC-A-610 Acceptability of Electronic Assemblies", size=13,
        color=RGBColor(0x9A, 0xB6, 0xD1))

# ============================================================
# SLIDE 2 - AGENDA
# ============================================================
s = add_slide()
header(s, "Overview", "Agenda")
agenda = [
    "1. What Is a Solder Joint?",
    "2. The Soldering Process",
    "3. Types of Solder Joints",
    "4. Anatomy of a Good Joint",
    "5. IPC-A-610 Classifications",
    "6. Common Solder Defects",
    "7. Cold Joints & Dry Joints",
    "8. Inspection Methods",
    "9. Reflow vs Wave Soldering",
    "10. Best Practices",
    "11. Summary",
]
bullets(s, Inches(0.9), Inches(1.6), Inches(10.5), Inches(5.2), agenda, size=20, color=NAVY, space_after=14)
footer(s, 2)

# ============================================================
# SLIDE 3 - WHAT IS A SOLDER JOINT
# ============================================================
s = add_slide()
header(s, "Fundamentals", "What Is a Solder Joint?")
textbox(s, Inches(0.55), Inches(1.5), Inches(6.3), Inches(0.5),
        "Definition", size=18, color=BLUE, bold=True)
bullets(s, Inches(0.55), Inches(2.0), Inches(6.3), Inches(4.5), [
    "A solder joint is a metallurgical bond formed when molten solder wets and adheres to two or more metal surfaces (e.g. a component lead and a PCB pad), then solidifies into a permanent electrical and mechanical connection.",
    "Unlike a weld, the base metals are not melted -- only the solder liquefies and forms an intermetallic compound (IMC) layer with the base metals.",
    "A properly formed joint provides:",
    ("Low-resistance electrical continuity", 1),
    ("Mechanical strength to withstand vibration/thermal cycling", 1),
    ("Environmental sealing against corrosion", 1),
], size=16, space_after=10)
rect(s, Inches(7.2), Inches(1.55), Inches(5.6), Inches(5.0), LIGHT_BLUE)
textbox(s, Inches(7.5), Inches(1.75), Inches(5.0), Inches(0.4), "Key Materials", size=16, color=NAVY, bold=True)
bullets(s, Inches(7.5), Inches(2.25), Inches(5.0), Inches(4.0), [
    "Solder alloy: SAC305 (Sn96.5/Ag3.0/Cu0.5) -- lead-free standard",
    "Sn63/Pb37 -- eutectic leaded (legacy/military/aerospace)",
    "Flux: removes oxides, improves wetting (rosin, no-clean, water-soluble)",
    "Base metals: Cu pads/traces, component leads (Cu, Sn, Ni-plated, etc.)",
    "Substrate: FR-4 PCB with copper pads/plating",
], size=14.5, space_after=10)
footer(s, 3)

# ============================================================
# SLIDE 4 - SOLDERING PROCESS
# ============================================================
s = add_slide()
header(s, "Fundamentals", "The Soldering Process")
steps = [
    ("1", "Surface Prep", "Clean pad/lead surfaces; remove oxides and contaminants."),
    ("2", "Flux Application", "Flux applied to reduce surface tension and promote wetting."),
    ("3", "Heating", "Heat via iron, hot air, or reflow oven raises joint above solder liquidus temp."),
    ("4", "Wetting", "Molten solder flows and spreads across the base metal surfaces."),
    ("5", "Metallurgical Bond", "Intermetallic compound (IMC) layer forms between solder and base metal."),
    ("6", "Cooling & Solidification", "Joint cools undisturbed to form a solid, shiny, concave fillet."),
]
x0 = Inches(0.55)
w = Inches(1.95)
gap = Inches(0.15)
y0 = Inches(1.6)
h = Inches(2.6)
for i, (num, title, desc) in enumerate(steps):
    x = x0 + i * (w + gap)
    rect(s, x, y0, w, h, LIGHT_BLUE)
    rect(s, x, y0, w, Inches(0.5), BLUE)
    textbox(s, x, y0 + Inches(0.02), w, Inches(0.46), num, size=20, color=WHITE, bold=True,
            align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
    textbox(s, x + Inches(0.1), y0 + Inches(0.6), w - Inches(0.2), Inches(0.5), title, size=13.5,
            color=NAVY, bold=True, align=PP_ALIGN.CENTER)
    textbox(s, x + Inches(0.1), y0 + Inches(1.1), w - Inches(0.2), Inches(1.4), desc, size=11,
            color=GREY, align=PP_ALIGN.CENTER)
textbox(s, Inches(0.55), Inches(4.6), Inches(12.2), Inches(0.6),
        "Typical peak reflow temperature: 235-250°C (lead-free) or 210-225°C (leaded); time above liquidus ~30-90 seconds.",
        size=14, color=GREY, italic=True)
rect(s, Inches(0.55), Inches(5.4), Inches(12.2), Inches(1.3), LIGHT_GREY)
textbox(s, Inches(0.75), Inches(5.55), Inches(11.8), Inches(1.0),
        "Golden Rule: Heat the joint (pad + lead together), not just the solder. Apply solder to the heated joint so it flows by capillary action -- never melt solder directly on the iron tip and drip it on.",
        size=14.5, color=NAVY, bold=True)
footer(s, 4)

# ============================================================
# SLIDE 5 - TYPES OF SOLDER JOINTS
# ============================================================
s = add_slide()
header(s, "Classification", "Types of Solder Joints")
cardw = Inches(3.9)
cardh = Inches(2.5)
gapx = Inches(0.25)
x0 = Inches(0.55)
y0 = Inches(1.55)
data = [
    ("Through-Hole (THT)", ["Lead inserted through plated via/hole", "Solder forms fillet on top & bottom", "High mechanical strength", "Used: connectors, power parts"]),
    ("Surface-Mount (SMT)", ["Component pad soldered flat to PCB pad", "No hole; smaller footprint", "Dominant in modern electronics", "Used: resistors, ICs, QFN/BGA"]),
    ("Gull-Wing / J-Lead", ["SMT lead types on ICs (SOIC, QFP)", "Toe, heel, and side fillets checked", "Visual inspection of lead shape", "Used: SOIC, TSOP, QFP packages"]),
]
for i, (title, items) in enumerate(data):
    x = x0 + i * (cardw + gapx)
    card(s, x, y0, cardw, cardh, title, [(it, 0) for it in items], title_color=BLUE)
data2 = [
    ("BGA (Ball Grid Array)", ["Solder balls under package, hidden joints", "Reflow forms balls into joints", "Inspected via X-ray only", "Used: CPUs, high-density ICs"]),
    ("Wire/Lead Splice", ["Two wires or a wire-to-terminal joint", "Solder wicks into stranded wire", "Common in cable harnesses", "Used: repairs, hand assemblies"]),
    ("Press-Fit / Hybrid", ["Mechanical press-fit + solder for sealing", "Combines mechanical & solder bond", "Used in connectors, power modules", "Higher vibration resistance"]),
]
y1 = y0 + cardh + Inches(0.2)
for i, (title, items) in enumerate(data2):
    x = x0 + i * (cardw + gapx)
    card(s, x, y1, cardw, cardh, title, [(it, 0) for it in items], title_color=ORANGE)
footer(s, 5)

# ============================================================
# SLIDE 6 - ANATOMY OF A GOOD JOINT
# ============================================================
s = add_slide()
header(s, "Quality", "Anatomy of a Good Solder Joint")
textbox(s, Inches(0.55), Inches(1.5), Inches(6.2), Inches(0.4), "Visual Hallmarks of Acceptance",
        size=17, color=BLUE, bold=True)
bullets(s, Inches(0.55), Inches(2.0), Inches(6.3), Inches(4.6), [
    "Shiny / smooth surface (satin finish acceptable for matte lead-free alloys)",
    "Concave fillet shape -- smoothly tapered, wetting both surfaces",
    "Complete wetting -- solder covers the entire pad and the lead/component termination",
    "Homogeneous -- no visible graininess, cracks, or pinholes",
    "Adequate fillet height -- lead/termination outline should still be discernible through solder",
    "No excess solder bridging to adjacent pads/leads",
    "No sharp peaks, icicles, or solder balls nearby",
], size=15.5, space_after=11)
rect(s, Inches(7.1), Inches(1.55), Inches(5.7), Inches(5.0), LIGHT_BLUE)
textbox(s, Inches(7.4), Inches(1.75), Inches(5.1), Inches(0.4), "Quick Check Criteria", size=16, color=NAVY, bold=True)
checks = [
    ("Wetting angle", "< 90° (ideally 20-30°) between solder and pad"),
    ("Fillet", "Concave, continuous, no voids"),
    ("Coverage", "Solder wets minimum 75% of terminal per IPC-A-610"),
    ("Color/texture", "Consistent -- shiny for SnPb, may be dull/matte for SAC alloys"),
    ("Alignment", "Component seated flat, not tombstoned or lifted"),
]
yy = Inches(2.3)
for label, desc in checks:
    textbox(s, Inches(7.4), yy, Inches(5.1), Inches(0.3), label, size=14, color=ORANGE, bold=True)
    textbox(s, Inches(7.4), yy + Inches(0.3), Inches(5.1), Inches(0.5), desc, size=12.5, color=GREY)
    yy += Inches(0.85)
footer(s, 6)

# ============================================================
# SLIDE 7 - IPC-A-610 CLASSIFICATIONS
# ============================================================
s = add_slide()
header(s, "Standards", "IPC-A-610 Acceptability Classes")
classes = [
    ("Class 1", "General Electronics", "Consumer products where cosmetic imperfections are not important; only function matters. Lowest reliability requirement."),
    ("Class 2", "Dedicated Service", "Continued/extended service life required; uninterrupted service is desirable but not critical. Most industrial/commercial electronics."),
    ("Class 3", "High Performance", "Continued/high reliability performance is critical; equipment must function on demand (medical, aerospace, military). Tightest acceptance criteria."),
]
x0 = Inches(0.55)
w = Inches(4.0)
gap = Inches(0.15)
y0 = Inches(1.55)
h = Inches(3.0)
colors = [GREEN, BLUE, RED]
for i, (cls, name, desc) in enumerate(classes):
    x = x0 + i * (w + gap)
    rect(s, x, y0, w, h, LIGHT_GREY)
    rect(s, x, y0, w, Inches(0.7), colors[i])
    textbox(s, x, y0 + Inches(0.08), w, Inches(0.55), cls, size=22, color=WHITE, bold=True,
            align=PP_ALIGN.CENTER)
    textbox(s, x + Inches(0.2), y0 + Inches(0.85), w - Inches(0.4), Inches(0.4), name, size=15,
            color=NAVY, bold=True, align=PP_ALIGN.CENTER)
    textbox(s, x + Inches(0.25), y0 + Inches(1.3), w - Inches(0.5), Inches(1.6), desc, size=12.5,
            color=GREY, align=PP_ALIGN.CENTER, line_spacing=1.1)
textbox(s, Inches(0.55), Inches(4.85), Inches(12.2), Inches(1.6),
        "IPC-A-610 defines three visual acceptance conditions for each defect type:", size=15, color=NAVY, bold=True)
bullets(s, Inches(0.9), Inches(5.3), Inches(11.5), Inches(1.4), [
    "Target Condition -- the ideal, defect-free result",
    "Acceptable Condition -- meets minimum requirements, joint is reliable",
    "Defect Condition -- fails to meet minimum requirements; must be reworked or rejected",
], size=14, space_after=6)
footer(s, 7)

# ============================================================
# SLIDE 8 - COMMON DEFECTS
# ============================================================
s = add_slide()
header(s, "Quality Control", "Common Solder Joint Defects")
defects = [
    ("Cold / Dry Joint", "Insufficient heat during formation. Dull, grainy, cracked surface; poor/no wetting.", RED),
    ("Solder Bridging", "Excess solder connects two adjacent pads/leads, causing a short circuit.", RED),
    ("Insufficient Solder", "Too little solder; fillet doesn't fully cover the pad/lead, weak joint.", ORANGE),
    ("Solder Balls", "Small spherical solder particles left near a joint after reflow, can cause shorts.", ORANGE),
    ("Tombstoning", "Small SMT component lifts on one end during reflow due to uneven wetting/heating.", ORANGE),
    ("Voids", "Gas pockets trapped inside the joint (common in BGA), reduce mechanical/thermal integrity.", BLUE),
    ("Dewetting", "Solder flows onto pad then recedes, leaving thin/no coverage on part of the surface.", BLUE),
    ("Non-wetting", "Solder never adheres to a surface at all -- base metal remains exposed.", BLUE),
]
x0 = Inches(0.55)
w = Inches(3.0)
gap = Inches(0.15)
y0 = Inches(1.5)
h = Inches(2.65)
for i, (name, desc, color) in enumerate(defects):
    col = i % 4
    row = i // 4
    x = x0 + col * (w + gap)
    y = y0 + row * (h + Inches(0.15))
    rect(s, x, y, w, h, LIGHT_GREY)
    rect(s, x, y, w, Inches(0.08), color)
    textbox(s, x + Inches(0.15), y + Inches(0.2), w - Inches(0.3), Inches(0.6), name, size=14,
            color=NAVY, bold=True, line_spacing=1.0)
    textbox(s, x + Inches(0.15), y + Inches(0.85), w - Inches(0.3), Inches(1.7), desc, size=11.5,
            color=GREY, line_spacing=1.1)
footer(s, 8)

# ============================================================
# SLIDE 9 - COLD / DRY JOINTS DEEP DIVE
# ============================================================
s = add_slide()
header(s, "Quality Control", "Cold Joints & Dry Joints -- Root Causes")
textbox(s, Inches(0.55), Inches(1.5), Inches(6.2), Inches(0.4), "Why They Happen", size=17, color=BLUE, bold=True)
bullets(s, Inches(0.55), Inches(2.0), Inches(6.3), Inches(4.6), [
    "Insufficient heat -- iron temperature too low or contact time too short",
    "Component or joint moved before the solder fully solidified",
    "Contaminated or oxidized surfaces prevent proper wetting",
    "Insufficient or expired flux, so oxides are not removed during heating",
    "Heat sink effect -- large pad/plane pulls heat away faster than it's supplied",
], size=15.5, space_after=12)
textbox(s, Inches(0.55), Inches(5.1), Inches(6.3), Inches(0.4), "Risk", size=17, color=RED, bold=True)
bullets(s, Inches(0.55), Inches(5.55), Inches(6.3), Inches(1.5), [
    "Intermittent connections -- works initially, fails under vibration/thermal cycling",
    "Increased electrical resistance and heat buildup at the joint",
], size=14.5, space_after=8, color=GREY)
rect(s, Inches(7.1), Inches(1.55), Inches(5.7), Inches(5.5), LIGHT_BLUE)
textbox(s, Inches(7.4), Inches(1.75), Inches(5.1), Inches(0.4), "Identification & Fix", size=16, color=NAVY, bold=True)
bullets(s, Inches(7.4), Inches(2.25), Inches(5.1), Inches(4.6), [
    "Look for: dull grey/frosted surface, granular texture, hairline cracks, uneven surface",
    "Test: mechanically probe or flex the lead gently; cold joints often show micro-movement",
    "Fix: reheat the entire joint (pad + lead) above liquidus, add a small amount of fresh flux-cored solder, allow to cool undisturbed",
    "Prevent: correct iron temperature (315-370°C typical), adequate dwell time, clean/tinned tips, fresh flux, hold parts still until solidified",
], size=14, space_after=12)
footer(s, 9)

# ============================================================
# SLIDE 10 - INSPECTION METHODS
# ============================================================
s = add_slide()
header(s, "Quality Control", "Inspection Methods")
methods = [
    ("Visual / Magnified Inspection", "Operator or loupe/microscope check against IPC-A-610 criteria. Fast, low-cost, but subjective and can't see hidden joints."),
    ("Automated Optical Inspection (AOI)", "Camera-based system compares joint images to a known-good library. Fast, consistent, catches bridging, tombstoning, missing components."),
    ("X-Ray Inspection", "Penetrates the package to reveal hidden joints (BGA, QFN). Detects voids, opens, insufficient solder under the package."),
    ("In-Circuit Test (ICT) / Functional Test", "Electrically probes the board to confirm continuity and function. Confirms the joint works electrically, even if it can't see it."),
]
y0 = Inches(1.55)
h = Inches(1.28)
for i, (title, desc) in enumerate(methods):
    y = y0 + i * (h + Inches(0.08))
    rect(s, Inches(0.55), y, Inches(12.2), h, LIGHT_GREY if i % 2 == 0 else WHITE)
    rect(s, Inches(0.55), y, Inches(0.08), h, BLUE)
    textbox(s, Inches(0.85), y + Inches(0.12), Inches(3.8), Inches(1.0), title, size=15,
            color=NAVY, bold=True, anchor=MSO_ANCHOR.MIDDLE)
    textbox(s, Inches(4.8), y + Inches(0.12), Inches(7.7), Inches(1.0), desc, size=13, color=GREY,
            anchor=MSO_ANCHOR.MIDDLE, line_spacing=1.1)
footer(s, 10)

# ============================================================
# SLIDE 11 - REFLOW VS WAVE
# ============================================================
s = add_slide()
header(s, "Process Comparison", "Reflow vs. Wave Soldering")
colw = Inches(5.9)
x0 = Inches(0.55)
gap = Inches(0.35)
y0 = Inches(1.55)
h = Inches(5.3)
tables = [
    ("Reflow Soldering", [
        "Used primarily for Surface-Mount (SMT) components",
        "Solder paste pre-applied via stencil printing",
        "Board passes through a multi-zone oven (preheat, soak, reflow, cool)",
        "Precise temperature profile controls joint formation",
        "Enables fine-pitch, high-density assemblies (BGA, QFN)",
    ], BLUE),
    ("Wave Soldering", [
        "Used primarily for Through-Hole (THT) components",
        "Board passes over a standing wave of molten solder",
        "Flux applied and board preheated before contact with wave",
        "Bottom-side leads/pads soldered in a single pass",
        "Cost-effective for high-volume THT and mixed assemblies",
    ], ORANGE),
]
for i, (title, items, color) in enumerate(tables):
    x = x0 + i * (colw + gap)
    rect(s, x, y0, colw, h, LIGHT_GREY)
    rect(s, x, y0, colw, Inches(0.6), color)
    textbox(s, x, y0 + Inches(0.08), colw, Inches(0.45), title, size=18, color=WHITE, bold=True,
            align=PP_ALIGN.CENTER)
    bullets(s, x + Inches(0.35), y0 + Inches(0.9), colw - Inches(0.7), h - Inches(1.1),
            [(it, 0) for it in items], size=14.5, space_after=14)
footer(s, 11)

# ============================================================
# SLIDE 12 - BEST PRACTICES / SUMMARY
# ============================================================
s = add_slide()
header(s, "Wrap-Up", "Best Practices & Summary")
textbox(s, Inches(0.55), Inches(1.5), Inches(6.2), Inches(0.4), "Best Practices", size=17, color=BLUE, bold=True)
bullets(s, Inches(0.55), Inches(2.0), Inches(6.3), Inches(4.6), [
    "Keep tips clean, tinned, and at the correct temperature for the alloy in use",
    "Use fresh, appropriate flux-cored solder; avoid excessive dwell time",
    "Heat both surfaces (pad and lead) before feeding solder -- never melt solder onto a cold joint",
    "Hold parts still until the joint fully solidifies (avoid movement/cold joints)",
    "Follow IPC-A-610 class requirements matched to the product's reliability needs",
    "Combine AOI/X-ray with sampled visual inspection for full defect coverage",
], size=15, space_after=11)
rect(s, Inches(7.1), Inches(1.55), Inches(5.7), Inches(5.0), LIGHT_BLUE)
textbox(s, Inches(7.4), Inches(1.75), Inches(5.1), Inches(0.4), "Key Takeaways", size=16, color=NAVY, bold=True)
bullets(s, Inches(7.4), Inches(2.25), Inches(5.1), Inches(4.2), [
    "A solder joint is a metallurgical bond, not a weld -- formed via wetting and IMC formation",
    "Joint quality is judged by fillet shape, wetting coverage, and surface texture",
    "IPC-A-610 Classes 1-3 define acceptance criteria by reliability need",
    "Cold joints, bridging, voids, and tombstoning are the most common defects",
    "Visual, AOI, X-ray, and electrical test together ensure full quality coverage",
], size=14, space_after=12)
footer(s, 12)

prs.save("/tmp/workspace/solder_joint_ppt/Solder_Joints.pptx")
print("DONE")
Running Command

rm -f /tmp/workspace/solder_joint_ppt/build_ppt.py

Writing File

~/solder_joint_ppt/build_ppt.py

from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE

NAVY = RGBColor(0x0B, 0x2B, 0x4A)
BLUE = RGBColor(0x1F, 0x6F, 0xB2)
LIGHT_BLUE = RGBColor(0xE8, 0xF1, 0xF8)
ORANGE = RGBColor(0xE8, 0x7A, 0x1E)
GREY = RGBColor(0x4A, 0x4A, 0x4A)
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
RED = RGBColor(0xC0, 0x39, 0x2B)
GREEN = RGBColor(0x27, 0xAE, 0x60)
LIGHT_GREY = RGBColor(0xF2, 0xF4, 0xF6)

prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
SW, SH = prs.slide_width, prs.slide_height
blank = prs.slide_layouts[6]
TOTAL = 12


def add_slide():
    return prs.slides.add_slide(blank)


def rect(slide, x, y, w, h, color, line_color=None):
    shp = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, x, y, w, h)
    shp.fill.solid()
    shp.fill.fore_color.rgb = color
    if line_color:
        shp.line.color.rgb = line_color
        shp.line.width = Pt(1)
    else:
        shp.line.fill.background()
    shp.shadow.inherit = False
    return shp


def textbox(slide, x, y, w, h, text, size=18, color=GREY, bold=False, align=PP_ALIGN.LEFT,
            font="Calibri", italic=False, anchor=MSO_ANCHOR.TOP, wrap=True, line_spacing=1.0):
    tb = slide.shapes.add_textbox(x, y, w, h)
    tf = tb.text_frame
    tf.word_wrap = wrap
    tf.vertical_anchor = anchor
    tf.margin_left = 0
    tf.margin_right = 0
    tf.margin_top = 0
    tf.margin_bottom = 0
    lines = text.split("\n")
    for i, line in enumerate(lines):
        p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
        p.text = line
        p.alignment = align
        p.line_spacing = line_spacing
        for r in p.runs:
            r.font.size = Pt(size)
            r.font.color.rgb = color
            r.font.bold = bold
            r.font.italic = italic
            r.font.name = font
    return tb


def bullets(slide, x, y, w, h, items, size=16, color=GREY, font="Calibri",
            space_after=8, line_spacing=1.05):
    tb = slide.shapes.add_textbox(x, y, w, h)
    tf = tb.text_frame
    tf.word_wrap = True
    tf.margin_left = 0
    tf.margin_right = 0
    tf.margin_top = 0
    tf.margin_bottom = 0
    for i, item in enumerate(items):
        if isinstance(item, tuple):
            txt, lvl = item
        else:
            txt, lvl = item, 0
        p = tf.paragraphs[0] if i == 0 else tf.add_paragraph()
        p.space_after = Pt(space_after)
        p.line_spacing = line_spacing
        prefix = "•  " if lvl == 0 else "-  "
        p.text = ("     " * lvl) + prefix + txt
        r = p.runs[0]
        r.font.size = Pt(size - (2 if lvl else 0))
        r.font.color.rgb = color
        r.font.name = font
    return tb


def footer(slide, num, title="Solder Joints"):
    rect(slide, 0, SH - Inches(0.35), SW, Inches(0.35), NAVY)
    textbox(slide, Inches(0.4), SH - Inches(0.33), Inches(6), Inches(0.3), title,
            size=10, color=WHITE, font="Calibri")
    textbox(slide, SW - Inches(1.2), SH - Inches(0.33), Inches(0.8), Inches(0.3),
            f"{num}/{TOTAL}", size=10, color=WHITE, align=PP_ALIGN.RIGHT)


def header(slide, kicker, title_text):
    rect(slide, 0, 0, SW, Inches(1.15), NAVY)
    rect(slide, 0, Inches(1.15), SW, Inches(0.06), ORANGE)
    textbox(slide, Inches(0.55), Inches(0.15), Inches(11), Inches(0.35), kicker.upper(),
            size=13, color=ORANGE, bold=True, font="Calibri")
    textbox(slide, Inches(0.55), Inches(0.5), Inches(12), Inches(0.6), title_text,
            size=28, color=WHITE, bold=True, font="Calibri")


def card(slide, x, y, w, h, title, body_lines, title_color=BLUE):
    rect(slide, x, y, w, h, LIGHT_GREY)
    rect(slide, x, y, Inches(0.08), h, title_color)
    ty = y + Inches(0.15)
    textbox(slide, x + Inches(0.25), ty, w - Inches(0.4), Inches(0.4), title,
            size=16, color=NAVY, bold=True)
    bullets(slide, x + Inches(0.25), ty + Inches(0.42), w - Inches(0.45), h - Inches(0.6),
            body_lines, size=12.5, color=GREY, space_after=3)


# ============================================================
# SLIDE 1 - TITLE
# ============================================================
s = add_slide()
rect(s, 0, 0, SW, SH, NAVY)
rect(s, 0, Inches(5.0), SW, Inches(0.08), ORANGE)
textbox(s, Inches(0.9), Inches(2.4), Inches(11.5), Inches(0.5), "SOLDER JOINTS",
        size=20, color=ORANGE, bold=True, font="Calibri")
textbox(s, Inches(0.9), Inches(2.9), Inches(11.5), Inches(1.4),
        "Formation, Types, Quality Criteria\n& Inspection", size=40, color=WHITE, bold=True, font="Calibri")
textbox(s, Inches(0.9), Inches(4.6), Inches(11), Inches(0.5),
        "A Technical Overview for Electronics Assembly", size=18, color=RGBColor(0xC9, 0xD9, 0xEA),
        font="Calibri", italic=True)
textbox(s, Inches(0.9), Inches(6.8), Inches(8), Inches(0.4),
        "Reference: IPC-A-610 Acceptability of Electronic Assemblies", size=13,
        color=RGBColor(0x9A, 0xB6, 0xD1))

# ============================================================
# SLIDE 2 - AGENDA
# ============================================================
s = add_slide()
header(s, "Overview", "Agenda")
agenda = [
    "1. What Is a Solder Joint?",
    "2. The Soldering Process",
    "3. Types of Solder Joints",
    "4. Anatomy of a Good Joint",
    "5. IPC-A-610 Classifications",
    "6. Common Solder Defects",
    "7. Cold Joints & Dry Joints",
    "8. Inspection Methods",
    "9. Reflow vs Wave Soldering",
    "10. Best Practices & Summary",
]
bullets(s, Inches(0.9), Inches(1.6), Inches(10.5), Inches(5.2), agenda, size=20, color=NAVY, space_after=14)
footer(s, 2)

# ============================================================
# SLIDE 3 - WHAT IS A SOLDER JOINT
# ============================================================
s = add_slide()
header(s, "Fundamentals", "What Is a Solder Joint?")
textbox(s, Inches(0.55), Inches(1.5), Inches(6.3), Inches(0.5),
        "Definition", size=18, color=BLUE, bold=True)
bullets(s, Inches(0.55), Inches(2.0), Inches(6.3), Inches(4.5), [
    "A solder joint is a metallurgical bond formed when molten solder wets and adheres to two or more metal surfaces (e.g. a component lead and a PCB pad), then solidifies into a permanent electrical and mechanical connection.",
    "Unlike a weld, the base metals are not melted -- only the solder liquefies and forms an intermetallic compound (IMC) layer with the base metals.",
    "A properly formed joint provides:",
    ("Low-resistance electrical continuity", 1),
    ("Mechanical strength to withstand vibration/thermal cycling", 1),
    ("Environmental sealing against corrosion", 1),
], size=16, space_after=10)
rect(s, Inches(7.2), Inches(1.55), Inches(5.6), Inches(5.0), LIGHT_BLUE)
textbox(s, Inches(7.5), Inches(1.75), Inches(5.0), Inches(0.4), "Key Materials", size=16, color=NAVY, bold=True)
bullets(s, Inches(7.5), Inches(2.25), Inches(5.0), Inches(4.0), [
    "Solder alloy: SAC305 (Sn96.5/Ag3.0/Cu0.5) -- lead-free standard",
    "Sn63/Pb37 -- eutectic leaded (legacy/military/aerospace)",
    "Flux: removes oxides, improves wetting (rosin, no-clean, water-soluble)",
    "Base metals: Cu pads/traces, component leads (Cu, Sn, Ni-plated, etc.)",
    "Substrate: FR-4 PCB with copper pads/plating",
], size=14.5, space_after=10)
footer(s, 3)

# ============================================================
# SLIDE 4 - SOLDERING PROCESS
# ============================================================
s = add_slide()
header(s, "Fundamentals", "The Soldering Process")
steps = [
    ("1", "Surface Prep", "Clean pad/lead surfaces; remove oxides and contaminants."),
    ("2", "Flux Application", "Flux applied to reduce surface tension and promote wetting."),
    ("3", "Heating", "Heat via iron, hot air, or reflow oven raises joint above solder liquidus temp."),
    ("4", "Wetting", "Molten solder flows and spreads across the base metal surfaces."),
    ("5", "Metallurgical Bond", "Intermetallic compound (IMC) layer forms between solder and base metal."),
    ("6", "Cooling & Solidification", "Joint cools undisturbed to form a solid, shiny, concave fillet."),
]
x0 = Inches(0.55)
w = Inches(1.95)
gap = Inches(0.15)
y0 = Inches(1.6)
h = Inches(2.6)
for i, (num, title, desc) in enumerate(steps):
    x = x0 + i * (w + gap)
    rect(s, x, y0, w, h, LIGHT_BLUE)
    rect(s, x, y0, w, Inches(0.5), BLUE)
    textbox(s, x, y0 + Inches(0.02), w, Inches(0.46), num, size=20, color=WHITE, bold=True,
            align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
    textbox(s, x + Inches(0.1), y0 + Inches(0.6), w - Inches(0.2), Inches(0.5), title, size=13.5,
            color=NAVY, bold=True, align=PP_ALIGN.CENTER)
    textbox(s, x + Inches(0.1), y0 + Inches(1.1), w - Inches(0.2), Inches(1.4), desc, size=11,
            color=GREY, align=PP_ALIGN.CENTER)
textbox(s, Inches(0.55), Inches(4.6), Inches(12.2), Inches(0.6),
        "Typical peak reflow temperature: 235-250°C (lead-free) or 210-225°C (leaded); time above liquidus ~30-90 seconds.",
        size=14, color=GREY, italic=True)
rect(s, Inches(0.55), Inches(5.4), Inches(12.2), Inches(1.3), LIGHT_GREY)
textbox(s, Inches(0.75), Inches(5.55), Inches(11.8), Inches(1.0),
        "Golden Rule: Heat the joint (pad + lead together), not just the solder. Apply solder to the heated joint so it flows by capillary action -- never melt solder directly on the iron tip and drip it on.",
        size=14.5, color=NAVY, bold=True)
footer(s, 4)

# ============================================================
# SLIDE 5 - TYPES OF SOLDER JOINTS
# ============================================================
s = add_slide()
header(s, "Classification", "Types of Solder Joints")
cardw = Inches(3.9)
cardh = Inches(2.5)
gapx = Inches(0.25)
x0 = Inches(0.55)
y0 = Inches(1.55)
data = [
    ("Through-Hole (THT)", ["Lead inserted through plated via/hole", "Solder forms fillet on top & bottom", "High mechanical strength", "Used: connectors, power parts"]),
    ("Surface-Mount (SMT)", ["Component pad soldered flat to PCB pad", "No hole; smaller footprint", "Dominant in modern electronics", "Used: resistors, ICs, QFN/BGA"]),
    ("Gull-Wing / J-Lead", ["SMT lead types on ICs (SOIC, QFP)", "Toe, heel, and side fillets checked", "Visual inspection of lead shape", "Used: SOIC, TSOP, QFP packages"]),
]
for i, (title, items) in enumerate(data):
    x = x0 + i * (cardw + gapx)
    card(s, x, y0, cardw, cardh, title, [(it, 0) for it in items], title_color=BLUE)
data2 = [
    ("BGA (Ball Grid Array)", ["Solder balls under package, hidden joints", "Reflow forms balls into joints", "Inspected via X-ray only", "Used: CPUs, high-density ICs"]),
    ("Wire/Lead Splice", ["Two wires or a wire-to-terminal joint", "Solder wicks into stranded wire", "Common in cable harnesses", "Used: repairs, hand assemblies"]),
    ("Press-Fit / Hybrid", ["Mechanical press-fit + solder for sealing", "Combines mechanical & solder bond", "Used in connectors, power modules", "Higher vibration resistance"]),
]
y1 = y0 + cardh + Inches(0.2)
for i, (title, items) in enumerate(data2):
    x = x0 + i * (cardw + gapx)
    card(s, x, y1, cardw, cardh, title, [(it, 0) for it in items], title_color=ORANGE)
footer(s, 5)

# ============================================================
# SLIDE 6 - ANATOMY OF A GOOD JOINT
# ============================================================
s = add_slide()
header(s, "Quality", "Anatomy of a Good Solder Joint")
textbox(s, Inches(0.55), Inches(1.5), Inches(6.2), Inches(0.4), "Visual Hallmarks of Acceptance",
        size=17, color=BLUE, bold=True)
bullets(s, Inches(0.55), Inches(2.0), Inches(6.3), Inches(4.6), [
    "Shiny / smooth surface (satin finish acceptable for matte lead-free alloys)",
    "Concave fillet shape -- smoothly tapered, wetting both surfaces",
    "Complete wetting -- solder covers the entire pad and the lead/component termination",
    "Homogeneous -- no visible graininess, cracks, or pinholes",
    "Adequate fillet height -- lead/termination outline should still be discernible through solder",
    "No excess solder bridging to adjacent pads/leads",
    "No sharp peaks, icicles, or solder balls nearby",
], size=15.5, space_after=11)
rect(s, Inches(7.1), Inches(1.55), Inches(5.7), Inches(5.0), LIGHT_BLUE)
textbox(s, Inches(7.4), Inches(1.75), Inches(5.1), Inches(0.4), "Quick Check Criteria", size=16, color=NAVY, bold=True)
checks = [
    ("Wetting angle", "< 90° (ideally 20-30°) between solder and pad"),
    ("Fillet", "Concave, continuous, no voids"),
    ("Coverage", "Solder wets minimum 75% of terminal per IPC-A-610"),
    ("Color/texture", "Consistent -- shiny for SnPb, may be dull/matte for SAC alloys"),
    ("Alignment", "Component seated flat, not tombstoned or lifted"),
]
yy = Inches(2.3)
for label, desc in checks:
    textbox(s, Inches(7.4), yy, Inches(5.1), Inches(0.3), label, size=14, color=ORANGE, bold=True)
    textbox(s, Inches(7.4), yy + Inches(0.3), Inches(5.1), Inches(0.5), desc, size=12.5, color=GREY)
    yy += Inches(0.85)
footer(s, 6)

# ============================================================
# SLIDE 7 - IPC-A-610 CLASSIFICATIONS
# ============================================================
s = add_slide()
header(s, "Standards", "IPC-A-610 Acceptability Classes")
classes = [
    ("Class 1", "General Electronics", "Consumer products where cosmetic imperfections are not important; only function matters. Lowest reliability requirement."),
    ("Class 2", "Dedicated Service", "Continued/extended service life required; uninterrupted service is desirable but not critical. Most industrial/commercial electronics."),
    ("Class 3", "High Performance", "Continued/high reliability performance is critical; equipment must function on demand (medical, aerospace, military). Tightest acceptance criteria."),
]
x0 = Inches(0.55)
w = Inches(4.0)
gap = Inches(0.15)
y0 = Inches(1.55)
h = Inches(3.0)
colors = [GREEN, BLUE, RED]
for i, (cls, name, desc) in enumerate(classes):
    x = x0 + i * (w + gap)
    rect(s, x, y0, w, h, LIGHT_GREY)
    rect(s, x, y0, w, Inches(0.7), colors[i])
    textbox(s, x, y0 + Inches(0.08), w, Inches(0.55), cls, size=22, color=WHITE, bold=True,
            align=PP_ALIGN.CENTER)
    textbox(s, x + Inches(0.2), y0 + Inches(0.85), w - Inches(0.4), Inches(0.4), name, size=15,
            color=NAVY, bold=True, align=PP_ALIGN.CENTER)
    textbox(s, x + Inches(0.25), y0 + Inches(1.3), w - Inches(0.5), Inches(1.6), desc, size=12.5,
            color=GREY, align=PP_ALIGN.CENTER, line_spacing=1.1)
textbox(s, Inches(0.55), Inches(4.85), Inches(12.2), Inches(0.4),
        "IPC-A-610 defines three visual acceptance conditions for each defect type:", size=15, color=NAVY, bold=True)
bullets(s, Inches(0.9), Inches(5.3), Inches(11.5), Inches(1.4), [
    "Target Condition -- the ideal, defect-free result",
    "Acceptable Condition -- meets minimum requirements, joint is reliable",
    "Defect Condition -- fails to meet minimum requirements; must be reworked or rejected",
], size=14, space_after=6)
footer(s, 7)

# ============================================================
# SLIDE 8 - COMMON DEFECTS
# ============================================================
s = add_slide()
header(s, "Quality Control", "Common Solder Joint Defects")
defects = [
    ("Cold / Dry Joint", "Insufficient heat during formation. Dull, grainy, cracked surface; poor/no wetting.", RED),
    ("Solder Bridging", "Excess solder connects two adjacent pads/leads, causing a short circuit.", RED),
    ("Insufficient Solder", "Too little solder; fillet doesn't fully cover the pad/lead, weak joint.", ORANGE),
    ("Solder Balls", "Small spherical solder particles left near a joint after reflow, can cause shorts.", ORANGE),
    ("Tombstoning", "Small SMT component lifts on one end during reflow due to uneven wetting/heating.", ORANGE),
    ("Voids", "Gas pockets trapped inside the joint (common in BGA), reduce mechanical/thermal integrity.", BLUE),
    ("Dewetting", "Solder flows onto pad then recedes, leaving thin/no coverage on part of the surface.", BLUE),
    ("Non-wetting", "Solder never adheres to a surface at all -- base metal remains exposed.", BLUE),
]
x0 = Inches(0.55)
w = Inches(3.0)
gap = Inches(0.15)
y0 = Inches(1.5)
h = Inches(2.65)
for i, (name, desc, color) in enumerate(defects):
    col = i % 4
    row = i // 4
    x = x0 + col * (w + gap)
    y = y0 + row * (h + Inches(0.15))
    rect(s, x, y, w, h, LIGHT_GREY)
    rect(s, x, y, w, Inches(0.08), color)
    textbox(s, x + Inches(0.15), y + Inches(0.2), w - Inches(0.3), Inches(0.6), name, size=14,
            color=NAVY, bold=True, line_spacing=1.0)
    textbox(s, x + Inches(0.15), y + Inches(0.85), w - Inches(0.3), Inches(1.7), desc, size=11.5,
            color=GREY, line_spacing=1.1)
footer(s, 8)

# ============================================================
# SLIDE 9 - COLD / DRY JOINTS DEEP DIVE
# ============================================================
s = add_slide()
header(s, "Quality Control", "Cold Joints & Dry Joints -- Root Causes")
textbox(s, Inches(0.55), Inches(1.5), Inches(6.2), Inches(0.4), "Why They Happen", size=17, color=BLUE, bold=True)
bullets(s, Inches(0.55), Inches(2.0), Inches(6.3), Inches(4.6), [
    "Insufficient heat -- iron temperature too low or contact time too short",
    "Component or joint moved before the solder fully solidified",
    "Contaminated or oxidized surfaces prevent proper wetting",
    "Insufficient or expired flux, so oxides are not removed during heating",
    "Heat sink effect -- large pad/plane pulls heat away faster than it's supplied",
], size=15.5, space_after=12)
textbox(s, Inches(0.55), Inches(5.1), Inches(6.3), Inches(0.4), "Risk", size=17, color=RED, bold=True)
bullets(s, Inches(0.55), Inches(5.55), Inches(6.3), Inches(1.5), [
    "Intermittent connections -- works initially, fails under vibration/thermal cycling",
    "Increased electrical resistance and heat buildup at the joint",
], size=14.5, space_after=8, color=GREY)
rect(s, Inches(7.1), Inches(1.55), Inches(5.7), Inches(5.5), LIGHT_BLUE)
textbox(s, Inches(7.4), Inches(1.75), Inches(5.1), Inches(0.4), "Identification & Fix", size=16, color=NAVY, bold=True)
bullets(s, Inches(7.4), Inches(2.25), Inches(5.1), Inches(4.6), [
    "Look for: dull grey/frosted surface, granular texture, hairline cracks, uneven surface",
    "Test: mechanically probe or flex the lead gently; cold joints often show micro-movement",
    "Fix: reheat the entire joint (pad + lead) above liquidus, add a small amount of fresh flux-cored solder, allow to cool undisturbed",
    "Prevent: correct iron temperature (315-370°C typical), adequate dwell time, clean/tinned tips, fresh flux, hold parts still until solidified",
], size=14, space_after=12)
footer(s, 9)

# ============================================================
# SLIDE 10 - INSPECTION METHODS
# ============================================================
s = add_slide()
header(s, "Quality Control", "Inspection Methods")
methods = [
    ("Visual / Magnified Inspection", "Operator or loupe/microscope check against IPC-A-610 criteria. Fast, low-cost, but subjective and can't see hidden joints."),
    ("Automated Optical Inspection (AOI)", "Camera-based system compares joint images to a known-good library. Fast, consistent, catches bridging, tombstoning, missing components."),
    ("X-Ray Inspection", "Penetrates the package to reveal hidden joints (BGA, QFN). Detects voids, opens, insufficient solder under the package."),
    ("In-Circuit Test (ICT) / Functional Test", "Electrically probes the board to confirm continuity and function. Confirms the joint works electrically, even if it can't see it."),
]
y0 = Inches(1.55)
h = Inches(1.28)
for i, (title, desc) in enumerate(methods):
    y = y0 + i * (h + Inches(0.08))
    rect(s, Inches(0.55), y, Inches(12.2), h, LIGHT_GREY if i % 2 == 0 else WHITE)
    rect(s, Inches(0.55), y, Inches(0.08), h, BLUE)
    textbox(s, Inches(0.85), y + Inches(0.12), Inches(3.8), Inches(1.0), title, size=15,
            color=NAVY, bold=True, anchor=MSO_ANCHOR.MIDDLE)
    textbox(s, Inches(4.8), y + Inches(0.12), Inches(7.7), Inches(1.0), desc, size=13, color=GREY,
            anchor=MSO_ANCHOR.MIDDLE, line_spacing=1.1)
footer(s, 10)

# ============================================================
# SLIDE 11 - REFLOW VS WAVE
# ============================================================
s = add_slide()
header(s, "Process Comparison", "Reflow vs. Wave Soldering")
colw = Inches(5.9)
x0 = Inches(0.55)
gap = Inches(0.35)
y0 = Inches(1.55)
h = Inches(5.3)
tables = [
    ("Reflow Soldering", [
        "Used primarily for Surface-Mount (SMT) components",
        "Solder paste pre-applied via stencil printing",
        "Board passes through a multi-zone oven (preheat, soak, reflow, cool)",
        "Precise temperature profile controls joint formation",
        "Enables fine-pitch, high-density assemblies (BGA, QFN)",
    ], BLUE),
    ("Wave Soldering", [
        "Used primarily for Through-Hole (THT) components",
        "Board passes over a standing wave of molten solder",
        "Flux applied and board preheated before contact with wave",
        "Bottom-side leads/pads soldered in a single pass",
        "Cost-effective for high-volume THT and mixed assemblies",
    ], ORANGE),
]
for i, (title, items, color) in enumerate(tables):
    x = x0 + i * (colw + gap)
    rect(s, x, y0, colw, h, LIGHT_GREY)
    rect(s, x, y0, colw, Inches(0.6), color)
    textbox(s, x, y0 + Inches(0.08), colw, Inches(0.45), title, size=18, color=WHITE, bold=True,
            align=PP_ALIGN.CENTER)
    bullets(s, x + Inches(0.35), y0 + Inches(0.9), colw - Inches(0.7), h - Inches(1.1),
            [(it, 0) for it in items], size=14.5, space_after=14)
footer(s, 11)

# ============================================================
# SLIDE 12 - BEST PRACTICES / SUMMARY
# ============================================================
s = add_slide()
header(s, "Wrap-Up", "Best Practices & Summary")
textbox(s, Inches(0.55), Inches(1.5), Inches(6.2), Inches(0.4), "Best Practices", size=17, color=BLUE, bold=True)
bullets(s, Inches(0.55), Inches(2.0), Inches(6.3), Inches(4.6), [
    "Keep tips clean, tinned, and at the correct temperature for the alloy in use",
    "Use fresh, appropriate flux-cored solder; avoid excessive dwell time",
    "Heat both surfaces (pad and lead) before feeding solder -- never melt solder onto a cold joint",
    "Hold parts still until the joint fully solidifies (avoid movement/cold joints)",
    "Follow IPC-A-610 class requirements matched to the product's reliability needs",
    "Combine AOI/X-ray with sampled visual inspection for full defect coverage",
], size=15, space_after=11)
rect(s, Inches(7.1), Inches(1.55), Inches(5.7), Inches(5.0), LIGHT_BLUE)
textbox(s, Inches(7.4), Inches(1.75), Inches(5.1), Inches(0.4), "Key Takeaways", size=16, color=NAVY, bold=True)
bullets(s, Inches(7.4), Inches(2.25), Inches(5.1), Inches(4.2), [
    "A solder joint is a metallurgical bond, not a weld -- formed via wetting and IMC formation",
    "Joint quality is judged by fillet shape, wetting coverage, and surface texture",
    "IPC-A-610 Classes 1-3 define acceptance criteria by reliability need",
    "Cold joints, bridging, voids, and tombstoning are the most common defects",
    "Visual, AOI, X-ray, and electrical test together ensure full quality coverage",
], size=14, space_after=12)
footer(s, 12)

prs.save("/tmp/workspace/solder_joint_ppt/Solder_Joints.pptx")
print("DONE")
Running Command

cd /tmp/workspace/solder_joint_ppt && python build_ppt.py

Running Command

ls -la /tmp/workspace/solder_joint_ppt/

Here's your presentation:

Solder Joints

Presentation · PPTX

It's a 12-slide deck covering:
  1. Title
  2. Agenda
  3. What Is a Solder Joint?
  4. The Soldering Process
  5. Types of Solder Joints (THT, SMT, gull-wing, BGA, wire splice, press-fit)
  6. Anatomy of a Good Joint
  7. IPC-A-610 Acceptability Classes (1/2/3)
  8. Common Solder Defects (cold joints, bridging, tombstoning, voids, etc.)
  9. Cold Joints & Dry Joints deep dive
  10. Inspection Methods (visual, AOI, X-ray, ICT)
  11. Reflow vs. Wave Soldering
  12. Best Practices & Summary
Note: I built this on the assumption that "solder joint" refers to electronics/PCB assembly soldering, since I never got confirmation on what "BDC" meant. If you actually needed it tied to a specific document, standard, or application (e.g. a BLDC motor context), let me know and I'll revise the content accordingly.
This is a shared conversation. Sign in to Orris to start your own chat.